Track command processing errors on CommandState (errorsCount, error, modifiedAt) - #103
Merged
pditommaso merged 1 commit intoJul 31, 2026
Conversation
Recovers the error tracking originally released as 0.6.0 (e54229e, #89), dropped by the revert to 0.4.0 in #100. VERSION is deliberately untouched. Companion to the retry fix in #102: once a thrown handler is retried instead of terminal-failed, a command can retry indefinitely with nothing recording that it is happening. These fields make that visible. - errorsCount: consecutive processing errors since the last successful processing - modifiedAt: last-write timestamp - error: now also carries the message of a transient (non-terminal) processing error. It holds the most recent message, transient or terminal; a terminal failure is identified by status == FAILED, not by error being non-null. recordError is best-effort — a failed write is logged and never changes control flow, so the command is still kept in the queue and retried. The streak is reset on recovery, with a single write and only when there is something to reset, so healthy re-polls stay write-free. Backward-compatible: the new fields default to 0/null when older serialized state is read. One deliberate adaptation from e54229e, required by this tree: 0.4.x still has executeWithTimeout, which wraps a handler exception in a generic RuntimeException("Command execution failed"). #89 was written against #84, which had removed that method, so recording e.getMessage() verbatim was correct there but here would stamp every transient error on the execute() path with the same useless string. recordError now records the root cause's message via rootMessage(), which is also correct for the checkStatus() path where the exception propagates directly. Caught by #89's own test asserting error == 'Persistent boom'; it failed with 'Command execution failed' before the adaptation. Tests: the two specs from #89 plus its CommandState serialization coverage. Module suite 18/18 green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
pditommaso
merged commit Jul 31, 2026
90465d4
into
fix/cmd-queue-retry-on-handler-exception
3 checks passed
pditommaso
added a commit
that referenced
this pull request
Jul 31, 2026
#100 and #102 (which also carried #103) are now on master, so this branch retargets there instead of stacking on the revert branch. Resolution: - VERSION and changelog changes are dropped from this branch entirely. Master merged #102/#103 without bumping cmd-queue past 0.4.0 or adding a changelog entry, so versioning for the whole 0.4.x line is one decision to make in one place, not something this PR should pre-empt. - CommandServiceImpl and AbstractMessageStream keep this branch's side, which is master's tree plus the drain: the #102 catch and #103 recordError/rootMessage reached this branch by cherry-pick before they were squashed onto master, so both sides carry them and only the drain is genuinely new. Verified: the diff against master is now the drain and nothing else — 5 files, no VERSION, no changelog. Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #102 (which is stacked on #100). Base is
fix/cmd-queue-retry-on-handler-exception. Merge order: #100 → #102 → this.Recovers the error tracking originally released as 0.6.0 (
e54229e, #89), which #100's revert to 0.4.0 dropped. VERSION is deliberately untouched — functionality only; numbering is a separate decision.Why this belongs with #102
#89's own changelog says it plainly: it exists because of #87. Once a thrown handler is retried instead of terminal-failed, a command can retry indefinitely with nothing recording that it is happening. #102 on its own creates that blind spot; this closes it.
errorsCount— consecutive processing errors since the last successful processingmodifiedAt— last-write timestamperror— now also carries the message of a transient (non-terminal) processing error. It holds the most recent message, transient or terminal; a terminal failure is identified bystatus == FAILED, not byerrorbeing non-null.recordErroris best-effort: a failed write is logged and never changes control flow, so the command is still kept in the queue and retried. The streak resets on recovery with a single write, and only when there is something to reset, so healthy re-polls stay write-free. Backward-compatible — new fields default to0/nullwhen older serialized state is read.One deliberate adaptation from
e54229eNot a verbatim cherry-pick. This tree still has
executeWithTimeout, which wraps a handler exception:#89 was written against #84, which had removed that method, so the handler's exception propagated directly and recording
e.getMessage()was correct there. On 0.4.x it is not: every transient error on theexecute()path would be stamped with the same useless"Command execution failed", defeating the whole purpose of the field.recordErrornow records the root cause's message via a smallrootMessage()helper, which is also correct for thecheckStatus()path where the exception propagates directly.This was caught by #89's own test, which asserts
error == 'Persistent boom'and failed withCommand execution failedbefore the adaptation:Note the rest of the mechanism was already correct in that run —
errorsCount=2,modifiedAtset, status non-terminal. Only the message needed unwrapping.Verification
:lib-cmd-queue-redis:test— 18 tests, 0 failures on a forced--rerun.CommandStateserialization coverage.🤖 Generated with Claude Code