Skip to content

Commit 1770b38

Browse files
committed
Merge branch 'master' into pr/riqts/4263
2 parents 40264eb + 34edf31 commit 1770b38

File tree

60 files changed

+804
-221
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+804
-221
lines changed

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
contents: read
2323
steps:
2424
- uses: actions/checkout@v4
25-
- uses: actions/setup-node@v3
25+
- uses: actions/setup-node@v4
2626
with:
2727
node-version: '20.x'
2828
registry-url: 'https://registry.npmjs.org'

.github/workflows/test-codegen.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ jobs:
1616
codegen: ${{ steps.filter.outputs.codegen }}
1717
steps:
1818
- uses: actions/checkout@v4
19-
- uses: dorny/paths-filter@v2
19+
- uses: dorny/paths-filter@v3
2020
id: filter
2121
with:
2222
filters: |
2323
codegen:
2424
- 'packages/rtk-query-codegen-openapi/**'
25+
- 'yarn.lock'
2526
2627
build:
2728
needs: changes
@@ -36,7 +37,7 @@ jobs:
3637
steps:
3738
- uses: actions/checkout@v4
3839
- name: Use Node.js ${{ matrix.node-version }}
39-
uses: actions/setup-node@v2
40+
uses: actions/setup-node@v4
4041
with:
4142
node-version: ${{ matrix.node }}
4243
cache: 'yarn'

.github/workflows/tests.yml

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ jobs:
1212
toolkit: ${{ steps.filter.outputs.toolkit }}
1313
steps:
1414
- uses: actions/checkout@v4
15-
- uses: dorny/paths-filter@v2
15+
- uses: dorny/paths-filter@v3
1616
id: filter
1717
with:
1818
filters: |
1919
toolkit:
2020
- 'packages/toolkit/**'
2121
- 'examples/publish-ci/**'
2222
- '.github/workflows/tests.yml'
23+
- 'yarn.lock'
2324
2425
build:
2526
needs: changes
@@ -37,7 +38,7 @@ jobs:
3738
uses: actions/checkout@v4
3839

3940
- name: Use node ${{ matrix.node }}
40-
uses: actions/setup-node@v2
41+
uses: actions/setup-node@v4
4142
with:
4243
node-version: ${{ matrix.node }}
4344
cache: 'yarn'
@@ -55,7 +56,7 @@ jobs:
5556
- name: Pack
5657
run: yarn pack
5758

58-
- uses: actions/upload-artifact@v2
59+
- uses: actions/upload-artifact@v4
5960
with:
6061
name: package
6162
path: packages/toolkit/package.tgz
@@ -73,15 +74,15 @@ jobs:
7374
uses: actions/checkout@v4
7475

7576
- name: Use node ${{ matrix.node }}
76-
uses: actions/setup-node@v2
77+
uses: actions/setup-node@v4
7778
with:
7879
node-version: ${{ matrix.node }}
7980
cache: 'yarn'
8081

8182
- name: Install deps
8283
run: yarn install
8384

84-
- uses: actions/download-artifact@v2
85+
- uses: actions/download-artifact@v4
8586
with:
8687
name: package
8788
path: packages/toolkit
@@ -111,7 +112,7 @@ jobs:
111112
uses: actions/checkout@v4
112113

113114
- name: Use node ${{ matrix.node }}
114-
uses: actions/setup-node@v2
115+
uses: actions/setup-node@v4
115116
with:
116117
node-version: ${{ matrix.node }}
117118
cache: 'yarn'
@@ -122,7 +123,7 @@ jobs:
122123
- name: Install TypeScript ${{ matrix.ts }}
123124
run: yarn add typescript@${{ matrix.ts }}
124125

