@ultrst-armada/kloks 1.4.2 → 1.4.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/package.json +8 -20
- package/packages/audio-midi/dist/index.d.ts +23 -14
- package/packages/audio-midi/dist/index.js +170 -45
- package/packages/audio-midi/kloks.manifest.json +8 -8
- package/packages/audio-midi/package.json +1 -1
- package/packages/backend/dist/{WebSocketTransport-CxUzUfwl.d.ts → WebSocketTransport-CHmkJ0tj.d.ts} +109 -2
- package/packages/backend/dist/auth/index.js +6 -6
- package/packages/backend/dist/chunk-5336MTXD.js +597 -0
- package/packages/backend/dist/{chunk-T3NYNBDC.js → chunk-5E6JRFUH.js} +201 -3
- package/packages/backend/dist/{chunk-XTWHEZWS.js → chunk-7B24ZWB3.js} +16 -1
- package/packages/backend/dist/{chunk-DZ4ZGIZM.js → chunk-JXUSBKJ2.js} +91 -654
- package/packages/backend/dist/{chunk-FO6WYLW4.js → chunk-KI3LHMUN.js} +133 -46
- package/packages/backend/dist/{chunk-4ZFXEFOE.js → chunk-MPYASJ5A.js} +2 -87
- package/packages/backend/dist/{chunk-KX3OTBQ3.js → chunk-OZDYAEH4.js} +0 -114
- package/packages/backend/dist/chunk-TY32TUNI.js +376 -0
- package/packages/backend/dist/chunk-VDROUXFT.js +116 -0
- package/packages/backend/dist/chunk-ZDH4XI7W.js +140 -0
- package/packages/backend/dist/client/index.d.ts +2 -3
- package/packages/backend/dist/connectivity/index.d.ts +18 -6
- package/packages/backend/dist/connectivity/index.js +3 -7
- package/packages/backend/dist/index.d.ts +3 -6
- package/packages/backend/dist/index.js +101 -91
- package/packages/backend/dist/krnl-services.d.ts +84 -7
- package/packages/backend/dist/krnl-services.js +40 -12
- package/packages/backend/dist/services/index.d.ts +4 -6
- package/packages/backend/dist/services/index.js +2 -2
- package/packages/backend/dist/srkl/index.js +6 -4
- package/packages/backend/dist/storage/index.js +7 -7
- package/packages/backend/dist/workspace/index.js +2 -2
- package/packages/backend/kloks.manifest.json +47 -45
- package/packages/backend/package.json +3 -8
- package/packages/client/package.json +1 -1
- package/packages/contracts/dist/index.js +5 -10
- package/packages/contracts/package.json +1 -1
- package/packages/functions/dist/index.d.ts +12 -1
- package/packages/functions/dist/index.js +132 -24
- package/packages/functions/package.json +1 -1
- package/packages/orchestrations/dist/index.d.ts +33 -31
- package/packages/orchestrations/dist/index.js +81 -203
- package/packages/orchestrations/kloks.manifest.json +10 -2
- package/packages/orchestrations/package.json +2 -2
- package/packages/services/dist/index.d.ts +51 -1
- package/packages/services/dist/index.js +249 -51
- package/packages/services/kloks.manifest.json +69 -33
- package/packages/services/package.json +1 -1
- package/packages/state-graph/dist/{BaseGraph-BvkSYOTw.d.ts → BaseGraph-Bd5F1NMP.d.ts} +1 -1
- package/packages/state-graph/dist/{BaseNode-DTcd3K1B.d.ts → BaseNode-DKpGXMy8.d.ts} +6 -0
- package/packages/state-graph/dist/{CompatibilityMatrix-Dj-tCWUA.d.ts → CompatibilityMatrix-TiEJ3j3_.d.ts} +1 -1
- package/packages/state-graph/dist/domain/index.d.ts +3 -3
- package/packages/state-graph/dist/domain/index.js +0 -1
- package/packages/state-graph/dist/index.d.ts +40 -8
- package/packages/state-graph/dist/index.js +193 -44
- package/packages/state-graph/dist/rules/index.d.ts +3 -3
- package/packages/state-graph/dist/rules/index.js +0 -1
- package/packages/state-graph/dist/spatial/index.d.ts +4 -4
- package/packages/state-graph/dist/spatial/index.js +0 -1
- package/packages/state-graph/dist/state/index.js +1 -3
- package/packages/state-graph/dist/store/index.d.ts +4 -4
- package/packages/state-graph/dist/store/index.js +0 -1
- package/packages/state-graph/dist/{types-VDoc4FIc.d.ts → types-D5kQSa65.d.ts} +2 -2
- package/packages/state-graph/kloks.manifest.json +26 -10
- package/packages/state-graph/package.json +2 -8
- package/packages/backend/dist/IdempotencyManager-B5MjK871.d.ts +0 -16
- package/packages/backend/dist/chunk-25Y7AVTP.js +0 -55
- package/packages/backend/dist/chunk-3EPY34R6.js +0 -67
- package/packages/backend/dist/chunk-7KNGX522.js +0 -220
- package/packages/backend/dist/chunk-FZKBTF34.js +0 -15
- package/packages/backend/dist/chunk-QGHDJGYS.js +0 -92
- package/packages/backend/dist/chunk-UPFKBBQI.js +0 -138
- package/packages/backend/dist/chunk-VQEFULWT.js +0 -88
- package/packages/backend/dist/execution/index.d.ts +0 -124
- package/packages/backend/dist/execution/index.js +0 -20
- package/packages/backend/dist/types-BERZJ93O.d.ts +0 -110
- package/packages/state-graph/dist/chunk-3RG5ZIWI.js +0 -10
- package/packages/state-graph/dist/chunk-Q5I42UX7.js +0 -0
- package/packages/state-graph/dist/chunk-ZTHBPV24.js +0 -267
- package/packages/state-graph/dist/execution/index.d.ts +0 -152
- package/packages/state-graph/dist/execution/index.js +0 -16
- /package/packages/state-graph/dist/{chunk-SHIBCPGQ.js → chunk-EW4ACSZB.js} +0 -0
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
// src/connectivity/IdempotencyManager.ts
|
|
2
|
-
var IdempotencyManager = class {
|
|
3
|
-
inFlight = /* @__PURE__ */ new Map();
|
|
4
|
-
completedCache = /* @__PURE__ */ new Map();
|
|
5
|
-
ttlMs;
|
|
6
|
-
constructor(ttlMs = 6e4) {
|
|
7
|
-
this.ttlMs = ttlMs;
|
|
8
|
-
}
|
|
9
|
-
async executeIdempotent(idempotencyKey, operation) {
|
|
10
|
-
const cached = this.completedCache.get(idempotencyKey);
|
|
11
|
-
if (cached) {
|
|
12
|
-
if (Date.now() - cached.timestamp < this.ttlMs) {
|
|
13
|
-
if (cached.status === "completed") {
|
|
14
|
-
return cached.result;
|
|
15
|
-
}
|
|
16
|
-
throw new Error(cached.error || "[IdempotencyManager] Previous execution failed.");
|
|
17
|
-
} else {
|
|
18
|
-
this.completedCache.delete(idempotencyKey);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const existingFlight = this.inFlight.get(idempotencyKey);
|
|
22
|
-
if (existingFlight) {
|
|
23
|
-
return await existingFlight;
|
|
24
|
-
}
|
|
25
|
-
const executionPromise = (async () => {
|
|
26
|
-
try {
|
|
27
|
-
const result = await operation();
|
|
28
|
-
this.completedCache.set(idempotencyKey, {
|
|
29
|
-
status: "completed",
|
|
30
|
-
result,
|
|
31
|
-
timestamp: Date.now()
|
|
32
|
-
});
|
|
33
|
-
return result;
|
|
34
|
-
} catch (err) {
|
|
35
|
-
this.completedCache.set(idempotencyKey, {
|
|
36
|
-
status: "failed",
|
|
37
|
-
error: err?.message || String(err),
|
|
38
|
-
timestamp: Date.now()
|
|
39
|
-
});
|
|
40
|
-
throw err;
|
|
41
|
-
} finally {
|
|
42
|
-
this.inFlight.delete(idempotencyKey);
|
|
43
|
-
}
|
|
44
|
-
})();
|
|
45
|
-
this.inFlight.set(idempotencyKey, executionPromise);
|
|
46
|
-
return await executionPromise;
|
|
47
|
-
}
|
|
48
|
-
has(idempotencyKey) {
|
|
49
|
-
return this.inFlight.has(idempotencyKey) || this.completedCache.has(idempotencyKey);
|
|
50
|
-
}
|
|
51
|
-
prune() {
|
|
52
|
-
const now = Date.now();
|
|
53
|
-
for (const [key, entry] of this.completedCache.entries()) {
|
|
54
|
-
if (now - entry.timestamp > this.ttlMs) {
|
|
55
|
-
this.completedCache.delete(key);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
clear() {
|
|
60
|
-
this.inFlight.clear();
|
|
61
|
-
this.completedCache.clear();
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export {
|
|
66
|
-
IdempotencyManager
|
|
67
|
-
};
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
// ../../node_modules/.pnpm/@ultrst-armada+krnl@1.0.2/node_modules/@ultrst-armada/krnl/packages/core/dist/index.js
|
|
2
|
-
var ServiceStateStore = class {
|
|
3
|
-
state;
|
|
4
|
-
listeners = /* @__PURE__ */ new Set();
|
|
5
|
-
constructor(initialState) {
|
|
6
|
-
this.state = { ...initialState };
|
|
7
|
-
}
|
|
8
|
-
getState() {
|
|
9
|
-
return Object.freeze({ ...this.state });
|
|
10
|
-
}
|
|
11
|
-
setState(mutation) {
|
|
12
|
-
this.state = { ...this.state, ...mutation };
|
|
13
|
-
const snapshot = this.getState();
|
|
14
|
-
for (const listener of this.listeners) {
|
|
15
|
-
listener(snapshot, mutation);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
subscribe(listener) {
|
|
19
|
-
this.listeners.add(listener);
|
|
20
|
-
return () => {
|
|
21
|
-
this.listeners.delete(listener);
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
reset(newState) {
|
|
25
|
-
this.state = { ...newState || {} };
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
var ServiceEventBus = class {
|
|
29
|
-
handlers = /* @__PURE__ */ new Map();
|
|
30
|
-
on(event, handler) {
|
|
31
|
-
if (!this.handlers.has(event)) {
|
|
32
|
-
this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
33
|
-
}
|
|
34
|
-
const set = this.handlers.get(event);
|
|
35
|
-
set.add(handler);
|
|
36
|
-
return () => {
|
|
37
|
-
set.delete(handler);
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
emit(event, payload) {
|
|
41
|
-
const set = this.handlers.get(event);
|
|
42
|
-
if (!set) return;
|
|
43
|
-
for (const handler of Array.from(set)) {
|
|
44
|
-
try {
|
|
45
|
-
handler(payload);
|
|
46
|
-
} catch (err) {
|
|
47
|
-
console.error(`[ServiceEventBus] Handler error for '${event}':`, err);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
clear() {
|
|
52
|
-
this.handlers.clear();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var LifecycleManager = class {
|
|
56
|
-
status = "uninitialized";
|
|
57
|
-
getStatus() {
|
|
58
|
-
return this.status;
|
|
59
|
-
}
|
|
60
|
-
setStatus(next) {
|
|
61
|
-
this.status = next;
|
|
62
|
-
}
|
|
63
|
-
assertRunning(serviceName) {
|
|
64
|
-
if (this.status !== "running") {
|
|
65
|
-
throw new Error(`[Service:${serviceName}] Cannot invoke operation while status is '${this.status}' (expected 'running').`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
var ServiceInstance = class {
|
|
70
|
-
constructor(definition) {
|
|
71
|
-
this.definition = definition;
|
|
72
|
-
this.id = definition.id;
|
|
73
|
-
this.name = definition.name;
|
|
74
|
-
this.version = definition.version;
|
|
75
|
-
this.lifecycle = new LifecycleManager();
|
|
76
|
-
this.eventBus = new ServiceEventBus();
|
|
77
|
-
if (definition.state?.initial) {
|
|
78
|
-
this.stateStore = new ServiceStateStore(definition.state.initial);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
definition;
|
|
82
|
-
id;
|
|
83
|
-
name;
|
|
84
|
-
version;
|
|
85
|
-
stateStore;
|
|
86
|
-
eventBus;
|
|
87
|
-
lifecycle;
|
|
88
|
-
getDefinition() {
|
|
89
|
-
return this.definition;
|
|
90
|
-
}
|
|
91
|
-
async start() {
|
|
92
|
-
this.lifecycle.setStatus("starting");
|
|
93
|
-
if (this.definition.lifecycle?.onInit) {
|
|
94
|
-
await this.definition.lifecycle.onInit();
|
|
95
|
-
}
|
|
96
|
-
if (this.definition.lifecycle?.onStart) {
|
|
97
|
-
await this.definition.lifecycle.onStart();
|
|
98
|
-
}
|
|
99
|
-
this.lifecycle.setStatus("running");
|
|
100
|
-
}
|
|
101
|
-
async stop() {
|
|
102
|
-
this.lifecycle.setStatus("stopping");
|
|
103
|
-
if (this.definition.lifecycle?.onStop) {
|
|
104
|
-
await this.definition.lifecycle.onStop();
|
|
105
|
-
}
|
|
106
|
-
if (this.definition.lifecycle?.onDispose) {
|
|
107
|
-
await this.definition.lifecycle.onDispose();
|
|
108
|
-
}
|
|
109
|
-
this.lifecycle.setStatus("stopped");
|
|
110
|
-
}
|
|
111
|
-
async call(op, input, ctx = {}) {
|
|
112
|
-
this.lifecycle.assertRunning(this.name);
|
|
113
|
-
const operation = this.definition.operations[op];
|
|
114
|
-
if (!operation) {
|
|
115
|
-
throw new Error(`[Service:${this.name}] Operation '${op}' not found.`);
|
|
116
|
-
}
|
|
117
|
-
return await operation.handler(input, ctx);
|
|
118
|
-
}
|
|
119
|
-
getState() {
|
|
120
|
-
if (!this.stateStore) {
|
|
121
|
-
return Object.freeze({});
|
|
122
|
-
}
|
|
123
|
-
return this.stateStore.getState();
|
|
124
|
-
}
|
|
125
|
-
setState(mutation) {
|
|
126
|
-
if (!this.stateStore) {
|
|
127
|
-
this.stateStore = new ServiceStateStore(mutation);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
this.stateStore.setState(mutation);
|
|
131
|
-
}
|
|
132
|
-
on(event, handler) {
|
|
133
|
-
return this.eventBus.on(event, handler);
|
|
134
|
-
}
|
|
135
|
-
emit(event, payload) {
|
|
136
|
-
this.eventBus.emit(event, payload);
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
var ServiceProxy = class {
|
|
140
|
-
constructor(definition, adapter, endpoint) {
|
|
141
|
-
this.definition = definition;
|
|
142
|
-
this.adapter = adapter;
|
|
143
|
-
this.endpoint = endpoint;
|
|
144
|
-
this.id = definition.id;
|
|
145
|
-
this.name = definition.name;
|
|
146
|
-
this.version = definition.version;
|
|
147
|
-
this.stateCache = definition.state?.initial || {};
|
|
148
|
-
}
|
|
149
|
-
definition;
|
|
150
|
-
adapter;
|
|
151
|
-
endpoint;
|
|
152
|
-
id;
|
|
153
|
-
name;
|
|
154
|
-
version;
|
|
155
|
-
stateCache;
|
|
156
|
-
eventHandlers = /* @__PURE__ */ new Map();
|
|
157
|
-
getDefinition() {
|
|
158
|
-
return this.definition;
|
|
159
|
-
}
|
|
160
|
-
async start() {
|
|
161
|
-
}
|
|
162
|
-
async stop() {
|
|
163
|
-
}
|
|
164
|
-
async call(op, input, ctx = {}) {
|
|
165
|
-
if (!this.adapter.send) {
|
|
166
|
-
throw new Error(`[ServiceProxy:${this.name}] Adapter does not support send().`);
|
|
167
|
-
}
|
|
168
|
-
const envelope = {
|
|
169
|
-
id: `req-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
170
|
-
type: "request",
|
|
171
|
-
operation: op,
|
|
172
|
-
payload: input,
|
|
173
|
-
timestamp: Date.now()
|
|
174
|
-
};
|
|
175
|
-
const response = await this.adapter.send(this.endpoint, envelope);
|
|
176
|
-
if (response.error) {
|
|
177
|
-
throw new Error(`[ServiceProxy:${this.name}] Remote error: ${response.error}`);
|
|
178
|
-
}
|
|
179
|
-
return response.payload;
|
|
180
|
-
}
|
|
181
|
-
getState() {
|
|
182
|
-
return Object.freeze({ ...this.stateCache });
|
|
183
|
-
}
|
|
184
|
-
setState(mutation) {
|
|
185
|
-
this.stateCache = { ...this.stateCache, ...mutation };
|
|
186
|
-
}
|
|
187
|
-
on(event, handler) {
|
|
188
|
-
if (!this.eventHandlers.has(event)) {
|
|
189
|
-
this.eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
190
|
-
}
|
|
191
|
-
const handlers = this.eventHandlers.get(event);
|
|
192
|
-
handlers.add(handler);
|
|
193
|
-
return () => {
|
|
194
|
-
handlers.delete(handler);
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
emit(event, payload) {
|
|
198
|
-
const handlers = this.eventHandlers.get(event);
|
|
199
|
-
if (handlers) {
|
|
200
|
-
for (const handler of Array.from(handlers)) {
|
|
201
|
-
handler(payload);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
function createServiceDefinition(definition) {
|
|
207
|
-
return definition;
|
|
208
|
-
}
|
|
209
|
-
function createService(definition) {
|
|
210
|
-
return new ServiceInstance(definition);
|
|
211
|
-
}
|
|
212
|
-
function createServiceProxy(definition, adapter, endpoint) {
|
|
213
|
-
return new ServiceProxy(definition, adapter, endpoint);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export {
|
|
217
|
-
createServiceDefinition,
|
|
218
|
-
createService,
|
|
219
|
-
createServiceProxy
|
|
220
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/workspace/WorkspaceCanonical.ts
|
|
2
|
-
function formatCanonicalWorkspaceFolderName(appName, userName, workspaceName) {
|
|
3
|
-
const safeApp = appName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
|
|
4
|
-
const safeUser = userName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
|
|
5
|
-
const safeWs = workspaceName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
|
|
6
|
-
return `ultrst_${safeApp}_${safeUser}_${safeWs}`;
|
|
7
|
-
}
|
|
8
|
-
function sanitizeWorkspaceName(name) {
|
|
9
|
-
return name.replace(/[^a-zA-Z0-9-_\s]/g, "").trim();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
formatCanonicalWorkspaceFolderName,
|
|
14
|
-
sanitizeWorkspaceName
|
|
15
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IdempotencyManager
|
|
3
|
-
} from "./chunk-3EPY34R6.js";
|
|
4
|
-
|
|
5
|
-
// src/execution/BackendFacade.ts
|
|
6
|
-
var ExecutableBackendFacade = class {
|
|
7
|
-
constructor(name, idempotency) {
|
|
8
|
-
this.name = name;
|
|
9
|
-
this.idempotency = idempotency || new IdempotencyManager();
|
|
10
|
-
}
|
|
11
|
-
name;
|
|
12
|
-
services = /* @__PURE__ */ new Map();
|
|
13
|
-
idempotency;
|
|
14
|
-
registerService(service) {
|
|
15
|
-
this.services.set(service.name, service);
|
|
16
|
-
return this;
|
|
17
|
-
}
|
|
18
|
-
async executeCommand(command, context) {
|
|
19
|
-
const startTime = Date.now();
|
|
20
|
-
if (!context || !context.isWorkerContext) {
|
|
21
|
-
return {
|
|
22
|
-
correlationId: command.correlationId,
|
|
23
|
-
status: "FAILED",
|
|
24
|
-
error: "[BackendFacade] DIRECT_COMPONENT -> BACKEND_FACADE is strictly FORBIDDEN. Access allowed for WORKER_ONLY.",
|
|
25
|
-
executionTimestamp: startTime
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const runCore = async () => {
|
|
29
|
-
try {
|
|
30
|
-
const parts = command.type.split(".");
|
|
31
|
-
if (parts.length < 2) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`[BackendFacade] Invalid command type "${command.type}". Expected "service.operation".`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
const [serviceName, operationName] = parts;
|
|
37
|
-
const service = this.services.get(serviceName);
|
|
38
|
-
if (!service) {
|
|
39
|
-
throw new Error(`[BackendFacade] Service "${serviceName}" not registered.`);
|
|
40
|
-
}
|
|
41
|
-
const data = await service.execute(operationName, command.payload);
|
|
42
|
-
return {
|
|
43
|
-
correlationId: command.correlationId,
|
|
44
|
-
status: "COMPLETED",
|
|
45
|
-
data,
|
|
46
|
-
executionTimestamp: Date.now()
|
|
47
|
-
};
|
|
48
|
-
} catch (err) {
|
|
49
|
-
return {
|
|
50
|
-
correlationId: command.correlationId,
|
|
51
|
-
status: "FAILED",
|
|
52
|
-
error: err?.message || String(err),
|
|
53
|
-
executionTimestamp: Date.now()
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
if (command.idempotencyKey) {
|
|
58
|
-
return await this.idempotency.executeIdempotent(command.idempotencyKey, runCore);
|
|
59
|
-
}
|
|
60
|
-
return await runCore();
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// src/execution/WorkerExecutionBoundary.ts
|
|
65
|
-
var WorkerExecutionBoundary = class {
|
|
66
|
-
constructor(workerId, facade) {
|
|
67
|
-
this.workerId = workerId;
|
|
68
|
-
this.facade = facade;
|
|
69
|
-
}
|
|
70
|
-
workerId;
|
|
71
|
-
facade;
|
|
72
|
-
async processJob(command) {
|
|
73
|
-
const context = {
|
|
74
|
-
isWorkerContext: true,
|
|
75
|
-
workerId: this.workerId,
|
|
76
|
-
timestamp: Date.now()
|
|
77
|
-
};
|
|
78
|
-
return await this.facade.executeCommand(command, context);
|
|
79
|
-
}
|
|
80
|
-
static assertWorkerContext(context) {
|
|
81
|
-
if (!context || !context.isWorkerContext) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
"[WorkerExecutionBoundary] Violation: DIRECT_COMPONENT -> BACKEND_FACADE is forbidden. Only BullMQ Workers may execute backend commands."
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export {
|
|
90
|
-
ExecutableBackendFacade,
|
|
91
|
-
WorkerExecutionBoundary
|
|
92
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
// src/connectivity/JobScheduler.ts
|
|
2
|
-
var JobScheduler = class {
|
|
3
|
-
jobs = /* @__PURE__ */ new Map();
|
|
4
|
-
handlers = /* @__PURE__ */ new Map();
|
|
5
|
-
sequenceCounters = /* @__PURE__ */ new Map();
|
|
6
|
-
activeCount = 0;
|
|
7
|
-
maxConcurrency;
|
|
8
|
-
paused = false;
|
|
9
|
-
constructor(maxConcurrency = 5) {
|
|
10
|
-
this.maxConcurrency = maxConcurrency;
|
|
11
|
-
}
|
|
12
|
-
registerHandler(type, handler) {
|
|
13
|
-
this.handlers.set(type, handler);
|
|
14
|
-
return this;
|
|
15
|
-
}
|
|
16
|
-
submit(input) {
|
|
17
|
-
const id = input.id || `job-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
18
|
-
const streamKey = input.sequenceKey || "default";
|
|
19
|
-
const seq = (this.sequenceCounters.get(streamKey) ?? 0) + 1;
|
|
20
|
-
this.sequenceCounters.set(streamKey, seq);
|
|
21
|
-
const job = {
|
|
22
|
-
id,
|
|
23
|
-
type: input.type,
|
|
24
|
-
payload: input.payload,
|
|
25
|
-
priority: input.priority || "NORMAL",
|
|
26
|
-
sequence: seq,
|
|
27
|
-
sequenceKey: streamKey,
|
|
28
|
-
dependencies: input.dependencies || [],
|
|
29
|
-
sessionId: input.sessionId,
|
|
30
|
-
correlationId: input.correlationId,
|
|
31
|
-
state: "PENDING",
|
|
32
|
-
progress: 0,
|
|
33
|
-
createdAt: Date.now(),
|
|
34
|
-
updatedAt: Date.now()
|
|
35
|
-
};
|
|
36
|
-
this.jobs.set(id, job);
|
|
37
|
-
this.checkAndQueue(job);
|
|
38
|
-
this.drainQueue();
|
|
39
|
-
return job;
|
|
40
|
-
}
|
|
41
|
-
checkAndQueue(job) {
|
|
42
|
-
if (job.state !== "PENDING") return false;
|
|
43
|
-
const depsResolved = (job.dependencies || []).every((depId) => {
|
|
44
|
-
const dep = this.jobs.get(depId);
|
|
45
|
-
return dep && dep.state === "COMPLETED";
|
|
46
|
-
});
|
|
47
|
-
if (depsResolved) {
|
|
48
|
-
job.state = "QUEUED";
|
|
49
|
-
job.updatedAt = Date.now();
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
priorityWeight(priority) {
|
|
55
|
-
switch (priority) {
|
|
56
|
-
case "CRITICAL":
|
|
57
|
-
return 4;
|
|
58
|
-
case "HIGH":
|
|
59
|
-
return 3;
|
|
60
|
-
case "NORMAL":
|
|
61
|
-
return 2;
|
|
62
|
-
case "LOW":
|
|
63
|
-
return 1;
|
|
64
|
-
default:
|
|
65
|
-
return 2;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
async drainQueue() {
|
|
69
|
-
if (this.paused || this.activeCount >= this.maxConcurrency) return;
|
|
70
|
-
const queuedJobs = Array.from(this.jobs.values()).filter((j) => j.state === "QUEUED").sort((a, b) => this.priorityWeight(b.priority) - this.priorityWeight(a.priority) || (a.sequence || 0) - (b.sequence || 0));
|
|
71
|
-
for (const job of queuedJobs) {
|
|
72
|
-
if (this.activeCount >= this.maxConcurrency) break;
|
|
73
|
-
this.executeJob(job);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async executeJob(job) {
|
|
77
|
-
const handler = this.handlers.get(job.type);
|
|
78
|
-
if (!handler) {
|
|
79
|
-
job.state = "FAILED";
|
|
80
|
-
job.error = `[JobScheduler] No registered handler for job type "${job.type}".`;
|
|
81
|
-
job.updatedAt = Date.now();
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.activeCount++;
|
|
85
|
-
job.state = "RUNNING";
|
|
86
|
-
job.updatedAt = Date.now();
|
|
87
|
-
const progressCallback = (progress) => {
|
|
88
|
-
job.progress = Math.min(100, Math.max(0, progress));
|
|
89
|
-
job.updatedAt = Date.now();
|
|
90
|
-
};
|
|
91
|
-
try {
|
|
92
|
-
job.result = await handler(job, progressCallback);
|
|
93
|
-
job.state = "COMPLETED";
|
|
94
|
-
job.progress = 100;
|
|
95
|
-
} catch (err) {
|
|
96
|
-
job.state = "FAILED";
|
|
97
|
-
job.error = err?.message || String(err);
|
|
98
|
-
} finally {
|
|
99
|
-
job.updatedAt = Date.now();
|
|
100
|
-
this.activeCount--;
|
|
101
|
-
for (const pendingJob of this.jobs.values()) {
|
|
102
|
-
if (pendingJob.dependencies?.includes(job.id)) {
|
|
103
|
-
this.checkAndQueue(pendingJob);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
this.drainQueue();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
cancel(jobId) {
|
|
110
|
-
const job = this.jobs.get(jobId);
|
|
111
|
-
if (!job || job.state === "COMPLETED" || job.state === "FAILED") return false;
|
|
112
|
-
job.state = "CANCELLED";
|
|
113
|
-
job.updatedAt = Date.now();
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
pause() {
|
|
117
|
-
this.paused = true;
|
|
118
|
-
}
|
|
119
|
-
resume() {
|
|
120
|
-
this.paused = false;
|
|
121
|
-
this.drainQueue();
|
|
122
|
-
}
|
|
123
|
-
status(jobId) {
|
|
124
|
-
return this.jobs.get(jobId);
|
|
125
|
-
}
|
|
126
|
-
getAllJobs() {
|
|
127
|
-
return Array.from(this.jobs.values());
|
|
128
|
-
}
|
|
129
|
-
clear() {
|
|
130
|
-
this.jobs.clear();
|
|
131
|
-
this.sequenceCounters.clear();
|
|
132
|
-
this.activeCount = 0;
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export {
|
|
137
|
-
JobScheduler
|
|
138
|
-
};
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
JobScheduler
|
|
3
|
-
} from "./chunk-UPFKBBQI.js";
|
|
4
|
-
|
|
5
|
-
// src/execution/OperationComponent.ts
|
|
6
|
-
function createOperationComponent(name, handler) {
|
|
7
|
-
return {
|
|
8
|
-
name,
|
|
9
|
-
async execute(input) {
|
|
10
|
-
try {
|
|
11
|
-
return await handler(input);
|
|
12
|
-
} catch (err) {
|
|
13
|
-
throw new Error(
|
|
14
|
-
`[OperationComponent:${name}] Execution failure: ${err?.message || String(err)}`
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// src/execution/ServiceDispatcher.ts
|
|
22
|
-
var ServiceDispatcher = class {
|
|
23
|
-
constructor(name) {
|
|
24
|
-
this.name = name;
|
|
25
|
-
}
|
|
26
|
-
name;
|
|
27
|
-
operations = {};
|
|
28
|
-
registerOperation(opName, operation) {
|
|
29
|
-
this.operations[opName] = operation;
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
async execute(operationName, input) {
|
|
33
|
-
const op = this.operations[operationName];
|
|
34
|
-
if (!op) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
`[ServiceDispatcher:${this.name}] Operation "${operationName}" not found.`
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
return await op.execute(input);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// src/execution/DependencyOrdering.ts
|
|
44
|
-
var JobDependencyGraph = class {
|
|
45
|
-
scheduler;
|
|
46
|
-
constructor(maxConcurrency = 5) {
|
|
47
|
-
this.scheduler = new JobScheduler(maxConcurrency);
|
|
48
|
-
}
|
|
49
|
-
registerHandler(type, handler) {
|
|
50
|
-
this.scheduler.registerHandler(type, (job) => handler(job));
|
|
51
|
-
return this;
|
|
52
|
-
}
|
|
53
|
-
submitJob(type, payload, dependencies = [], idempotencyKey) {
|
|
54
|
-
return this.scheduler.submit({
|
|
55
|
-
type,
|
|
56
|
-
payload,
|
|
57
|
-
dependencies,
|
|
58
|
-
correlationId: idempotencyKey
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
getJob(jobId) {
|
|
62
|
-
return this.scheduler.status(jobId);
|
|
63
|
-
}
|
|
64
|
-
clear() {
|
|
65
|
-
this.scheduler.clear();
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// src/execution/ResultFlowBridge.ts
|
|
70
|
-
var ResultFlowBridge = class {
|
|
71
|
-
static formatStateUpdate(result) {
|
|
72
|
-
return {
|
|
73
|
-
type: "SKIPO_STATE_UPDATE",
|
|
74
|
-
correlationId: result.correlationId,
|
|
75
|
-
status: result.status,
|
|
76
|
-
data: result.data,
|
|
77
|
-
error: result.error,
|
|
78
|
-
timestamp: result.executionTimestamp
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export {
|
|
84
|
-
createOperationComponent,
|
|
85
|
-
ServiceDispatcher,
|
|
86
|
-
JobDependencyGraph,
|
|
87
|
-
ResultFlowBridge
|
|
88
|
-
};
|