Line data Source code
1 : import type * as arrow from 'apache-arrow';
2 :
3 : import type { ParquetDatabase } from '../platform/hyperdb/hyperdb_parquet_export.js';
4 :
5 : /// The error of a query that may only read a cached result, see `cacheOnly` of the query execution args
6 1 : export class QueryCacheMissError extends Error {
7 1 : constructor() {
8 1 : super('The query result is not cached');
9 1 : this.name = 'QueryCacheMissError';
10 1 : }
11 1 : }
12 :
13 : /// Did a query fail because it may only read a cached result that is not cached?
14 1 : export function isQueryCacheMiss(error: unknown): boolean {
15 1 : return error instanceof Error && error.name === 'QueryCacheMissError';
16 1 : }
17 :
18 : /// A cached query result, a Parquet file of the query result cache of the app
19 : export interface QueryResultCacheEntry {
20 : /// The file name, `<key>.<uuid>.parquet`
21 : name: string;
22 : /// The cache key
23 : key: string;
24 : /// The size in bytes
25 : size: number;
26 : /// The time the result was written
27 : cachedAtMs: number;
28 : /// The time the result was read last
29 : lastAccessMs: number;
30 : }
31 :
32 : /// The query result cache of the app (docs/design/query_cache.md).
33 : ///
34 : /// The cache holds Parquet files in the origin private file system for every session and connection, keyed by the
35 : /// connection, the script and the scripts it references. The compute database mounts the files at `mountPath` and
36 : /// writes and reads them there. A file keeps its content: a write of a key creates a new file and removes the older
37 : /// files of the key, a lookup finds the newest one. A transient file holds a result that can't be reused, e.g. the
38 : /// materialized result of a script whose connection doesn't cache results: it has no key and is removed once nobody
39 : /// pins it. Readers pin the files they read, eviction and deletion leave pinned files alone, also those of other
40 : /// windows of the app.
41 : export interface QueryResultCache {
42 : /// The mount path of the files in the compute database
43 : readonly mountPath: string;
44 : /// The newest file of a key, null on a miss
45 : lookup(key: string): Promise<QueryResultCacheEntry | null>;
46 : /// Is a key cached?
47 : has(key: string): Promise<boolean>;
48 : /// The newest file of a key, pinned until the release and present when it resolves, null on a miss. Records a
49 : /// read of the file.
50 : retain(key: string): Promise<{ entry: QueryResultCacheEntry; release: () => Promise<void> } | null>;
51 : /// The cached results
52 : list(): Promise<QueryResultCacheEntry[]>;
53 : /// Record a read of a file, eviction drops the least recently read files first
54 : touch(name: string): Promise<void>;
55 : /// Remove the files of a key that nobody reads, resolves true if no file of the key is left
56 : delete(key: string): Promise<boolean>;
57 : /// Remove every file that nobody reads, also files without keys, returns the keys that no file is left of
58 : clear(): Promise<string[]>;
59 : /// Keep a file while it is read, resolves with the release once the file is pinned. The release resolves once
60 : /// the file can be removed.
61 : pin(name: string): Promise<() => Promise<void>>;
62 : /// The name of a new file of a key
63 : newFileName(key: string): string;
64 : /// The name of a new transient file, removed by the first listing after nobody pins it any more
65 : newTransientFileName(): string;
66 : /// Mount the files in a database. The mount is shared and stays, after files were removed it is refreshed, so
67 : /// the database forgets the files it opened. Queries that read files keep reading them.
68 : mount(database: ParquetDatabase): Promise<void>;
69 : /// Write a table as file `name` while the files are mounted in the database. The file of a key is written under
70 : /// another name and moved in place once it is complete, the older files of the key are removed. Returns the file.
71 : writeTable(database: ParquetDatabase, table: arrow.Table, name: string): Promise<File>;
72 : /// Read a file into a table while it is pinned and mounted in the database
73 : readTable(database: ParquetDatabase, name: string): Promise<arrow.Table>;
74 : /// Remove a file that nobody reads, e.g. a transient file of a run once the run ended
75 : remove(name: string): Promise<void>;
76 : }
|