Builds on cf70021, which added the read-only yeeke client/session/sync core
but left it unreachable and unconfigurable. This commit:
- Wires config.ExtConfig.Yeeke (settings.yml + config.yaml + GOAUTO_YEEKE_*
env vars), mirroring the existing SYB credential pattern exactly, with a
dedicated OcrURL and shared OCR client from sybclient.
- Adds yeeke.StartSync as the single entry point for both a manual admin
trigger and the scheduled job, sharing one in-memory gate plus the existing
DB-level unique active_slot lease so they can never run concurrently.
- Fixes sync.go bugs found in review: Service.Sync always returned a nil
error even when the run failed (start/resume semantics were untestable),
item upserts on ctx-less s.db calls, and no error_message/last_success_at
was ever recorded on the run row.
- Adds status_unrecognized to yeeke_return_package: an unknown claim status
is preserved verbatim and flagged rather than silently bucketed.
- Adds the admin read-only surface (GET .../sync-runs, GET
.../sync-runs/:runId, POST .../sync) under /api/admin/v1/yeeke-returns,
visible to admin and purchaser per the #336 review comment, registered as
a GoAuto access module/menu group and purchaser API.
- Registers GoAutoYeekeReturnSync in the existing job/lease framework
(app/jobs), seeded disabled (Status 2) by a new version-local migration,
following 1786701600000_syb_hourly_sync_job.go's pattern exactly.
- Expands tests: session reuse/bounded re-login/timeout-preserves-cache in
yeekeclient; paging robustness (total changing mid-run, duplicate page,
empty page, timeout, simulated restart/resume), idempotent upserts,
unrecognized-status flagging, active_slot lease contention, StartSync gate
contention, and a credential/captcha redaction check in yeeke; settings.yml
binding and env var precedence in config.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
package jobs
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"go-admin/app/goauto/shopeeproduct"
|
|
"go-admin/app/goauto/sybimport"
|
|
"go-admin/app/goauto/yeeke"
|
|
)
|
|
|
|
// InitJob
|
|
// 需要将定义的struct 添加到字典中;
|
|
// 字典 key 可以配置到 自动任务 调用目标 中;
|
|
func InitJob() {
|
|
jobList = map[string]JobExec{
|
|
"ExamplesOne": ExamplesOne{},
|
|
sybimport.HourlySyncInvokeTarget: sybimport.HourlySyncJob{},
|
|
sybimport.SpecAIParseInvokeTarget: sybimport.ScheduledSpecAIParseJob{},
|
|
shopeeproduct.SpecAutoMatchInvokeTarget: shopeeproduct.ScheduledAutoMatchJob{},
|
|
yeeke.ReturnSyncInvokeTarget: yeeke.ReturnSyncJob{},
|
|
// ...
|
|
}
|
|
}
|
|
|
|
// ExamplesOne
|
|
// 新添加的job 必须按照以下格式定义,并实现Exec函数
|
|
type ExamplesOne struct {
|
|
}
|
|
|
|
func (t ExamplesOne) Exec(arg interface{}) error {
|
|
str := time.Now().Format(timeFormat) + " [INFO] JobCore ExamplesOne exec success"
|
|
// TODO: 这里需要注意 Examples 传入参数是 string 所以 arg.(string);请根据对应的类型进行转化;
|
|
switch arg.(type) {
|
|
|
|
case string:
|
|
if arg.(string) != "" {
|
|
fmt.Println("string", arg.(string))
|
|
fmt.Println(str, arg.(string))
|
|
} else {
|
|
fmt.Println("arg is nil")
|
|
fmt.Println(str, "arg is nil")
|
|
}
|
|
break
|
|
}
|
|
|
|
return nil
|
|
}
|