A music player that connects to your cloud/distributed storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: shared worker

+113 -48
+82 -9
src/common/worker.js
··· 4 4 import { xxh32 } from "xxh32"; 5 5 6 6 /** 7 - * @import {NodeWorkerOrNodeMessagePort} from "@mys/m-rpc"; 7 + * @import {NodeWorkerOrNodeMessagePort, WorkerGlobalScope} from "@mys/m-rpc"; 8 8 * @import {Announcement} from "./worker.d.ts" 9 9 */ 10 10 11 - export const define = defineWorkerFn; 12 - export const use = useWorkerFn; 11 + //////////////////////////////////////////// 12 + // MISC 13 + //////////////////////////////////////////// 14 + 15 + /** 16 + * Manage incoming connections for a shared worker. 17 + * If a regular worker is used instead, it'll just execute the callback immediately. 18 + * 19 + * @template {MessagePort | Worker | WorkerGlobalScope} T 20 + * @param {(context: MessagePort | T) => void} callback 21 + * @param {T} [context] Uses `globalThis` by default. 22 + */ 23 + export function ostiary( 24 + callback, 25 + context = /** @type {T} */ (/** @type {unknown} */ (globalThis)), 26 + ) { 27 + if (/** @type {any} */ (context).onmessage === null) { 28 + return callback(context); 29 + } 30 + 31 + context.addEventListener( 32 + "connect", 33 + /** 34 + * @param {any} event 35 + */ 36 + (event) => { 37 + /** @type {MessagePort} */ 38 + const port = event.ports[0]; 39 + port.start(); 40 + 41 + // Initiate setup 42 + callback(port); 43 + }, 44 + ); 45 + } 46 + 47 + //////////////////////////////////////////// 48 + // RAW 49 + //////////////////////////////////////////// 13 50 14 51 /** 15 52 * @template T 16 53 * @param {string} name 17 54 * @param {T} args 55 + * @param {MessagePort | Worker | WorkerGlobalScope} [context] Uses `globalThis` by default. 18 56 */ 19 - export function announce(name, args) { 57 + export function announce( 58 + name, 59 + args, 60 + context = /** @type {WorkerGlobalScope} */ (globalThis), 61 + ) { 20 62 const transferables = getTransferables(args); 21 - globalThis.postMessage(constructMsg(name, args), { transfer: transferables }); 63 + context.postMessage(constructMsg(name, args), { transfer: transferables }); 22 64 } 23 65 24 66 /** 25 67 * @template T 26 68 * @param {string} name 27 69 * @param {(args: T) => void} fn 28 - * @param {Worker | NodeWorkerOrNodeMessagePort} context 70 + * @param {MessagePort | Worker | WorkerGlobalScope} [context] 29 71 */ 30 72 export function listen( 31 73 name, 32 74 fn, 33 - context = globalThis, 75 + context = /** @type {WorkerGlobalScope} */ (globalThis), 34 76 ) { 35 77 context.addEventListener( 36 78 "message", 37 - /** @param {MessageEvent} event */ (event) => { 79 + /** @param {any} event */ (event) => { 38 80 const announcement = /** @type {Announcement<T>} */ (event.data); 39 81 const { ns, type } = announcement; 40 82 ··· 47 89 } 48 90 49 91 //////////////////////////////////////////// 50 - // PRIVATE 92 + // RPC 93 + //////////////////////////////////////////// 94 + 95 + /** 96 + * @template {(...args: any[]) => any} Fn 97 + * @param {string} name 98 + * @param {Fn} fn 99 + * @param {MessagePort | Worker | WorkerGlobalScope} [context] Uses `globalThis` by default. 100 + */ 101 + export function define( 102 + name, 103 + fn, 104 + context = /** @type {WorkerGlobalScope} */ (globalThis), 105 + ) { 106 + return defineWorkerFn(name, fn, { 107 + port: /** @type {any} */ (context), 108 + }); 109 + } 110 + 111 + /** 112 + * @param {string} name 113 + * @param {MessagePort | Worker | WorkerGlobalScope} [context] Uses `globalThis` by default. 114 + */ 115 + export function use( 116 + name, 117 + context = /** @type {WorkerGlobalScope} */ (globalThis), 118 + ) { 119 + return useWorkerFn(name, /** @type {any} */ (context)); 120 + } 121 + 122 + //////////////////////////////////////////// 123 + // ⛔️ 51 124 //////////////////////////////////////////// 52 125 53 126 const ANNOUNCEMENT = "announcement";
+6 -24
src/component/engine/queue/element.js
··· 18 18 constructor() { 19 19 super(); 20 20 21 - // TODO: 22 - // const worker = new SharedWorker(new URL("./worker.js", import.meta.url), { 23 - // type: "module", 24 - // }); 25 - // 26 - // const port = worker.port; 27 - 28 - const worker = new Worker(new URL("./worker.js", import.meta.url), { 21 + // Setup shared worker 22 + const worker = new SharedWorker(new URL("./worker.js", import.meta.url), { 29 23 type: "module", 30 24 }); 31 25 32 - const port = worker; 26 + const port = worker.port; 27 + port.start(); 33 28 29 + // Sync data with worker 34 30 listen("future", this.future, port); 35 31 listen("now", this.now, port); 36 32 listen("past", this.past, port); 37 33 34 + // Worker proxy 38 35 this.add = use("add", port); 39 - 40 - this.load(port); 41 - } 42 - 43 - /** 44 - * @param {Worker} port 45 - */ 46 - async load(port) { 47 - const f = await use("future", port)(); 48 - const n = await use("now", port)(); 49 - const p = await use("past", port)(); 50 - 51 - this.future(f); 52 - this.now(n); 53 - this.past(p); 54 36 } 55 37 56 38 // SIGNALS
+25 -15
src/component/engine/queue/worker.js
··· 1 - import { announce, define } from "@common/worker.js"; 1 + import { announce, define, ostiary } from "@common/worker.js"; 2 2 import { effect, signal } from "@common/signal.js"; 3 3 import { arrayShuffle } from "@common/index.js"; 4 4 ··· 18 18 const now = signal(/** @type {Item | null} */ (null)); 19 19 const past = signal(/** @type {Item[]} */ ([])); 20 20 21 - effect(() => announce("future", future())); 22 - effect(() => announce("now", now())); 23 - effect(() => announce("past", past())); 24 - 25 - define("future", () => future()); 26 - define("now", () => now()); 27 - define("past", () => past()); 28 - 29 21 //////////////////////////////////////////// 30 22 // ACTIONS 31 23 //////////////////////////////////////////// 32 - 33 - define("add", add); 34 - define("pool", pool); 35 - define("shift", shift); 36 - define("unshift", unshift); 37 24 38 25 /** 39 26 * @param {Item[]} items ··· 81 68 } 82 69 83 70 //////////////////////////////////////////// 84 - // PRIVATE 71 + // ⚡️ 72 + //////////////////////////////////////////// 73 + 74 + ostiary((port) => { 75 + // Setup RPC 76 + 77 + define("future", () => future(), port); 78 + define("now", () => now(), port); 79 + define("past", () => past(), port); 80 + 81 + define("add", add, port); 82 + define("pool", pool, port); 83 + define("shift", shift, port); 84 + define("unshift", unshift, port); 85 + 86 + // Communicate 87 + 88 + effect(() => announce("future", future(), port)); 89 + effect(() => announce("now", now(), port)); 90 + effect(() => announce("past", past(), port)); 91 + }); 92 + 93 + //////////////////////////////////////////// 94 + // ⛔️ 85 95 //////////////////////////////////////////// 86 96 87 97 /**