@@ -217,10 +217,7 @@ export function buildSlice({
217217
218218 function writeFulfilledCacheEntry (
219219 draft : QueryState < any > ,
220- meta : {
221- arg : QueryThunkArg
222- requestId : string
223- } & {
220+ meta : { arg : QueryThunkArg ; requestId : string } & {
224221 fulfilledTimeStamp : number
225222 baseQueryMeta : unknown
226223 } ,
@@ -297,11 +294,7 @@ export function buildSlice({
297294 action : PayloadAction <
298295 ProcessedQueryUpsertEntry [ ] ,
299296 string ,
300- {
301- RTK_autoBatch : boolean
302- requestId : string
303- timestamp : number
304- }
297+ { RTK_autoBatch : boolean ; requestId : string ; timestamp : number }
305298 > ,
306299 ) {
307300 for ( const entry of action . payload ) {
@@ -488,67 +481,66 @@ export function buildSlice({
488481 | ReturnType < ReturnType < InfiniteQueryThunk < any > > >
489482 >
490483
484+ const initialInvalidationState : InvalidationState < string > = {
485+ tags : { } ,
486+ keys : { } ,
487+ }
488+
491489 const invalidationSlice = createSlice ( {
492490 name : `${ reducerPath } /invalidation` ,
493- initialState : initialState as InvalidationState < string > ,
491+ initialState : initialInvalidationState ,
494492 reducers : {
495493 updateProvidedBy : {
496494 reducer (
497495 draft ,
498- action : PayloadAction < {
499- queryCacheKey : QueryCacheKey
500- providedTags : readonly FullTagDescription < string > [ ]
501- } > ,
496+ action : PayloadAction <
497+ Array < {
498+ queryCacheKey : QueryCacheKey
499+ providedTags : readonly FullTagDescription < string > [ ]
500+ } >
501+ > ,
502502 ) {
503- const { queryCacheKey, providedTags } = action . payload
503+ for ( const { queryCacheKey, providedTags } of action . payload ) {
504+ removeCacheKeyFromTags ( draft , queryCacheKey )
504505
505- for ( const tagTypeSubscriptions of Object . values ( draft ) ) {
506- for ( const idSubscriptions of Object . values ( tagTypeSubscriptions ) ) {
507- const foundAt = idSubscriptions . indexOf ( queryCacheKey )
508- if ( foundAt !== - 1 ) {
509- idSubscriptions . splice ( foundAt , 1 )
506+ for ( const { type, id } of providedTags ) {
507+ const subscribedQueries = ( ( draft . tags [ type ] ??= { } ) [
508+ id || '__internal_without_id'
509+ ] ??= [ ] )
510+ const alreadySubscribed =
511+ subscribedQueries . includes ( queryCacheKey )
512+ if ( ! alreadySubscribed ) {
513+ subscribedQueries . push ( queryCacheKey )
510514 }
511515 }
512- }
513516
514- for ( const { type, id } of providedTags ) {
515- const subscribedQueries = ( ( draft [ type ] ??= { } ) [
516- id || '__internal_without_id'
517- ] ??= [ ] )
518- const alreadySubscribed = subscribedQueries . includes ( queryCacheKey )
519- if ( ! alreadySubscribed ) {
520- subscribedQueries . push ( queryCacheKey )
521- }
517+ // Remove readonly from the providedTags array
518+ draft . keys [ queryCacheKey ] =
519+ providedTags as FullTagDescription < string > [ ]
522520 }
523521 } ,
524- prepare : prepareAutoBatched < {
525- queryCacheKey : QueryCacheKey
526- providedTags : readonly FullTagDescription < string > [ ]
527- } > ( ) ,
522+ prepare :
523+ prepareAutoBatched <
524+ Array < {
525+ queryCacheKey : QueryCacheKey
526+ providedTags : readonly FullTagDescription < string > [ ]
527+ } >
528+ > ( ) ,
528529 } ,
529530 } ,
530531 extraReducers ( builder ) {
531532 builder
532533 . addCase (
533534 querySlice . actions . removeQueryResult ,
534535 ( draft , { payload : { queryCacheKey } } ) => {
535- for ( const tagTypeSubscriptions of Object . values ( draft ) ) {
536- for ( const idSubscriptions of Object . values (
537- tagTypeSubscriptions ,
538- ) ) {
539- const foundAt = idSubscriptions . indexOf ( queryCacheKey )
540- if ( foundAt !== - 1 ) {
541- idSubscriptions . splice ( foundAt , 1 )
542- }
543- }
544- }
536+ removeCacheKeyFromTags ( draft , queryCacheKey )
545537 } ,
546538 )
547539 . addMatcher ( hasRehydrationInfo , ( draft , action ) => {
548540 const { provided } = extractRehydrationInfo ( action ) !
549541 for ( const [ type , incomingTags ] of Object . entries ( provided ) ) {
550542 for ( const [ id , cacheKeys ] of Object . entries ( incomingTags ) ) {
551- const subscribedQueries = ( ( draft [ type ] ??= { } ) [
543+ const subscribedQueries = ( ( draft . tags [ type ] ??= { } ) [
552544 id || '__internal_without_id'
553545 ] ??= [ ] )
554546 for ( const queryCacheKey of cacheKeys ) {
@@ -564,48 +556,71 @@ export function buildSlice({
564556 . addMatcher (
565557 isAnyOf ( isFulfilled ( queryThunk ) , isRejectedWithValue ( queryThunk ) ) ,
566558 ( draft , action ) => {
567- writeProvidedTagsForQuery ( draft , action )
559+ writeProvidedTagsForQueries ( draft , [ action ] )
568560 } ,
569561 )
570562 . addMatcher (
571563 querySlice . actions . cacheEntriesUpserted . match ,
572564 ( draft , action ) => {
573- for ( const { queryDescription : arg , value } of action . payload ) {
574- const action : CalculateProvidedByAction = {
575- type : 'UNKNOWN' ,
576- payload : value ,
577- meta : {
578- requestStatus : 'fulfilled' ,
579- requestId : 'UNKNOWN' ,
580- arg,
581- } ,
582- }
583-
584- writeProvidedTagsForQuery ( draft , action )
585- }
565+ const mockActions : CalculateProvidedByAction [ ] = action . payload . map (
566+ ( { queryDescription, value } ) => {
567+ return {
568+ type : 'UNKNOWN' ,
569+ payload : value ,
570+ meta : {
571+ requestStatus : 'fulfilled' ,
572+ requestId : 'UNKNOWN' ,
573+ arg : queryDescription ,
574+ } ,
575+ }
576+ } ,
577+ )
578+ writeProvidedTagsForQueries ( draft , mockActions )
586579 } ,
587580 )
588581 } ,
589582 } )
590583
591- function writeProvidedTagsForQuery (
584+ function removeCacheKeyFromTags (
585+ draft : InvalidationState < any > ,
586+ queryCacheKey : QueryCacheKey ,
587+ ) {
588+ const existingTags = draft . keys [ queryCacheKey ] ?? [ ]
589+
590+ // Delete this cache key from any existing tags that may have provided it
591+ for ( const tag of existingTags ) {
592+ const tagType = tag . type
593+ const tagId = tag . id ?? '__internal_without_id'
594+ const tagSubscriptions = draft . tags [ tagType ] ?. [ tagId ]
595+
596+ if ( tagSubscriptions ) {
597+ draft . tags [ tagType ] [ tagId ] = tagSubscriptions . filter (
598+ ( qc ) => qc !== queryCacheKey ,
599+ )
600+ }
601+ }
602+
603+ delete draft . keys [ queryCacheKey ]
604+ }
605+
606+ function writeProvidedTagsForQueries (
592607 draft : InvalidationState < string > ,
593- action : CalculateProvidedByAction ,
608+ actions : CalculateProvidedByAction [ ] ,
594609 ) {
595- const providedTags = calculateProvidedByThunk (
596- action ,
597- 'providesTags' ,
598- definitions ,
599- assertTagType ,
600- )
601- const { queryCacheKey } = action . meta . arg
610+ const providedByEntries = actions . map ( ( action ) => {
611+ const providedTags = calculateProvidedByThunk (
612+ action ,
613+ 'providesTags' ,
614+ definitions ,
615+ assertTagType ,
616+ )
617+ const { queryCacheKey } = action . meta . arg
618+ return { queryCacheKey, providedTags }
619+ } )
602620
603621 invalidationSlice . caseReducers . updateProvidedBy (
604622 draft ,
605- invalidationSlice . actions . updateProvidedBy ( {
606- queryCacheKey,
607- providedTags,
608- } ) ,
623+ invalidationSlice . actions . updateProvidedBy ( providedByEntries ) ,
609624 )
610625 }
611626
0 commit comments