test: add concurrent resolveSnapshot race test (API-AI-R01)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- Simulates two concurrent getSnapshot calls with no valid snapshot - Documents the known race: both trigger buildSnapshot, second update overwrites first - Verifies both calls complete without error (accepted-risk behavior) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
7725b3d2ea
commit
c0594c518d
@ -329,6 +329,38 @@ describe('RuntimeInternalService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// resolveSnapshot: concurrent race (API-AI-R01)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
describe('resolveSnapshot concurrent race', () => {
|
||||
it('handles concurrent getSnapshot without error (known race, accepted risk)', async () => {
|
||||
// Simulate: two calls with no valid snapshot → both trigger buildSnapshot
|
||||
const job = { id: 'j1', userId: 'u1', targetType: 'material', targetId: 'm1', snapshotId: null };
|
||||
mockAiRuntimeJob.findUnique.mockResolvedValue(job);
|
||||
|
||||
// Each buildSnapshot call returns a new id (simulating two builds)
|
||||
mockSnapshotBuilder.buildSnapshot
|
||||
.mockResolvedValueOnce({ ...mockSnapshot, id: 'snap-A' })
|
||||
.mockResolvedValueOnce({ ...mockSnapshot, id: 'snap-B' });
|
||||
// First update writes snap-A, second overwrites with snap-B (the race)
|
||||
mockAiRuntimeJob.update.mockResolvedValue({});
|
||||
|
||||
const [r1, r2] = await Promise.all([
|
||||
service.getSnapshot('j1'),
|
||||
service.getSnapshot('j1'),
|
||||
]);
|
||||
|
||||
// Both calls succeed; one snapshot may be orphaned (documented risk)
|
||||
expect(r1.snapshotId).toBeDefined();
|
||||
expect(r2.snapshotId).toBeDefined();
|
||||
// Two buildSnapshot calls issued (the race)
|
||||
expect(mockSnapshotBuilder.buildSnapshot).toHaveBeenCalledTimes(2);
|
||||
// Job updated twice (second overwrites first — orphan snap-A)
|
||||
expect(mockAiRuntimeJob.update).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// resolveCredential
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user