test: Backend-e2e in CI stabil (eigene Jahre, Sperren, ein Server je App)
- daily-evaluation nutzt die Jahre 2011/2012 statt 2001, damit der Job nicht die Daten von autopilot und reminders liest und verändert. - throttler: app.listen(0) einmal je App statt eines Servers je Anfrage (ECONNRESET bei 40 parallelen Anfragen). - outbox-claims: 120 s Zeitlimit für 2000 sequentielle Anweisungen. - migration-harness: eine `migrate deploy` zur Zeit über eine eigene Advisory-Sperre (P1002 bei parallelen Migrations-Suites). - authority-notices und authority-notices-herd laufen über exclusive-suite nacheinander; Herd-Wiederholung räumt eigene Entwürfe. Refs #32 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
258e90828f
commit
6edae3efec
7 files changed
+217
-140
No files matched your search
@@ -5,6 +5,10 @@ import { PrismaModule } from '../src/prisma/prisma.module';
|
||||
import { PrismaService } from '../src/prisma/prisma.service';
|
||||
|
||||
const ROUNDS = 1000;
|
||||
// 2 x ROUNDS sequential statements: seconds locally, but on a loaded CI
|
||||
// database the default 20 s is too tight. The rounds themselves stay (they are
|
||||
// what catches the rounding race).
|
||||
const ROUNDS_TIMEOUT_MS = 120_000;
|
||||
|
||||
/**
|
||||
* "availableAt" is TIMESTAMP(3): a value written from SQL now() (stale
|
||||
@@ -30,28 +34,32 @@ describe('claimBatch and millisecond rounding (e2e)', () => {
|
||||
await moduleRef.close();
|
||||
});
|
||||
|
||||
it('claims an entry whose availableAt was just set to now()', async () => {
|
||||
const event = await prisma.domainEvent.create({
|
||||
data: {
|
||||
type: 'TaskDue',
|
||||
aggregateType: 'Task',
|
||||
aggregateId: correlationId,
|
||||
payload: {},
|
||||
correlationId,
|
||||
},
|
||||
});
|
||||
let missed = 0;
|
||||
for (let round = 0; round < ROUNDS; round++) {
|
||||
await prisma.$executeRaw`UPDATE "DomainEvent" SET "status" = 'PENDING', "claimedAt" = NULL, "availableAt" = now() WHERE "id" = ${event.id}`;
|
||||
const claimed = await claimBatch(prisma, 'DomainEvent', {
|
||||
limit: 1,
|
||||
filter: Prisma.sql`"correlationId" = ${correlationId}`,
|
||||
orderBy: 'occurredAt',
|
||||
it(
|
||||
'claims an entry whose availableAt was just set to now()',
|
||||
async () => {
|
||||
const event = await prisma.domainEvent.create({
|
||||
data: {
|
||||
type: 'TaskDue',
|
||||
aggregateType: 'Task',
|
||||
aggregateId: correlationId,
|
||||
payload: {},
|
||||
correlationId,
|
||||
},
|
||||
});
|
||||
if (claimed.length !== 1) {
|
||||
missed++;
|
||||
let missed = 0;
|
||||
for (let round = 0; round < ROUNDS; round++) {
|
||||
await prisma.$executeRaw`UPDATE "DomainEvent" SET "status" = 'PENDING', "claimedAt" = NULL, "availableAt" = now() WHERE "id" = ${event.id}`;
|
||||
const claimed = await claimBatch(prisma, 'DomainEvent', {
|
||||
limit: 1,
|
||||
filter: Prisma.sql`"correlationId" = ${correlationId}`,
|
||||
orderBy: 'occurredAt',
|
||||
});
|
||||
if (claimed.length !== 1) {
|
||||
missed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect(missed).toBe(0);
|
||||
});
|
||||
expect(missed).toBe(0);
|
||||
},
|
||||
ROUNDS_TIMEOUT_MS,
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user