Skip to content

Commit

Permalink
createStreamingCache add convenience method readAsync for blocking (a…
Browse files Browse the repository at this point in the history
…sync) reads
  • Loading branch information
bvaughn committed Jul 19, 2023
1 parent eb924d3 commit 3adc81e
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
98 changes: 98 additions & 0 deletions packages/suspense/src/cache/createStreamingCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,104 @@ describe("createStreamingCache", () => {
});
});

describe("readAsync", () => {
it("notifies subscriber(s) of progress and completion", async () => {
const promise = cache.readAsync("string");

expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(expect.anything(), "string");

const options = optionsMap.get("string")!;
options.update([1, 2], 0.66);
options.update([1, 2, 3, 4], 1);
options.resolve();

const { status, value } = await promise;

expect(status).toEqual(STATUS_RESOLVED);
expect(value).toEqual([1, 2, 3, 4]);
});

it("notifies subscriber(s) of progress and rejection", async () => {
const promise = cache.readAsync("string");

// Prevent Jest from failing due to unhandled promise rejection
promise.then(
() => {},
() => {}
);

expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(expect.anything(), "string");

const options = optionsMap.get("string")!;
options.update([1]);
options.reject("Expected");

let didCatch = false;
try {
await promise;
} catch (error) {
didCatch = true;
}

expect(didCatch).toBe(true);
});

it("automatically reject the stream if the loading function throws", async () => {
fetch.mockImplementation(() => {
throw Error("Expected");
});

const promise = cache.readAsync("string");

// Prevent Jest from failing due to unhandled promise rejection
promise.then(
() => {},
() => {}
);

expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(expect.anything(), "string");

let didCatch = false;
try {
await promise;
} catch (error) {
didCatch = true;
}

expect(didCatch).toBe(true);
});

it("caches values so they are only streamed once", async () => {
const promise = cache.readAsync("string");

const options = optionsMap.get("string")!;
options.update([1, 2], 1);
options.resolve();

expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(expect.anything(), "string");

await promise;
await cache.readAsync("string");

expect(fetch).toHaveBeenCalledTimes(1);
});

it("should support additional data passed by the fetcher", () => {
const streaming = cache.stream("string");
const options = optionsMap.get("string")!;

options.update([1], 0.5, { data: 1 });
expect(streaming.data).toEqual({ data: 1 });

options.update([1], 1, { data: 2 });
expect(streaming.data).toEqual({ data: 2 });
});
});

describe("stream", () => {
it("notifies subscriber(s) of progress and completion", async () => {
const streaming = cache.stream("string");
Expand Down
7 changes: 7 additions & 0 deletions packages/suspense/src/cache/createStreamingCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ export function createStreamingCache<
getOrCreateStreamingValue(...params);
}

async function readAsync(...params: Params) {
const { resolver } = stream(...params);
const { data, status, value } = await resolver;
return { data, status, value };
}

function stream(...params: Params) {
// getOrCreateStreamingValue() will call debugLog (cache hit or miss)
return getOrCreateStreamingValue(...params);
Expand Down Expand Up @@ -272,6 +278,7 @@ export function createStreamingCache<
evict,
evictAll,
prefetch,
readAsync,
stream,
};
}
5 changes: 5 additions & 0 deletions packages/suspense/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ export interface StreamingCache<
evict(...params: Params): boolean;
evictAll(): boolean;
prefetch(...params: Params): void;
readAsync(
...params: Params
): PromiseLike<
Pick<StreamingValue<Value, AdditionalData>, "data" | "status" | "value">
>;
stream(...params: Params): StreamingValue<Value, AdditionalData>;
}

Expand Down

0 comments on commit 3adc81e

Please sign in to comment.