fix(publish): require submit marker before platform write
Desktop Client Build / Resolve Build Metadata (push) Successful in 20s
Frontend CI / Frontend (push) Successful in 2m57s
Desktop Client Build / Build Desktop Client (push) Successful in 25m11s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 34s
Backend CI / Backend (push) Successful in 50m56s

This commit is contained in:
2026-05-30 22:29:28 +08:00
parent dbd2a1c9f6
commit 8ea4a2ffff
20 changed files with 227 additions and 155 deletions
@@ -722,8 +722,9 @@ func (s *DesktopTaskService) Extend(ctx context.Context, client *repository.Desk
// MarkPublishSubmitStarted records a durable intent marker right before the client performs the
// irreversible platform submit POST. Lease-recovery uses it to avoid silently re-posting a
// non-idempotent article: once submit may have started, recovery routes the task to 'unknown'
// (manual reconcile) instead of auto-requeueing it. Best-effort — a stale/lost lease is a no-op
// and must never block the in-flight publish.
// (manual reconcile) instead of auto-requeueing it. The client must receive a
// positive marker write before it performs the platform submit; a stale/lost
// lease is rejected so the client can stop before the irreversible request.
func (s *DesktopTaskService) MarkPublishSubmitStarted(ctx context.Context, client *repository.DesktopClient, taskID uuid.UUID, leaseToken string) error {
if s == nil || s.pool == nil || client == nil {
return nil
@@ -732,7 +733,7 @@ func (s *DesktopTaskService) MarkPublishSubmitStarted(ctx context.Context, clien
if leaseToken == "" {
return response.ErrBadRequest(40001, "invalid_params", "lease_token is required")
}
if _, err := s.pool.Exec(ctx, `
tag, err := s.pool.Exec(ctx, `
UPDATE desktop_tasks
SET publish_submit_started_at = COALESCE(publish_submit_started_at, NOW()),
updated_at = NOW()
@@ -741,9 +742,13 @@ func (s *DesktopTaskService) MarkPublishSubmitStarted(ctx context.Context, clien
AND kind = 'publish'
AND status = 'in_progress'
AND lease_token_hash = $3
`, taskID, client.ID, HashDesktopClientToken(leaseToken)); err != nil {
`, taskID, client.ID, HashDesktopClientToken(leaseToken))
if err != nil {
return response.ErrInternal(50200, "desktop_task_submit_marker_failed", "failed to mark publish submit started")
}
if tag.RowsAffected() == 0 {
return response.ErrConflict(40983, "desktop_task_lease_invalid", "desktop task lease token is invalid or expired")
}
return nil
}