@@ -217,10 +217,7 @@ export function buildSlice({
217
217
218
218
function writeFulfilledCacheEntry (
219
219
draft : QueryState < any > ,
220
- meta : {
221
- arg : QueryThunkArg
222
- requestId : string
223
- } & {
220
+ meta : { arg : QueryThunkArg ; requestId : string } & {
224
221
fulfilledTimeStamp : number
225
222
baseQueryMeta : unknown
226
223
} ,
@@ -297,11 +294,7 @@ export function buildSlice({
297
294
action : PayloadAction <
298
295
ProcessedQueryUpsertEntry [ ] ,
299
296
string ,
300
- {
301
- RTK_autoBatch : boolean
302
- requestId : string
303
- timestamp : number
304
- }
297
+ { RTK_autoBatch : boolean ; requestId : string ; timestamp : number }
305
298
> ,
306
299
) {
307
300
for ( const entry of action . payload ) {
@@ -488,67 +481,66 @@ export function buildSlice({
488
481
| ReturnType < ReturnType < InfiniteQueryThunk < any > > >
489
482
>
490
483
484
+ const initialInvalidationState : InvalidationState < string > = {
485
+ tags : { } ,
486
+ keys : { } ,
487
+ }
488
+
491
489
const invalidationSlice = createSlice ( {
492
490
name : `${ reducerPath } /invalidation` ,
493
- initialState : initialState as InvalidationState < string > ,
491
+ initialState : initialInvalidationState ,
494
492
reducers : {
495
493
updateProvidedBy : {
496
494
reducer (
497
495
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
+ > ,
502
502
) {
503
- const { queryCacheKey, providedTags } = action . payload
503
+ for ( const { queryCacheKey, providedTags } of action . payload ) {
504
+ removeCacheKeyFromTags ( draft , queryCacheKey )
504
505
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 )
510
514
}
511
515
}
512
- }
513
516
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 > [ ]
522
520
}
523
521
} ,
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
+ > ( ) ,
528
529
} ,
529
530
} ,
530
531
extraReducers ( builder ) {
531
532
builder
532
533
. addCase (
533
534
querySlice . actions . removeQueryResult ,
534
535
( 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 )
545
537
} ,
546
538
)
547
539
. addMatcher ( hasRehydrationInfo , ( draft , action ) => {
548
540
const { provided } = extractRehydrationInfo ( action ) !
549
541
for ( const [ type , incomingTags ] of Object . entries ( provided ) ) {
550
542
for ( const [ id , cacheKeys ] of Object . entries ( incomingTags ) ) {
551
- const subscribedQueries = ( ( draft [ type ] ??= { } ) [
543
+ const subscribedQueries = ( ( draft . tags [ type ] ??= { } ) [
552
544
id || '__internal_without_id'
553
545
] ??= [ ] )
554
546
for ( const queryCacheKey of cacheKeys ) {
@@ -564,48 +556,71 @@ export function buildSlice({
564
556
. addMatcher (
565
557
isAnyOf ( isFulfilled ( queryThunk ) , isRejectedWithValue ( queryThunk ) ) ,
566
558
( draft , action ) => {
567
- writeProvidedTagsForQuery ( draft , action )
559
+ writeProvidedTagsForQueries ( draft , [ action ] )
568
560
} ,
569
561
)
570
562
. addMatcher (
571
563
querySlice . actions . cacheEntriesUpserted . match ,
572
564
( 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 )
586
579
} ,
587
580
)
588
581
} ,
589
582
} )
590
583
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 (
592
607
draft : InvalidationState < string > ,
593
- action : CalculateProvidedByAction ,
608
+ actions : CalculateProvidedByAction [ ] ,
594
609
) {
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
+ } )
602
620
603
621
invalidationSlice . caseReducers . updateProvidedBy (
604
622
draft ,
605
- invalidationSlice . actions . updateProvidedBy ( {
606
- queryCacheKey,
607
- providedTags,
608
- } ) ,
623
+ invalidationSlice . actions . updateProvidedBy ( providedByEntries ) ,
609
624
)
610
625
}
611
626
0 commit comments