From 87980bbba1fbe7b3f7208dee4dc5d4058a75a944 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 15 Nov 2023 16:22:57 -0600 Subject: [PATCH] Add an SqliteWorker --- src/workers.ts | 5 +++++ src/workers/sqlite.ts | 37 ++++++++++++++++++++++++++++++++++++ src/workers/sqlite.worker.ts | 32 +++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/workers.ts create mode 100644 src/workers/sqlite.ts create mode 100644 src/workers/sqlite.worker.ts diff --git a/src/workers.ts b/src/workers.ts new file mode 100644 index 0000000..f00c43a --- /dev/null +++ b/src/workers.ts @@ -0,0 +1,5 @@ +import SqliteWorker from './workers/sqlite.ts'; + +const sqliteWorker = new SqliteWorker('./data/db.sqlite3'); + +export { sqliteWorker }; \ No newline at end of file diff --git a/src/workers/sqlite.ts b/src/workers/sqlite.ts new file mode 100644 index 0000000..aaab650 --- /dev/null +++ b/src/workers/sqlite.ts @@ -0,0 +1,37 @@ +class SqliteWorker { + #path: string; + #worker: Worker; + + constructor(path: string) { + this.#path = path; + this.#worker = new Worker(new URL('./sqlite.worker.ts', import.meta.url).href, { type: 'module' }); + } + + open(): Promise { + return this.#call(['open', [this.#path]]); + } + + query(sql: string, params?: any): Promise { + return this.#call(['query', [sql, params]]); + } + + #call(msg: [string, unknown[]]): Promise { + const id = crypto.randomUUID(); + + this.#worker.postMessage([id, msg]); + + // TODO: use a hashmap instead of an event listener for better performance. + return new Promise((resolve) => { + const handleEvent = (event: MessageEvent<[string, T]>) => { + const [_id, result] = event.data; + if (_id === id) { + this.#worker.removeEventListener('message', handleEvent); + resolve(result); + } + }; + this.#worker.addEventListener('message', handleEvent); + }); + } +} + +export default SqliteWorker; diff --git a/src/workers/sqlite.worker.ts b/src/workers/sqlite.worker.ts new file mode 100644 index 0000000..ea024dc --- /dev/null +++ b/src/workers/sqlite.worker.ts @@ -0,0 +1,32 @@ +/// + +import { DenoSqlite3 } from '@/deps.ts'; + +let db: DenoSqlite3; + +type Msg = + | ['open', [string]] + | ['query', [string, unknown[]]]; + +function call([cmd, args]: Msg) { + switch(cmd) { + case 'open': + return handleOpen(args[0]); + case 'query': + return handleQuery(args[0], args[1]); + } +} + +function handleOpen(path: string): void { + db = new DenoSqlite3(path); +} + +function handleQuery(sql: string, params: any[] = []) { + return db.prepare(sql).all(...params); +} + +self.addEventListener('message', (event: MessageEvent<[string, Msg]>) => { + const [id, msg] = event.data; + const result = call(msg); + self.postMessage([id, result]); +}); \ No newline at end of file