Converts using full document state management

This commit is contained in:
2025-07-02 17:01:56 -07:00
parent 32c5c40466
commit f27432ef05
13 changed files with 468 additions and 211 deletions

View File

@@ -5,42 +5,45 @@ import {
type Relationship,
type DocumentId,
type RelationshipId,
type DbRecord,
} from "./types";
type CacheKey<C extends CollectionId = CollectionId> = `${C}:${string}`;
export type CacheKey<C extends CollectionId = CollectionId> = `${C}:${string}`;
export type CacheValue<C extends CollectionId = CollectionId> = {
record: Promise<DbRecord<C>>;
subscriptions: ((record: DbRecord<C> | null) => void)[];
};
type DocumentKey = CacheKey<typeof CollectionIds.Documents>;
type RelationshipKey = CacheKey<typeof CollectionIds.Relationships>;
export class RecordCache {
private cache: Record<
`${CollectionId}:${string}`,
{
record: AnyDocument | Relationship;
subscriptions: ((record: AnyDocument | Relationship | null) => void)[];
}
> = {};
private cache: Record<`${CollectionId}:${string}`, CacheValue> = {};
private makeKey<C extends CollectionId>(
static makeKey<C extends CollectionId>(
collectionId: C,
id: string,
): CacheKey<C> {
return `${collectionId}:${id}`;
}
private docKey = (id: DocumentId): DocumentKey =>
this.makeKey(CollectionIds.Documents, id);
static docKey = (id: DocumentId): DocumentKey =>
RecordCache.makeKey(CollectionIds.Documents, id);
private relationKey = (id: RelationshipId): RelationshipKey =>
this.makeKey(CollectionIds.Relationships, id);
static relationKey = (id: RelationshipId): RelationshipKey =>
RecordCache.makeKey(CollectionIds.Relationships, id);
get = (key: CacheKey): AnyDocument | Relationship | undefined =>
this.cache[key]?.record;
get = <C extends CollectionId>(
key: CacheKey<C>,
): Promise<DbRecord<C>> | undefined =>
this.cache[key]?.record as Promise<DbRecord<C>> | undefined;
set = (record: AnyDocument | Relationship) => {
const key = this.makeKey(record.collectionName, record.id);
pending = <C extends CollectionId>(
key: CacheKey<C>,
record: Promise<DbRecord<C>>,
) => {
if (this.cache[key] === undefined) {
this.cache[key] = {
record,
record: record,
subscriptions: [],
};
}
@@ -48,6 +51,34 @@ export class RecordCache {
entry.record = record;
record.then((record) => {
for (const subscription of entry.subscriptions) {
subscription(record);
}
for (const doc of record.expand?.secondary ?? []) {
this.set(doc);
}
for (const rel of record.expand?.relationships_via_primary ?? []) {
this.set(rel);
}
});
};
set = <C extends CollectionId>(record: DbRecord<C>) => {
const key = RecordCache.makeKey(
record.collectionName as CollectionId,
record.id,
);
if (this.cache[key] === undefined) {
this.cache[key] = {
record: Promise.resolve(record),
subscriptions: [],
};
}
const entry = this.cache[key];
entry.record = Promise.resolve(record);
for (const subscription of entry.subscriptions) {
subscription(record);
}
@@ -69,13 +100,13 @@ export class RecordCache {
};
getDocument = (id: DocumentId): AnyDocument | undefined =>
this.get(this.docKey(id)) as AnyDocument | undefined;
this.get(RecordCache.docKey(id)) as AnyDocument | undefined;
getRelationship = (id: RelationshipId): Relationship | undefined =>
this.get(this.relationKey(id)) as Relationship | undefined;
this.get(RecordCache.relationKey(id)) as Relationship | undefined;
removeDocument = (id: DocumentId) => this.remove(this.docKey(id));
removeDocument = (id: DocumentId) => this.remove(RecordCache.docKey(id));
removeRelationship = (id: RelationshipId) =>
this.remove(this.relationKey(id));
this.remove(RecordCache.relationKey(id));
}