@@ -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
0 commit comments