mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Fix early Live choice queue ownership
AI-assisted: Codex
This commit is contained in:
@@ -290,6 +290,22 @@ function acknowledgePendingEvent(id, sourceEventType) {
|
||||
return acknowledged;
|
||||
}
|
||||
|
||||
function retirePendingGeneration(id) {
|
||||
if (!id) return 0;
|
||||
let retired = 0;
|
||||
for (let index = state.pendingEvents.length - 1; index >= 0; index -= 1) {
|
||||
const event = state.pendingEvents[index]?.event;
|
||||
if (event?.id !== id || event.type !== 'generate') continue;
|
||||
state.pendingEvents.splice(index, 1);
|
||||
retired += 1;
|
||||
}
|
||||
if (retired > 0) {
|
||||
scheduleLeaseFlush();
|
||||
broadcastAgentPollingIfChanged();
|
||||
}
|
||||
return retired;
|
||||
}
|
||||
|
||||
function findPendingEventById(id, sourceEventType) {
|
||||
if (!id) return null;
|
||||
const entry = state.pendingEvents.find((item) => (
|
||||
@@ -823,6 +839,9 @@ function createRequestHandler({ detectScript, liveScriptParts }) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (msg.type === 'accept' || msg.type === 'discard') {
|
||||
retirePendingGeneration(msg.id);
|
||||
}
|
||||
recordGenerationCheckpoint(msg);
|
||||
if (msg.type === 'exit') {
|
||||
cleanupSvelteComponentSessionsBeforeExit();
|
||||
|
||||
@@ -2599,6 +2599,59 @@ colors: {}
|
||||
assert.equal(acked.type, 'timeout', 'acked event should be removed from the poll queue');
|
||||
});
|
||||
|
||||
it('retires the leased Generate when early Accept or Discard takes ownership', async () => {
|
||||
await drainPolls(server);
|
||||
for (const [type, id] of [['accept', 'ea11ac01'], ['discard', 'ea11dc01']]) {
|
||||
const generated = await fetch(`http://localhost:${server.port}/events`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
token: server.token,
|
||||
type: 'generate',
|
||||
id,
|
||||
action: 'bolder',
|
||||
count: 3,
|
||||
element: { outerHTML: '<section>early choice</section>', tagName: 'section' },
|
||||
}),
|
||||
});
|
||||
assert.equal(generated.status, 200);
|
||||
const generation = await fetch(`http://localhost:${server.port}/poll?token=${server.token}&types=generate&timeout=100&leaseMs=40`).then((response) => response.json());
|
||||
assert.equal(generation.id, id);
|
||||
|
||||
const chosen = await fetch(`http://localhost:${server.port}/events`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
token: server.token,
|
||||
type,
|
||||
id,
|
||||
...(type === 'accept' ? { variantId: '1' } : {}),
|
||||
}),
|
||||
});
|
||||
assert.equal(chosen.status, 200);
|
||||
const choice = await fetch(`http://localhost:${server.port}/poll?token=${server.token}&types=${type}&timeout=100&leaseMs=40`).then((response) => response.json());
|
||||
assert.equal(choice.type, type);
|
||||
assert.equal(choice.id, id);
|
||||
const reply = await fetch(`http://localhost:${server.port}/poll`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
token: server.token,
|
||||
id,
|
||||
sourceEventType: type,
|
||||
type: type === 'discard' ? 'discarded' : 'complete',
|
||||
}),
|
||||
});
|
||||
assert.equal(reply.status, 200);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 60));
|
||||
const stale = await fetch(`http://localhost:${server.port}/poll?token=${server.token}&types=generate&timeout=30&leaseMs=20`).then((response) => response.json());
|
||||
assert.equal(stale.type, 'timeout', `${type} must prevent Generate redelivery after its old lease expires`);
|
||||
const status = await fetch(`http://localhost:${server.port}/status?token=${server.token}`).then((response) => response.json());
|
||||
assert.equal(status.pendingEvents.some((event) => event.id === id && event.type === 'generate'), false);
|
||||
}
|
||||
});
|
||||
|
||||
it('wakes a parked poll as soon as a missed-ack lease expires', async () => {
|
||||
await drainPolls(server);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user