125-
- uses: actions/download-artifact@v2
126+
- uses: actions/download-artifact@v4
126127
with:
127128
name: package
128129
path: packages/toolkit
@@ -164,13 +165,13 @@ jobs:
164165
run:
165166
working-directory: ./examples/publish-ci/${{ matrix.example }}
166167
env:
167-
YARN_ENABLE_IMMUTABLE_INSTALLS: 'false'
168+
YARN_ENABLE_IMMUTABLE_INSTALLS: false
168169
steps:
169170
- name: Checkout repo
170171
uses: actions/checkout@v4
171172

172173
- name: Use node ${{ matrix.node }}
173-
uses: actions/setup-node@v2
174+
uses: actions/setup-node@v4
174175
with:
175176
node-version: ${{ matrix.node }}
176177
cache: 'yarn'
@@ -181,7 +182,7 @@ jobs:
181182
- name: Remove existing RTK
182183
run: yarn remove @reduxjs/toolkit
183184

184-
- uses: actions/download-artifact@v2
185+
- uses: actions/download-artifact@v4
185186
with:
186187
name: package
187188
path: ./examples/publish-ci/${{ matrix.example }}
@@ -197,13 +198,15 @@ jobs:
197198

198199
- name: Set up JDK 17 for React Native build
199200
if: matrix.example == 'react-native' || matrix.example == 'expo'
200-
uses: actions/setup-java@v2
201+
uses: actions/setup-java@v4
201202
with:
202203
java-version: '17.x'
203204
distribution: 'temurin'
204205

205206
- name: Build example
206-
run: NODE_OPTIONS=--openssl-legacy-provider yarn build
207+
env:
208+
NODE_OPTIONS: --openssl-legacy-provider
209+
run: yarn build
207210

208211
- name: Run test step
209212
run: yarn test
@@ -222,15 +225,15 @@ jobs:
222225
uses: actions/checkout@v4
223226

224227
- name: Use node ${{ matrix.node }}
225-
uses: actions/setup-node@v2
228+
uses: actions/setup-node@v4
226229
with:
227230
node-version: ${{ matrix.node }}
228231
cache: 'yarn'
229232

230233
- name: Install deps
231234
run: yarn install
232235

233-
- uses: actions/download-artifact@v2
236+
- uses: actions/download-artifact@v4
234237
with:
235238
name: package
236239
path: packages/toolkit

docs/api/autoBatchEnhancer.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Any action that is tagged with `action.meta[SHOULD_AUTOBATCH] = true` will be tr
9999

100100
- `{type: 'raf'}`: queues using `requestAnimationFrame` (default)
101101
- `{type: 'tick'}`: queues using `queueMicrotask`
102-
- `{type: 'timer, timeout: number}`: queues using `setTimeout`
102+
- `{type: 'timer', timeout: number}`: queues using `setTimeout`
103103
- `{type: 'callback', queueNotification: (notify: () => void) => void}`: lets you provide your own callback, such as a debounced or throttled function
104104

