@metamask/kernel-store
Version:
Ocap Kernel storage abstractions and implementations
1 lines • 19.9 kB
Source Map (JSON)
{"version":3,"file":"wasm.mjs","sourceRoot":"","sources":["../../src/sqlite/wasm.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger } from '@metamask/logger';\nimport type { Database as SqliteDatabase } from '@sqlite.org/sqlite-wasm';\nimport sqlite3InitModule from '@sqlite.org/sqlite-wasm';\n\nimport {\n DEFAULT_DB_FILENAME,\n assertSafeIdentifier,\n SQL_QUERIES,\n} from './common.ts';\nimport { getDBFolder } from './env.ts';\nimport type { KVStore, VatStore, KernelDatabase } from '../types.ts';\n\nexport type Database = SqliteDatabase & {\n _inTx: boolean;\n // stack of active savepoint names\n _spStack: string[];\n};\n\n/**\n * Ensure that SQLite is initialized.\n *\n * @param dbFilename - The filename of the database to use.\n * @param logger - The logger to use, if any.\n * @returns The SQLite database object.\n */\nexport async function initDB(\n dbFilename: string,\n logger?: Logger,\n): Promise<Database> {\n const sqlite3 = await sqlite3InitModule();\n let db: SqliteDatabase;\n\n if (sqlite3.oo1.OpfsDb) {\n const dbName = dbFilename.startsWith(':')\n ? dbFilename\n : ['ocap', getDBFolder(), dbFilename].filter(Boolean).join('-');\n db = new sqlite3.oo1.OpfsDb(dbName, 'cw');\n } else {\n logger?.warn(`OPFS not enabled, database will be ephemeral`);\n db = new sqlite3.oo1.DB(`:memory:`, 'cw');\n }\n\n const dbWithTx = db as Database;\n dbWithTx._inTx = false;\n dbWithTx._spStack = [];\n\n return dbWithTx;\n}\n\n/**\n * Makes a {@link KVStore} on top of a SQLite database\n *\n * @param db - The (open) database to use.\n * @param logger - A logger object for recording activity.\n * @returns A key/value store using the given database.\n */\nfunction makeKVStore(db: Database, logger?: Logger): KVStore {\n db.exec(SQL_QUERIES.CREATE_TABLE);\n\n const sqlKVGet = db.prepare(SQL_QUERIES.GET);\n\n /**\n * Read a key's value from the database.\n *\n * @param key - A key to fetch.\n * @param required - True if it is an error for the entry not to be there.\n * @returns The value at that key.\n */\n function kvGet(key: string, required: boolean): string | undefined {\n sqlKVGet.bind([key]);\n if (sqlKVGet.step()) {\n const result = sqlKVGet.getString(0);\n if (result) {\n sqlKVGet.reset();\n logger?.debug(`kv get '${key}' as '${result}'`);\n return result;\n }\n }\n sqlKVGet.reset();\n if (required) {\n throw Error(`no record matching key '${key}'`);\n }\n return undefined;\n }\n\n const sqlKVGetNextKey = db.prepare(SQL_QUERIES.GET_NEXT);\n\n /**\n * Get the lexicographically next key in the KV store after a given key.\n *\n * @param previousKey - The key you want to know the key after.\n *\n * @returns The key after `previousKey`, or undefined if `previousKey` is the\n * last key in the store.\n */\n function kvGetNextKey(previousKey: string): string | undefined {\n sqlKVGetNextKey.bind([previousKey]);\n if (sqlKVGetNextKey.step()) {\n const result = sqlKVGetNextKey.getString(0);\n if (result) {\n sqlKVGetNextKey.reset();\n logger?.debug(`kv getNextKey '${previousKey}' as '${result}'`);\n return result;\n }\n }\n sqlKVGetNextKey.reset();\n return undefined;\n }\n\n const sqlKVSet = db.prepare(SQL_QUERIES.SET);\n\n /**\n * Set the value associated with a key in the database.\n *\n * @param key - A key to assign.\n * @param value - The value to assign to it.\n */\n function kvSet(key: string, value: string): void {\n logger?.debug(`kv set '${key}' to '${value}'`);\n sqlKVSet.bind([key, value]);\n sqlKVSet.step();\n sqlKVSet.reset();\n }\n\n const sqlKVDelete = db.prepare(SQL_QUERIES.DELETE);\n\n /**\n * Delete a key from the database.\n *\n * @param key - The key to remove.\n */\n function kvDelete(key: string): void {\n logger?.debug(`kv delete '${key}'`);\n sqlKVDelete.bind([key]);\n sqlKVDelete.step();\n sqlKVDelete.reset();\n }\n\n return {\n get: (key) => kvGet(key, false),\n getNextKey: kvGetNextKey,\n getRequired: (key) => kvGet(key, true) as string,\n set: kvSet,\n delete: kvDelete,\n };\n}\n\n/**\n * Makes a {@link KernelDatabase} for low-level persistent storage.\n *\n * @param options - The options for the database.\n * @param options.dbFilename - The filename of the database to use. Defaults to {@link DEFAULT_DB_FILENAME}.\n * @param options.logger - A logger to use.\n * @returns A key/value store to base higher level stores on.\n */\nexport async function makeSQLKernelDatabase({\n dbFilename,\n logger,\n}: {\n dbFilename?: string | undefined;\n logger?: Logger;\n}): Promise<KernelDatabase> {\n const db = await initDB(dbFilename ?? DEFAULT_DB_FILENAME, logger);\n\n logger?.debug('Initializing kernel store');\n const kvStore = makeKVStore(db, logger?.subLogger({ tags: ['kv'] }));\n\n db.exec(SQL_QUERIES.CREATE_TABLE_VS);\n\n const sqlKVClear = db.prepare(SQL_QUERIES.CLEAR);\n const sqlKVClearVS = db.prepare(SQL_QUERIES.CLEAR_VS);\n const sqlVatstoreGetAll = db.prepare(SQL_QUERIES.GET_ALL_VS);\n const sqlVatstoreSet = db.prepare(SQL_QUERIES.SET_VS);\n const sqlVatstoreDelete = db.prepare(SQL_QUERIES.DELETE_VS);\n const sqlVatstoreDeleteAll = db.prepare(SQL_QUERIES.DELETE_VS_ALL);\n const sqlBeginTransaction = db.prepare(SQL_QUERIES.BEGIN_TRANSACTION);\n const sqlCommitTransaction = db.prepare(SQL_QUERIES.COMMIT_TRANSACTION);\n const sqlAbortTransaction = db.prepare(SQL_QUERIES.ABORT_TRANSACTION);\n\n /**\n * Begin a transaction if not already in one\n *\n * @returns True if a new transaction was started, false if already in one\n */\n function beginIfNeeded(): boolean {\n if (db._inTx) {\n return false;\n }\n sqlBeginTransaction.step();\n sqlBeginTransaction.reset();\n db._inTx = true;\n return true;\n }\n\n /**\n * Commit a transaction if one is active and no savepoints remain\n */\n function commitIfNeeded(): void {\n if (db._inTx && db._spStack.length === 0) {\n sqlCommitTransaction.step();\n sqlCommitTransaction.reset();\n db._inTx = false;\n }\n }\n\n /**\n * Rollback a transaction\n */\n function rollbackIfNeeded(): void {\n if (db._inTx) {\n sqlAbortTransaction.step();\n sqlAbortTransaction.reset();\n db._inTx = false;\n db._spStack.length = 0;\n }\n }\n\n /**\n * Safely mutate the database with proper transaction management\n *\n * @param mutator - Function that performs the database mutations\n */\n function safeMutate(mutator: () => void): void {\n const startedTx = beginIfNeeded();\n try {\n mutator();\n if (startedTx) {\n commitIfNeeded();\n }\n } catch (error) {\n if (startedTx) {\n rollbackIfNeeded();\n }\n throw error;\n }\n }\n\n /**\n * Delete everything from the database.\n */\n function kvClear(): void {\n logger?.debug('clearing all kernel state');\n sqlKVClear.step();\n sqlKVClear.reset();\n sqlKVClearVS.step();\n sqlKVClearVS.reset();\n }\n\n /**\n * Execute a SQL query.\n *\n * @param sql - The SQL query to execute.\n * @returns An array of results.\n */\n function executeQuery(sql: string): Record<string, string>[] {\n const stmt = db.prepare(sql);\n const results: Record<string, string>[] = [];\n try {\n const { columnCount } = stmt;\n while (stmt.step()) {\n const row: Record<string, string> = {};\n for (let i = 0; i < columnCount; i++) {\n const columnName = stmt.getColumnName(i);\n if (columnName) {\n row[columnName] = String(stmt.get(i) as string);\n }\n }\n results.push(row);\n }\n } finally {\n stmt.reset();\n }\n return results;\n }\n\n /**\n * Create a new VatStore for a vat.\n *\n * @param vatID - The vat for which this is being done.\n *\n * @returns a a VatStore object for the given vat.\n */\n function makeVatStore(vatID: string): VatStore {\n /**\n * Fetch all the data in the vatstore.\n *\n * @returns the vatstore contents as a key-value Map.\n */\n function getKVData(): [string, string][] {\n const result: [string, string][] = [];\n sqlVatstoreGetAll.bind([vatID]);\n try {\n while (sqlVatstoreGetAll.step()) {\n const key = sqlVatstoreGetAll.getString(0) as string;\n const value = sqlVatstoreGetAll.getString(1) as string;\n result.push([key, value]);\n }\n } finally {\n sqlVatstoreGetAll.reset();\n }\n return result;\n }\n\n /**\n * Update the state of the vatstore\n *\n * @param sets - A map of key values that have been changed.\n * @param deletes - A set of keys that have been deleted.\n */\n function updateKVData(sets: [string, string][], deletes: string[]): void {\n safeMutate(() => {\n for (const [key, value] of sets) {\n sqlVatstoreSet.bind([vatID, key, value]);\n sqlVatstoreSet.step();\n sqlVatstoreSet.reset();\n }\n for (const value of deletes) {\n sqlVatstoreDelete.bind([vatID, value]);\n sqlVatstoreDelete.step();\n sqlVatstoreDelete.reset();\n }\n });\n }\n\n return {\n getKVData,\n updateKVData,\n };\n }\n\n /**\n * Delete an entire VatStore.\n *\n * @param vatId - The vat whose store is to be deleted.\n */\n function deleteVatStore(vatId: string): void {\n sqlVatstoreDeleteAll.bind([vatId]);\n sqlVatstoreDeleteAll.step();\n sqlVatstoreDeleteAll.reset();\n }\n\n /**\n * Create a savepoint in the database.\n *\n * @param name - The name of the savepoint.\n */\n function createSavepoint(name: string): void {\n // We must be in a transaction when creating the savepoint or releasing it\n // later will cause an autocommit.\n // See https://github.com/Agoric/agoric-sdk/issues/8423\n beginIfNeeded();\n assertSafeIdentifier(name);\n const query = SQL_QUERIES.CREATE_SAVEPOINT.replace('%NAME%', name);\n db.exec(query);\n db._spStack.push(name);\n }\n\n /**\n * Rollback to a savepoint in the database.\n *\n * @param name - The name of the savepoint.\n */\n function rollbackSavepoint(name: string): void {\n assertSafeIdentifier(name);\n const idx = db._spStack.lastIndexOf(name);\n if (idx < 0) {\n throw new Error(`No such savepoint: ${name}`);\n }\n const query = SQL_QUERIES.ROLLBACK_SAVEPOINT.replace('%NAME%', name);\n db.exec(query);\n db._spStack.splice(idx);\n if (db._spStack.length === 0) {\n rollbackIfNeeded();\n }\n }\n\n /**\n * Release a savepoint in the database.\n *\n * @param name - The name of the savepoint.\n */\n function releaseSavepoint(name: string): void {\n assertSafeIdentifier(name);\n const idx = db._spStack.lastIndexOf(name);\n if (idx < 0) {\n throw new Error(`No such savepoint: ${name}`);\n }\n const query = SQL_QUERIES.RELEASE_SAVEPOINT.replace('%NAME%', name);\n db.exec(query);\n db._spStack.splice(idx);\n if (db._spStack.length === 0) {\n commitIfNeeded();\n }\n }\n\n return {\n kernelKVStore: kvStore,\n clear: kvClear,\n executeQuery,\n makeVatStore,\n deleteVatStore,\n createSavepoint,\n rollbackSavepoint,\n releaseSavepoint,\n };\n}\n"]}