fix(chat-flow): serialize per-chat processing, end flow on dead-leaf nodes (v1.0.3)#4
Merged
Conversation
…nodes (v1.0.3) - processMessage now serializes per (session, chat) through a self-evicting promise chain, closing a read->write race where two near-simultaneous messages could lose or duplicate navigation (double greeting, resurrected leaf). The bounded invalid-path re-process recurses on the locked body to avoid self-deadlock. - When a config edit parks an in-flight user on a node that no longer has options, the flow ends cleanly instead of looping "Invalid option" until the 15-minute expiry.
# Conflicts: # README.md
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.
Summary
Two robustness fixes to chat-flow, released as v1.0.3.
Per-(session, chat) serialization
processMessageread flow state, navigated, then wrote it back withawaits in between. Two near-simultaneous messages for the same chat could both read the same state and race the write — a double greeting on first contact, a lost path advance, or a resurrected leaf. Processing is now chained per${sessionId}__${chatId}through a promise lock (settled tail so a rejection can't wedge the chain; self-evicting when the chain drains). The bounded invalid-path re-process recurses on the locked body, not the public entry, to avoid waiting on its own pending chain entry.Dead-leaf flow end
If a config edit left an in-flight user parked on a node that no longer has any options, every subsequent message hit the fallback branch, replied "Invalid option", and re-saved the state — an endless loop until the 15-minute expiry. When the resolved node has no options, the flow now ends cleanly (state cleared) so the next trigger starts fresh. The legitimate "typed an option that isn't in the menu" case (node still has options) is unchanged.
Tests
tsc --noEmitclean, bundle packages cleanly. The publicprocessMessagesignature drops the internaldeptharg (it was always defaulted; no caller passed it).