Skip to content

Commit 72ac07d

Browse files
authored
Add providesTags handling for upsertQueryEntries (#4872)
* Add providesTags handling for upsertQueryEntries * Fix flakiness in infinite query polling test
1 parent 2751bec commit 72ac07d

File tree

3 files changed

+66
-33
lines changed

3 files changed

+66
-33
lines changed

packages/toolkit/src/query/core/buildSlice.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Action, PayloadAction, UnknownAction } from '@reduxjs/toolkit'
1+
import type { PayloadAction } from '@reduxjs/toolkit'
22
import {
33
combineReducers,
44
createAction,
@@ -23,7 +23,6 @@ import type {
2323
QueryCacheKey,
2424
SubscriptionState,
2525
ConfigState,
26-
QueryKeys,
2726
InfiniteQuerySubState,
2827
InfiniteQueryDirection,
2928
} from './apiState'
@@ -36,18 +35,14 @@ import type {
3635
MutationThunk,
3736
QueryThunk,
3837
QueryThunkArg,
39-
RejectedAction,
4038
} from './buildThunks'
4139
import { calculateProvidedByThunk } from './buildThunks'
4240
import {
4341
isInfiniteQueryDefinition,
4442
type AssertTagTypes,
45-
type DefinitionType,
4643
type EndpointDefinitions,
4744
type FullTagDescription,
48-
type QueryArgFrom,
4945
type QueryDefinition,
50-
type ResultTypeFrom,
5146
} from '../endpointDefinitions'
5247
import type { Patch } from 'immer'
5348
import { isDraft } from 'immer'
@@ -61,6 +56,7 @@ import {
6156
import type { ApiContext } from '../apiTypes'
6257
import { isUpsertQuery } from './buildInitiate'
6358
import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
59+
import type { UnwrapPromise } from '../tsHelpers'
6460

6561
/**
6662
* A typesafe single entry to be upserted into the cache
@@ -279,6 +275,7 @@ export function buildSlice({
279275
substate.fulfilledTimeStamp = meta.fulfilledTimeStamp
280276
})
281277
}
278+
282279
const querySlice = createSlice({
283280
name: `${reducerPath}/queries`,
284281
initialState: initialState as QueryState<any>,
@@ -486,6 +483,11 @@ export function buildSlice({
486483
},
487484
})
488485

486+
type CalculateProvidedByAction = UnwrapPromise<
487+
| ReturnType<ReturnType<QueryThunk>>
488+
| ReturnType<ReturnType<InfiniteQueryThunk<any>>>
489+
>
490+
489491
const invalidationSlice = createSlice({
490492
name: `${reducerPath}/invalidation`,
491493
initialState: initialState as InvalidationState<string>,
@@ -562,26 +564,51 @@ export function buildSlice({
562564
.addMatcher(
563565
isAnyOf(isFulfilled(queryThunk), isRejectedWithValue(queryThunk)),
564566
(draft, action) => {
565-
const providedTags = calculateProvidedByThunk(
566-
action,
567-
'providesTags',
568-
definitions,
569-
assertTagType,
570-
)
571-
const { queryCacheKey } = action.meta.arg
567+
writeProvidedTagsForQuery(draft, action)
568+
},
569+
)
570+
.addMatcher(
571+
querySlice.actions.cacheEntriesUpserted.match,
572+
(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+
}
572583

573-
invalidationSlice.caseReducers.updateProvidedBy(
574-
draft,
575-
invalidationSlice.actions.updateProvidedBy({
576-
queryCacheKey,
577-
providedTags,
578-
}),
579-
)
584+
writeProvidedTagsForQuery(draft, action)
585+
}
580586
},
581587
)
582588
},
583589
})
584590

591+
function writeProvidedTagsForQuery(
592+
draft: InvalidationState<string>,
593+
action: CalculateProvidedByAction,
594+
) {
595+
const providedTags = calculateProvidedByThunk(
596+
action,
597+
'providesTags',
598+
definitions,
599+
assertTagType,
600+
)
601+
const { queryCacheKey } = action.meta.arg
602+
603+
invalidationSlice.caseReducers.updateProvidedBy(
604+
draft,
605+
invalidationSlice.actions.updateProvidedBy({
606+
queryCacheKey,
607+
providedTags,
608+
}),
609+
)
610+
}
611+
585612
// Dummy slice to generate actions
586613
const subscriptionSlice = createSlice({
587614
name: `${reducerPath}/subscriptions`,

packages/toolkit/src/query/tests/infiniteQueries.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,10 @@ describe('Infinite queries', () => {
567567
])
568568

569569
thirdPromise.updateSubscriptionOptions({
570-
pollingInterval: 10,
570+
pollingInterval: 50,
571571
})
572572

573-
await delay(5)
573+
await delay(25)
574574

575575
let entry = countersApi.endpoints.counters.select('item')(
576576
storeRef.store.getState(),
@@ -582,7 +582,7 @@ describe('Infinite queries', () => {
582582
{ page: 5, hitCounter: 3 },
583583
])
584584

585-
await delay(10)
585+
await delay(50)
586586

587587
entry = countersApi.endpoints.counters.select('item')(
588588
storeRef.store.getState(),

packages/toolkit/src/query/tests/optimisticUpserts.test.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,12 @@ const api = createApi({
8181
}),
8282
postWithSideEffect: build.query<Post, string>({
8383
query: (id) => `post/${id}`,
84-
providesTags: ['Post'],
84+
providesTags: (result) => {
85+
if (result) {
86+
return [{ type: 'Post', id: result.id } as const]
87+
}
88+
return []
89+
},
8590
async onCacheEntryAdded(arg, api) {
8691
// Verify that lifecycle promise resolution works
8792
const res = await api.cacheDataLoaded
@@ -419,15 +424,16 @@ describe('upsertQueryEntries', () => {
419424

420425
expect(api.endpoints.getPosts.select()(state).data).toBe(posts)
421426

422-
expect(api.endpoints.postWithSideEffect.select('1')(state).data).toBe(
423-
posts[0],
424-
)
425-
expect(api.endpoints.postWithSideEffect.select('2')(state).data).toBe(
426-
posts[1],
427-
)
428-
expect(api.endpoints.postWithSideEffect.select('3')(state).data).toBe(
429-
posts[2],
430-
)
427+
for (const post of posts) {
428+
expect(api.endpoints.postWithSideEffect.select(post.id)(state).data).toBe(
429+
post,
430+
)
431+
432+
// Should have added tags
433+
expect(state.api.provided.Post[post.id]).toEqual([
434+
`postWithSideEffect("${post.id}")`,
435+
])
436+
}
431437
})
432438

433439
test('Triggers cache lifecycles and side effects', async () => {

0 commit comments

Comments
 (0)