revert build & worker changes (unused)

This commit is contained in:
dwelle 2025-04-06 23:14:13 +02:00
parent 057331431f
commit a7668890fb
4 changed files with 48 additions and 89 deletions

View file

@ -23,7 +23,7 @@ export const subsetWoff2GlyphsByCodepoints = async (
codePoints: Array<number>,
): Promise<string> => {
const { Commands, subsetToBase64, toBase64 } =
await lazyLoadSubsetSharedChunk();
await lazyLoadSharedSubsetChunk();
if (!shouldUseWorkers) {
return subsetToBase64(arrayBuffer, codePoints);
@ -75,7 +75,7 @@ export const subsetWoff2GlyphsByCodepoints = async (
let subsetWorker: Promise<typeof import("./subset-worker.chunk")> | null = null;
let subsetShared: Promise<typeof import("./subset-shared.chunk")> | null = null;
const lazyLoadSubsetWorkerChunk = async () => {
const lazyLoadWorkerSubsetChunk = async () => {
if (!subsetWorker) {
subsetWorker = import("./subset-worker.chunk");
}
@ -83,7 +83,7 @@ const lazyLoadSubsetWorkerChunk = async () => {
return subsetWorker;
};
const lazyLoadSubsetSharedChunk = async () => {
const lazyLoadSharedSubsetChunk = async () => {
if (!subsetShared) {
// load dynamically to force create a shared chunk reused between main thread and the worker thread
subsetShared = import("./subset-shared.chunk");
@ -93,20 +93,17 @@ const lazyLoadSubsetSharedChunk = async () => {
};
// could be extended with multiple commands in the future
export type SubsetWorkerInput = {
type SubsetWorkerData = {
command: typeof Commands.Subset;
arrayBuffer: ArrayBuffer;
codePoints: Array<number>;
};
export type SubsetWorkerOutput<T extends SubsetWorkerInput["command"]> =
type SubsetWorkerResult<T extends SubsetWorkerData["command"]> =
T extends typeof Commands.Subset ? ArrayBuffer : never;
let workerPool: Promise<
WorkerPool<
SubsetWorkerInput,
SubsetWorkerOutput<SubsetWorkerInput["command"]>
>
WorkerPool<SubsetWorkerData, SubsetWorkerResult<SubsetWorkerData["command"]>>
> | null = null;
/**
@ -118,11 +115,11 @@ const getOrCreateWorkerPool = () => {
if (!workerPool) {
// immediate concurrent-friendly return, to ensure we have only one pool instance
workerPool = promiseTry(async () => {
const { WorkerUrl } = await lazyLoadSubsetWorkerChunk();
const { WorkerUrl } = await lazyLoadWorkerSubsetChunk();
const pool = WorkerPool.create<
SubsetWorkerInput,
SubsetWorkerOutput<SubsetWorkerInput["command"]>
SubsetWorkerData,
SubsetWorkerResult<SubsetWorkerData["command"]>
>(WorkerUrl);
return pool;

View file

@ -9,8 +9,6 @@
import { Commands, subsetToBinary } from "./subset-shared.chunk";
import type { SubsetWorkerInput } from "./subset-main";
/**
* Due to this export (and related dynamic import), this worker code will be included in the bundle automatically (as a separate chunk),
* without the need for esbuild / vite /rollup plugins and special browser / server treatment.
@ -23,7 +21,13 @@ export const WorkerUrl: URL | undefined = import.meta.url
// run only in the worker context
if (typeof window === "undefined" && typeof self !== "undefined") {
self.onmessage = async (e: MessageEvent<SubsetWorkerInput>) => {
self.onmessage = async (e: {
data: {
command: typeof Commands.Subset;
arrayBuffer: ArrayBuffer;
codePoints: Array<number>;
};
}) => {
switch (e.data.command) {
case Commands.Subset:
const buffer = await subsetToBinary(

View file

@ -16,28 +16,24 @@ class IdleWorker {
}
/**
* Pool of idle short-lived workers, so that they can be reused in a short period of time (`ttl`), instead of having to create a new worker from scratch.
* Pool of idle short-lived workers.
*
* IMPORTANT: for simplicity it does not limit the number of newly created workers, leaving it up to the caller to manage the pool size.
*/
export class WorkerPool<T, R> {
private idleWorkers: Set<IdleWorker> = new Set();
private activeWorkers: Set<IdleWorker> = new Set();
private readonly workerUrl: URL;
private readonly workerTTL: number;
private readonly maxPoolSize: number;
private constructor(
workerUrl: URL,
options: {
ttl?: number;
maxPoolSize?: number;
},
) {
this.workerUrl = workerUrl;
// by default, active & idle workers will be terminated after 1s of inactivity
this.workerTTL = options.ttl || 1000;
// by default, active workers are limited to 3 instances
this.maxPoolSize = options.maxPoolSize || 3;
}
/**
@ -52,7 +48,6 @@ export class WorkerPool<T, R> {
workerUrl: URL | undefined,
options: {
ttl?: number;
maxPoolSize?: number;
} = {},
): WorkerPool<T, R> {
if (!workerUrl) {
@ -77,18 +72,13 @@ export class WorkerPool<T, R> {
let worker: IdleWorker;
const idleWorker = Array.from(this.idleWorkers).shift();
if (idleWorker) {
this.idleWorkers.delete(idleWorker);
worker = idleWorker;
} else if (this.activeWorkers.size < this.maxPoolSize) {
worker = await this.createWorker();
} else {
worker = await this.waitForActiveWorker();
worker = await this.createWorker();
}
this.activeWorkers.add(worker);
return new Promise((resolve, reject) => {
worker.instance.onmessage = this.onMessageHandler(worker, resolve);
worker.instance.onerror = this.onErrorHandler(worker, reject);
@ -111,13 +101,7 @@ export class WorkerPool<T, R> {
worker.instance.terminate();
}
for (const worker of this.activeWorkers) {
worker.debounceTerminate.cancel();
worker.instance.terminate();
}
this.idleWorkers.clear();
this.activeWorkers.clear();
}
/**
@ -146,25 +130,9 @@ export class WorkerPool<T, R> {
return worker;
}
private waitForActiveWorker(): Promise<IdleWorker> {
return Promise.race(
Array.from(this.activeWorkers).map(
(worker) =>
new Promise<IdleWorker>((resolve) => {
const originalOnMessage = worker.instance.onmessage;
worker.instance.onmessage = (e) => {
worker.instance.onmessage = originalOnMessage;
resolve(worker);
};
}),
),
);
}
private onMessageHandler(worker: IdleWorker, resolve: (value: R) => void) {
return (e: { data: R }) => {
worker.debounceTerminate();
this.activeWorkers.delete(worker);
this.idleWorkers.add(worker);
resolve(e.data);
};
@ -175,8 +143,6 @@ export class WorkerPool<T, R> {
reject: (reason: ErrorEvent) => void,
) {
return (e: ErrorEvent) => {
this.activeWorkers.delete(worker);
// terminate the worker immediately before rejection
worker.debounceTerminate(() => reject(e));
worker.debounceTerminate.flush();