Skip to content

fix!: eliminate MessageId collisions in dialogue routing#47

Merged
YuKitsune merged 7 commits into
mainfrom
fix/dialogue-message-id-collision
May 23, 2026
Merged

fix!: eliminate MessageId collisions in dialogue routing#47
YuKitsune merged 7 commits into
mainfrom
fix/dialogue-message-id-collision

Conversation

@YuKitsune
Copy link
Copy Markdown
Owner

Replies were landing in the wrong dialogue because MessageId is not unique across dialogues, uplinks, or downlinks, making the search in FindDialogueForMessage unreliable. Replaced the ambiguous search with four explicit paths - controller uplinks now route via BeginDialogueCommand or ReplyToDownlinkCommand (using DialogueId directly), and incoming downlinks route via dedicated notifications that either create a new dialogue or search open dialogues by uplink message ID only.

Closes #34

YuKitsune added 2 commits May 19, 2026 07:36
Replace the ambiguous FindDialogueForMessage search (which could match
the wrong dialogue due to MessageId reuse across dialogues, uplinks, and
downlinks) with four explicit paths:

- BeginDialogueCommand / BeginDialogueCommandHandler: controller starts
  a new dialogue with an uplink (no search)
- ReplyToDownlinkCommand / ReplyToDownlinkCommandHandler: controller
  replies to a known downlink, looks up dialogue by ID (no search)
- NewDialogueFromDownlinkNotification / handler: aircraft initiates,
  MessageReference is null
- AircraftRepliedToUplinkNotification / handler: aircraft replies,
  MessageReference is set; searches open dialogues by uplink ID only

FindDialogueForMessage is replaced by FindOpenDialogueByUplink, scoped
to open (non-archived) dialogues and uplink messages only, eliminating
both the uplink/downlink type collision and the cross-dialogue collision.

SendUplinkCommand is retained for system-internal use (logon, error
responses) where no server-side dialogue ID is available.
@YuKitsune YuKitsune changed the title fix: eliminate MessageId collisions in dialogue routing fix!: eliminate MessageId collisions in dialogue routing May 19, 2026
YuKitsune added 3 commits May 20, 2026 07:02
…sts for #34

- Fix all test compilation errors caused by domain model API changes (Dialogue.AddUplink/AddDownlink, ReceivedDownlink, updated constructors)
- Add BeginDialogueCommandHandlerTests and ReplyToDownlinkCommandHandlerTests
- Add regression tests verifying replies append to existing dialogues rather than creating new ones, and that DialogueId lookup is used when multiple dialogues share the same downlink MessageId
- Add DownlinkReceivedNotificationHandler tests for fallback-to-new-dialogue, closed-dialogue isolation, and logoff message handling
@YuKitsune
Copy link
Copy Markdown
Owner Author

Code review

Found 1 issue:

  1. SendUplinkCommandHandler now unconditionally creates a new Dialogue (even when ReplyToDownlinkId is set), but LogonCommandHandler still calls SendUplinkCommand with ReplyToDownlinkId: request.DownlinkId on all three paths. The LOGON downlink is added to a dialogue by DownlinkReceivedNotificationHandler, then the LOGON ACCEPTED / LOGON REJECTED uplink lands in a separate orphan dialogue instead of being appended to it. The previous append-on-reference branch was removed and the regression is locked in by the renamed test Handle_AlwaysCreatesNewDialogue_EvenWithReference.

var dialogue = new Dialogue(request.Recipient);
var uplinkMessage = dialogue.AddUplink(
messageId,
request.ReplyToDownlinkId,
request.Recipient,
request.Sender,

new SendUplinkCommand(
"SYSTEM",
request.Callsign,
request.DownlinkId,
CpdlcUplinkResponseType.NoResponse,
"LOGON ACCEPTED"),
cancellationToken);

await mediator.Send(
new SendUplinkCommand(
"SYSTEM",
request.Callsign,
ReplyToDownlinkId: request.DownlinkId,
CpdlcUplinkResponseType.NoResponse,
"LOGON REJECTED. NO ATS AVBL."),
cancellationToken);

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@YuKitsune YuKitsune merged commit 4bca5d3 into main May 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replies from the CPDLC Editor are starting new messages

1 participant