@rivetkit/sqlite-vfs 2.1.5 → 2.1.6-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,29 @@ interface KvVfsOptions {
32
32
  * logic and keeps memory usage predictable for each actor.
33
33
  */
34
34
 
35
+ /**
36
+ * Common interface for database handles returned by ISqliteVfs.open().
37
+ * Both the concrete Database class and the pool's TrackedDatabase wrapper
38
+ * implement this, so consumers can use either interchangeably.
39
+ */
40
+ interface IDatabase {
41
+ exec(sql: string, callback?: (row: unknown[], columns: string[]) => void): Promise<void>;
42
+ run(sql: string, params?: SqliteBindings): Promise<void>;
43
+ query(sql: string, params?: SqliteBindings): Promise<{
44
+ rows: unknown[][];
45
+ columns: string[];
46
+ }>;
47
+ close(): Promise<void>;
48
+ readonly fileName: string;
49
+ }
50
+ /**
51
+ * Common interface for SQLite VFS backends. Both standalone SqliteVfs and
52
+ * PooledSqliteHandle implement this so callers can use either interchangeably.
53
+ */
54
+ interface ISqliteVfs {
55
+ open(fileName: string, options: KvVfsOptions): Promise<IDatabase>;
56
+ destroy(): Promise<void>;
57
+ }
35
58
  type SQLite3Api = ReturnType<typeof Factory>;
36
59
  type SqliteBindings = Parameters<SQLite3Api["bind_collection"]>[1];
37
60
  /**
@@ -47,9 +70,9 @@ declare class AsyncMutex {
47
70
  /**
48
71
  * Database wrapper that provides a simplified SQLite API
49
72
  */
50
- declare class Database {
73
+ declare class Database implements IDatabase {
51
74
  #private;
52
- constructor(sqlite3: SQLite3Api, handle: number, fileName: string, onClose: () => void, sqliteMutex: AsyncMutex);
75
+ constructor(sqlite3: SQLite3Api, handle: number, fileName: string, onClose: () => Promise<void>, sqliteMutex: AsyncMutex);
53
76
  /**
54
77
  * Execute SQL with optional row callback
55
78
  * @param sql - SQL statement to execute
@@ -76,6 +99,10 @@ declare class Database {
76
99
  * Close the database
77
100
  */
78
101
  close(): Promise<void>;
102
+ /**
103
+ * Get the database file name
104
+ */
105
+ get fileName(): string;
79
106
  /**
80
107
  * Get the raw @rivetkit/sqlite API (for advanced usage)
81
108
  */
@@ -91,9 +118,9 @@ declare class Database {
91
118
  * Each instance is independent and has its own @rivetkit/sqlite WASM module.
92
119
  * This allows multiple instances to operate concurrently without interference.
93
120
  */
94
- declare class SqliteVfs {
121
+ declare class SqliteVfs implements ISqliteVfs {
95
122
  #private;
96
- constructor();
123
+ constructor(wasmModule?: WebAssembly.Module);
97
124
  /**
98
125
  * Open a SQLite database using KV storage backend
99
126
  *
@@ -101,7 +128,27 @@ declare class SqliteVfs {
101
128
  * @param options - KV storage operations for this database
102
129
  * @returns A Database instance
103
130
  */
104
- open(fileName: string, options: KvVfsOptions): Promise<Database>;
131
+ open(fileName: string, options: KvVfsOptions): Promise<IDatabase>;
132
+ /**
133
+ * Force-close all Database handles whose fileName exactly matches the
134
+ * given name. Snapshots the set to an array before iterating to avoid
135
+ * mutation during async iteration.
136
+ *
137
+ * Uses exact file name match because short names are numeric strings
138
+ * ('0', '1', ..., '10', '11', ...) and a prefix match like
139
+ * startsWith('1') would incorrectly match '10', '11', etc., causing
140
+ * cross-actor corruption. Sidecar files (-journal, -wal, -shm) are not
141
+ * tracked as separate Database handles, so prefix matching for sidecars
142
+ * is not needed.
143
+ */
144
+ forceCloseByFileName(fileName: string): Promise<{
145
+ allSucceeded: boolean;
146
+ }>;
147
+ /**
148
+ * Force-close all open Database handles. Best-effort: errors are
149
+ * swallowed so this is safe to call during instance teardown.
150
+ */
151
+ forceCloseAll(): Promise<void>;
105
152
  /**
106
153
  * Tears down this VFS instance and releases internal references.
107
154
  */
@@ -112,4 +159,87 @@ declare class SqliteVfs {
112
159
  close(): Promise<void>;
113
160
  }
114
161
 
115
- export { Database, type KvVfsOptions, SqliteVfs };
162
+ /**
163
+ * SQLite VFS Pool - shares WASM SQLite instances across actors to reduce
164
+ * memory overhead. Instead of one WASM module per actor, multiple actors
165
+ * share a single instance, with short file names routing to separate KV
166
+ * namespaces.
167
+ */
168
+
169
+ interface SqliteVfsPoolConfig {
170
+ actorsPerInstance: number;
171
+ idleDestroyMs?: number;
172
+ }
173
+ /**
174
+ * Manages a pool of SqliteVfs instances, assigning actors to instances using
175
+ * bin-packing to maximize density. The WASM module is compiled once and
176
+ * reused across all instances.
177
+ */
178
+ declare class SqliteVfsPool {
179
+ #private;
180
+ constructor(config: SqliteVfsPoolConfig);
181
+ /** Number of live WASM instances in the pool. */
182
+ get instanceCount(): number;
183
+ /** Number of actors currently assigned to pool instances. */
184
+ get actorCount(): number;
185
+ /**
186
+ * Acquire a pooled VFS handle for the given actor. Returns a
187
+ * PooledSqliteHandle with sticky assignment. If the actor is already
188
+ * assigned, the existing handle is returned.
189
+ *
190
+ * Bin-packing: picks the instance with the most actors that still has
191
+ * capacity. If all instances are full, creates a new one using the
192
+ * cached WASM module.
193
+ */
194
+ acquire(actorId: string): Promise<PooledSqliteHandle>;
195
+ /**
196
+ * Release an actor's assignment from the pool. Force-closes all database
197
+ * handles for the actor, recycles or poisons the short name, and
198
+ * decrements the instance refcount.
199
+ */
200
+ release(actorId: string): Promise<void>;
201
+ /**
202
+ * Open a database on behalf of an actor, tracked as an in-flight
203
+ * operation. Used by PooledSqliteHandle to avoid exposing PoolInstance.
204
+ */
205
+ openForActor(actorId: string, shortName: string, options: KvVfsOptions): Promise<IDatabase>;
206
+ /**
207
+ * Track an in-flight database operation for the given actor. Resolves the
208
+ * actor's pool instance and wraps the operation with opsInFlight tracking.
209
+ * If the actor has already been released, the operation runs without
210
+ * tracking since the instance may already be destroyed.
211
+ */
212
+ trackOpForActor<T>(actorId: string, fn: () => Promise<T>): Promise<T>;
213
+ /**
214
+ * Graceful shutdown. Rejects new acquire() calls, cancels idle timers,
215
+ * force-closes all databases, destroys all VFS instances, and clears pool
216
+ * state.
217
+ */
218
+ shutdown(): Promise<void>;
219
+ }
220
+ /**
221
+ * A pooled VFS handle for a single actor. Implements ISqliteVfs so callers
222
+ * can use it interchangeably with a standalone SqliteVfs. The short name
223
+ * assigned by the pool is used as the VFS file path, while the caller's
224
+ * KvVfsOptions routes data to the correct KV namespace.
225
+ */
226
+ declare class PooledSqliteHandle implements ISqliteVfs {
227
+ #private;
228
+ constructor(shortName: string, actorId: string, pool: SqliteVfsPool);
229
+ /**
230
+ * Open a database on the shared instance. Uses the pool-assigned short
231
+ * name as the VFS file path, with the caller's KvVfsOptions for KV
232
+ * routing. The open call itself is tracked as an in-flight operation,
233
+ * and the returned Database is wrapped so that exec(), run(), query(),
234
+ * and close() are also tracked via opsInFlight.
235
+ */
236
+ open(_fileName: string, options: KvVfsOptions): Promise<IDatabase>;
237
+ /**
238
+ * Release this actor's assignment back to the pool. Idempotent: calling
239
+ * destroy() more than once is a no-op, preventing double-release from
240
+ * decrementing the instance refcount below actual.
241
+ */
242
+ destroy(): Promise<void>;
243
+ }
244
+
245
+ export { Database, type IDatabase, type ISqliteVfs, type KvVfsOptions, PooledSqliteHandle, SqliteVfs, SqliteVfsPool, type SqliteVfsPoolConfig };