fix(orchestrator): fix score reconciliation bugs#399
Conversation
|
The retry loop shouldn't be here. The consumer framework is already the retry loop: a nack re-enters The actual gap is classification:
That covers every CAS-writing controller (score, speculate, merge, cancel — the cancel DLQ race is this same bug). Controllers stay thin state machines; retryability stays in classifiers, which is where this repo puts it. Keep the new state branches — that's the real fix. With the loop gone, add a direct test for redelivery of an already- |
|
ErrVersionMismatch is likely always retryable? |
0e310ba to
bb21054
Compare
00c135f to
5904769
Compare
|
@behinddwalls @sbalabanov Addressed feedback in
I kept |
5904769 to
64b6dde
Compare
sbalabanov
left a comment
There was a problem hiding this comment.
If Runway and Stovepipe use the same optimistic concurrency pattern with database checkpoints, then we have to
- either duplicate such a classifier across all services
- or come up with a platform alternative - but it should not have access to storage-specific sentinels
- or go with "classify at declaration" path
which one to prefer?
bb21054 to
f601ca2
Compare
64b6dde to
da340ff
Compare
For classifier placement, I prefer the SubmitQueue domain classifier for now:
If another domain later needs the same consumer-level semantics, I think the appropriate extraction is a platform-neutral optimistic-conflict marker plus generic classification. That avoids importing domain storage sentinels into platform code without making the storage extension directly own transport retry policy. |
f601ca2 to
b0ec1ed
Compare
da340ff to
06ef990
Compare
Summary
Fix score reconciliation so redelivery converges from the batch's durable state instead of repeating or regressing work.
Bugs
SpeculatingorMergingback toScored.Scoredstate was persisted but publishing request logs or thespeculatemessage failed, redelivery recalculated the score and wrote anotherScoredversion instead of replaying fanout from the persisted checkpoint.storage.ErrVersionMismatchwas not classified as retryable. An optimistic-lock race could therefore be rejected and sent to the DLQ instead of being redelivered to reconcile from fresh state.Fix
Created: calculate the score and conditionally transition toScored.Scored: preserve the persisted score and replay request logs plus thespeculatemessage.SpeculatingorMerging: acknowledge the stale score delivery without regressing state.Cancellingor terminal: acknowledge because another controller owns recovery.storage.ErrVersionMismatchto the consumer instead of retrying inside the controller.storage.ErrVersionMismatchtoInfraRetryable, allowing consumer redelivery to reload and reconcile the latest state.Scoredbatch.Test Plan
✅
make fmt✅
make lint✅
make check-tidy✅
make check-gazelle✅
make build✅
make testIssues
Stack