@@ -669,6 +669,48 @@ export function queryCollectionOptions(
669669 handleQueryResult ( observer . getCurrentResult ( ) )
670670 } )
671671
672+ // Subscribe to the query client's cache to handle queries that are GCed by tanstack query
673+ const unsubscribeQueryCache = queryClient
674+ . getQueryCache ( )
675+ . subscribe ( ( event ) => {
676+ const hashedKey = event . query . queryHash
677+ if ( event . type === `removed` ) {
678+ cleanupQuery ( hashedKey )
679+ }
680+ } )
681+
682+ function cleanupQuery ( hashedQueryKey : string ) {
683+ // Unsubscribe from the query's observer
684+ unsubscribes . get ( hashedQueryKey ) ?.( )
685+
686+ // Get all the rows that are in the result of this query
687+ const rowKeys = queryToRows . get ( hashedQueryKey ) ?? new Set ( )
688+
689+ // Remove the query from these rows
690+ rowKeys . forEach ( ( rowKey ) => {
691+ const queries = rowToQueries . get ( rowKey ) // set of queries that reference this row
692+ if ( queries && queries . size > 0 ) {
693+ queries . delete ( hashedQueryKey )
694+ if ( queries . size === 0 ) {
695+ // Reference count dropped to 0, we can GC the row
696+ rowToQueries . delete ( rowKey )
697+
698+ if ( collection . has ( rowKey ) ) {
699+ begin ( )
700+ write ( { type : `delete` , value : collection . get ( rowKey ) } )
701+ commit ( )
702+ }
703+ }
704+ }
705+ } )
706+
707+ // Remove the query from the internal state
708+ unsubscribes . delete ( hashedQueryKey )
709+ observers . delete ( hashedQueryKey )
710+ queryToRows . delete ( hashedQueryKey )
711+ hashToQueryKey . delete ( hashedQueryKey )
712+ }
713+
672714 const cleanup = async ( ) => {
673715 unsubscribeFromCollectionEvents ( )
674716 unsubscribeFromQueries ( )
@@ -679,6 +721,7 @@ export function queryCollectionOptions(
679721 queryToRows . clear ( )
680722 rowToQueries . clear ( )
681723 observers . clear ( )
724+ unsubscribeQueryCache ( )
682725
683726 await Promise . all (
684727 queryKeys . map ( async ( queryKey ) => {
0 commit comments