@@ -1030,5 +1030,105 @@ describe(`Electric Integration`, () => {
10301030 await expect ( testCollection . utils . awaitTxId ( 300 ) ) . resolves . toBe ( true )
10311031 await expect ( testCollection . utils . awaitTxId ( 400 ) ) . resolves . toBe ( true )
10321032 } )
1033+
1034+ it ( `should resync after garbage collection and new subscription` , ( ) => {
1035+ // Use fake timers for this test
1036+ vi . useFakeTimers ( )
1037+
1038+ const config = {
1039+ id : `gc-resync-test` ,
1040+ shapeOptions : {
1041+ url : `http://test-url` ,
1042+ params : {
1043+ table : `test_table` ,
1044+ } ,
1045+ } ,
1046+ getKey : ( item : Row ) => item . id as number ,
1047+ startSync : true ,
1048+ gcTime : 100 , // Short GC time for testing
1049+ }
1050+
1051+ const testCollection = createCollection ( electricCollectionOptions ( config ) )
1052+
1053+ // Populate collection with initial data
1054+ subscriber ( [
1055+ {
1056+ key : `1` ,
1057+ value : { id : 1 , name : `Initial User` } ,
1058+ headers : { operation : `insert` } ,
1059+ } ,
1060+ {
1061+ key : `2` ,
1062+ value : { id : 2 , name : `Another User` } ,
1063+ headers : { operation : `insert` } ,
1064+ } ,
1065+ {
1066+ headers : { control : `up-to-date` } ,
1067+ } ,
1068+ ] )
1069+
1070+ // Verify initial data is present
1071+ expect ( testCollection . has ( 1 ) ) . toBe ( true )
1072+ expect ( testCollection . has ( 2 ) ) . toBe ( true )
1073+ expect ( testCollection . size ) . toBe ( 2 )
1074+
1075+ // Subscribe and then unsubscribe to trigger GC timer
1076+ const unsubscribe = testCollection . subscribeChanges ( ( ) => { } )
1077+ unsubscribe ( )
1078+
1079+ // Collection should still be ready before GC timer fires
1080+ expect ( testCollection . status ) . toBe ( `ready` )
1081+ expect ( testCollection . size ) . toBe ( 2 )
1082+
1083+ // Fast-forward time to trigger GC (past the 100ms gcTime)
1084+ vi . advanceTimersByTime ( 150 )
1085+
1086+ // Collection should be cleaned up
1087+ expect ( testCollection . status ) . toBe ( `cleaned-up` )
1088+ expect ( testCollection . size ) . toBe ( 0 )
1089+
1090+ // Reset mock call count for new subscription
1091+ const initialMockCallCount = mockSubscribe . mock . calls . length
1092+
1093+ // Subscribe again - this should restart the sync
1094+ const newUnsubscribe = testCollection . subscribeChanges ( ( ) => { } )
1095+
1096+ // Should have created a new stream
1097+ expect ( mockSubscribe . mock . calls . length ) . toBe ( initialMockCallCount + 1 )
1098+ expect ( testCollection . status ) . toBe ( `loading` )
1099+
1100+ // Send new data to simulate resync
1101+ subscriber ( [
1102+ {
1103+ key : `3` ,
1104+ value : { id : 3 , name : `Resynced User` } ,
1105+ headers : { operation : `insert` } ,
1106+ } ,
1107+ {
1108+ key : `1` ,
1109+ value : { id : 1 , name : `Updated User` } ,
1110+ headers : { operation : `insert` } ,
1111+ } ,
1112+ {
1113+ headers : { control : `up-to-date` } ,
1114+ } ,
1115+ ] )
1116+
1117+ // Verify the collection has resynced with new data
1118+ expect ( testCollection . status ) . toBe ( `ready` )
1119+ expect ( testCollection . has ( 1 ) ) . toBe ( true )
1120+ expect ( testCollection . has ( 3 ) ) . toBe ( true )
1121+ expect ( testCollection . get ( 1 ) ) . toEqual ( { id : 1 , name : `Updated User` } )
1122+ expect ( testCollection . get ( 3 ) ) . toEqual ( { id : 3 , name : `Resynced User` } )
1123+ expect ( testCollection . size ) . toBe ( 2 )
1124+
1125+ // Old data should not be present (collection was cleaned)
1126+ expect ( testCollection . has ( 2 ) ) . toBe ( false )
1127+
1128+ newUnsubscribe ( )
1129+
1130+ // Restore real timers
1131+ vi . useRealTimers ( )
1132+ } )
10331133 } )
10341134} )
0 commit comments