Skip to content

Commit

Permalink
Calling while a value is being loaded will resolve/replace the pendin…
Browse files Browse the repository at this point in the history
…g record.
  • Loading branch information
bvaughn committed Mar 21, 2023
1 parent bac7cb9 commit 903b1a1
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
3 changes: 3 additions & 0 deletions packages/suspense/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.0.29
* Edge case bugfix: Calling `cache` while a value is being loaded will resolve/replace the pending record.

## 0.0.28
* Add `useImperativeIntervalCacheValue` hook for imperatively loading and subscribing to `createIntervalCache` data.
* Add `getValue` and `getValueIfCached` methods to `createIntervalCache` type.
Expand Down
17 changes: 17 additions & 0 deletions packages/suspense/src/cache/createCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ describe("createCache", () => {

expect(load).not.toHaveBeenCalled();
});

it("should resolve an in-progress read", async () => {
const wouldReject = cache.readAsync("error");

expect(cache.getValueIfCached("error")).toBeUndefined();
expect(cache.getStatus("error")).toBe(STATUS_PENDING);

cache.cache("VALUE", "error");

expect(cache.getValueIfCached("error")).toBe("VALUE");
expect(cache.getStatus("error")).toBe(STATUS_RESOLVED);

await wouldReject;

expect(cache.getValueIfCached("error")).toBe("VALUE");
expect(cache.getStatus("error")).toBe(STATUS_RESOLVED);
});
});

describe("evict", () => {
Expand Down
35 changes: 30 additions & 5 deletions packages/suspense/src/cache/createCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
CacheMap,
PendingRecord,
Record,
ResolvedRecord,
Status,
StatusCallback,
UnsubscribeCallback,
Expand Down Expand Up @@ -142,9 +141,27 @@ export function createCache<Params extends Array<any>, Value>(
createPendingMutationRecordMap
);

const record: ResolvedRecord<Value> = createResolvedRecord(value);
let record: Record<Value> | undefined = getRecord(...params);
if (record != null) {
if (isPendingRecord(record)) {
debugLogInDev("cache()", params, "Update pending record to:", value);

debugLogInDev("cache()", params, value);
const { abortController, deferred } = record.data;

abortController.abort();

updateRecordToResolved(record, value);

// Don't leave any pending request hanging
deferred.resolve(value);

return;
}
}

debugLogInDev("cache()", params, "Create new resolved record with:", value);

record = createResolvedRecord<Value>(value);

recordMap.set(cacheKey, record);
pendingMutationRecordMap.set(cacheKey, record);
Expand Down Expand Up @@ -193,14 +210,22 @@ export function createCache<Params extends Array<any>, Value>(
subscriberMap.clear();
}

function getRecord(...params: Params): Record<Value> | undefined {
const cacheKey = getKey(params);
const pendingMutationRecordMap = getCacheForType(
createPendingMutationRecordMap
);

return pendingMutationRecordMap.get(cacheKey) ?? recordMap.get(cacheKey);
}

function getOrCreateRecord(...params: Params): Record<Value> {
const cacheKey = getKey(params);
const pendingMutationRecordMap = getCacheForType(
createPendingMutationRecordMap
);

let record =
pendingMutationRecordMap.get(cacheKey) ?? recordMap.get(cacheKey);
let record = getRecord(...params);
if (record == null) {
debugLogInDev(
"getOrCreateRecord(): record not found. creating record...",
Expand Down

0 comments on commit 903b1a1

Please sign in to comment.