@lokvis/runtime 0.1.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/dist/asset-store.d.ts +72 -0
- package/dist/asset-store.d.ts.map +1 -0
- package/dist/asset-store.js +167 -0
- package/dist/asset-store.js.map +1 -0
- package/dist/capability-registry.d.ts +38 -0
- package/dist/capability-registry.d.ts.map +1 -0
- package/dist/capability-registry.js +100 -0
- package/dist/capability-registry.js.map +1 -0
- package/dist/event-bus.d.ts +9 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +33 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/executor.d.ts +42 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +237 -0
- package/dist/executor.js.map +1 -0
- package/dist/history.d.ts +92 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +171 -0
- package/dist/history.js.map +1 -0
- package/dist/idb-asset-store.d.ts +46 -0
- package/dist/idb-asset-store.d.ts.map +1 -0
- package/dist/idb-asset-store.js +76 -0
- package/dist/idb-asset-store.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/opfs-asset-store.d.ts +38 -0
- package/dist/opfs-asset-store.d.ts.map +1 -0
- package/dist/opfs-asset-store.js +122 -0
- package/dist/opfs-asset-store.js.map +1 -0
- package/dist/runtime.d.ts +87 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +475 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +99 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/worker-host.d.ts +154 -0
- package/dist/worker-host.d.ts.map +1 -0
- package/dist/worker-host.js +394 -0
- package/dist/worker-host.js.map +1 -0
- package/dist/worker-protocol.d.ts +103 -0
- package/dist/worker-protocol.d.ts.map +1 -0
- package/dist/worker-protocol.js +87 -0
- package/dist/worker-protocol.js.map +1 -0
- package/package.json +49 -0
- package/src/asset-store.ts +222 -0
- package/src/capability-registry.ts +135 -0
- package/src/event-bus.ts +41 -0
- package/src/executor.ts +303 -0
- package/src/history.ts +229 -0
- package/src/idb-asset-store.ts +121 -0
- package/src/index.ts +20 -0
- package/src/opfs-asset-store.ts +167 -0
- package/src/runtime.ts +564 -0
- package/src/types.ts +121 -0
- package/src/worker-host.ts +531 -0
- package/src/worker-protocol.ts +187 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkerHost —— 主线程侧的 Worker 管理器
|
|
3
|
+
*
|
|
4
|
+
* 职责(对应 PROJECT_PLAN 1.6):
|
|
5
|
+
* - 生成 / 重启 Worker,完成 ready 握手。
|
|
6
|
+
* - Request/Response 按 id 关联,每请求独立超时。
|
|
7
|
+
* - 心跳(Heartbeat):周期 ping,超时未 pong 视为崩溃。
|
|
8
|
+
* - 崩溃重启:传输层 error / 心跳超时 → 终止并重建(最多 maxRestarts 次)。
|
|
9
|
+
* - 事件分发:Worker 主动 event + 生命周期事件(ready/restart/crash/dead)。
|
|
10
|
+
*
|
|
11
|
+
* 传输层抽象(WorkerTransport)使其与具体 Worker 实现解耦:
|
|
12
|
+
* - 浏览器:createBrowserWorkerTransport(url)
|
|
13
|
+
* - 测试:注入 Fake 传输,无需真实 Worker。
|
|
14
|
+
*/
|
|
15
|
+
/** 规范化的传输层错误 */
|
|
16
|
+
export interface WorkerTransportError {
|
|
17
|
+
message: string;
|
|
18
|
+
filename?: string;
|
|
19
|
+
lineno?: number;
|
|
20
|
+
stack?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 传输层接口:屏蔽 浏览器 Worker / Node worker_threads / Fake 差异。
|
|
24
|
+
* Host 仅依赖该接口,便于单测注入 Fake。
|
|
25
|
+
*/
|
|
26
|
+
export interface WorkerTransport {
|
|
27
|
+
/** 向 Worker 发消息(可附带可转移对象) */
|
|
28
|
+
send(message: unknown, transfer?: Transferable[]): void;
|
|
29
|
+
/** 监听 Worker → Host 消息,返回取消订阅 */
|
|
30
|
+
onMessage(handler: (data: unknown) => void): () => void;
|
|
31
|
+
/** 监听传输层错误(脚本加载失败 / 未捕获异常 / 异常退出),返回取消订阅 */
|
|
32
|
+
onError(handler: (err: WorkerTransportError) => void): () => void;
|
|
33
|
+
/** 终止 Worker */
|
|
34
|
+
terminate(): void;
|
|
35
|
+
}
|
|
36
|
+
/** Worker 崩溃(传输层错误或心跳超时) */
|
|
37
|
+
export declare class WorkerCrashedError extends Error {
|
|
38
|
+
readonly reason: string;
|
|
39
|
+
readonly restartCount: number;
|
|
40
|
+
constructor(reason: string, restartCount: number);
|
|
41
|
+
}
|
|
42
|
+
/** Worker 正在重启,拒绝新请求 */
|
|
43
|
+
export declare class WorkerRestartingError extends Error {
|
|
44
|
+
constructor();
|
|
45
|
+
}
|
|
46
|
+
/** Worker 已死亡(超过最大重启次数) */
|
|
47
|
+
export declare class WorkerDeadError extends Error {
|
|
48
|
+
readonly restartCount: number;
|
|
49
|
+
constructor(restartCount: number);
|
|
50
|
+
}
|
|
51
|
+
/** 单个请求超时 */
|
|
52
|
+
export declare class WorkerRequestTimeoutError extends Error {
|
|
53
|
+
readonly method: string;
|
|
54
|
+
constructor(method: string, timeoutMs: number);
|
|
55
|
+
}
|
|
56
|
+
/** ready 握手失败(协议版本不匹配或超时) */
|
|
57
|
+
export declare class WorkerHandshakeError extends Error {
|
|
58
|
+
constructor(message: string);
|
|
59
|
+
}
|
|
60
|
+
export interface WorkerHostOptions {
|
|
61
|
+
/** 心跳发送间隔 */
|
|
62
|
+
heartbeatIntervalMs?: number;
|
|
63
|
+
/** 心跳超时(未收到 pong 视为崩溃) */
|
|
64
|
+
heartbeatTimeoutMs?: number;
|
|
65
|
+
/** 单个请求默认超时 */
|
|
66
|
+
requestTimeoutMs?: number;
|
|
67
|
+
/** 等待 Worker ready 的超时 */
|
|
68
|
+
readyTimeoutMs?: number;
|
|
69
|
+
/** 崩溃后最大重启次数 */
|
|
70
|
+
maxRestarts?: number;
|
|
71
|
+
/** 传输层工厂(重启时复用) */
|
|
72
|
+
createTransport: () => WorkerTransport;
|
|
73
|
+
/** 是否输出日志 */
|
|
74
|
+
enableLog?: boolean;
|
|
75
|
+
}
|
|
76
|
+
export type WorkerHostStatus = 'idle' | 'ready' | 'restarting' | 'dead' | 'disposed';
|
|
77
|
+
/** 生命周期 + Worker 主动事件 */
|
|
78
|
+
export interface WorkerHostEventMap {
|
|
79
|
+
ready: {
|
|
80
|
+
restartCount: number;
|
|
81
|
+
};
|
|
82
|
+
restart: {
|
|
83
|
+
reason: string;
|
|
84
|
+
restartCount: number;
|
|
85
|
+
};
|
|
86
|
+
crash: {
|
|
87
|
+
reason: string;
|
|
88
|
+
restartCount: number;
|
|
89
|
+
};
|
|
90
|
+
dead: {
|
|
91
|
+
reason: string;
|
|
92
|
+
restartCount: number;
|
|
93
|
+
};
|
|
94
|
+
event: {
|
|
95
|
+
event: string;
|
|
96
|
+
payload?: unknown;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export type WorkerHostEventType = keyof WorkerHostEventMap;
|
|
100
|
+
type Listener<T> = (payload: T) => void;
|
|
101
|
+
export declare class WorkerHost {
|
|
102
|
+
private opts;
|
|
103
|
+
private status;
|
|
104
|
+
private transport;
|
|
105
|
+
private pending;
|
|
106
|
+
private listeners;
|
|
107
|
+
private restartCount;
|
|
108
|
+
private heartbeatTimer;
|
|
109
|
+
private pongTimer;
|
|
110
|
+
private awaitingPong;
|
|
111
|
+
private offMessage;
|
|
112
|
+
private offError;
|
|
113
|
+
constructor(opts: WorkerHostOptions);
|
|
114
|
+
get currentStatus(): WorkerHostStatus;
|
|
115
|
+
/** 已发生的重启次数 */
|
|
116
|
+
get currentRestartCount(): number;
|
|
117
|
+
/** 订阅事件,返回取消订阅 */
|
|
118
|
+
on<K extends WorkerHostEventType>(type: K, handler: Listener<WorkerHostEventMap[K]>): () => void;
|
|
119
|
+
private emit;
|
|
120
|
+
private log;
|
|
121
|
+
/** 启动并完成 ready 握手 */
|
|
122
|
+
init(): Promise<void>;
|
|
123
|
+
/** 销毁:终止 Worker、清理定时器、拒绝所有 pending */
|
|
124
|
+
dispose(): Promise<void>;
|
|
125
|
+
/** 调用 Worker 方法并等待响应 */
|
|
126
|
+
request<T = unknown>(method: string, params?: unknown, options?: {
|
|
127
|
+
transfer?: Transferable[];
|
|
128
|
+
timeoutMs?: number;
|
|
129
|
+
}): Promise<T>;
|
|
130
|
+
/** 创建传输层、绑定监听、等待 ready */
|
|
131
|
+
private spawn;
|
|
132
|
+
private handleMessage;
|
|
133
|
+
/** 崩溃处理:拒绝 pending → 终止 → 重启(受 maxRestarts 限制) */
|
|
134
|
+
private handleCrash;
|
|
135
|
+
/**
|
|
136
|
+
* 重启尝试循环。spawn 失败(ready 超时)时,直接 teardown 并重试,
|
|
137
|
+
* 不经过 handleCrash 的 restarting 守卫——否则永远到不了 dead。
|
|
138
|
+
*/
|
|
139
|
+
private tryRestart;
|
|
140
|
+
/** 解绑当前 transport 的监听并终止 */
|
|
141
|
+
private teardownTransport;
|
|
142
|
+
private startHeartbeat;
|
|
143
|
+
private sendPing;
|
|
144
|
+
private clearHeartbeat;
|
|
145
|
+
private send;
|
|
146
|
+
private rejectAllPending;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 创建浏览器 Web Worker 传输层。
|
|
150
|
+
* 仅在浏览器主线程可用(Node 测试应注入 Fake 传输)。
|
|
151
|
+
*/
|
|
152
|
+
export declare function createBrowserWorkerTransport(url: string | URL): WorkerTransport;
|
|
153
|
+
export {};
|
|
154
|
+
//# sourceMappingURL=worker-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-host.d.ts","sourceRoot":"","sources":["../src/worker-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkerHost —— 主线程侧的 Worker 管理器
|
|
3
|
+
*
|
|
4
|
+
* 职责(对应 PROJECT_PLAN 1.6):
|
|
5
|
+
* - 生成 / 重启 Worker,完成 ready 握手。
|
|
6
|
+
* - Request/Response 按 id 关联,每请求独立超时。
|
|
7
|
+
* - 心跳(Heartbeat):周期 ping,超时未 pong 视为崩溃。
|
|
8
|
+
* - 崩溃重启:传输层 error / 心跳超时 → 终止并重建(最多 maxRestarts 次)。
|
|
9
|
+
* - 事件分发:Worker 主动 event + 生命周期事件(ready/restart/crash/dead)。
|
|
10
|
+
*
|
|
11
|
+
* 传输层抽象(WorkerTransport)使其与具体 Worker 实现解耦:
|
|
12
|
+
* - 浏览器:createBrowserWorkerTransport(url)
|
|
13
|
+
* - 测试:注入 Fake 传输,无需真实 Worker。
|
|
14
|
+
*/
|
|
15
|
+
import { WORKER_PROTOCOL_VERSION, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_HEARTBEAT_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_MAX_RESTARTS, DEFAULT_READY_TIMEOUT_MS, createRequestId, isWorkerResponse, isWorkerPong, isWorkerReady, isWorkerEvent, isWorkerFatalError, } from './worker-protocol.js';
|
|
16
|
+
// ─── 错误类型 ───────────────────────────────────────────────────
|
|
17
|
+
/** Worker 崩溃(传输层错误或心跳超时) */
|
|
18
|
+
export class WorkerCrashedError extends Error {
|
|
19
|
+
reason;
|
|
20
|
+
restartCount;
|
|
21
|
+
constructor(reason, restartCount) {
|
|
22
|
+
super(`Worker crashed: ${reason}`);
|
|
23
|
+
this.name = 'WorkerCrashedError';
|
|
24
|
+
this.reason = reason;
|
|
25
|
+
this.restartCount = restartCount;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Worker 正在重启,拒绝新请求 */
|
|
29
|
+
export class WorkerRestartingError extends Error {
|
|
30
|
+
constructor() {
|
|
31
|
+
super('Worker is restarting');
|
|
32
|
+
this.name = 'WorkerRestartingError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Worker 已死亡(超过最大重启次数) */
|
|
36
|
+
export class WorkerDeadError extends Error {
|
|
37
|
+
restartCount;
|
|
38
|
+
constructor(restartCount) {
|
|
39
|
+
super(`Worker is dead after ${restartCount} restart attempts`);
|
|
40
|
+
this.name = 'WorkerDeadError';
|
|
41
|
+
this.restartCount = restartCount;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** 单个请求超时 */
|
|
45
|
+
export class WorkerRequestTimeoutError extends Error {
|
|
46
|
+
method;
|
|
47
|
+
constructor(method, timeoutMs) {
|
|
48
|
+
super(`Request "${method}" timed out after ${timeoutMs}ms`);
|
|
49
|
+
this.name = 'WorkerRequestTimeoutError';
|
|
50
|
+
this.method = method;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** ready 握手失败(协议版本不匹配或超时) */
|
|
54
|
+
export class WorkerHandshakeError extends Error {
|
|
55
|
+
constructor(message) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = 'WorkerHandshakeError';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ─── WorkerHost ─────────────────────────────────────────────────
|
|
61
|
+
export class WorkerHost {
|
|
62
|
+
opts;
|
|
63
|
+
status = 'idle';
|
|
64
|
+
transport = null;
|
|
65
|
+
pending = new Map();
|
|
66
|
+
listeners = new Map();
|
|
67
|
+
restartCount = 0;
|
|
68
|
+
heartbeatTimer = null;
|
|
69
|
+
pongTimer = null;
|
|
70
|
+
awaitingPong = false;
|
|
71
|
+
offMessage = null;
|
|
72
|
+
offError = null;
|
|
73
|
+
constructor(opts) {
|
|
74
|
+
this.opts = {
|
|
75
|
+
heartbeatIntervalMs: opts.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS,
|
|
76
|
+
heartbeatTimeoutMs: opts.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS,
|
|
77
|
+
requestTimeoutMs: opts.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
|
|
78
|
+
readyTimeoutMs: opts.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,
|
|
79
|
+
maxRestarts: opts.maxRestarts ?? DEFAULT_MAX_RESTARTS,
|
|
80
|
+
createTransport: opts.createTransport,
|
|
81
|
+
enableLog: opts.enableLog ?? false,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
get currentStatus() {
|
|
85
|
+
return this.status;
|
|
86
|
+
}
|
|
87
|
+
/** 已发生的重启次数 */
|
|
88
|
+
get currentRestartCount() {
|
|
89
|
+
return this.restartCount;
|
|
90
|
+
}
|
|
91
|
+
/** 订阅事件,返回取消订阅 */
|
|
92
|
+
on(type, handler) {
|
|
93
|
+
let set = this.listeners.get(type);
|
|
94
|
+
if (!set) {
|
|
95
|
+
set = new Set();
|
|
96
|
+
this.listeners.set(type, set);
|
|
97
|
+
}
|
|
98
|
+
set.add(handler);
|
|
99
|
+
return () => set.delete(handler);
|
|
100
|
+
}
|
|
101
|
+
emit(type, payload) {
|
|
102
|
+
const set = this.listeners.get(type);
|
|
103
|
+
if (!set)
|
|
104
|
+
return;
|
|
105
|
+
for (const h of set)
|
|
106
|
+
h(payload);
|
|
107
|
+
}
|
|
108
|
+
log(message) {
|
|
109
|
+
if (this.opts.enableLog)
|
|
110
|
+
console.debug(`[WorkerHost] ${message}`);
|
|
111
|
+
}
|
|
112
|
+
// ─── 生命周期 ───────────────────────────────────────────────
|
|
113
|
+
/** 启动并完成 ready 握手 */
|
|
114
|
+
async init() {
|
|
115
|
+
if (this.status === 'disposed')
|
|
116
|
+
throw new Error('WorkerHost is disposed');
|
|
117
|
+
if (this.status !== 'idle')
|
|
118
|
+
return; // 已启动
|
|
119
|
+
await this.spawn();
|
|
120
|
+
}
|
|
121
|
+
/** 销毁:终止 Worker、清理定时器、拒绝所有 pending */
|
|
122
|
+
async dispose() {
|
|
123
|
+
if (this.status === 'disposed')
|
|
124
|
+
return;
|
|
125
|
+
this.status = 'disposed';
|
|
126
|
+
this.clearHeartbeat();
|
|
127
|
+
this.rejectAllPending(new Error('WorkerHost disposed'));
|
|
128
|
+
this.offMessage?.();
|
|
129
|
+
this.offError?.();
|
|
130
|
+
this.offMessage = null;
|
|
131
|
+
this.offError = null;
|
|
132
|
+
this.transport?.terminate();
|
|
133
|
+
this.transport = null;
|
|
134
|
+
this.listeners.clear();
|
|
135
|
+
}
|
|
136
|
+
// ─── 请求 ───────────────────────────────────────────────────
|
|
137
|
+
/** 调用 Worker 方法并等待响应 */
|
|
138
|
+
async request(method, params, options) {
|
|
139
|
+
if (this.status === 'disposed')
|
|
140
|
+
throw new Error('WorkerHost is disposed');
|
|
141
|
+
if (this.status === 'dead')
|
|
142
|
+
throw new WorkerDeadError(this.restartCount);
|
|
143
|
+
if (this.status === 'restarting' || this.status === 'idle') {
|
|
144
|
+
throw new WorkerRestartingError();
|
|
145
|
+
}
|
|
146
|
+
const id = createRequestId();
|
|
147
|
+
const timeoutMs = options?.timeoutMs ?? this.opts.requestTimeoutMs;
|
|
148
|
+
const msg = { id, type: 'request', method, params };
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
const timer = setTimeout(() => {
|
|
151
|
+
if (this.pending.delete(id)) {
|
|
152
|
+
reject(new WorkerRequestTimeoutError(method, timeoutMs));
|
|
153
|
+
}
|
|
154
|
+
}, timeoutMs);
|
|
155
|
+
this.pending.set(id, {
|
|
156
|
+
resolve: (v) => resolve(v),
|
|
157
|
+
reject,
|
|
158
|
+
timer,
|
|
159
|
+
method,
|
|
160
|
+
});
|
|
161
|
+
this.send(msg, options?.transfer);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
// ─── 内部:spawn / 消息处理 / 崩溃 ──────────────────────────
|
|
165
|
+
/** 创建传输层、绑定监听、等待 ready */
|
|
166
|
+
async spawn() {
|
|
167
|
+
const transport = this.opts.createTransport();
|
|
168
|
+
this.transport = transport;
|
|
169
|
+
this.offMessage = transport.onMessage((data) => this.handleMessage(data));
|
|
170
|
+
this.offError = transport.onError((err) => this.handleCrash(`transport error: ${err.message}`));
|
|
171
|
+
// 等待 ready 握手(超时或协议不匹配则拒绝,由 catch 清理 transport)
|
|
172
|
+
let readyTimer;
|
|
173
|
+
try {
|
|
174
|
+
await new Promise((resolve, reject) => {
|
|
175
|
+
let done = false;
|
|
176
|
+
readyTimer = setTimeout(() => {
|
|
177
|
+
if (done)
|
|
178
|
+
return;
|
|
179
|
+
done = true;
|
|
180
|
+
reject(new WorkerHandshakeError(`Worker did not send ready within ${this.opts.readyTimeoutMs}ms`));
|
|
181
|
+
}, this.opts.readyTimeoutMs);
|
|
182
|
+
readyTimer.unref?.();
|
|
183
|
+
const off = this.on('ready', () => {
|
|
184
|
+
if (done)
|
|
185
|
+
return;
|
|
186
|
+
done = true;
|
|
187
|
+
clearTimeout(readyTimer);
|
|
188
|
+
off();
|
|
189
|
+
resolve();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
clearTimeout(readyTimer);
|
|
195
|
+
this.offMessage?.();
|
|
196
|
+
this.offError?.();
|
|
197
|
+
this.offMessage = null;
|
|
198
|
+
this.offError = null;
|
|
199
|
+
transport.terminate();
|
|
200
|
+
this.transport = null;
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
this.status = 'ready';
|
|
204
|
+
this.startHeartbeat();
|
|
205
|
+
}
|
|
206
|
+
handleMessage(data) {
|
|
207
|
+
// ready(可能在握手期间或重启后)
|
|
208
|
+
if (isWorkerReady(data)) {
|
|
209
|
+
if (!data.protocolVersion || data.protocolVersion !== WORKER_PROTOCOL_VERSION) {
|
|
210
|
+
this.handleCrash(`protocol mismatch: worker=${data.protocolVersion} host=${WORKER_PROTOCOL_VERSION}`);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// ready 事件由 spawn() 的监听器消费;重启后再次 ready 也触发
|
|
214
|
+
this.emit('ready', { restartCount: this.restartCount });
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (isWorkerPong(data)) {
|
|
218
|
+
this.awaitingPong = false;
|
|
219
|
+
if (this.pongTimer) {
|
|
220
|
+
clearTimeout(this.pongTimer);
|
|
221
|
+
this.pongTimer = null;
|
|
222
|
+
}
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (isWorkerResponse(data)) {
|
|
226
|
+
const pending = this.pending.get(data.id);
|
|
227
|
+
if (!pending)
|
|
228
|
+
return; // 已超时或已取消
|
|
229
|
+
this.pending.delete(data.id);
|
|
230
|
+
clearTimeout(pending.timer);
|
|
231
|
+
if (data.ok)
|
|
232
|
+
pending.resolve(data.result);
|
|
233
|
+
else {
|
|
234
|
+
const e = data.error;
|
|
235
|
+
const err = new Error(e.message);
|
|
236
|
+
err.name = e.code ?? 'WorkerError';
|
|
237
|
+
if (e.stack)
|
|
238
|
+
err.stack = e.stack;
|
|
239
|
+
pending.reject(err);
|
|
240
|
+
}
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (isWorkerEvent(data)) {
|
|
244
|
+
this.emit('event', { event: data.event, payload: data.payload });
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (isWorkerFatalError(data)) {
|
|
248
|
+
// Worker 主动上报致命错误 → 视为崩溃
|
|
249
|
+
this.handleCrash(`worker fatal: ${data.message}`);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/** 崩溃处理:拒绝 pending → 终止 → 重启(受 maxRestarts 限制) */
|
|
254
|
+
handleCrash(reason) {
|
|
255
|
+
// 正在重启/已死亡/已销毁时,忽略额外的崩溃信号(避免重入)
|
|
256
|
+
if (this.status === 'disposed' ||
|
|
257
|
+
this.status === 'dead' ||
|
|
258
|
+
this.status === 'restarting') {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
this.log(`crash: ${reason}`);
|
|
262
|
+
this.status = 'restarting';
|
|
263
|
+
this.teardownTransport();
|
|
264
|
+
this.rejectAllPending(new WorkerCrashedError(reason, this.restartCount));
|
|
265
|
+
this.emit('crash', { reason, restartCount: this.restartCount });
|
|
266
|
+
this.tryRestart(reason);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* 重启尝试循环。spawn 失败(ready 超时)时,直接 teardown 并重试,
|
|
270
|
+
* 不经过 handleCrash 的 restarting 守卫——否则永远到不了 dead。
|
|
271
|
+
*/
|
|
272
|
+
tryRestart(reason) {
|
|
273
|
+
if (this.status === 'disposed')
|
|
274
|
+
return;
|
|
275
|
+
if (this.restartCount >= this.opts.maxRestarts) {
|
|
276
|
+
this.status = 'dead';
|
|
277
|
+
this.emit('dead', { reason, restartCount: this.restartCount });
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
this.restartCount++;
|
|
281
|
+
this.log(`restarting (attempt ${this.restartCount}/${this.opts.maxRestarts})`);
|
|
282
|
+
this.spawn()
|
|
283
|
+
.then(() => {
|
|
284
|
+
this.emit('restart', { reason, restartCount: this.restartCount });
|
|
285
|
+
})
|
|
286
|
+
.catch((err) => {
|
|
287
|
+
// 重启失败:终止本次(未握手成功的)transport,继续下一轮重试
|
|
288
|
+
this.teardownTransport();
|
|
289
|
+
this.tryRestart(`restart failed: ${err.message}`);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
/** 解绑当前 transport 的监听并终止 */
|
|
293
|
+
teardownTransport() {
|
|
294
|
+
this.clearHeartbeat();
|
|
295
|
+
this.offMessage?.();
|
|
296
|
+
this.offError?.();
|
|
297
|
+
this.offMessage = null;
|
|
298
|
+
this.offError = null;
|
|
299
|
+
this.transport?.terminate();
|
|
300
|
+
this.transport = null;
|
|
301
|
+
}
|
|
302
|
+
// ─── 心跳 ───────────────────────────────────────────────────
|
|
303
|
+
startHeartbeat() {
|
|
304
|
+
this.clearHeartbeat();
|
|
305
|
+
this.awaitingPong = false;
|
|
306
|
+
this.heartbeatTimer = setInterval(() => {
|
|
307
|
+
this.sendPing();
|
|
308
|
+
}, this.opts.heartbeatIntervalMs);
|
|
309
|
+
this.heartbeatTimer.unref?.();
|
|
310
|
+
}
|
|
311
|
+
sendPing() {
|
|
312
|
+
if (this.awaitingPong)
|
|
313
|
+
return; // 上一轮 pong 未回,等超时触发崩溃
|
|
314
|
+
this.awaitingPong = true;
|
|
315
|
+
const msg = {
|
|
316
|
+
id: createRequestId(),
|
|
317
|
+
type: 'ping',
|
|
318
|
+
ts: Date.now(),
|
|
319
|
+
};
|
|
320
|
+
this.send(msg);
|
|
321
|
+
this.pongTimer = setTimeout(() => {
|
|
322
|
+
this.handleCrash(`heartbeat timeout (no pong in ${this.opts.heartbeatTimeoutMs}ms)`);
|
|
323
|
+
}, this.opts.heartbeatTimeoutMs);
|
|
324
|
+
this.pongTimer.unref?.();
|
|
325
|
+
}
|
|
326
|
+
clearHeartbeat() {
|
|
327
|
+
if (this.heartbeatTimer) {
|
|
328
|
+
clearInterval(this.heartbeatTimer);
|
|
329
|
+
this.heartbeatTimer = null;
|
|
330
|
+
}
|
|
331
|
+
if (this.pongTimer) {
|
|
332
|
+
clearTimeout(this.pongTimer);
|
|
333
|
+
this.pongTimer = null;
|
|
334
|
+
}
|
|
335
|
+
this.awaitingPong = false;
|
|
336
|
+
}
|
|
337
|
+
// ─── 工具 ───────────────────────────────────────────────────
|
|
338
|
+
send(message, transfer) {
|
|
339
|
+
if (!this.transport)
|
|
340
|
+
return;
|
|
341
|
+
this.transport.send(message, transfer);
|
|
342
|
+
}
|
|
343
|
+
rejectAllPending(error) {
|
|
344
|
+
for (const [, p] of this.pending) {
|
|
345
|
+
clearTimeout(p.timer);
|
|
346
|
+
p.reject(error);
|
|
347
|
+
}
|
|
348
|
+
this.pending.clear();
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// ─── 浏览器默认传输层 ───────────────────────────────────────────
|
|
352
|
+
/**
|
|
353
|
+
* 创建浏览器 Web Worker 传输层。
|
|
354
|
+
* 仅在浏览器主线程可用(Node 测试应注入 Fake 传输)。
|
|
355
|
+
*/
|
|
356
|
+
export function createBrowserWorkerTransport(url) {
|
|
357
|
+
const worker = new Worker(url, { type: 'module' });
|
|
358
|
+
const messageHandlers = new Set();
|
|
359
|
+
const errorHandlers = new Set();
|
|
360
|
+
worker.addEventListener('message', (ev) => {
|
|
361
|
+
for (const h of messageHandlers)
|
|
362
|
+
h(ev.data);
|
|
363
|
+
});
|
|
364
|
+
worker.addEventListener('error', (ev) => {
|
|
365
|
+
const err = {
|
|
366
|
+
message: ev.message || 'Worker error',
|
|
367
|
+
filename: ev.filename,
|
|
368
|
+
lineno: ev.lineno,
|
|
369
|
+
stack: ev.error instanceof Error ? ev.error.stack : undefined,
|
|
370
|
+
};
|
|
371
|
+
for (const h of errorHandlers)
|
|
372
|
+
h(err);
|
|
373
|
+
});
|
|
374
|
+
return {
|
|
375
|
+
send(message, transfer) {
|
|
376
|
+
if (transfer && transfer.length > 0)
|
|
377
|
+
worker.postMessage(message, transfer);
|
|
378
|
+
else
|
|
379
|
+
worker.postMessage(message);
|
|
380
|
+
},
|
|
381
|
+
onMessage(handler) {
|
|
382
|
+
messageHandlers.add(handler);
|
|
383
|
+
return () => messageHandlers.delete(handler);
|
|
384
|
+
},
|
|
385
|
+
onError(handler) {
|
|
386
|
+
errorHandlers.add(handler);
|
|
387
|
+
return () => errorHandlers.delete(handler);
|
|
388
|
+
},
|
|
389
|
+
terminate() {
|
|
390
|
+
worker.terminate();
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=worker-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-host.js","sourceRoot":"","sources":["../src/worker-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker 通信协议
|
|
3
|
+
*
|
|
4
|
+
* 定义 主线程(Host) ↔ Worker 之间的消息格式与握手/心跳规范。
|
|
5
|
+
* 协议本身与传输层解耦(纯类型 + 常量 + 校验助手),
|
|
6
|
+
* 既可用于浏览器 Web Worker,也可在测试中被 Fake 传输层复用。
|
|
7
|
+
*
|
|
8
|
+
* 设计目标(对应 whitepaper T1「浏览器内存/性能 ★★★★★」与 PROJECT_PLAN 1.6/1.7):
|
|
9
|
+
* - 每个请求有唯一 id,Response 按 id 关联,避免错配。
|
|
10
|
+
* - 心跳(Heartbeat):Host 周期性 ping,Worker 必须在超时内 pong,否则视为崩溃。
|
|
11
|
+
* - Ready 握手:Worker 启动后主动发 ready,Host 据此判定可用。
|
|
12
|
+
* - 错误通道:Worker 主动 error(可恢复) vs 传输层 error/exit(不可恢复,触发重启)。
|
|
13
|
+
*
|
|
14
|
+
* 消息流向:
|
|
15
|
+
* Host → Worker: request | ping
|
|
16
|
+
* Worker → Host: response | pong | event | ready | error
|
|
17
|
+
*/
|
|
18
|
+
/** 协议版本(Host 与 Worker 握手时校验,不一致则拒绝) */
|
|
19
|
+
export declare const WORKER_PROTOCOL_VERSION = "0.1.0";
|
|
20
|
+
/** 心跳发送间隔 */
|
|
21
|
+
export declare const DEFAULT_HEARTBEAT_INTERVAL_MS = 5000;
|
|
22
|
+
/** 心跳超时:超过该时间未收到 pong 视为 Worker 无响应 */
|
|
23
|
+
export declare const DEFAULT_HEARTBEAT_TIMEOUT_MS = 15000;
|
|
24
|
+
/** 单个请求的默认超时 */
|
|
25
|
+
export declare const DEFAULT_REQUEST_TIMEOUT_MS = 60000;
|
|
26
|
+
/** 崩溃后最大重启次数(超过则放弃,交由上层降级) */
|
|
27
|
+
export declare const DEFAULT_MAX_RESTARTS = 3;
|
|
28
|
+
/** Worker 启动后等待 ready 的超时 */
|
|
29
|
+
export declare const DEFAULT_READY_TIMEOUT_MS = 10000;
|
|
30
|
+
/** 请求:Host 调用 Worker 暴露的方法 */
|
|
31
|
+
export interface WorkerRequest {
|
|
32
|
+
id: string;
|
|
33
|
+
type: 'request';
|
|
34
|
+
method: string;
|
|
35
|
+
params: unknown;
|
|
36
|
+
}
|
|
37
|
+
/** 心跳探测 */
|
|
38
|
+
export interface WorkerPing {
|
|
39
|
+
id: string;
|
|
40
|
+
type: 'ping';
|
|
41
|
+
ts: number;
|
|
42
|
+
}
|
|
43
|
+
export type WorkerMessageToWorker = WorkerRequest | WorkerPing;
|
|
44
|
+
/** 响应:成功 */
|
|
45
|
+
export interface WorkerResponseOk {
|
|
46
|
+
id: string;
|
|
47
|
+
type: 'response';
|
|
48
|
+
ok: true;
|
|
49
|
+
result: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** 响应:失败 */
|
|
52
|
+
export interface WorkerResponseErr {
|
|
53
|
+
id: string;
|
|
54
|
+
type: 'response';
|
|
55
|
+
ok: false;
|
|
56
|
+
error: {
|
|
57
|
+
message: string;
|
|
58
|
+
code?: string;
|
|
59
|
+
stack?: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export type WorkerResponse = WorkerResponseOk | WorkerResponseErr;
|
|
63
|
+
/** 心跳回应 */
|
|
64
|
+
export interface WorkerPong {
|
|
65
|
+
id: string;
|
|
66
|
+
type: 'pong';
|
|
67
|
+
ts: number;
|
|
68
|
+
}
|
|
69
|
+
/** Worker 主动事件(进度、日志等,无需 ack) */
|
|
70
|
+
export interface WorkerEvent {
|
|
71
|
+
type: 'event';
|
|
72
|
+
event: string;
|
|
73
|
+
payload?: unknown;
|
|
74
|
+
}
|
|
75
|
+
/** Worker 就绪(启动后主动发送,携带协议版本) */
|
|
76
|
+
export interface WorkerReady {
|
|
77
|
+
type: 'ready';
|
|
78
|
+
protocolVersion: string;
|
|
79
|
+
}
|
|
80
|
+
/** Worker 主动上报的致命错误(自身仍存活但无法继续) */
|
|
81
|
+
export interface WorkerFatalError {
|
|
82
|
+
type: 'error';
|
|
83
|
+
message: string;
|
|
84
|
+
stack?: string;
|
|
85
|
+
}
|
|
86
|
+
export type WorkerMessageToHost = WorkerResponse | WorkerPong | WorkerEvent | WorkerReady | WorkerFatalError;
|
|
87
|
+
/** 生成唯一请求/心跳 id */
|
|
88
|
+
export declare function createRequestId(): string;
|
|
89
|
+
/** 类型守卫:是否为 Worker → Host 消息 */
|
|
90
|
+
export declare function isWorkerMessageToHost(data: unknown): data is WorkerMessageToHost;
|
|
91
|
+
/** 类型守卫:是否为响应消息 */
|
|
92
|
+
export declare function isWorkerResponse(data: unknown): data is WorkerResponse;
|
|
93
|
+
/** 类型守卫:是否为 pong */
|
|
94
|
+
export declare function isWorkerPong(data: unknown): data is WorkerPong;
|
|
95
|
+
/** 类型守卫:是否为 ready */
|
|
96
|
+
export declare function isWorkerReady(data: unknown): data is WorkerReady;
|
|
97
|
+
/** 类型守卫:是否为 Worker 主动事件 */
|
|
98
|
+
export declare function isWorkerEvent(data: unknown): data is WorkerEvent;
|
|
99
|
+
/** 类型守卫:是否为 Worker 主动上报错误 */
|
|
100
|
+
export declare function isWorkerFatalError(data: unknown): data is WorkerFatalError;
|
|
101
|
+
/** 协议版本是否兼容(目前采用严格相等) */
|
|
102
|
+
export declare function isProtocolCompatible(version: string): boolean;
|
|
103
|
+
//# sourceMappingURL=worker-protocol.d.ts.map
|