Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions test/mcpl-coalescing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,26 +402,43 @@ test('vectors 7/47: restart keeps accepted content, receipts, and appends after
});

test('#196 finding 2 / vector 34c: a busy channel never hits a subject cap', async (t) => {
const f = await fixture({ framework: { gate: { config: { policies: [{ name: 'attention', match: { tagsAny: ['chat:mention'] }, behavior: 'always' }], default: 'skip' } } } as never }); t.after(f.close); await f.register();
// start() arms the periodic store sync, and this fixture never calls it;
// syncIntervalMs: 0 keeps that sync off if one ever does.
const f = await fixture({ framework: { gate: { config: { policies: [{ name: 'attention', match: { tagsAny: ['chat:mention'] }, behavior: 'always' }], default: 'skip' } }, syncIntervalMs: 0 } as never }); t.after(f.close); await f.register();
const msg = (i: number | string, tags: string[]) => ({ channelId: 'chat', messageId: 'm' + i, eventId: 'e' + i, timestamp: TS, author: { id: 'u', name: 'User' }, tags,
content: [{ type: 'text', text: 'text_' + i }], coalesce: { key: 'message:m' + i, initial: true } });
// #196's review measured 85 ms a message on this path, because its journal
// synced the store for each of three operations per message. An acceptance
// now awaits one durable commit (RFC-006), so messages sent one at a time
// make one store sync each. The count takes every store sync during the
// sends; nothing else in this fixture syncs the store meanwhile. It must be
// at least one, or the count no longer sees the commits, and at most one a
// message, so commits shared between acceptances would still pass. The
// total time depends on the disk and the host's load, so it's reported, not
// asserted; each send keeps the fixture's reply deadline, its guard against
// a hang.
const store = (f.framework as unknown as { store: { sync: (...a: unknown[]) => unknown } }).store;
const sync = store.sync.bind(store);
let syncs = 0;
store.sync = (...a: unknown[]) => { syncs++; return sync(...a); };
const sends = 300;
const t0 = Date.now();
for (let i = 0; i < 300; i++) {
for (let i = 0; i < sends; i++) {
const r = await f.send('channels/incoming', { messages: [msg(i, [])] });
assert.equal(r.result.results[0].accepted, true);
}
const elapsed = Date.now() - t0;
const synced = syncs;
await f.framework.runUntilIdle();
assert.equal(f.membrane.calls.length, 0);
const mention = await f.send('channels/incoming', { messages: [msg('mention', ['chat:mention'])] });
assert.equal(mention.result.results[0].accepted, true);
await f.framework.runUntilIdle();
assert.equal(f.membrane.calls.length, 1);
assert(f.lastRequest().includes('text_mention') && f.lastRequest().includes('text_0'));
// Each acceptance awaits a group-committed fsync (RFC-006 durability); serial
// sends cannot batch, so this is ~300 fsyncs. Bounded, and reported.
console.log(`# 300 serial coalesced channel messages: ${elapsed}ms (${(elapsed / 300).toFixed(1)} ms/msg incl. fsync)`);
assert(elapsed < 30_000, `300 coalesced messages took ${elapsed}ms`);
console.log(`# ${sends} serial coalesced channel messages: ${elapsed}ms (${(elapsed / sends).toFixed(1)} ms/msg incl. fsync), ${synced} store syncs`);
assert(synced > 0, `${sends} coalesced messages made no store sync: the acceptances didn't commit, or the count can't see their commits`);
assert(synced <= sends, `${sends} coalesced messages made ${synced} store syncs, more than one a message`);
});

test('#196 finding 4: a context-budget restart does not assemble a pending batch', async (t) => {
Expand Down
Loading