feat: PDD 批量采集支持可选客户端 (#74)

This commit is contained in:
chengma
2026-08-10 00:49:51 +08:00
parent c52d730728
commit d99c81310d
6 changed files with 196 additions and 31 deletions
+20 -12
View File
@@ -21,8 +21,8 @@ const claimCandidateLimit = 10
// 指定给本机的 assigned_client = 我 且 status = 'assigned'
// 无主的 assigned_client 为空 且 status = 'pending'
//
// 采集任务创建时不指定客户端(浏览商品页没有副作用,哪台设备采都一样),
// 所以必须支持第二种,否则那些任务永远没人能领。
// 采集任务默认不指定客户端(浏览商品页没有副作用,哪台设备采都一样),
// PDD 批量页面也允许人工指定,因此两种领取条件都必须保留。
// 采购任务可以指定也可以留空——涉及钱和账号时应当显式分配。
//
// **指定给本机的优先。** 显式分配是人为决定,应当先兑现;
@@ -422,24 +422,32 @@ func DeleteTasks(q Execer, taskIDs []string) (int64, error) {
return res.RowsAffected()
}
// InsertCollectTask 建一条采集任务。
//
// `[必须]` 采集任务**不指定客户端**:assigned_client 为 NULL、status 为 pending,
// 谁领到就在领取时标记谁(见 #17 和 ClaimNextTask)。采集是纯读取操作,
// 哪台机器跑都一样,指定了反而会在那台机器关着的时候干等。
//
// goodsURL 必填 —— Client 契约里 pdd_goods_url 是 NOT NULL,
// 没有它客户端拿到任务也不知道去哪采。
// InsertCollectTask 建一条不指定客户端的采集任务。
// 保留这个入口给蝦皮、顺运宝等现有流程使用,避免它们被 PDD 页的新选项影响。
func InsertCollectTask(q Execer, taskID, goodsID, goodsURL string) error {
return InsertCollectTaskForClient(q, taskID, goodsID, goodsURL, "")
}
// InsertCollectTaskForClient 建一条采集任务。
// assignedClient 为空时任务无主待领;有值时只等待指定客户端领取。
// goodsURL 必填 —— Client 契约里 pdd_goods_url 是 NOT NULL。
func InsertCollectTaskForClient(q Execer, taskID, goodsID, goodsURL, assignedClient string) error {
if goodsID == "" || goodsURL == "" {
return fmt.Errorf("采集任务的商品 ID 和链接都不能为空")
}
assignedClient = strings.TrimSpace(assignedClient)
status := model.TaskPending
assigned := sql.NullString{}
if assignedClient != "" {
status = model.TaskAssigned
assigned = sql.NullString{String: assignedClient, Valid: true}
}
now := model.NowISO()
_, err := q.Exec(`
INSERT INTO tasks (task_id, task_type, status, assigned_client,
pdd_goods_url, pdd_goods_id, created_at, updated_at)
VALUES (?, 'collect', 'pending', NULL, ?, ?, ?, ?)`,
taskID, goodsURL, goodsID, now, now)
VALUES (?, 'collect', ?, ?, ?, ?, ?, ?)`,
taskID, status, assigned, goodsURL, goodsID, now, now)
if err != nil {
return fmt.Errorf("创建商品 %s 的采集任务失败: %w", goodsID, err)
}