Multi-User Interactions
Role-targeted interactions go to multiple users simultaneously. The first user to respond closes the interaction for all others — "first-to-respond wins." This page covers how multi-user delivery and dismissal work at the subscriber level.
Role-Targeted Delivery Flow
Role Resolution
Server resolves role:finance-managers to [usr_alice, usr_bob, usr_carol]. Three separate publish calls go to their individual interaction topics.
All Three Receive the Interaction
Alice, Bob, and Carol all see the interaction in their HIL inboxes. The interactionId is the same for all three.
Bob Responds First
Bob clicks Approve. His InteractionResponse arrives at the server. The pipeline atomically claims the interaction. Bob's response is accepted.
Alice and Carol Receive Dismissal
The pipeline publishes a dismissal signal to interactions.dismiss.{aliceId} and interactions.dismiss.{carolId}. Their clients remove the interaction from the inbox with a "Responded by another team member" message.
Concurrent Response Attempt (Rejected)
If Alice tries to respond in the same moment as Bob, her response is rejected with InteractionAlreadyRespondedException. Her client shows an error and dismisses the interaction.
Dismissal Signal Format
// Received on interactions.dismiss.{userId}
interface InteractionDismissalSignal {
interactionId: string;
reason: 'responded_by_other' | 'timed_out' | 'cancelled';
respondedBy?: string; // present when reason is 'responded_by_other'
message?: string; // human-readable dismissal message
}
Client Handling of Dismissal Signals
// InteractionSubscriber also listens to the dismiss topic
edgeStreamClient.subscribe(`interactions.dismiss.${userId}`, (msg) => {
const dismissal = JSON.parse(msg.body) as InteractionDismissalSignal;
// Remove from queue
queue.dismiss(dismissal.interactionId, dismissal.reason);
// Notify the UI
if (dismissal.reason === 'responded_by_other') {
toast.info(`Interaction responded to by ${dismissal.respondedBy}`);
} else if (dismissal.reason === 'timed_out') {
toast.warning('An interaction expired without a response.');
}
});
Viewing Who Responded (Audit)
The InteractionResponse.RespondedBy field identifies which role member responded. The audit log records this for every interaction, allowing you to see the full history of who responded to role-targeted interactions:
| Field | Value (example) |
|---|---|
interactionId | 8f4a91bc-... |
targetUserId | role:finance-managers |
respondedBy | usr_bob |
outcome | approved |
| Dismissed users | usr_alice, usr_carol |