Export template source from be30143a326d5d7d7b0cbabea5bc5ac0301ef5b9:examples/local-first/packages/language-reader-runtime
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/** Cache only semantic inputs. Scope/context stay in the source-range identity; generation is scheduling.
|
||||
* This pure wire-format helper is shared by the runtime and presentation.
|
||||
*/
|
||||
export function cacheConfiguration(
|
||||
identity: string,
|
||||
scope: string,
|
||||
_generation: string,
|
||||
options: Record<string, unknown>,
|
||||
inputs: readonly string[],
|
||||
) {
|
||||
return JSON.stringify({
|
||||
processor: identity,
|
||||
scope,
|
||||
options: Object.fromEntries([...inputs].sort().map((key) => [key, options[key]])),
|
||||
});
|
||||
}
|
||||
|
||||
/** Keep transaction reads bounded, without one serial RPC per historical job.
|
||||
* Relationship order still decides which reusable result wins. */
|
||||
export async function findCachedJob<T>(
|
||||
history: readonly T[],
|
||||
read: (reference: T) => Promise<{ key: string; status: string }>,
|
||||
key: string,
|
||||
retry: boolean,
|
||||
) {
|
||||
let retries = 0;
|
||||
for (let offset = 0; offset < history.length; offset += 32) {
|
||||
const batch = history.slice(offset, offset + 32);
|
||||
const records = await Promise.all(batch.map(read));
|
||||
for (let index = 0; index < batch.length; index++) {
|
||||
const data = records[index];
|
||||
if (data.key !== key) continue;
|
||||
retries++;
|
||||
if (data.status === "queued" || (!retry && data.status === "ready")) return { reference: batch[index], retries };
|
||||
}
|
||||
}
|
||||
return { reference: undefined, retries };
|
||||
}
|
||||
|
||||
/** Compare persisted semantic configurations without scheduling choices. The
|
||||
* original wire format retained generation; removing it preserves old results
|
||||
* when an author switches between preparation and intent-driven generation. */
|
||||
export function sameCacheConfiguration(a: string, b: string) {
|
||||
if (a === b) return true;
|
||||
try {
|
||||
const semantic = (raw: string) => {
|
||||
const { processor, scope, options } = JSON.parse(raw);
|
||||
if (
|
||||
typeof processor !== "string" ||
|
||||
typeof scope !== "string" ||
|
||||
!options ||
|
||||
typeof options !== "object" ||
|
||||
Array.isArray(options)
|
||||
)
|
||||
return null;
|
||||
return JSON.stringify({
|
||||
processor,
|
||||
scope,
|
||||
options: Object.fromEntries(Object.entries(options).sort(([a], [b]) => a.localeCompare(b))),
|
||||
});
|
||||
};
|
||||
const left = semantic(a);
|
||||
return left !== null && left === semantic(b);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user