Skip to content

Commit

Permalink
feat(query): allow invalidating of all cache (#2053)
Browse files Browse the repository at this point in the history
  • Loading branch information
odinr authored Apr 9, 2024
1 parent a27cc07 commit f5e4090
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 6 deletions.
29 changes: 29 additions & 0 deletions .changeset/twenty-boxes-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
"@equinor/fusion-query": minor
---

`QueryCache` now supports invalidation of all entries

When not providing key for `QueryCache.invalidate`, all records will be set to invalid

```diff
QueryCache.ts
- public invalidate(key: string) {
+ public invalidate(key?: string) {
this.#state.next(actions.invalidate(key));
}
```

```diff
create-reducer.ts
.addCase(actions.invalidate, (state, action) => {
+ const invalidKey = action.payload ? [action.payload] : Object.keys(state);
- const entry = state[action.payload];
+ for (const key of invalidKey) {
+ const entry = state[key];
if (entry) {
delete entry.updated;
}
+ }
})
```
2 changes: 1 addition & 1 deletion packages/utils/query/src/cache/QueryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class QueryCache<TType, TArgs> {
this.#state.next(actions.remove(key));
}

public invalidate(key: string) {
public invalidate(key?: string) {
this.#state.next(actions.invalidate(key));
}

Expand Down
43 changes: 41 additions & 2 deletions packages/utils/query/src/cache/actions.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,58 @@
import { ActionInstanceMap, ActionTypes, createAction } from '@equinor/fusion-observable';
import { CacheSortFn, QueryCacheRecord } from './types';

/**
* Creates a set of actions for manipulating the cache.
*
* @template TType - The type of the cache value.
* @template TArgs - The type of the cache arguments.
* @returns An object containing the cache actions.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function createActions<TType = any, TArgs = any>() {
return {
set: createAction(
'cache/set',
/**
* Sets a cache entry.
*
* @param key - The unique key for the cache entry.
* @param entry - The cache entry object containing value, args, and transaction.
* @returns An action with the type 'cache/set' and the payload containing the key and entry.
*/
(key: string, entry: { value: TType; args: TArgs; transaction: string }) => {
return { payload: { key, entry } };
},
),
remove: createAction('cache/remove', (key: string) => ({ payload: key })),
invalidate: createAction('cache/invalidate', (key: string) => ({ payload: key })),
remove: createAction(
'cache/remove',
/**
* Removes a cache entry.
*
* @param key - The unique key for the cache entry to remove.
* @returns An action with the type 'cache/remove' and the payload containing the key.
*/
(key: string) => ({ payload: key }),
),

invalidate: createAction(
'cache/invalidate',
/**
* Invalidates a cache entry or the entire cache if no key is provided.
*
* @param key - The unique key for the cache entry to invalidate. If omitted, all entries are invalidated.
* @returns An action with the type 'cache/invalidate' and the payload containing the key or undefined.
*/
(key?: string) => ({ payload: key }),
),
trim: createAction(
'cache/trim',
/**
* Trims the cache based on a sorting function, a validation function, and a size limit.
*
* @param payload - An object containing optional sort function, validate function, and size limit.
* @returns An action with the type 'cache/trim' and the payload containing the provided arguments.
*/
(payload: {
sort?: CacheSortFn<TType, TArgs>;
validate?: (item: QueryCacheRecord<TType, TArgs>) => boolean;
Expand Down
21 changes: 18 additions & 3 deletions packages/utils/query/src/cache/create-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,22 @@ import type { CacheSortFn, QueryCacheRecord, QueryCacheStateData } from './types

import { ActionBuilder, Actions } from './actions';

/**
* Default sorting function for caching, which sorts based on the 'updated' timestamp.
* @param a - The first QueryCacheRecord to compare.
* @param b - The second QueryCacheRecord to compare.
* @returns A number indicating the sort order.
*/
const sortCache: CacheSortFn = (a: QueryCacheRecord, b: QueryCacheRecord): number => {
return (b.updated ?? 0) - (a.updated ?? 0);
};

/**
* Creates a reducer for managing query cache state.
* @param actions - An instance of ActionBuilder containing action creators.
* @param initial - The initial state of the query cache.
* @returns A reducer function for the query cache state.
*/
export default function <TType, TArgs>(
actions: ActionBuilder<TType, TArgs>,
initial: QueryCacheStateData<TType, TArgs> = {},
Expand Down Expand Up @@ -40,9 +52,12 @@ export default function <TType, TArgs>(
delete state[action.payload];
})
.addCase(actions.invalidate, (state, action) => {
const entry = state[action.payload];
if (entry) {
delete entry.updated;
const invalidKey = action.payload ? [action.payload] : Object.keys(state);
for (const key of invalidKey) {
const entry = state[key];
if (entry) {
delete entry.updated;
}
}
})
.addCase(actions.trim, (state, action) => {
Expand Down

0 comments on commit f5e4090

Please sign in to comment.