feat: 迁移 Admin Repository 到 MySQL 8 (#79)
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cmautobuy/admin/internal/testutil"
|
||||
"cmautobuy/admin/model"
|
||||
"cmautobuy/admin/repository"
|
||||
)
|
||||
@@ -53,16 +54,7 @@ func TestListClientPageForUser_分页统计不泄露其他采购员客户端(t *
|
||||
// 用真实的 migrations,这样表结构变了测试会跟着失败。
|
||||
func newTestDB(t *testing.T) *sql.DB {
|
||||
t.Helper()
|
||||
|
||||
db, err := repository.Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatalf("打开测试库失败: %v", err)
|
||||
}
|
||||
if err := repository.Migrate(db); err != nil {
|
||||
t.Fatalf("迁移失败: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
return db
|
||||
return testutil.OpenMySQL(t)
|
||||
}
|
||||
|
||||
// insertTask 插一条待领取的任务,供领取相关的测试使用。
|
||||
|
||||
@@ -305,7 +305,7 @@ func TestListPddProducts_规格数(t *testing.T) {
|
||||
}
|
||||
|
||||
// skus_json 存进了坏数据时,列表页必须还能打开。
|
||||
// json_array_length 碰到非法 JSON 会让整条查询报错,那样页面直接白屏。
|
||||
// JSON_LENGTH 碰到非法 JSON 会让整条查询报错,那样页面直接白屏。
|
||||
func TestListPddProducts_坏掉的采集结果不影响列表打开(t *testing.T) {
|
||||
db := newTestDB(t)
|
||||
createProduct(t, db, "100000000001")
|
||||
@@ -843,7 +843,7 @@ func insertStaleCollectingProduct(t *testing.T, db *sql.DB, goodsID string) {
|
||||
INSERT INTO tasks (task_id, task_type, status, assigned_client,
|
||||
pdd_goods_url, pdd_goods_id, created_at, updated_at)
|
||||
VALUES (?, 'collect', 'claimed', 'client-已离线',
|
||||
'https://mobile.yangkeduo.com/goods.html?goods_id=' || ?, ?, ?, ?)`,
|
||||
CONCAT('https://mobile.yangkeduo.com/goods.html?goods_id=', ?), ?, ?, ?)`,
|
||||
"COL-STALE-"+goodsID, goodsID, goodsID, staleAt, staleAt); err != nil {
|
||||
t.Fatalf("构造卡死任务失败: %v", err)
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ func insertShopeeSKU(t *testing.T, db *sql.DB, goodsID, skuID string) {
|
||||
if _, err := db.Exec(`
|
||||
INSERT INTO shopee_products (goods_id, title, created_at, updated_at)
|
||||
VALUES (?, '测试商品', ?, ?)
|
||||
ON CONFLICT(goods_id) DO NOTHING`, goodsID, now, now); err != nil {
|
||||
ON DUPLICATE KEY UPDATE goods_id = VALUES(goods_id)`, goodsID, now, now); err != nil {
|
||||
t.Fatalf("插入蝦皮商品失败: %v", err)
|
||||
}
|
||||
if _, err := db.Exec(`
|
||||
|
||||
@@ -57,11 +57,17 @@ func TestSybMapping_动态维度保存并复用(t *testing.T) {
|
||||
if err := SaveSybMapping(db, "SYB-1", key, "USR-1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
detail, _ = GetSybProcessingDetail(db, "SYB-1")
|
||||
detail, err = GetSybProcessingDetail(db, "SYB-1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !detail.MappingValid {
|
||||
t.Fatal("保存后相同蝦皮 SKU + 当前 PDD 商品应自动复用")
|
||||
}
|
||||
list, _ := ListSybOrdersView(db, "", SybStagePurchaseReady, 1)
|
||||
list, err := ListSybOrdersView(db, "", SybStagePurchaseReady, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if list.Total != 1 || !list.Rows[0].CanPurchase || list.Rows[0].DefaultMaxPrice != "39.90" {
|
||||
t.Fatalf("可采购阶段不对: %+v", list)
|
||||
}
|
||||
|
||||
@@ -292,6 +292,22 @@ func submitInTx(
|
||||
// 5. 记下幂等键。和业务写入在同一个事务里——
|
||||
// 分开写的话,业务写成功但幂等没记上,客户端重试会被重复处理。
|
||||
if err := repository.SaveIdempotent(tx, idemKey, hash, string(respJSON)); err != nil {
|
||||
// 两个首次请求可能同时通过前面的“不存在”检查。唯一键会让其中一个
|
||||
// 等待另一个提交后返回重复键;此时回滚本事务的业务写入,再读取赢家
|
||||
// 保存的响应,保证并发重试拿到完全相同的结果。
|
||||
if errors.Is(err, repository.ErrIdempotencyAlreadySaved) {
|
||||
if rollbackErr := tx.Rollback(); rollbackErr != nil && !errors.Is(rollbackErr, sql.ErrTxDone) {
|
||||
return "", fmt.Errorf("回滚重复幂等请求失败: %w", rollbackErr)
|
||||
}
|
||||
body, done, lookupErr := repository.LookupIdempotent(db, idemKey, hash)
|
||||
if lookupErr != nil {
|
||||
return "", lookupErr
|
||||
}
|
||||
if !done {
|
||||
return "", fmt.Errorf("并发幂等请求已提交但未找到保存结果")
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
@@ -359,15 +359,7 @@ func writeEnvelope(t *testing.T, w http.ResponseWriter, status bool, msg string,
|
||||
|
||||
func newSyncTestDB(t *testing.T) *sql.DB {
|
||||
t.Helper()
|
||||
db, err := repository.Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatalf("打开测试库失败: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { db.Close() })
|
||||
if err := repository.Migrate(db); err != nil {
|
||||
t.Fatalf("迁移失败: %v", err)
|
||||
}
|
||||
return db
|
||||
return newTestDB(t)
|
||||
}
|
||||
|
||||
func TestRunSybSync_已有的ShopeeSKUID同步后仍在(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user