@navaramap/worker 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +3 -0
- package/dist/helpers/transferConstructedPolygonGeometry.d.ts +6 -0
- package/dist/helpers/transferConstructedPolylineGeometry.d.ts +6 -0
- package/dist/helpers/transferReturnedConstructedTerrainMesh.d.ts +6 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3203 -0
- package/dist/index.umd.cjs +11 -0
- package/dist/manager.d.ts +19 -0
- package/dist/pool.d.ts +17 -0
- package/dist/recyclingPool.d.ts +86 -0
- package/dist/tasks/constructPolygonBatchedFeature.d.ts +2 -0
- package/dist/tasks/constructPolylineBatchedFeature.d.ts +2 -0
- package/dist/tasks/constructQuantizedMeshTerrainMesh.d.ts +4 -0
- package/dist/tasks/constructTerrainMesh.d.ts +4 -0
- package/dist/tasks/getImageDataFromBlob.d.ts +12 -0
- package/dist/tasks/getImageDataFromImageBitmap.d.ts +1 -0
- package/dist/tasks/index.d.ts +26 -0
- package/dist/tasks/parseMvtTile.d.ts +15 -0
- package/dist/tasks/upsampleQuantizedMeshTerrainMesh.d.ts +2 -0
- package/dist/tasks/upsampleTerrainMesh.d.ts +2 -0
- package/dist/tasks/waitWasm.d.ts +8 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/toExtentRadianF32Like.d.ts +3 -0
- package/dist/utils/toPolygonMaterialLike.d.ts +3 -0
- package/dist/utils/toPolylineMaterialLike.d.ts +3 -0
- package/dist/utils/toTransferableMartiniLike.d.ts +3 -0
- package/dist/utils/toTransferablePolygonBatchedFeatureLike.d.ts +3 -0
- package/dist/utils/toTransferablePolylineBatchedFeatureLike.d.ts +3 -0
- package/dist/utils/toTransferableRasterDEMDataLike.d.ts +3 -0
- package/dist/utils/toTransferableTileLike.d.ts +5 -0
- package/dist/utils/toUpsamplableTerrainGeometryLike.d.ts +3 -0
- package/dist/utils/toVec3Like.d.ts +3 -0
- package/dist/worker/index.d.ts +4 -0
- package/dist/worker/transfer.d.ts +1 -0
- package/package.json +37 -0
- package/src/helpers/transferConstructedPolygonGeometry.ts +25 -0
- package/src/helpers/transferConstructedPolylineGeometry.ts +28 -0
- package/src/helpers/transferReturnedConstructedTerrainMesh.ts +21 -0
- package/src/index.ts +4 -0
- package/src/manager.test.ts +45 -0
- package/src/manager.ts +43 -0
- package/src/pool.test.ts +87 -0
- package/src/pool.ts +150 -0
- package/src/recyclingPool.test.ts +404 -0
- package/src/recyclingPool.ts +385 -0
- package/src/tasks/constructPolygonBatchedFeature.ts +40 -0
- package/src/tasks/constructPolylineBatchedFeature.ts +36 -0
- package/src/tasks/constructQuantizedMeshTerrainMesh.ts +36 -0
- package/src/tasks/constructTerrainMesh.ts +44 -0
- package/src/tasks/getImageDataFromBlob.ts +30 -0
- package/src/tasks/getImageDataFromImageBitmap.ts +19 -0
- package/src/tasks/index.ts +31 -0
- package/src/tasks/parseMvtTile.ts +67 -0
- package/src/tasks/upsampleQuantizedMeshTerrainMesh.ts +38 -0
- package/src/tasks/upsampleTerrainMesh.ts +40 -0
- package/src/tasks/waitWasm.ts +19 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/toExtentRadianF32Like.ts +6 -0
- package/src/utils/toPolygonMaterialLike.ts +20 -0
- package/src/utils/toPolylineMaterialLike.ts +17 -0
- package/src/utils/toTransferableMartiniLike.ts +6 -0
- package/src/utils/toTransferablePolygonBatchedFeatureLike.ts +41 -0
- package/src/utils/toTransferablePolylineBatchedFeatureLike.ts +21 -0
- package/src/utils/toTransferableRasterDEMDataLike.ts +22 -0
- package/src/utils/toTransferableTileLike.ts +34 -0
- package/src/utils/toUpsamplableTerrainGeometryLike.ts +14 -0
- package/src/utils/toVec3Like.ts +6 -0
- package/src/vite-env.d.ts +1 -0
- package/src/worker/index.ts +44 -0
- package/src/worker/transfer.ts +6 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ReturnedConstructedTerrainMeshLike } from "@navaramap/core";
|
|
2
|
+
import type { ReturnedConstructedTerrainMesh } from "@navaramap/engine-worker";
|
|
3
|
+
|
|
4
|
+
export function transferReturnedConstructedTerrainMesh(
|
|
5
|
+
r: ReturnedConstructedTerrainMesh,
|
|
6
|
+
) {
|
|
7
|
+
const like = new ReturnedConstructedTerrainMeshLike(r);
|
|
8
|
+
const transfers: ArrayBufferLike[] = [
|
|
9
|
+
like.vertices.buffer,
|
|
10
|
+
like.uvs.buffer,
|
|
11
|
+
like.indices.buffer,
|
|
12
|
+
like.heights.buffer,
|
|
13
|
+
];
|
|
14
|
+
if (like.normals) transfers.push(like.normals.buffer);
|
|
15
|
+
if (like.skirt_vertices) transfers.push(like.skirt_vertices.buffer);
|
|
16
|
+
if (like.skirt_uvs) transfers.push(like.skirt_uvs.buffer);
|
|
17
|
+
if (like.skirt_indices) transfers.push(like.skirt_indices.buffer);
|
|
18
|
+
if (like.skirt_normals) transfers.push(like.skirt_normals.buffer);
|
|
19
|
+
if (like.watermask) transfers.push(like.watermask.buffer);
|
|
20
|
+
return { result: like, transfers };
|
|
21
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { createConcurrencyManager } from "./manager";
|
|
4
|
+
|
|
5
|
+
it("should get correct concurrency states", () => {
|
|
6
|
+
const manager = createConcurrencyManager(1);
|
|
7
|
+
|
|
8
|
+
// Initialize
|
|
9
|
+
expect(manager.actives()).toBe(0);
|
|
10
|
+
expect(manager.idles()).toBe(1);
|
|
11
|
+
expect(manager.total).toBe(1);
|
|
12
|
+
|
|
13
|
+
// Increment
|
|
14
|
+
|
|
15
|
+
expect(manager.canIncrement()).toBeTruthy();
|
|
16
|
+
|
|
17
|
+
manager.increment();
|
|
18
|
+
expect(manager.actives()).toBe(1);
|
|
19
|
+
expect(manager.idles()).toBe(0);
|
|
20
|
+
|
|
21
|
+
expect(manager.canIncrement()).toBeFalsy();
|
|
22
|
+
manager.increment();
|
|
23
|
+
expect(manager.actives()).toBe(1);
|
|
24
|
+
expect(manager.idles()).toBe(0);
|
|
25
|
+
|
|
26
|
+
// Decrement
|
|
27
|
+
|
|
28
|
+
expect(manager.canDecrement()).toBeTruthy();
|
|
29
|
+
|
|
30
|
+
manager.decrement();
|
|
31
|
+
expect(manager.actives()).toBe(0);
|
|
32
|
+
expect(manager.idles()).toBe(1);
|
|
33
|
+
|
|
34
|
+
expect(manager.canDecrement()).toBeFalsy();
|
|
35
|
+
manager.decrement();
|
|
36
|
+
expect(manager.actives()).toBe(0);
|
|
37
|
+
expect(manager.idles()).toBe(1);
|
|
38
|
+
|
|
39
|
+
// Reset
|
|
40
|
+
|
|
41
|
+
manager.increment();
|
|
42
|
+
manager.reset();
|
|
43
|
+
expect(manager.actives()).toBe(0);
|
|
44
|
+
expect(manager.idles()).toBe(1);
|
|
45
|
+
});
|
package/src/manager.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type ConcurrencyManager = {
|
|
2
|
+
/** Total concurrency */
|
|
3
|
+
total: number;
|
|
4
|
+
/** Increment the count according to the activated process */
|
|
5
|
+
increment: () => void;
|
|
6
|
+
/** Decrement the count according to the deactivated process */
|
|
7
|
+
decrement: () => void;
|
|
8
|
+
/** Reset the count */
|
|
9
|
+
reset: () => void;
|
|
10
|
+
/** The number of activated processes */
|
|
11
|
+
actives: () => number;
|
|
12
|
+
/** The number of idle processes */
|
|
13
|
+
idles: () => number;
|
|
14
|
+
/** Whether it can activate the process */
|
|
15
|
+
canIncrement: () => boolean;
|
|
16
|
+
/** Whether there is an activated process */
|
|
17
|
+
canDecrement: () => boolean;
|
|
18
|
+
};
|
|
19
|
+
export const createConcurrencyManager = (total: number): ConcurrencyManager => {
|
|
20
|
+
let actives = 0;
|
|
21
|
+
|
|
22
|
+
const canIncrement = () => actives !== total;
|
|
23
|
+
const canDecrement = () => actives !== 0;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
total,
|
|
27
|
+
actives: () => actives,
|
|
28
|
+
idles: () => total - actives,
|
|
29
|
+
increment: () => {
|
|
30
|
+
if (!canIncrement()) return;
|
|
31
|
+
actives++;
|
|
32
|
+
},
|
|
33
|
+
decrement: () => {
|
|
34
|
+
if (!canDecrement()) return;
|
|
35
|
+
actives--;
|
|
36
|
+
},
|
|
37
|
+
canIncrement,
|
|
38
|
+
canDecrement,
|
|
39
|
+
reset: () => {
|
|
40
|
+
actives = 0;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
};
|
package/src/pool.test.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { beforeEach, expect, it, vi } from "vitest";
|
|
2
|
+
import workerpool from "workerpool";
|
|
3
|
+
import type Pool from "workerpool/types/Pool";
|
|
4
|
+
|
|
5
|
+
import { createConcurrencyManager } from "./manager";
|
|
6
|
+
import { initializeWorkerPool, queueTask } from "./pool";
|
|
7
|
+
|
|
8
|
+
const workPoolExecStates = (() => {
|
|
9
|
+
const states = {
|
|
10
|
+
resolve: false,
|
|
11
|
+
reject: false,
|
|
12
|
+
rejectBeforePromise: false,
|
|
13
|
+
};
|
|
14
|
+
const reset = () => {
|
|
15
|
+
states.rejectBeforePromise = false;
|
|
16
|
+
states.resolve = false;
|
|
17
|
+
states.reject = false;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return { states, reset };
|
|
21
|
+
})();
|
|
22
|
+
|
|
23
|
+
vi.spyOn(workerpool, "pool").mockImplementation(
|
|
24
|
+
() =>
|
|
25
|
+
({
|
|
26
|
+
exec: (_method: string, _params?: unknown, _options?: unknown) => {
|
|
27
|
+
if (workPoolExecStates.states.rejectBeforePromise) {
|
|
28
|
+
throw new Error();
|
|
29
|
+
}
|
|
30
|
+
return new workerpool.Promise(
|
|
31
|
+
(resolve: () => void, reject: () => void) => {
|
|
32
|
+
if (workPoolExecStates.states.resolve) {
|
|
33
|
+
resolve();
|
|
34
|
+
}
|
|
35
|
+
if (workPoolExecStates.states.reject) {
|
|
36
|
+
reject();
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
terminate: () => undefined,
|
|
42
|
+
}) as unknown as Pool,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// Worker pool is initialized globally.
|
|
46
|
+
const manager = createConcurrencyManager(1);
|
|
47
|
+
const incrementFnMock = vi.spyOn(manager, "increment");
|
|
48
|
+
initializeWorkerPool("https://example.com", manager);
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
workPoolExecStates.reset();
|
|
52
|
+
incrementFnMock.mockClear();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should increment and decrement concurrency when the promise is resolved", async () => {
|
|
56
|
+
workPoolExecStates.states.resolve = true;
|
|
57
|
+
|
|
58
|
+
const promise = queueTask("test" as any);
|
|
59
|
+
await promise;
|
|
60
|
+
expect(incrementFnMock).toHaveBeenCalledOnce();
|
|
61
|
+
expect(manager.actives()).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should increment and decrement concurrency when the promise is rejected", async () => {
|
|
65
|
+
workPoolExecStates.states.reject = true;
|
|
66
|
+
|
|
67
|
+
const promise = queueTask("test" as any);
|
|
68
|
+
try {
|
|
69
|
+
await promise;
|
|
70
|
+
expect.fail("Expect that this case throws an error");
|
|
71
|
+
} catch {
|
|
72
|
+
expect(incrementFnMock).toHaveBeenCalledOnce();
|
|
73
|
+
expect(manager.actives()).toBe(0);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should increment and decrement concurrency when the function throws an error before returning the promise", async () => {
|
|
78
|
+
workPoolExecStates.states.rejectBeforePromise = true;
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
queueTask("test" as any);
|
|
82
|
+
expect.fail("Expect that this case throws an error");
|
|
83
|
+
} catch {
|
|
84
|
+
expect(incrementFnMock).toHaveBeenCalledOnce();
|
|
85
|
+
expect(manager.actives()).toBe(0);
|
|
86
|
+
}
|
|
87
|
+
});
|
package/src/pool.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import invariant from "tiny-invariant";
|
|
2
|
+
import type { Promise } from "workerpool";
|
|
3
|
+
import type { ExecOptions } from "workerpool/types/types";
|
|
4
|
+
|
|
5
|
+
import type { ConcurrencyManager } from "./manager";
|
|
6
|
+
import {
|
|
7
|
+
RecyclingWorkerPool,
|
|
8
|
+
type RecyclingWorkerPoolOptions,
|
|
9
|
+
} from "./recyclingPool";
|
|
10
|
+
import { type CommonTasks } from "./worker";
|
|
11
|
+
|
|
12
|
+
export type { Promise } from "workerpool";
|
|
13
|
+
export type {
|
|
14
|
+
RecyclingWorkerPoolOptions,
|
|
15
|
+
WorkerPoolHeapStats,
|
|
16
|
+
WorkerPoolStats,
|
|
17
|
+
} from "./recyclingPool";
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
initializeWorkerPool,
|
|
21
|
+
terminateWorkerPool,
|
|
22
|
+
warmUpWorkerPool,
|
|
23
|
+
worker,
|
|
24
|
+
workerPoolStats,
|
|
25
|
+
workerPoolHeapStats,
|
|
26
|
+
probeWorkerPoolHeap,
|
|
27
|
+
} = (() => {
|
|
28
|
+
// Restrict access to this object.
|
|
29
|
+
let worker:
|
|
30
|
+
| {
|
|
31
|
+
pool: RecyclingWorkerPool;
|
|
32
|
+
manager: ConcurrencyManager;
|
|
33
|
+
}
|
|
34
|
+
| undefined;
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
initializeWorkerPool: (
|
|
38
|
+
url: string,
|
|
39
|
+
manager: ConcurrencyManager,
|
|
40
|
+
options?: RecyclingWorkerPoolOptions,
|
|
41
|
+
) => {
|
|
42
|
+
if (worker) {
|
|
43
|
+
throw new Error("Worker pool has already been initialized.");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
worker = {
|
|
47
|
+
// Recycles worker threads to bound WASM linear memory growth; see
|
|
48
|
+
// recyclingPool.ts for the policy.
|
|
49
|
+
pool: new RecyclingWorkerPool(url, manager.total, options),
|
|
50
|
+
manager,
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
terminateWorkerPool: () => {
|
|
54
|
+
if (worker) {
|
|
55
|
+
worker.pool.terminate();
|
|
56
|
+
worker = undefined;
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* Pre-initializes WASM on the workers so that upcoming tasks don't pay
|
|
61
|
+
* the initialization latency. Warms a single worker and resolves once
|
|
62
|
+
* it is ready; the rest warm in the background.
|
|
63
|
+
*/
|
|
64
|
+
warmUpWorkerPool: () => {
|
|
65
|
+
invariant(worker, "initializeWorkerPool() must be invoked first.");
|
|
66
|
+
return worker.pool.warmUp();
|
|
67
|
+
},
|
|
68
|
+
worker: () => {
|
|
69
|
+
invariant(worker, "initializeWorkerPool() must be invoked first.");
|
|
70
|
+
return {
|
|
71
|
+
pool: worker.pool,
|
|
72
|
+
manager: worker.manager,
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
workerPoolStats: () => worker?.pool.stats(),
|
|
76
|
+
/** Last-probed WASM heap per worker; see RecyclingWorkerPool.heapStats. */
|
|
77
|
+
workerPoolHeapStats: () => worker?.pool.heapStats(),
|
|
78
|
+
/** Requests fresh heap probes (coalesced per worker; display-rate safe). */
|
|
79
|
+
probeWorkerPoolHeap: () => worker?.pool.probeHeap(),
|
|
80
|
+
};
|
|
81
|
+
})();
|
|
82
|
+
|
|
83
|
+
export {
|
|
84
|
+
initializeWorkerPool,
|
|
85
|
+
terminateWorkerPool,
|
|
86
|
+
warmUpWorkerPool,
|
|
87
|
+
workerPoolStats,
|
|
88
|
+
workerPoolHeapStats,
|
|
89
|
+
probeWorkerPoolHeap,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const canWorkerProcessImmediately = () => {
|
|
93
|
+
const { pool, manager } = worker();
|
|
94
|
+
// Also pauses intake while every worker is over its WASM heap budget
|
|
95
|
+
// (draining); a recycled worker restores capacity moments later.
|
|
96
|
+
return manager.canIncrement() && pool.canAcceptTasks();
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type { ExecOptions } from "workerpool/types/types";
|
|
100
|
+
|
|
101
|
+
type GetTaskName<Task> =
|
|
102
|
+
Task extends Record<string, unknown> ? keyof Task : string;
|
|
103
|
+
|
|
104
|
+
type AnyFunction = (...args: any) => any;
|
|
105
|
+
|
|
106
|
+
export type WorkerTask<T extends Record<string, AnyFunction>> = T & CommonTasks;
|
|
107
|
+
|
|
108
|
+
export type TaskParams<
|
|
109
|
+
Task extends CommonTasks,
|
|
110
|
+
Name extends keyof Task,
|
|
111
|
+
> = Parameters<
|
|
112
|
+
Task[Name] extends AnyFunction ? Task[Name] : (...args: unknown[]) => unknown
|
|
113
|
+
>;
|
|
114
|
+
type MethodReturnType<
|
|
115
|
+
Task extends CommonTasks,
|
|
116
|
+
Name extends GetTaskName<Task>,
|
|
117
|
+
R = Awaited<ReturnType<Task[Name]>>,
|
|
118
|
+
> = R extends infer U ? U : R;
|
|
119
|
+
|
|
120
|
+
export function queueTask<
|
|
121
|
+
Task extends CommonTasks,
|
|
122
|
+
Name extends GetTaskName<Task>,
|
|
123
|
+
>(
|
|
124
|
+
method: Name,
|
|
125
|
+
params?: TaskParams<Task, Name>,
|
|
126
|
+
options?: ExecOptions,
|
|
127
|
+
): Promise<MethodReturnType<Task, Name>> {
|
|
128
|
+
const { pool, manager } = worker();
|
|
129
|
+
|
|
130
|
+
manager.increment();
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
return (
|
|
134
|
+
pool
|
|
135
|
+
.exec(method, params, options)
|
|
136
|
+
// `finally` doesn't work, so use `then()` and `catch()` to ensure that `manager.decrement()` is invoked.
|
|
137
|
+
.then((p) => {
|
|
138
|
+
manager.decrement();
|
|
139
|
+
return p;
|
|
140
|
+
})
|
|
141
|
+
.catch((e) => {
|
|
142
|
+
manager.decrement();
|
|
143
|
+
throw e;
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
} catch (e) {
|
|
147
|
+
manager.decrement();
|
|
148
|
+
throw e;
|
|
149
|
+
}
|
|
150
|
+
}
|