feat: multi-worker instance_id presence + claim routing #17

Merged
janpeter merged 3 commits from feat/multi-worker-instance-id into main 2026-05-27 10:26:16 +02:00
Owner

Bumps vendor/scrum4me-shared submodule to multi-worker-aware version. Updates registerWorker (composite-key UPSERT), startHeartbeat (composite-key WHERE), tryClaimJob (writes worker_instance_id), rollbackClaim (clears worker_instance_id — Codex P1-3), resetStaleClaimedJobs requeue path (clears worker_instance_id; FAILED path retains for forensics). Adds 4 tests, 522/522 pass.

Bumps vendor/scrum4me-shared submodule to multi-worker-aware version. Updates registerWorker (composite-key UPSERT), startHeartbeat (composite-key WHERE), tryClaimJob (writes worker_instance_id), rollbackClaim (clears worker_instance_id — Codex P1-3), resetStaleClaimedJobs requeue path (clears worker_instance_id; FAILED path retains for forensics). Adds 4 tests, 522/522 pass.
Bumps vendor/scrum4me-shared to 1446d2c (feat/multi-worker-
instance-id) which adds instance_id/hostname/pid to ClaudeWorker,
drops @@unique([token_id]), adds composite unique, and changes
ApiToken back-relation to one-to-many ClaudeWorker[].

Regenerates prisma/schema.prisma and adds migration multi_worker_instance:
- Three new claude_workers columns (additive, default 'legacy')
- Drops single-token unique index
- Adds composite unique (user_id, token_id, instance_id)
- Adds claude_jobs.worker_instance_id + index

Migration is NOT applied — to be deployed in sub-step 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Migrations are managed in the Scrum4Me main app repo, not in
scrum4me-mcp. The submodule-bump + regenerated schema.prisma stays
(needed for prisma generate to produce up-to-date types for the
runtime), but the migration SQL file belongs in
Scrum4Me/prisma/migrations/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- registerWorker UPSERTs by composite key (user_id, token_id, instance_id)
  with hostname/pid on create-only; heartbeat update by composite key.
- startHeartbeat takes instanceId and uses it in the updateMany WHERE.
- unregisterWorker scopes delete by composite key so only the exiting
  instance is retired (was: deleteMany by token_id alone).
- src/index.ts reads SCRUM4ME_INSTANCE_ID via new getInstanceId() helper
  (default 'legacy' to match the DB column default for back-compat) and
  threads it through registerWorker/startHeartbeat/registerShutdownHandlers.
- tryClaimJob accepts instanceId and writes worker_instance_id on claim.
- rollbackClaim clears worker_instance_id (was missing - Codex P1-3).
- resetStaleClaimedJobs requeue path clears worker_instance_id; FAILED
  path retains it for forensic diagnosis (unchanged).

Tests:
- registerWorker writes row via composite-key upsert with given instance_id
  and hostname/pid present in create payload, absent in update payload.
- Two (user, token, instance_id) rows coexist (blocked previously by
  @@unique([token_id])) - now allowed by composite unique.
- tryClaimJob writes worker_instance_id, rollbackClaim clears it, a
  second claim by another instance rotates the value cleanly.
- Stale requeue clears worker_instance_id; stale FAILED leaves it intact.

run-one-job.ts in scrum4me-docker wiring (setting SCRUM4ME_INSTANCE_ID
when spawning Claude) is deferred to Phase 3 Task 3.3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-mcp!17
No description provided.