fix(whatsapp-bridge): clarify FIFO outbound-id tracker semantics

Rename LRU/refresh wording to match Set insertion-order eviction and
reject non-positive maxSize at construction time.
This commit is contained in:
Kong 2026-06-27 14:15:00 +08:00 committed by Teknium
parent 24aa02179b
commit 6d6702ef50
2 changed files with 15 additions and 3 deletions

View file

@ -1,10 +1,13 @@
/**
* Bounded LRU set of outbound message IDs.
* Bounded FIFO set of outbound message IDs.
*
* Used by the WhatsApp bridge to distinguish "echo of our own /send" from
* "owner-typed message on the linked device" when forwarding `fromMe`
* inbound events back to the Python adapter.
*
* Eviction drops the oldest insertion-order entry when the cap is exceeded.
* Re-remembering an existing id is a no-op for ordering (not LRU refresh).
*
* Heuristic limitation (intentional, documented for future debugging):
* the set is in-memory only. On bridge restart it is empty, so for the
* brief window between restart and the first new outbound, any in-flight
@ -15,6 +18,9 @@
*/
export function createOutboundIdTracker(maxSize = 512) {
if (!Number.isInteger(maxSize) || maxSize < 1) {
throw new RangeError('createOutboundIdTracker: maxSize must be a positive integer');
}
const ids = new Set();
function remember(id) {

View file

@ -46,11 +46,11 @@ test('cap holds across many inserts (bounded memory)', () => {
assert.equal(tracker.has('id-99'), true);
});
test('re-remembering an existing id refreshes its position', () => {
test('re-remembering an existing id does not promote it (FIFO, not LRU)', () => {
// Insertion-order semantics: re-adding doesn't move it forward in
// Set iteration order. This is intentional — we don't need recency,
// just bounded membership. Pin the actual behaviour so future
// refactors don't accidentally introduce LRU semantics.
// refactors don't accidentally introduce LRU refresh semantics.
const tracker = createOutboundIdTracker(2);
tracker.remember('a');
tracker.remember('b');
@ -60,3 +60,9 @@ test('re-remembering an existing id refreshes its position', () => {
assert.equal(tracker.has('b'), true);
assert.equal(tracker.has('c'), true);
});
test('rejects non-positive maxSize', () => {
assert.throws(() => createOutboundIdTracker(0), RangeError);
assert.throws(() => createOutboundIdTracker(-1), RangeError);
assert.throws(() => createOutboundIdTracker(1.5), RangeError);
});