feat(t224): add incremental freight sync
This commit is contained in:
@@ -52,14 +52,18 @@ func (store *Store) CreateFreightSync(
|
||||
ctx,
|
||||
`INSERT INTO erp_sync_runs (
|
||||
id, creator_subject, created_by_user_id, mode, order_number,
|
||||
query_sha256, idempotency_key, request_sha256, status,
|
||||
order_count, item_count, created_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, ?)`,
|
||||
created_from, created_to, watermark_through, query_sha256,
|
||||
idempotency_key, request_sha256, status, order_count, item_count,
|
||||
created_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, ?)`,
|
||||
run.ID,
|
||||
run.CreatorSubject,
|
||||
run.CreatedByUserID,
|
||||
run.Mode,
|
||||
run.OrderNumber,
|
||||
nullableFreightSyncValue(run.OrderNumber),
|
||||
nullableFreightSyncValue(run.CreatedFrom),
|
||||
nullableFreightSyncValue(run.CreatedTo),
|
||||
nullableTimestamp(run.WatermarkThrough),
|
||||
run.QuerySHA256,
|
||||
idempotencyKey,
|
||||
requestSHA256,
|
||||
@@ -106,6 +110,32 @@ func (store *Store) CompleteFreightSync(
|
||||
run domain.FreightSyncRun,
|
||||
batch domain.FreightImportBatch,
|
||||
finishedAt time.Time,
|
||||
) error {
|
||||
return store.completeFreightSync(ctx, run, batch, nil, finishedAt)
|
||||
}
|
||||
|
||||
func (store *Store) CompleteFreightDateSync(
|
||||
ctx context.Context,
|
||||
run domain.FreightSyncRun,
|
||||
batch domain.FreightImportBatch,
|
||||
watermarkThrough time.Time,
|
||||
finishedAt time.Time,
|
||||
) error {
|
||||
return store.completeFreightSync(
|
||||
ctx,
|
||||
run,
|
||||
batch,
|
||||
&watermarkThrough,
|
||||
finishedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func (store *Store) completeFreightSync(
|
||||
ctx context.Context,
|
||||
run domain.FreightSyncRun,
|
||||
batch domain.FreightImportBatch,
|
||||
watermarkThrough *time.Time,
|
||||
finishedAt time.Time,
|
||||
) error {
|
||||
tx, err := store.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
@@ -184,6 +214,28 @@ func (store *Store) CompleteFreightSync(
|
||||
if changed != 1 {
|
||||
return usecase.ErrTaskStateConflict
|
||||
}
|
||||
if watermarkThrough != nil {
|
||||
if _, err := tx.ExecContext(
|
||||
ctx,
|
||||
`INSERT INTO erp_sync_watermarks (
|
||||
creator_subject, source_system, last_successful_to,
|
||||
last_successful_run_id, updated_at
|
||||
) VALUES (?, 'SHUNYUNBAO', ?, ?, ?)
|
||||
ON CONFLICT (creator_subject, source_system)
|
||||
DO UPDATE SET
|
||||
last_successful_to = excluded.last_successful_to,
|
||||
last_successful_run_id = excluded.last_successful_run_id,
|
||||
updated_at = excluded.updated_at
|
||||
WHERE julianday(erp_sync_watermarks.last_successful_to)
|
||||
< julianday(excluded.last_successful_to)`,
|
||||
run.CreatorSubject,
|
||||
formatTimestamp(*watermarkThrough),
|
||||
run.ID,
|
||||
formatTimestamp(finishedAt),
|
||||
); err != nil {
|
||||
return repositoryFailure(err)
|
||||
}
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return repositoryFailure(err)
|
||||
}
|
||||
@@ -377,6 +429,43 @@ func (store *Store) GetFreightSync(
|
||||
return run, nil
|
||||
}
|
||||
|
||||
func (store *Store) GetFreightSyncWatermark(
|
||||
ctx context.Context,
|
||||
creatorSubject string,
|
||||
) (*domain.FreightSyncWatermark, error) {
|
||||
var watermark domain.FreightSyncWatermark
|
||||
var lastSuccessfulTo, updatedAt string
|
||||
err := store.db.QueryRowContext(
|
||||
ctx,
|
||||
`SELECT creator_subject, source_system, last_successful_to,
|
||||
last_successful_run_id, updated_at
|
||||
FROM erp_sync_watermarks
|
||||
WHERE creator_subject = ? AND source_system = 'SHUNYUNBAO'`,
|
||||
creatorSubject,
|
||||
).Scan(
|
||||
&watermark.CreatorSubject,
|
||||
&watermark.SourceSystem,
|
||||
&lastSuccessfulTo,
|
||||
&watermark.LastSuccessfulRunID,
|
||||
&updatedAt,
|
||||
)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, repositoryFailure(err)
|
||||
}
|
||||
watermark.LastSuccessfulTo, err = parseTimestamp(lastSuccessfulTo)
|
||||
if err != nil {
|
||||
return nil, repositoryFailure(err)
|
||||
}
|
||||
watermark.UpdatedAt, err = parseTimestamp(updatedAt)
|
||||
if err != nil {
|
||||
return nil, repositoryFailure(err)
|
||||
}
|
||||
return &watermark, nil
|
||||
}
|
||||
|
||||
func (store *Store) ListFreightOrders(
|
||||
ctx context.Context,
|
||||
creatorSubject string,
|
||||
@@ -458,13 +547,15 @@ func (store *Store) GetFreightOrder(
|
||||
|
||||
const freightSyncSelect = `SELECT
|
||||
id, creator_subject, created_by_user_id, mode, order_number,
|
||||
query_sha256, status, error_code, order_count, item_count,
|
||||
created_at, started_at, finished_at
|
||||
created_from, created_to, watermark_through, query_sha256, status,
|
||||
error_code, order_count, item_count, created_at, started_at, finished_at
|
||||
FROM erp_sync_runs
|
||||
`
|
||||
|
||||
func scanFreightSync(scanner rowScanner) (domain.FreightSyncRun, error) {
|
||||
var run domain.FreightSyncRun
|
||||
var orderNumber, createdFrom, createdTo sql.NullString
|
||||
var watermarkThrough sql.NullString
|
||||
var errorCode sql.NullString
|
||||
var createdAt string
|
||||
var startedAt sql.NullString
|
||||
@@ -474,7 +565,10 @@ func scanFreightSync(scanner rowScanner) (domain.FreightSyncRun, error) {
|
||||
&run.CreatorSubject,
|
||||
&run.CreatedByUserID,
|
||||
&run.Mode,
|
||||
&run.OrderNumber,
|
||||
&orderNumber,
|
||||
&createdFrom,
|
||||
&createdTo,
|
||||
&watermarkThrough,
|
||||
&run.QuerySHA256,
|
||||
&run.Status,
|
||||
&errorCode,
|
||||
@@ -490,6 +584,19 @@ func scanFreightSync(scanner rowScanner) (domain.FreightSyncRun, error) {
|
||||
if errorCode.Valid {
|
||||
run.ErrorCode = &errorCode.String
|
||||
}
|
||||
if orderNumber.Valid {
|
||||
run.OrderNumber = orderNumber.String
|
||||
}
|
||||
if createdFrom.Valid {
|
||||
run.CreatedFrom = createdFrom.String
|
||||
}
|
||||
if createdTo.Valid {
|
||||
run.CreatedTo = createdTo.String
|
||||
}
|
||||
run.WatermarkThrough, err = parseNullableTimestamp(watermarkThrough)
|
||||
if err != nil {
|
||||
return domain.FreightSyncRun{}, err
|
||||
}
|
||||
run.CreatedAt, err = parseTimestamp(createdAt)
|
||||
if err != nil {
|
||||
return domain.FreightSyncRun{}, err
|
||||
@@ -622,6 +729,13 @@ func nullableFreightQuantity(value *int) any {
|
||||
return *value
|
||||
}
|
||||
|
||||
func nullableFreightSyncValue(value string) any {
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func optionalString(value sql.NullString) *string {
|
||||
if !value.Valid {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user