Skip to content

Fix graceful shutdown ordering and background-job cancellation #342

Description

@joestump

Part of #321. Governing: ADR-0013, ADR-0018, SPEC graceful-shutdown REQ-TMO-003/REQ-WG-004/REQ-SIG-004, SPEC metadata-enrichment-pipeline REQ-ENRICH-041. Depends on: #341 (same shutdown path), #324 (shutdown_timeout config). Hotspot: cmd/server/main.go — serialize with #326/#341/#324.

Requirements

  • REQ-TMO-003 order inverted: spec says drain goroutines (≤25s) THEN HTTP shutdown (5s); code runs srv.Shutdown first with the full 30s ctx then races wg.Wait() on the same ctx (cmd/server/main.go:637-659) — audit CRITICAL. Fix order or amend the spec (state which in the PR)
  • REQ-WG-004: ticker loops and per-user work goroutines share one WaitGroup; spec requires separating them — audit CRITICAL
  • REQ-SIG-004: include the received signal attribute in the "shutdown initiated" log line (main.go:617)
  • FindSimilarArtistsForAll never checks ctx.Done() and sleeps 500ms per artist uncancellably (internal/services/similar_artists.go:451-476); also note it has no callers — wire it to a scheduler or remove it. And ArtistFindSimilar spawns an untracked goroutine with context.Background() (internal/handlers/artists.go:653-656) — tie to lifecycle
  • REQ-ENRICH-041: overlapping metadata ticks are NOT prevented — syncMetadataForUsers spawns per-user goroutines and returns immediately, and its governing comment falsely claims it blocks (cmd/server/main.go:283-338) — audit CRITICAL. Add a per-loop in-flight guard (this also removes the tag-upsert concurrency trigger tracked under EPIC: Unified Tag Taxonomy Completion #303)

Acceptance Criteria

  • SIGTERM under load: background work drains inside the budget, exit code 0, correct log attributes
  • A long tick provably prevents the next tick from starting (test with fake clock or instrumentation)
  • go test -race clean over the shutdown path

Branch

feature/342-graceful-shutdown-ordering

PR Convention

PR title references the story; body ends with Closes #342, references the parent epic and governing artifacts above.

🤖 Posted on behalf of @joestump by Claude.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendGo backend codebugSomething isn't workingqueuedIssue is queued for workstoryStory issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions