Yield bounded catch-up batches behind per-user readiness queues
This commit is contained in:
@@ -57,3 +57,29 @@ test('unchanged dashboard and calendar reads write no rows after synchronization
|
||||
expect((f.sqlite.query('SELECT total_changes() AS n').get() as {n:number}).n).toBe(before);
|
||||
} finally {f.close();}
|
||||
});
|
||||
|
||||
test('catch-up yields to other users and serializes same-user edits until fully ready', async () => {
|
||||
const f = fixture();
|
||||
try {
|
||||
const habit = await f.json('/habits', 'POST', {name:'Many tasks', method:'tasks', tasks:Array.from({length:50}, (_,i)=>({name:`Task ${i}`}))}, 201);
|
||||
f.setTime('2027-09-04T12:00:00Z');
|
||||
let complete = false;
|
||||
const dashboard = f.json('/today').then(value => {complete=true; return value;});
|
||||
await new Promise(resolve=>setTimeout(resolve,0));
|
||||
expect(complete).toBe(false);
|
||||
// Another user's request can complete while Alice is still catching up.
|
||||
expect((await f.request('/today','GET',undefined,'b')).status).toBe(200);
|
||||
expect(complete).toBe(false);
|
||||
// The actual date can advance while catch-up yields; readiness revalidates it.
|
||||
f.setTime('2027-09-05T12:00:00Z');
|
||||
const edit = f.json(`/habits/${habit.id}`, 'PATCH', {name:'Renamed'});
|
||||
const [today, changed] = await Promise.all([dashboard, edit]);
|
||||
expect(today.date).toBe('2027-09-05');
|
||||
expect(today.habits[0].tasks).toHaveLength(50);
|
||||
expect(changed.name).toBe('Renamed');
|
||||
const through = f.sqlite.query('SELECT materialized_through AS date FROM habits WHERE id=?').get(habit.id) as {date:string};
|
||||
expect(through.date).toBe('2027-09-05');
|
||||
const day = await f.json(`/habits/${habit.id}/days/2026-09-05`);
|
||||
expect(day.tasks.every((task:any)=>task.expiredAt!==null && task.closedAt!==null)).toBe(true);
|
||||
} finally {f.close();}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user