Skip to content

Commit

Permalink
refactor: simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
cevr committed May 5, 2024
1 parent 2d8208b commit 6e96520
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 61 deletions.
42 changes: 20 additions & 22 deletions lib/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export class SuspenseCache<TParams extends any[], TValue> {
});

if (CacheRecord.isPending(record)) {
// abort but do not delete the record
this.logEvent({
type: "abort",
key: cacheKey,
Expand Down Expand Up @@ -220,9 +221,9 @@ export class SuspenseCache<TParams extends any[], TValue> {
CacheRecord.pend(record);
this.loadValue(cacheKey, record, ...args);
} else {
this.getOrCreateRecord(...args);
record = this.getOrCreateRecord(...args);
}
records.push([args, this.recordMap.get(cacheKey)!]);
records.push([args, record]);
});
records.forEach(([args, record]) => {
this.notifySubscribers(args, record);
Expand All @@ -248,17 +249,15 @@ export class SuspenseCache<TParams extends any[], TValue> {
const cacheKey = this.options.getKey(args);
const record = this.recordMap.get(cacheKey);

if (record) {
if (CacheRecord.isResolved(record)) {
return record.data.value;
}
if (CacheRecord.isResolved(record)) {
return record.data.value;
}

if (CacheRecord.isRejected(record)) {
throw record.data.error;
}
if (record.data.lastValue) {
return record.data.lastValue;
}
if (CacheRecord.isRejected(record)) {
throw record.data.error;
}
if (record?.data.lastValue) {
return record.data.lastValue;
}
}

Expand Down Expand Up @@ -344,19 +343,20 @@ export class SuspenseCache<TParams extends any[], TValue> {
currentRecord.data.controller.abort();
}
let nextValue = value;
if (currentRecord) {
if (CacheRecord.isResolved(currentRecord)) {
nextValue = replaceEqualDeep(currentRecord.data.value, value);
} else if (CacheRecord.isPending(currentRecord)) {
nextValue = replaceEqualDeep(currentRecord.data.lastValue, value);
}

if (CacheRecord.isResolved(currentRecord)) {
nextValue = replaceEqualDeep(currentRecord.data.value, value);
} else if (CacheRecord.isPending(currentRecord)) {
nextValue = replaceEqualDeep(currentRecord.data.lastValue, value);
}

if (!currentRecord) {
currentRecord = CacheRecord.makeResolved(nextValue);
this.recordMap.set(cacheKey, currentRecord);
} else {
CacheRecord.resolve(currentRecord, nextValue, Promise.resolve(nextValue));
}

this.logEvent({
type: "set",
key: cacheKey,
Expand Down Expand Up @@ -491,11 +491,9 @@ export class SuspenseCache<TParams extends any[], TValue> {
abort<Key extends TParams>(...args: Key): boolean {
const cacheKey = this.options.getKey(args);
const record = this.recordMap.get(cacheKey);
if (record && CacheRecord.isPending(record)) {
if (CacheRecord.isPending(record)) {
record.data.controller.abort();
if (CacheRecord.isPending(record)) {
return this.delete(...args);
}
return this.delete(...args);
}
return false;
}
Expand Down
91 changes: 52 additions & 39 deletions lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { invariant } from './internals';
import type { Deferred } from './utils';
import { defer, DeferredStatus } from './utils';
import { invariant } from "./internals";
import type { Deferred } from "./utils";
import { defer, DeferredStatus } from "./utils";

export const CacheStatus = {
...DeferredStatus,
Expand Down Expand Up @@ -48,25 +48,27 @@ type CacheRecordStatic = {
makeResolved<TValue>(value: TValue): ResolvedCacheRecord<TValue>;
makeRejected<TValue>(error: unknown): RejectedCacheRecord<TValue>;
isPending<TValue>(
record: CacheRecord<TValue> | CacheRecord<TValue>['data'],
record?: CacheRecord<TValue>
): record is PendingCacheRecord<TValue>;
isResolved<TValue>(
record: CacheRecord<TValue> | CacheRecord<TValue>['data'],
record?: CacheRecord<TValue>
): record is ResolvedCacheRecord<TValue>;
isRejected<TValue>(
record: CacheRecord<TValue> | CacheRecord<TValue>['data'],
record?: CacheRecord<TValue>
): record is RejectedCacheRecord<TValue>;
resolve<TValue>(
record: CacheRecord<TValue>,
value: TValue,
promise: Promise<TValue>,
promise: Promise<TValue>
): asserts record is ResolvedCacheRecord<TValue>;
reject<TValue>(
record: CacheRecord<TValue>,
error: unknown,
promise: Promise<TValue>,
promise: Promise<TValue>
): asserts record is RejectedCacheRecord<TValue>;
pend<TValue>(record: CacheRecord<TValue>): asserts record is PendingCacheRecord<TValue>;
pend<TValue>(
record: CacheRecord<TValue>
): asserts record is PendingCacheRecord<TValue>;
};

// this is kept in the type file to take advantage of the type merging
Expand Down Expand Up @@ -103,33 +105,28 @@ export const CacheRecord: CacheRecordStatic = {
},

isPending<TValue>(
record: CacheRecord<TValue> | CacheRecord<TValue>['data'],
record?: CacheRecord<TValue>
): record is PendingCacheRecord<TValue> {
if ('data' in record) {
return record.data.status === CacheStatus.PENDING;
}
return record.status === CacheStatus.PENDING;
return record?.data.status === CacheStatus.PENDING;
},

isResolved<TValue>(
record: CacheRecord<TValue> | CacheRecord<TValue>['data'],
record?: CacheRecord<TValue>
): record is ResolvedCacheRecord<TValue> {
if ('data' in record) {
return record.data.status === CacheStatus.RESOLVED;
}
return record.status === CacheStatus.RESOLVED;
return record?.data.status === CacheStatus.RESOLVED;
},

isRejected<TValue>(
record: CacheRecord<TValue> | CacheRecord<TValue>['data'],
record?: CacheRecord<TValue>
): record is RejectedCacheRecord<TValue> {
if ('data' in record) {
return record.data.status === CacheStatus.REJECTED;
}
return record.status === CacheStatus.REJECTED;
return record?.data.status === CacheStatus.REJECTED;
},

resolve<TValue>(record: CacheRecord<TValue>, value: TValue, promise: Promise<TValue>) {
resolve<TValue>(
record: CacheRecord<TValue>,
value: TValue,
promise: Promise<TValue>
) {
if (CacheRecord.isResolved(record) || CacheRecord.isRejected(record)) {
record.data = {
status: CacheStatus.RESOLVED,
Expand All @@ -150,11 +147,15 @@ export const CacheRecord: CacheRecordStatic = {
};
},

reject<TValue>(record: CacheRecord<TValue>, error: unknown, promise: Promise<TValue>) {
reject<TValue>(
record: CacheRecord<TValue>,
error: unknown,
promise: Promise<TValue>
) {
invariant(
CacheRecord.isPending(record),
'Cannot reject a record that is not pending or revalidating. record is: ' +
record.data.status,
"Cannot reject a record that is not pending or revalidating. record is: " +
record.data.status
);

const deferred = record.data.value;
Expand All @@ -178,9 +179,10 @@ export const CacheRecord: CacheRecordStatic = {

export const CacheResultStatus = {
...CacheStatus,
REVALIDATING: 'revalidating',
REVALIDATING: "revalidating",
} as const;
export type CacheResultStatus = (typeof CacheResultStatus)[keyof typeof CacheResultStatus];
export type CacheResultStatus =
(typeof CacheResultStatus)[keyof typeof CacheResultStatus];
export type CacheValueResult<TValue> =
| [status: typeof CacheResultStatus.PENDING, value: undefined]
| [status: typeof CacheResultStatus.REVALIDATING, value: TValue]
Expand All @@ -195,12 +197,16 @@ export interface CacheMap<Key, Value> {
get(key: Key): Value | undefined;
has(key: Key): boolean;
set(key: Key, value: Value): this;
forEach(callbackfn: (value: Value, key: Key, map: CacheMap<Key, Value>) => void): void;
forEach(
callbackfn: (value: Value, key: Key, map: CacheMap<Key, Value>) => void
): void;
}

export type SuspenseCacheOptions<TParams extends any[], TValue> = {
getKey: (args: TParams) => string;
getCache: (onEviction: onEviction<string>) => CacheMap<string, CacheRecord<TValue>>;
getCache: (
onEviction: onEviction<string>
) => CacheMap<string, CacheRecord<TValue>>;
load: (context: CacheLoadContext, ...args: TParams) => Promise<TValue>;
debug: boolean;
name: string;
Expand All @@ -217,7 +223,11 @@ export type CacheLoadContext = {
abort: () => void;
};

export type GetLoadParameters<T> = T extends (...args: [any, ...infer args]) => any ? args : never;
export type GetLoadParameters<T> = T extends (
...args: [any, ...infer args]
) => any
? args
: never;

export type Resource = Record<
string,
Expand All @@ -232,28 +242,31 @@ export type ResourceValues<T extends Resource> = {
[Key in keyof T]: Awaited<ReturnType<T[Key]>>;
};

export type Mutation<Trigger extends AnyFunction<any>> = [trigger: Trigger, isPending: boolean];
export type Mutation<Trigger extends AnyFunction<any>> = [
trigger: Trigger,
isPending: boolean
];

export type SuspenseCacheEvent = {
key: string;
args: any[];
} & (
| {
type: 'pending' | 'abort' | 'evict' | 'invalidate' | 'delete' | 'clear';
type: "pending" | "abort" | "evict" | "invalidate" | "delete" | "clear";
}
| {
type: 'resolve';
type: "resolve";
value: any;
}
| {
type: 'reject';
type: "reject";
error: any;
}
| {
type: 'set';
type: "set";
value: any;
lastValue: any;
}
);

export const DevtoolsSymbol = Symbol.for('cache/devtools');
export const DevtoolsSymbol = Symbol.for("cache/devtools");

0 comments on commit 6e96520

Please sign in to comment.