summaryrefslogtreecommitdiff
path: root/packages/frontend-shared/js/worker-multi-dispatch.ts
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2024-09-10 18:39:53 +0900
committerGitHub <noreply@github.com>2024-09-10 18:39:53 +0900
commit837a8e15d893a670ab2ce51b3ec87e6b62a51da7 (patch)
tree0b651782db2bf440f1c789606d6367226f2e2253 /packages/frontend-shared/js/worker-multi-dispatch.ts
parentDev: cypressをdev containerで実行可に(e2e-dev-container) (#14526) (diff)
downloadmisskey-837a8e15d893a670ab2ce51b3ec87e6b62a51da7.tar.gz
misskey-837a8e15d893a670ab2ce51b3ec87e6b62a51da7.tar.bz2
misskey-837a8e15d893a670ab2ce51b3ec87e6b62a51da7.zip
refactor(frontend): frontend-embed/src/to-be-sharedを共通化 (#14536)
* refactor(frontend): shouldCollapsedを共通化 * refactor(frontend): config.js, worker-multi-dispatch.js, intl-const.jsを共通化 * fix(frontend-shared): fix type error * refactor(frontend): is-link.jsと、同一の振る舞いをする記述を共通化 * fix * fix lint * lint fixes
Diffstat (limited to 'packages/frontend-shared/js/worker-multi-dispatch.ts')
-rw-r--r--packages/frontend-shared/js/worker-multi-dispatch.ts86
1 files changed, 86 insertions, 0 deletions
diff --git a/packages/frontend-shared/js/worker-multi-dispatch.ts b/packages/frontend-shared/js/worker-multi-dispatch.ts
new file mode 100644
index 0000000000..5d393ed1ed
--- /dev/null
+++ b/packages/frontend-shared/js/worker-multi-dispatch.ts
@@ -0,0 +1,86 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+function defaultUseWorkerNumber(prev: number) {
+ return prev + 1;
+}
+
+type WorkerNumberGetter = (prev: number, totalWorkers: number) => number;
+
+export class WorkerMultiDispatch<POST = unknown, RETURN = unknown> {
+ private symbol = Symbol('WorkerMultiDispatch');
+ private workers: Worker[] = [];
+ private terminated = false;
+ private prevWorkerNumber = 0;
+ private getUseWorkerNumber: WorkerNumberGetter;
+ private finalizationRegistry: FinalizationRegistry<symbol>;
+
+ constructor(workerConstructor: () => Worker, concurrency: number, getUseWorkerNumber = defaultUseWorkerNumber) {
+ this.getUseWorkerNumber = getUseWorkerNumber;
+ for (let i = 0; i < concurrency; i++) {
+ this.workers.push(workerConstructor());
+ }
+
+ this.finalizationRegistry = new FinalizationRegistry(() => {
+ this.terminate();
+ });
+ this.finalizationRegistry.register(this, this.symbol);
+
+ if (_DEV_) console.log('WorkerMultiDispatch: Created', this);
+ }
+
+ public postMessage(message: POST, options?: Transferable[] | StructuredSerializeOptions, useWorkerNumber: WorkerNumberGetter = this.getUseWorkerNumber) {
+ let workerNumber = useWorkerNumber(this.prevWorkerNumber, this.workers.length);
+ workerNumber = Math.abs(Math.round(workerNumber)) % this.workers.length;
+ if (_DEV_) console.log('WorkerMultiDispatch: Posting message to worker', workerNumber, useWorkerNumber);
+ this.prevWorkerNumber = workerNumber;
+
+ // 不毛だがunionをoverloadに突っ込めない
+ // https://stackoverflow.com/questions/66507585/overload-signatures-union-types-and-no-overload-matches-this-call-error
+ // https://github.com/microsoft/TypeScript/issues/14107
+ if (Array.isArray(options)) {
+ this.workers[workerNumber].postMessage(message, options);
+ } else {
+ this.workers[workerNumber].postMessage(message, options);
+ }
+ return workerNumber;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public addListener(callback: (this: Worker, ev: MessageEvent<RETURN>) => any, options?: boolean | AddEventListenerOptions) {
+ this.workers.forEach(worker => {
+ worker.addEventListener('message', callback, options);
+ });
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public removeListener(callback: (this: Worker, ev: MessageEvent<RETURN>) => any, options?: boolean | AddEventListenerOptions) {
+ this.workers.forEach(worker => {
+ worker.removeEventListener('message', callback, options);
+ });
+ }
+
+ public terminate() {
+ this.terminated = true;
+ if (_DEV_) console.log('WorkerMultiDispatch: Terminating', this);
+ this.workers.forEach(worker => {
+ worker.terminate();
+ });
+ this.workers = [];
+ this.finalizationRegistry.unregister(this);
+ }
+
+ public isTerminated() {
+ return this.terminated;
+ }
+
+ public getWorkers() {
+ return this.workers;
+ }
+
+ public getSymbol() {
+ return this.symbol;
+ }
+}