Skip to content

Commit d9dbcbf

Browse files
authored
Merge pull request #929 from Caneryy/feat/issue-839
test(stream): cover COMPLETED status and StreamEvent unique dedup
2 parents 539e6f6 + 9dac2e3 commit d9dbcbf

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

backend/tests/integration/stream-lifecycle.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,72 @@ describe("Stream Lifecycle Integration Tests", () => {
557557
});
558558
});
559559

560+
describe("StreamEvent @@unique([transactionHash, eventType]) deduplication", () => {
561+
it("rejects a duplicate (transactionHash, eventType) insert at the database level", async () => {
562+
const streamId = 11;
563+
const txHash = "unique-constraint-tx-hash";
564+
565+
await testPrisma.stream.create({
566+
data: {
567+
streamId,
568+
sender: SENDER,
569+
recipient: RECIPIENT,
570+
tokenAddress: TOKEN,
571+
ratePerSecond: "10",
572+
depositedAmount: "86400",
573+
withdrawnAmount: "0",
574+
startTime: 1700000000,
575+
endTime: 1700000000 + 8640,
576+
lastUpdateTime: 1700000000,
577+
isActive: true,
578+
isPaused: false,
579+
},
580+
});
581+
582+
const eventData = {
583+
streamId,
584+
eventType: "CREATED",
585+
transactionHash: txHash,
586+
ledgerSequence: 12345,
587+
timestamp: 1700000000,
588+
};
589+
590+
await testPrisma.streamEvent.create({ data: eventData });
591+
592+
await expect(
593+
testPrisma.streamEvent.create({
594+
data: {
595+
...eventData,
596+
ledgerSequence: 12346,
597+
timestamp: 1700000001,
598+
},
599+
}),
600+
).rejects.toMatchObject({ code: "P2002" });
601+
602+
const count = await testPrisma.streamEvent.count({
603+
where: { transactionHash: txHash, eventType: "CREATED" },
604+
});
605+
expect(count).toBe(1);
606+
});
607+
608+
it("dedupes worker replay of the same event without creating a second row", async () => {
609+
const streamId = 12;
610+
const txHash = "worker-replay-dedup-tx-hash";
611+
const event = { ...createStreamCreatedEvent(streamId), txHash };
612+
613+
await worker.processEvent(event);
614+
await expect(worker.processEvent(event)).resolves.toBeUndefined();
615+
616+
const count = await testPrisma.streamEvent.count({
617+
where: {
618+
transactionHash: event.txHash,
619+
eventType: "CREATED",
620+
},
621+
});
622+
expect(count).toBe(1);
623+
});
624+
});
625+
560626
describe("SSE client receives broadcast for each stream event", () => {
561627
let eventSource: EventSource;
562628

backend/tests/stream.repository.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ describe('Stream Repository', () => {
2323
});
2424
});
2525

26+
it('should update isActive to false for COMPLETED', async () => {
27+
await updateStatus(123, 'COMPLETED');
28+
expect(prisma.stream.update).toHaveBeenCalledWith({
29+
where: { streamId: 123 },
30+
data: { isActive: false },
31+
});
32+
});
33+
2634
it('should update isActive to true for ACTIVE', async () => {
2735
await updateStatus(123, 'ACTIVE');
2836
expect(prisma.stream.update).toHaveBeenCalledWith({

0 commit comments

Comments
 (0)