]> zoso.dev Git - libnemo.git/commitdiff
Create Thread class to manage worker messages in an asynchronous queue, and begin...
authorChris Duncan <chris@zoso.dev>
Mon, 18 Nov 2024 17:52:51 +0000 (09:52 -0800)
committerChris Duncan <chris@zoso.dev>
Mon, 18 Nov 2024 17:52:51 +0000 (09:52 -0800)
src/lib/safe.ts
src/lib/thread.ts [new file with mode: 0644]

index 8654756877403ba8931cf492a198465dec1d3144..9fc411935b3e915ba4f0c792187af527b85a04b7 100644 (file)
@@ -3,11 +3,13 @@
 
 import { buffer, hex, utf8 } from './convert.js'
 import { Entropy } from './entropy.js'
+import { Thread } from './thread.js'
 const { subtle } = globalThis.crypto
 const ERR_MSG = 'Failed to store item in Safe'
 
 export class Safe {
        #storage = globalThis.sessionStorage
+       #thread = new Thread(new URL('./placeholder.js', import.meta.url))
 
        /**
        * Encrypts data with a password and stores it in the Safe.
diff --git a/src/lib/thread.ts b/src/lib/thread.ts
new file mode 100644 (file)
index 0000000..79addc4
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+if (globalThis.Worker == null) {
+  const { Worker } = await import('node:worker_threads')
+  //@ts-expect-error
+  Worker.prototype.addEventListener = Worker.prototype.addListener
+  //@ts-expect-error
+  globalThis.Worker = Worker
+}
+
+type Task = {
+  data: object,
+  resolve: Function
+}
+
+/**
+* Processes tasks from a queue using a Web Worker.
+*/
+export class Thread {
+  #isAvailable: boolean = true
+  #queue: Task[] = []
+  #task?: Task
+  #worker: Worker
+
+  #post (next: Task) {
+    this.#isAvailable = false
+    this.#task = next
+    this.#worker.postMessage(next.data)
+  }
+
+  constructor (url: string | URL) {
+    this.#worker = new Worker(new URL(url, import.meta.url), { type: 'module' })
+    this.#worker.addEventListener('message', (event) => {
+      const result = event.data ?? event
+      if (this.#task == null) {
+        throw new ReferenceError(`Error resolving Worker result: ${result}`)
+      }
+      const resolve = this.#task.resolve
+      const next = this.#queue.shift()
+      if (next == null) {
+        this.#isAvailable = true
+      } else {
+        this.#post(next)
+      }
+      resolve(result)
+    })
+  }
+
+  async work (data: object): Promise<any> {
+    return new Promise(resolve => {
+      if (this.#isAvailable) {
+        this.#post({ data, resolve })
+      } else {
+        this.#queue.push({ data, resolve })
+      }
+    })
+  }
+}