@flaxia/node 0.3.3 → 0.3.4
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/assets/memoryProbe.js +28 -0
- package/dist/client/SignalingClient.d.ts.map +1 -1
- package/dist/client/__tests__/SignalingClient.incapable.test.d.ts +2 -0
- package/dist/client/__tests__/SignalingClient.incapable.test.d.ts.map +1 -0
- package/dist/executor/__tests__/memoryProbe.test.d.ts +2 -0
- package/dist/executor/__tests__/memoryProbe.test.d.ts.map +1 -0
- package/dist/executor/memoryProbe.d.ts +4 -0
- package/dist/executor/memoryProbe.d.ts.map +1 -0
- package/dist/index.js +71 -67
- package/dist/worker/__tests__/main.worker.capable.test.d.ts +2 -0
- package/dist/worker/__tests__/main.worker.capable.test.d.ts.map +1 -0
- package/dist/worker/__tests__/main.worker.incapable.test.d.ts +2 -0
- package/dist/worker/__tests__/main.worker.incapable.test.d.ts.map +1 -0
- package/dist/worker.js +39 -40
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/executor/memoryProbe.ts
|
|
2
|
+
var e = 2 * 1024 ** 3, t = 65536, n = 16 * 1024 * 1024;
|
|
3
|
+
function r(r = e, i = n) {
|
|
4
|
+
let a;
|
|
5
|
+
try {
|
|
6
|
+
a = new WebAssembly.Memory({ initial: 0 });
|
|
7
|
+
} catch {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
let o = 0;
|
|
11
|
+
for (; o < r;) {
|
|
12
|
+
let e = r - o, n = Math.ceil(Math.min(i, e) / t);
|
|
13
|
+
try {
|
|
14
|
+
a.grow(n);
|
|
15
|
+
} catch {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
let s = new Uint8Array(a.buffer);
|
|
19
|
+
for (let e = 0; e < n; e++) s[o + e * t] = 0;
|
|
20
|
+
o += n * t;
|
|
21
|
+
}
|
|
22
|
+
return o;
|
|
23
|
+
}
|
|
24
|
+
function i() {
|
|
25
|
+
return r() >= e;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { i as n, r, e as t };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SignalingClient.d.ts","sourceRoot":"","sources":["../../src/client/SignalingClient.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SignalingClient.d.ts","sourceRoot":"","sources":["../../src/client/SignalingClient.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK5D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2RD,eAAO,MAAM,cAAc,GAAI,QAAQ,UAAU,SAsBhD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignalingClient.incapable.test.d.ts","sourceRoot":"","sources":["../../../src/client/__tests__/SignalingClient.incapable.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoryProbe.test.d.ts","sourceRoot":"","sources":["../../../src/executor/__tests__/memoryProbe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const HEAVY_WORKLOAD_WASM_MEMORY_BYTES: number;
|
|
2
|
+
export declare function probeMaxWasmMemoryBytes(targetBytes?: number, chunkBytes?: number): number;
|
|
3
|
+
export declare function hasEnoughWasmMemoryForHeavy(): boolean;
|
|
4
|
+
//# sourceMappingURL=memoryProbe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoryProbe.d.ts","sourceRoot":"","sources":["../../src/executor/memoryProbe.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,gCAAgC,QAAgB,CAAC;AAI9D,wBAAgB,uBAAuB,CACrC,WAAW,GAAE,MAAyC,EACtD,UAAU,GAAE,MAA0B,GACrC,MAAM,CA4BR;AAED,wBAAgB,2BAA2B,IAAI,OAAO,CAErD"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { r as e, t } from "./assets/memoryProbe.js";
|
|
1
2
|
//#region src/consent/ConsentUI.ts
|
|
2
|
-
var
|
|
3
|
+
var n = class {
|
|
3
4
|
constructor(e, t, n) {
|
|
4
5
|
this.shadow = e.attachShadow({ mode: "open" }), this.render(t, n);
|
|
5
6
|
}
|
|
@@ -39,39 +40,39 @@ var e = class {
|
|
|
39
40
|
c.remove(), t();
|
|
40
41
|
}), this.shadow.appendChild(s), this.shadow.appendChild(c);
|
|
41
42
|
}
|
|
42
|
-
},
|
|
43
|
-
function
|
|
43
|
+
}, r = "flaxia_consent_granted", i = "flaxia_consent_expiry", a = 720 * 60 * 60 * 1e3, o = /* @__PURE__ */ new Map();
|
|
44
|
+
function s(e) {
|
|
44
45
|
try {
|
|
45
46
|
return localStorage.getItem(e);
|
|
46
47
|
} catch {
|
|
47
|
-
return
|
|
48
|
+
return o.get(e) ?? null;
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
function
|
|
51
|
+
function c(e, t) {
|
|
51
52
|
try {
|
|
52
53
|
localStorage.setItem(e, t);
|
|
53
54
|
} catch {
|
|
54
|
-
|
|
55
|
+
o.set(e, t);
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
|
-
function
|
|
58
|
+
function l(e) {
|
|
58
59
|
try {
|
|
59
60
|
localStorage.removeItem(e);
|
|
60
61
|
} catch {
|
|
61
|
-
|
|
62
|
+
o.delete(e);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
|
-
var
|
|
65
|
-
if (
|
|
66
|
-
let e =
|
|
65
|
+
var u = () => {
|
|
66
|
+
if (s(r) !== "true") return !1;
|
|
67
|
+
let e = s(i);
|
|
67
68
|
if (e) {
|
|
68
|
-
let
|
|
69
|
-
if (!Number.isFinite(
|
|
69
|
+
let t = parseInt(e, 10);
|
|
70
|
+
if (!Number.isFinite(t) || Date.now() > t) return l(r), l(i), !1;
|
|
70
71
|
}
|
|
71
72
|
return !0;
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
},
|
|
73
|
+
}, d = () => {
|
|
74
|
+
c(r, "true"), c(i, String(Date.now() + a));
|
|
75
|
+
}, f = s, p = c, m = () => {
|
|
75
76
|
try {
|
|
76
77
|
if (typeof crypto < "u" && typeof crypto.randomUUID == "function") return crypto.randomUUID();
|
|
77
78
|
} catch {}
|
|
@@ -79,7 +80,7 @@ var c = () => {
|
|
|
79
80
|
let t = Math.random() * 16 | 0;
|
|
80
81
|
return (e === "x" ? t : t & 3 | 8).toString(16);
|
|
81
82
|
});
|
|
82
|
-
},
|
|
83
|
+
}, h = (...e) => console.log("[flaxia-node]", ...e), g = class {
|
|
83
84
|
constructor(e, t = 3e5) {
|
|
84
85
|
this.worker = null, this.queue = [], this.active = null, this._lastCpuLoad = 0, this.workerUrl = e || "/worker.js", this.defaultTimeoutMs = t, this.initWorker();
|
|
85
86
|
}
|
|
@@ -99,7 +100,7 @@ var c = () => {
|
|
|
99
100
|
return;
|
|
100
101
|
}
|
|
101
102
|
let c = () => this.execute(e, t, n, r, i, a, o, s);
|
|
102
|
-
this.active ? (
|
|
103
|
+
this.active ? (h(`task queued id=${e} workload=${t} (active task running)`), this.queue.push(c)) : c();
|
|
103
104
|
});
|
|
104
105
|
}
|
|
105
106
|
execute(e, t, n, r, i, a, o, s) {
|
|
@@ -109,27 +110,27 @@ var c = () => {
|
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
112
|
let l = r ?? this.defaultTimeoutMs, u = !1, d = performance.now();
|
|
112
|
-
|
|
113
|
+
h(`task start id=${e} workload=${t} timeoutMs=${l}`);
|
|
113
114
|
let f = (e) => {
|
|
114
115
|
if (u) return;
|
|
115
116
|
u = !0;
|
|
116
117
|
let t = this.active;
|
|
117
118
|
t && (clearTimeout(t.timer), t.removeListener()), this.active = null, e(), this.dequeue();
|
|
118
|
-
},
|
|
119
|
-
let { id: r, type: a, result: c, error: l, token: u, cpuLoad:
|
|
119
|
+
}, p = (n) => {
|
|
120
|
+
let { id: r, type: a, result: c, error: l, token: u, cpuLoad: p } = n.data;
|
|
120
121
|
if (r === e) {
|
|
121
122
|
if (a === "token") {
|
|
122
123
|
i?.(u);
|
|
123
124
|
return;
|
|
124
125
|
}
|
|
125
126
|
if (a === "heartbeat") {
|
|
126
|
-
typeof
|
|
127
|
+
typeof p == "number" && Number.isFinite(p) && (this._lastCpuLoad = Math.min(1, Math.max(0, p)));
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
|
-
a === "done" ? (
|
|
130
|
+
a === "done" ? (h(`task done id=${e} workload=${t} durationMs=${Math.round(performance.now() - d)}`), f(() => o(c))) : a === "error" ? (h(`task failed id=${e} workload=${t} error=${l}`), f(() => s(Error(l)))) : (h(`task unknown-message id=${e} type=${String(a)}`), f(() => s(/* @__PURE__ */ Error(`Unknown message type: ${String(a)}`))));
|
|
130
131
|
}
|
|
131
|
-
},
|
|
132
|
-
|
|
132
|
+
}, m = () => c.removeEventListener("message", p), g = setTimeout(() => {
|
|
133
|
+
h(`task timeout id=${e} workload=${t} (worker terminated after ${l}ms)`), this.cleanupWorker(), f(() => s(/* @__PURE__ */ Error("TIMEOUT")));
|
|
133
134
|
}, l);
|
|
134
135
|
this.active = {
|
|
135
136
|
id: e,
|
|
@@ -137,8 +138,8 @@ var c = () => {
|
|
|
137
138
|
reject: s,
|
|
138
139
|
timer: g,
|
|
139
140
|
worker: c,
|
|
140
|
-
removeListener:
|
|
141
|
-
}, c.addEventListener("message",
|
|
141
|
+
removeListener: m
|
|
142
|
+
}, c.addEventListener("message", p);
|
|
142
143
|
try {
|
|
143
144
|
c.postMessage({
|
|
144
145
|
id: e,
|
|
@@ -152,7 +153,7 @@ var c = () => {
|
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
155
|
handleWorkerError(e) {
|
|
155
|
-
|
|
156
|
+
h(`worker error error=${e.message}`);
|
|
156
157
|
let t = this.active;
|
|
157
158
|
this.cleanupWorker(), t && (clearTimeout(t.timer), this.active = null, t.reject(e), this.dequeue());
|
|
158
159
|
}
|
|
@@ -172,13 +173,13 @@ var c = () => {
|
|
|
172
173
|
get lastCpuLoad() {
|
|
173
174
|
return this._lastCpuLoad;
|
|
174
175
|
}
|
|
175
|
-
},
|
|
176
|
+
}, _ = (...e) => console.log("[flaxia-node]", ...e), v = (...e) => console.error("[flaxia-node]", ...e), y = "flaxia_node_id", b = "flaxia_node_token", x = class {
|
|
176
177
|
constructor(e, t, n) {
|
|
177
178
|
this.config = e, this.workerPool = t, this.nodeId = n, this.ws = null, this.reconnectAttempts = 0, this.MAX_RECONNECT_DELAY = 3e4, this.destroyed = !1, this.suspended = !1, this.visibilityHandler = null, this.inflightTasks = /* @__PURE__ */ new Set();
|
|
178
179
|
}
|
|
179
180
|
async connect() {
|
|
180
181
|
if (this.destroyed) return;
|
|
181
|
-
if (
|
|
182
|
+
if (_(`connect nodeId=${this.nodeId}`), this.ws) {
|
|
182
183
|
let e = this.ws;
|
|
183
184
|
e.onclose = null;
|
|
184
185
|
try {
|
|
@@ -189,14 +190,14 @@ var c = () => {
|
|
|
189
190
|
this.setupVisibilityHandler();
|
|
190
191
|
let e = await this.obtainToken();
|
|
191
192
|
if (!e) {
|
|
192
|
-
|
|
193
|
+
v("token acquisition failed; scheduling reconnect"), this.scheduleReconnect();
|
|
193
194
|
return;
|
|
194
195
|
}
|
|
195
196
|
let t = this.config.orchestratorUrl.replace(/\/+$/, "").replace(/^http/, "ws"), n = new URL(`${t}/crowd/signal`);
|
|
196
197
|
n.searchParams.set("token", e.token);
|
|
197
198
|
let r = new WebSocket(n.toString());
|
|
198
199
|
this.ws = r, r.onopen = () => {
|
|
199
|
-
this.reconnectAttempts = 0,
|
|
200
|
+
this.reconnectAttempts = 0, _(`signal connected ${n.toString()}`);
|
|
200
201
|
}, r.onmessage = async (e) => {
|
|
201
202
|
let t;
|
|
202
203
|
try {
|
|
@@ -213,12 +214,12 @@ var c = () => {
|
|
|
213
214
|
}
|
|
214
215
|
if (t.type === "task") {
|
|
215
216
|
let e = t;
|
|
216
|
-
|
|
217
|
+
_(`task received taskId=${e.taskId} workload=${e.workload} timeoutMs=${e.timeoutMs ?? "default"}`);
|
|
217
218
|
try {
|
|
218
219
|
await this.handleTask(e);
|
|
219
220
|
} catch (n) {
|
|
220
221
|
let r = n instanceof Error ? n.message : String(n);
|
|
221
|
-
|
|
222
|
+
v(`task failed taskId=${e.taskId} workload=${e.workload} error=${r}`), this.send({
|
|
222
223
|
type: "error",
|
|
223
224
|
taskId: String(t.taskId ?? ""),
|
|
224
225
|
error: r
|
|
@@ -226,7 +227,7 @@ var c = () => {
|
|
|
226
227
|
}
|
|
227
228
|
}
|
|
228
229
|
}, r.onclose = () => {
|
|
229
|
-
r.onclose = null, this.ws === r && (this.ws = null, !this.destroyed && (
|
|
230
|
+
r.onclose = null, this.ws === r && (this.ws = null, !this.destroyed && (_(`signal disconnected; scheduling reconnect attempt=${this.reconnectAttempts + 1}`), this.scheduleReconnect()));
|
|
230
231
|
};
|
|
231
232
|
}
|
|
232
233
|
scheduleReconnect() {
|
|
@@ -236,13 +237,13 @@ var c = () => {
|
|
|
236
237
|
}, e);
|
|
237
238
|
}
|
|
238
239
|
disconnect() {
|
|
239
|
-
|
|
240
|
+
_(`disconnect nodeId=${this.nodeId}`), this.destroyed = !0, this.suspended = !1, this.removeVisibilityHandler();
|
|
240
241
|
try {
|
|
241
242
|
this.ws?.close();
|
|
242
243
|
} catch {}
|
|
243
244
|
this.ws = null;
|
|
244
245
|
try {
|
|
245
|
-
delete window[
|
|
246
|
+
delete window[C];
|
|
246
247
|
} catch {}
|
|
247
248
|
try {
|
|
248
249
|
this.workerPool.terminate();
|
|
@@ -250,7 +251,7 @@ var c = () => {
|
|
|
250
251
|
}
|
|
251
252
|
suspend() {
|
|
252
253
|
if (!(this.suspended || this.destroyed)) {
|
|
253
|
-
if (
|
|
254
|
+
if (_("suspended (visibility or manual)"), this.suspended = !0, this.ws) {
|
|
254
255
|
let e = this.ws;
|
|
255
256
|
e.onclose = null;
|
|
256
257
|
try {
|
|
@@ -262,35 +263,38 @@ var c = () => {
|
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
265
|
resume() {
|
|
265
|
-
!this.suspended || this.destroyed || (
|
|
266
|
+
!this.suspended || this.destroyed || (_("resumed"), this.suspended = !1, this.workerPool.resume(), this.connect());
|
|
266
267
|
}
|
|
267
268
|
async obtainToken() {
|
|
268
269
|
try {
|
|
269
|
-
let
|
|
270
|
-
if (
|
|
271
|
-
let
|
|
272
|
-
if (
|
|
270
|
+
let n = f(b);
|
|
271
|
+
if (n) try {
|
|
272
|
+
let e = JSON.parse(n);
|
|
273
|
+
if (e.token && e.nodeId && e.expiresAt > Date.now() + 6e4) return _(`token cached nodeId=${e.nodeId} expiresIn=${Math.round((e.expiresAt - Date.now()) / 1e3)}s`), e;
|
|
273
274
|
} catch {}
|
|
274
|
-
let t = this.config.
|
|
275
|
+
let r = e(), i = r >= t, a = i ? this.config.capabilities ?? ["ai-inference", "image-process"] : [];
|
|
276
|
+
_(`register capability probe capable=${i} wasmMemoryBytes=${r} capabilities=${JSON.stringify(a)}`);
|
|
277
|
+
let o = this.config.orchestratorUrl.replace(/\/+$/, ""), s = await fetch(`${o}/crowd/nodes/register`, {
|
|
275
278
|
method: "POST",
|
|
276
279
|
headers: { "Content-Type": "application/json" },
|
|
277
280
|
body: JSON.stringify({
|
|
278
281
|
siteId: this.config.siteId,
|
|
279
282
|
nodeId: this.nodeId,
|
|
280
|
-
capabilities:
|
|
283
|
+
capabilities: a,
|
|
284
|
+
wasmMemoryBytes: e(),
|
|
281
285
|
deviceMemory: typeof navigator.deviceMemory == "number" ? navigator.deviceMemory : null
|
|
282
286
|
})
|
|
283
287
|
});
|
|
284
|
-
if (!
|
|
285
|
-
let
|
|
286
|
-
if (!
|
|
287
|
-
|
|
288
|
+
if (!s.ok) return v(`node register failed HTTP ${s.status} (${o}/crowd/nodes/register)`), null;
|
|
289
|
+
let c = await s.json();
|
|
290
|
+
if (!c.token) return v("node register returned no token"), null;
|
|
291
|
+
_(`node registered nodeId=${this.nodeId} expiresIn=${Math.round((c.expiresAt - Date.now()) / 1e3)}s`);
|
|
288
292
|
try {
|
|
289
|
-
|
|
293
|
+
p(b, JSON.stringify(c));
|
|
290
294
|
} catch {}
|
|
291
|
-
return
|
|
295
|
+
return c;
|
|
292
296
|
} catch (e) {
|
|
293
|
-
return
|
|
297
|
+
return v("node register threw", e instanceof Error ? e.message : e), null;
|
|
294
298
|
}
|
|
295
299
|
}
|
|
296
300
|
send(e) {
|
|
@@ -312,7 +316,7 @@ var c = () => {
|
|
|
312
316
|
type: "result",
|
|
313
317
|
taskId: e.taskId,
|
|
314
318
|
payload: r
|
|
315
|
-
}),
|
|
319
|
+
}), _(`task result sent taskId=${e.taskId} workload=${e.workload} durationMs=${Math.round(performance.now() - t)}`);
|
|
316
320
|
} finally {
|
|
317
321
|
this.inflightTasks.delete(e.taskId);
|
|
318
322
|
}
|
|
@@ -325,23 +329,23 @@ var c = () => {
|
|
|
325
329
|
removeVisibilityHandler() {
|
|
326
330
|
this.visibilityHandler &&= (document.removeEventListener("visibilitychange", this.visibilityHandler), null);
|
|
327
331
|
}
|
|
328
|
-
},
|
|
329
|
-
let t = window[
|
|
332
|
+
}, S = "__flaxia_node_signal_client", C = "__flaxia_node_init_started", w = (e) => {
|
|
333
|
+
let t = window[S];
|
|
330
334
|
t && t.disconnect();
|
|
331
|
-
let n = new URL("./worker.js", "" + import.meta.url).href, r = new
|
|
332
|
-
i || (i =
|
|
333
|
-
let a = new
|
|
334
|
-
window[
|
|
335
|
-
},
|
|
336
|
-
if (window[
|
|
337
|
-
if (window[
|
|
338
|
-
|
|
335
|
+
let n = new URL("./worker.js", "" + import.meta.url).href, r = new g(n), i = f(y);
|
|
336
|
+
i || (i = m(), p(y, i));
|
|
337
|
+
let a = new x(e, r, i);
|
|
338
|
+
window[S] = a, a.connect();
|
|
339
|
+
}, T = (e) => {
|
|
340
|
+
if (window[C]) return;
|
|
341
|
+
if (window[C] = !0, u()) {
|
|
342
|
+
w(e);
|
|
339
343
|
return;
|
|
340
344
|
}
|
|
341
|
-
let
|
|
342
|
-
|
|
343
|
-
|
|
345
|
+
let t = document.createElement("div");
|
|
346
|
+
t.id = "flaxia-consent-container", document.body.appendChild(t), new n(t, e.consent, () => {
|
|
347
|
+
d(), t.remove(), w(e);
|
|
344
348
|
});
|
|
345
349
|
};
|
|
346
350
|
//#endregion
|
|
347
|
-
export {
|
|
351
|
+
export { T as initFlaxiaNode };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.worker.capable.test.d.ts","sourceRoot":"","sources":["../../../src/worker/__tests__/main.worker.capable.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.worker.incapable.test.d.ts","sourceRoot":"","sources":["../../../src/worker/__tests__/main.worker.incapable.test.ts"],"names":[],"mappings":""}
|
package/dist/worker.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { n as e, r as t, t as n } from "./assets/memoryProbe.js";
|
|
1
2
|
//#region src/executor/throttle.ts
|
|
2
|
-
function
|
|
3
|
+
function r(e) {
|
|
3
4
|
return new Promise((t) => setTimeout(t, e));
|
|
4
5
|
}
|
|
5
|
-
var
|
|
6
|
+
var i = 3e4, a = 3e4, o = class {
|
|
6
7
|
constructor(e = .15) {
|
|
7
8
|
this.windowStart = performance.now(), this.windowBusyMs = 0, this.lastLoad = 0, this.maxLoad = Math.max(.05, Math.min(.3, e));
|
|
8
9
|
}
|
|
9
10
|
markTaskComplete(e) {
|
|
10
|
-
let
|
|
11
|
-
|
|
11
|
+
let t = performance.now();
|
|
12
|
+
t - this.windowStart > i && (this.windowStart = t, this.windowBusyMs = 0), this.windowBusyMs += Math.max(0, e), this.lastLoad = this.estimate();
|
|
12
13
|
}
|
|
13
14
|
estimate() {
|
|
14
15
|
let e = performance.now() - this.windowStart;
|
|
@@ -17,9 +18,9 @@ var t = 3e4, n = 3e4, r = class {
|
|
|
17
18
|
async shouldPause() {
|
|
18
19
|
return this.estimate() > this.maxLoad;
|
|
19
20
|
}
|
|
20
|
-
async waitForSlot(
|
|
21
|
-
let
|
|
22
|
-
for (; await this.shouldPause() && !(performance.now() -
|
|
21
|
+
async waitForSlot(e = a) {
|
|
22
|
+
let t = performance.now();
|
|
23
|
+
for (; await this.shouldPause() && !(performance.now() - t > e);) await r(500);
|
|
23
24
|
}
|
|
24
25
|
get lastMeasuredLoad() {
|
|
25
26
|
return this.lastLoad;
|
|
@@ -27,69 +28,67 @@ var t = 3e4, n = 3e4, r = class {
|
|
|
27
28
|
get maxLoadValue() {
|
|
28
29
|
return this.maxLoad;
|
|
29
30
|
}
|
|
30
|
-
},
|
|
31
|
+
}, s = null, c = new Set([
|
|
31
32
|
"ai-inference",
|
|
32
33
|
"vector-embed",
|
|
33
34
|
"vector-query",
|
|
34
35
|
"nudenet",
|
|
35
36
|
"image-process",
|
|
36
37
|
"container"
|
|
37
|
-
]),
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return
|
|
38
|
+
]), l = 6e4, u = t(), d = u >= n;
|
|
39
|
+
console.log(`[flaxia-node:worker] startup memory probe wasmMemoryBytes=${u} capable=${d}`);
|
|
40
|
+
function f() {
|
|
41
|
+
return e();
|
|
41
42
|
}
|
|
42
|
-
var
|
|
43
|
-
function
|
|
44
|
-
for (let e of
|
|
43
|
+
var p = /* @__PURE__ */ new Map(), m = null;
|
|
44
|
+
function h() {
|
|
45
|
+
for (let e of p.values()) try {
|
|
45
46
|
e();
|
|
46
47
|
} catch {}
|
|
47
|
-
|
|
48
|
+
p.clear();
|
|
48
49
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
},
|
|
50
|
+
function g() {
|
|
51
|
+
m && clearTimeout(m), m = setTimeout(() => {
|
|
52
|
+
m = null, h();
|
|
53
|
+
}, l);
|
|
53
54
|
}
|
|
54
|
-
async function
|
|
55
|
+
async function _(e, t, n) {
|
|
55
56
|
switch (e) {
|
|
56
57
|
case "ai-inference":
|
|
57
58
|
let r = await import("./assets/ai-inference.js");
|
|
58
|
-
return
|
|
59
|
+
return p.set(e, r.releaseCache), await r.handleAiInference(t, n);
|
|
59
60
|
case "image-process": return await (await import("./assets/image-process.js")).handleImageProcess(t);
|
|
60
61
|
case "container": return await (await import("./assets/container.js")).handleContainer(t);
|
|
61
62
|
case "vector-embed":
|
|
62
63
|
let i = await import("./assets/vector-embed.js");
|
|
63
|
-
return
|
|
64
|
+
return p.set(e, i.releaseCache), await i.handleVectorEmbed(t);
|
|
64
65
|
case "vector-store":
|
|
65
66
|
let a = await import("./assets/vector-store.js");
|
|
66
|
-
return
|
|
67
|
+
return p.set(e, a.releaseCache), await a.handleVectorStore(t);
|
|
67
68
|
case "vector-query":
|
|
68
69
|
let o = await import("./assets/vector-query.js");
|
|
69
|
-
return
|
|
70
|
+
return p.set(e, o.releaseCache), await o.handleVectorQuery(t);
|
|
70
71
|
case "nudenet":
|
|
71
72
|
let s = await import("./assets/nudenet.js");
|
|
72
|
-
return
|
|
73
|
+
return p.set(e, s.releaseCache), await s.handleNudeNet(t);
|
|
73
74
|
default: throw Error(`Unknown workload type: ${e}`);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
self.onmessage = async (e) => {
|
|
77
|
-
let { id: t, workload:
|
|
78
|
+
let { id: t, workload: r, payload: i, config: a } = e.data, l = performance.now();
|
|
78
79
|
try {
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
await i.waitForSlot();
|
|
80
|
+
if (s ||= new o(a?.maxCpuLoad), console.log(`[flaxia-node:worker] task start id=${t} workload=${r}`), !d) throw Error(`node incapable: insufficient WASM memory (${u} bytes < ${n}); rejecting all tasks`);
|
|
81
|
+
if (c.has(r) && !f()) throw Error(`${r}: insufficient WASM memory (${u} bytes < ${n})`);
|
|
82
|
+
await s.waitForSlot();
|
|
84
83
|
let e = setInterval(() => {
|
|
85
84
|
self.postMessage({
|
|
86
85
|
id: t,
|
|
87
86
|
type: "heartbeat",
|
|
88
|
-
cpuLoad:
|
|
87
|
+
cpuLoad: s?.lastMeasuredLoad ?? 0
|
|
89
88
|
});
|
|
90
|
-
}, 1e4),
|
|
89
|
+
}, 1e4), p = performance.now();
|
|
91
90
|
try {
|
|
92
|
-
let e = await
|
|
91
|
+
let e = await _(r, i, (e) => {
|
|
93
92
|
self.postMessage({
|
|
94
93
|
id: t,
|
|
95
94
|
type: "token",
|
|
@@ -100,16 +99,16 @@ self.onmessage = async (e) => {
|
|
|
100
99
|
id: t,
|
|
101
100
|
type: "done",
|
|
102
101
|
result: e
|
|
103
|
-
}), console.log(`[flaxia-node:worker] task done id=${t} workload=${
|
|
102
|
+
}), console.log(`[flaxia-node:worker] task done id=${t} workload=${r} durationMs=${Math.round(performance.now() - l)}`);
|
|
104
103
|
} finally {
|
|
105
|
-
clearInterval(e),
|
|
104
|
+
clearInterval(e), s.markTaskComplete(performance.now() - p), g();
|
|
106
105
|
}
|
|
107
106
|
} catch (e) {
|
|
108
|
-
let
|
|
109
|
-
console.error(`[flaxia-node:worker] task error id=${t} workload=${
|
|
107
|
+
let n = e instanceof Error ? e.message : String(e);
|
|
108
|
+
console.error(`[flaxia-node:worker] task error id=${t} workload=${r} error=${n}`), self.postMessage({
|
|
110
109
|
id: t,
|
|
111
110
|
type: "error",
|
|
112
|
-
error:
|
|
111
|
+
error: n
|
|
113
112
|
});
|
|
114
113
|
}
|
|
115
114
|
};
|