105105
The default behavior is to queue the notifications using `requestAnimationFrame`.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# invalidationByTags
2+
3+
## Overview
4+
5+
`InvalidationByTagsHandler` is a handler instantiated during the (BuildMiddleware) step of the build. The handler acts as a (Middleware) and executes each step in response to matching of internal asyncThunk actions.
6+
7+
The matchers used for a "invalidation sequence" are these two cases:
8+
9+
```ts no-transpile
10+
const isThunkActionWithTags = isAnyOf(
11+
isFulfilled(mutationThunk),
12+
isRejectedWithValue(mutationThunk),
13+
)
14+
15+
const isQueryEnd = isAnyOf(
16+
isFulfilled(mutationThunk, queryThunk),
17+
isRejected(mutationThunk, queryThunk),
18+
)
19+
```
20+
21+
## Triggers
22+
23+
The handler has 3 core conditionals that trigger a sequence:
24+
25+
_Conditional 1 AND 3 are identical in process except the tags are calculated from the payload rather than from the action and endpointDefinition_
26+
27+
1. Mutation trigger
28+
2. Query trigger
29+
3. Manual invalidation via `api.util.invalidateTags` trigger
30+
31+
```ts no-transpile
32+
const handler: ApiMiddlewareInternalHandler = (action, mwApi) => {
33+
if (isThunkActionWithTags(action)) {
34+
invalidateTags(
35+
calculateProvidedByThunk(
36+
action,
37+
'invalidatesTags',
38+
endpointDefinitions,
39+
assertTagType,
40+
),
41+
mwApi,
42+
)
43+
} else if (isQueryEnd(action)) {
44+
invalidateTags([], mwApi)
45+
} else if (api.util.invalidateTags.match(action)) {
46+
invalidateTags(
47+
calculateProvidedBy(
48+
action.payload,
49+
undefined,
50+
undefined,
51+
undefined,
52+
undefined,
53+
assertTagType,
54+
),
55+
mwApi,
56+
)
57+
}
58+
}
59+
```
60+
61+
## Core Sequence
62+
63+
1. `invalidateTags()` initiates:
64+
1. invalidateTags function is called with a list of tags generated from the action metadata
65+
2. in the case of a [queryThunk] resolution an empty set of tags is always provided
66+
2. The tags calculated are added to the list of pending tags to invalidate (see [delayed](#Delayed))
67+
3. (optional: 'Delayed') the invalidateTags function is ended if the `apiSlice.invalidationBehaviour` is set to "delayed" and there are any pending thunks/queries running in that `apiSlice`
68+
4. Pending tags are reset to an empty list, if there are no tags the function ends here
69+
5. Selects all `{ endpointName, originalArgs, queryCacheKey }` combinations that would be invalidated by a specific set of tags.
70+
6. Iterates through queryCacheKeys selected and performs one of two actions if the query exists\*
71+
1. removes cached query result - via the `removeQueryResult` action - if no subscription is active
72+
2. if the query is "uninitialized" it initiates a `refetchQuery` action
73+
74+
```js no-transpile
75+
const toInvalidate = api.util.selectInvalidatedBy(rootState, tags)
76+
context.batch(() => {
77+
const valuesArray = Array.from(toInvalidate.values())
78+
for (const { queryCacheKey } of valuesArray) {
79+
const querySubState = state.queries[queryCacheKey]
80+
const subscriptionSubState =
81+
internalState.currentSubscriptions[queryCacheKey] ?? {}
82+
if (querySubState) {
83+
if (countObjectKeys(subscriptionSubState) === 0) {
84+
mwApi.dispatch(
85+
removeQueryResult({
86+
queryCacheKey,
87+
}),
88+
)
89+
} else if (querySubState.status !== 'uninitialized' /* uninitialized */) {
90+
mwApi.dispatch(refetchQuery(querySubState, queryCacheKey))
91+
}
92+
}
93+
}
94+
})
95+
```
96+
97+
:::note
98+
Step 6 is performed within a `context.batch()` call.
99+
:::
100+
101+
### Delayed
102+
103+
RTKQ now has internal logic to delay tag invalidation briefly, to allow multiple invalidations to get handled together. This is controlled by a new `invalidationBehavior: 'immediate' | 'delayed'` flag on `createApi`. The new default behavior is `'delayed'`. Set it to `'immediate'` to revert to the behavior in RTK 1.9.
104+
105+
The `'delayed'` behaviour enables a check inside `invalidationByTags` that will cause any invalidation that is triggered while a query/mutation is still pending to batch the invalidation until no query/mutation is running.
106+
107+
```ts no-transpile
108+
function invalidateTags(
109+
newTags: readonly FullTagDescription<string>[],
110+
mwApi: SubMiddlewareApi,
111+
) {
112+
const rootState = mwApi.getState()
113+
const state = rootState[reducerPath]
114+
115+
pendingTagInvalidations.push(...newTags)
116+
117+
if (
118+
state.config.invalidationBehavior === 'delayed' &&
119+
hasPendingRequests(state)
120+
) {
121+
return
122+
}
123+
```

0 commit comments

Comments
 (0)