Drain before autofetch, fix same-second collisions, and always mc.disconnect() on false/probe failure

This commit is contained in:
Jack Kingsman
2026-02-23 17:33:35 -08:00
parent 619973bdf0
commit cba9e20698
5 changed files with 427 additions and 16 deletions
@@ -50,7 +50,11 @@ function mergePendingAck(
// Generate a key for deduplicating messages by content
export function getMessageContentKey(msg: Message): string {
return `${msg.type}-${msg.conversation_key}-${msg.text}-${msg.sender_timestamp}`;
// When sender_timestamp exists, dedup by content (catches radio-path duplicates with different IDs).
// When null, include msg.id so each message gets a unique key — avoids silently dropping
// different messages that share the same text and received_at second.
const ts = msg.sender_timestamp ?? `r${msg.received_at}-${msg.id}`;
return `${msg.type}-${msg.conversation_key}-${msg.text}-${ts}`;
}
export interface UseConversationMessagesResult {
@@ -86,12 +86,13 @@ describe('getMessageContentKey', () => {
expect(getMessageContentKey(msg1)).toBe(getMessageContentKey(msg2));
});
it('handles null sender_timestamp', () => {
it('handles null sender_timestamp by falling back to received_at and id', () => {
const msg = createMessage({ sender_timestamp: null });
const key = getMessageContentKey(msg);
expect(key).toBe('CHAN-channel123-Hello world-null');
// Falls back to `r${received_at}-${id}` when sender_timestamp is null
expect(key).toBe('CHAN-channel123-Hello world-r1700000001-1');
});
it('handles empty text', () => {
@@ -109,6 +110,54 @@ describe('getMessageContentKey', () => {
expect(key).toContain('Hello: World! @user #channel');
});
it('null-timestamp messages with different received_at produce different keys', () => {
const msg1 = createMessage({ sender_timestamp: null, received_at: 1700000001 });
const msg2 = createMessage({ sender_timestamp: null, received_at: 1700000002 });
expect(getMessageContentKey(msg1)).not.toBe(getMessageContentKey(msg2));
});
it('null-timestamp key does not collide with numeric timestamp key', () => {
// A message with sender_timestamp=null and received_at=123
// should not match a message with sender_timestamp that looks similar
const nullTsMsg = createMessage({ sender_timestamp: null, received_at: 123 });
const numericTsMsg = createMessage({ sender_timestamp: 123 });
expect(getMessageContentKey(nullTsMsg)).not.toBe(getMessageContentKey(numericTsMsg));
});
it('same text and null timestamp but different conversations produce different keys', () => {
const msg1 = createMessage({
sender_timestamp: null,
conversation_key: 'chan1',
received_at: 1700000001,
});
const msg2 = createMessage({
sender_timestamp: null,
conversation_key: 'chan2',
received_at: 1700000001,
});
expect(getMessageContentKey(msg1)).not.toBe(getMessageContentKey(msg2));
});
it('null-timestamp messages with same text and same received_at but different ids produce different keys', () => {
// This is the key fix: two genuinely different messages arriving in the same second
// with null sender_timestamp must NOT collide, even if text is identical
const msg1 = createMessage({ id: 10, sender_timestamp: null, received_at: 1700000001 });
const msg2 = createMessage({ id: 11, sender_timestamp: null, received_at: 1700000001 });
expect(getMessageContentKey(msg1)).not.toBe(getMessageContentKey(msg2));
});
it('null-timestamp messages with same id produce same key (true duplicates dedup)', () => {
// Same message arriving via WS + API fetch has the same id — should still dedup
const msg1 = createMessage({ id: 42, sender_timestamp: null, received_at: 1700000001 });
const msg2 = createMessage({ id: 42, sender_timestamp: null, received_at: 1700000001 });
expect(getMessageContentKey(msg1)).toBe(getMessageContentKey(msg2));
});
});
describe('updateMessageAck logic', () => {