@ariestools/aries-dapp-core 0.1.15 → 0.1.17
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/bin/dappServer.mjs +77 -290
- package/dist/node/DappActor.d.ts +27 -23
- package/dist/node/DappActor.d.ts.map +1 -1
- package/dist/node/actor/types.d.ts +14 -28
- package/dist/node/actor/types.d.ts.map +1 -1
- package/dist/node/bin/loadReducer.d.ts +3 -1
- package/dist/node/bin/loadReducer.d.ts.map +1 -1
- package/dist/node/boot/bootDappActors.d.ts +4 -3
- package/dist/node/boot/bootDappActors.d.ts.map +1 -1
- package/dist/node/consumer.mjs.map +2 -2
- package/dist/node/index.d.ts +1 -2
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.mjs +51 -264
- package/dist/node/index.mjs.map +4 -4
- package/dist/node/providers/DappBucketStore.d.ts +3 -1
- package/dist/node/providers/DappBucketStore.d.ts.map +1 -1
- package/dist/node/providers/capabilities.d.ts +3 -1
- package/dist/node/providers/capabilities.d.ts.map +1 -1
- package/dist/node/providers/hashBytes.d.ts +3 -1
- package/dist/node/providers/hashBytes.d.ts.map +1 -1
- package/dist/node/providers/joinKey.d.ts +6 -2
- package/dist/node/providers/joinKey.d.ts.map +1 -1
- package/dist/node/providers/types.d.ts +21 -7
- package/dist/node/providers/types.d.ts.map +1 -1
- package/dist/node/publication/constants.d.ts +24 -8
- package/dist/node/publication/constants.d.ts.map +1 -1
- package/dist/node/publication/gc.d.ts +6 -2
- package/dist/node/publication/gc.d.ts.map +1 -1
- package/dist/node/publication/incremental.d.ts +9 -3
- package/dist/node/publication/incremental.d.ts.map +1 -1
- package/dist/node/publication/releases.d.ts +12 -4
- package/dist/node/publication/releases.d.ts.map +1 -1
- package/dist/node/publication/status.d.ts +3 -1
- package/dist/node/publication/status.d.ts.map +1 -1
- package/dist/node/publication/statusPatch.d.ts +9 -3
- package/dist/node/publication/statusPatch.d.ts.map +1 -1
- package/dist/node/publication/types.d.ts +42 -14
- package/dist/node/publication/types.d.ts.map +1 -1
- package/dist/node/reducer/DappReducer.d.ts +9 -3
- package/dist/node/reducer/DappReducer.d.ts.map +1 -1
- package/examples/countFactsReducer.mjs +3 -1
- package/package.json +17 -9
- package/dist/node/actor/AbstractActor.d.ts +0 -53
- package/dist/node/actor/AbstractActor.d.ts.map +0 -1
package/dist/bin/dappServer.mjs
CHANGED
|
@@ -3,169 +3,17 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import { runActorsService } from "@ariestools/actor-cli";
|
|
6
7
|
import { DAPP_BACKINGS, DAPP_BUCKETS, isDappBackingKind, resolveBacking, startDappServer } from "@ariestools/aries-dapp-serve";
|
|
7
|
-
import {
|
|
8
|
+
import { createNodeProcessHost } from "@ariestools/cli-kit-node";
|
|
9
|
+
import { ConsoleLogger, assertEx, creatable } from "@ariestools/sdk";
|
|
10
|
+
import { PeriodicActor } from "@ariestools/actor";
|
|
8
11
|
import { DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
9
12
|
import { pathToFileURL } from "node:url";
|
|
10
|
-
//#region src/
|
|
11
|
-
function createDeferred$1() {
|
|
12
|
-
let resolve;
|
|
13
|
-
let reject;
|
|
14
|
-
const promise = new Promise((res, rej) => {
|
|
15
|
-
resolve = res;
|
|
16
|
-
reject = rej;
|
|
17
|
-
});
|
|
18
|
-
promise.catch(() => {});
|
|
19
|
-
return {
|
|
20
|
-
promise,
|
|
21
|
-
reject,
|
|
22
|
-
resolve
|
|
23
|
-
};
|
|
24
|
-
}
|
|
13
|
+
//#region src/providers/capabilities.ts
|
|
25
14
|
/**
|
|
26
|
-
|
|
27
|
-
* lifecycle from `AbstractCreatable`, plus non-overlapping interval timers and
|
|
28
|
-
* a readiness contract. It deliberately swaps the chain's
|
|
29
|
-
* `ProviderFactoryLocator`/`LocatorConfig` machinery for the small
|
|
30
|
-
* {@link DappProviderLocator} seam, so a dapp actor resolves providers by
|
|
31
|
-
* moniker without dragging the chain protocol config model in.
|
|
32
|
-
*
|
|
33
|
-
* The locator is process-wide: the daemon builds it once and passes the same
|
|
34
|
-
* instance to every actor via `params.locator` (see `bootDappActors`). When
|
|
35
|
-
* this graduates into a shared cli/actor toolkit — and, later, xl1-protocol —
|
|
36
|
-
* this base can re-adopt the real locator.
|
|
15
|
+
Thrown when a read-only capability wrapper receives a write.
|
|
37
16
|
*/
|
|
38
|
-
var AbstractActor = class extends AbstractCreatable {
|
|
39
|
-
_intervals = /* @__PURE__ */ new Map();
|
|
40
|
-
_timeouts = /* @__PURE__ */ new Map();
|
|
41
|
-
_abortController = new AbortController();
|
|
42
|
-
_idLogger;
|
|
43
|
-
_inFlight = /* @__PURE__ */ new Map();
|
|
44
|
-
_readyDeferred = createDeferred$1();
|
|
45
|
-
_readyError;
|
|
46
|
-
_readyState = "pending";
|
|
47
|
-
get logger() {
|
|
48
|
-
this._idLogger ??= new IdLogger(assertEx(this.context.logger, () => `Logger is required in context for actor ${this.name}.`), () => this.name);
|
|
49
|
-
return this._idLogger;
|
|
50
|
-
}
|
|
51
|
-
get readyError() {
|
|
52
|
-
return this._readyError;
|
|
53
|
-
}
|
|
54
|
-
get readyState() {
|
|
55
|
-
return this._readyState;
|
|
56
|
-
}
|
|
57
|
-
get context() {
|
|
58
|
-
return this.locator.context;
|
|
59
|
-
}
|
|
60
|
-
get locator() {
|
|
61
|
-
return this.params.locator;
|
|
62
|
-
}
|
|
63
|
-
/** Abort signal cancelled when the actor stops (or is replaced on restart). */
|
|
64
|
-
get signal() {
|
|
65
|
-
return this._abortController.signal;
|
|
66
|
-
}
|
|
67
|
-
static async paramsHandler(params) {
|
|
68
|
-
const inParams = params ?? {};
|
|
69
|
-
const baseParams = await super.paramsHandler({
|
|
70
|
-
...inParams,
|
|
71
|
-
name: inParams.name ?? "UnknownActor"
|
|
72
|
-
});
|
|
73
|
-
const locator = assertEx(inParams.locator, () => `params.locator is required for actor ${String(baseParams.name)}.`);
|
|
74
|
-
return {
|
|
75
|
-
...baseParams,
|
|
76
|
-
locator
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
/** Override to prove the actor can do useful work. Default: no-op. */
|
|
80
|
-
async readyHandler() {}
|
|
81
|
-
/**
|
|
82
|
-
* Register a recurring task. The first invocation fires after `dueTimeMs`
|
|
83
|
-
* (the documented first-run delay); subsequent invocations fire every
|
|
84
|
-
* `periodMs` while the actor is `started`. A run is skipped if the previous
|
|
85
|
-
* one is still in flight, so a slow pass can never stack on top of itself.
|
|
86
|
-
* Must be called from `startHandler` (guards on `starting` status).
|
|
87
|
-
*/
|
|
88
|
-
registerTimer(timerName, callback, dueTimeMs, periodMs) {
|
|
89
|
-
if (this.status !== "starting") {
|
|
90
|
-
this.logger.warn(`Cannot register timer '${timerName}' because actor is not starting.`);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const tick = () => {
|
|
94
|
-
if (this.status !== "started") return;
|
|
95
|
-
if (this._inFlight.has(timerName)) {
|
|
96
|
-
this.logger.warn(`Skipping timer '${this.name}:${timerName}' because the previous run is still in flight.`);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const run = (async () => {
|
|
100
|
-
const startTime = Date.now();
|
|
101
|
-
try {
|
|
102
|
-
await callback();
|
|
103
|
-
} catch (error) {
|
|
104
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
105
|
-
this.logger.error(`Error in timer '${this.name}:${timerName}': ${err.message}`);
|
|
106
|
-
} finally {
|
|
107
|
-
const duration = Date.now() - startTime;
|
|
108
|
-
if (duration > periodMs) this.logger.warn(`Timer '${this.name}:${timerName}' took ${duration}ms, longer than its ${periodMs}ms period.`);
|
|
109
|
-
}
|
|
110
|
-
})();
|
|
111
|
-
this._inFlight.set(timerName, run.finally(() => {
|
|
112
|
-
this._inFlight.delete(timerName);
|
|
113
|
-
}));
|
|
114
|
-
};
|
|
115
|
-
const timeoutId = setTimeout(() => {
|
|
116
|
-
if (this.status !== "started") return;
|
|
117
|
-
this._intervals.set(timerName, setInterval(tick, periodMs));
|
|
118
|
-
tick();
|
|
119
|
-
}, dueTimeMs);
|
|
120
|
-
this._timeouts.set(timerName, timeoutId);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Run the warm-pass once. The standard boot path invokes this after
|
|
124
|
-
* `start()` so readiness either resolves or rejects.
|
|
125
|
-
*/
|
|
126
|
-
async runReadyHandler() {
|
|
127
|
-
if (this._readyState !== "pending") return;
|
|
128
|
-
try {
|
|
129
|
-
await this.readyHandler();
|
|
130
|
-
this._readyState = "ready";
|
|
131
|
-
this._readyDeferred.resolve();
|
|
132
|
-
} catch (error) {
|
|
133
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
134
|
-
this._readyState = "failed";
|
|
135
|
-
this._readyError = err;
|
|
136
|
-
this._readyDeferred.reject(err);
|
|
137
|
-
throw err;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
async startHandler() {
|
|
141
|
-
if (this._abortController.signal.aborted) this._abortController = new AbortController();
|
|
142
|
-
await super.startHandler();
|
|
143
|
-
}
|
|
144
|
-
async stopHandler() {
|
|
145
|
-
await super.stopHandler();
|
|
146
|
-
this._abortController.abort();
|
|
147
|
-
for (const timeoutRef of this._timeouts.values()) clearTimeout(timeoutRef);
|
|
148
|
-
this._timeouts.clear();
|
|
149
|
-
for (const intervalRef of this._intervals.values()) clearInterval(intervalRef);
|
|
150
|
-
this._intervals.clear();
|
|
151
|
-
const inFlight = [...this._inFlight.values()];
|
|
152
|
-
this._inFlight.clear();
|
|
153
|
-
const timeoutMs = this.params.shutdownTimeoutMs;
|
|
154
|
-
if (timeoutMs === void 0) {
|
|
155
|
-
await Promise.allSettled(inFlight);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
await Promise.race([Promise.allSettled(inFlight), new Promise((resolve) => {
|
|
159
|
-
setTimeout(resolve, timeoutMs);
|
|
160
|
-
})]);
|
|
161
|
-
}
|
|
162
|
-
async whenReady() {
|
|
163
|
-
await this._readyDeferred.promise;
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
//#endregion
|
|
167
|
-
//#region src/providers/capabilities.ts
|
|
168
|
-
/** Thrown when a read-only capability wrapper receives a write. */
|
|
169
17
|
var ReadOnlyStoreError = class extends Error {
|
|
170
18
|
name = "ReadOnlyStoreError";
|
|
171
19
|
constructor(role, operation = "put") {
|
|
@@ -222,10 +70,14 @@ const DappStateStoreMoniker = "DappStateStore";
|
|
|
222
70
|
const DappIndexStoreMoniker = "DappIndexStore";
|
|
223
71
|
//#endregion
|
|
224
72
|
//#region src/publication/constants.ts
|
|
225
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
Well-known relative keys published by the coherent generation protocol.
|
|
75
|
+
*/
|
|
226
76
|
const HEAD_KEY = "head.json";
|
|
227
77
|
const STATUS_KEY = "status.json";
|
|
228
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
CDN caching: mutable head and status objects that must revalidate.
|
|
80
|
+
*/
|
|
229
81
|
const CACHE_CONTROL_REVALIDATE = "public, max-age=0, must-revalidate";
|
|
230
82
|
const INDEXER_STATUS_SCHEMA = "network.aries.dapp.indexer.status";
|
|
231
83
|
//#endregion
|
|
@@ -290,7 +142,9 @@ const PROGRESS_KEYS = [
|
|
|
290
142
|
"generation",
|
|
291
143
|
"generationRoot"
|
|
292
144
|
];
|
|
293
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
Carry forward durable progress fields from a prior status object.
|
|
147
|
+
*/
|
|
294
148
|
function priorProgressFields(prior) {
|
|
295
149
|
if (prior === void 0) return {};
|
|
296
150
|
return {
|
|
@@ -298,7 +152,9 @@ function priorProgressFields(prior) {
|
|
|
298
152
|
...prior.lastSuccessAt !== void 0 && { lastSuccessAt: prior.lastSuccessAt }
|
|
299
153
|
};
|
|
300
154
|
}
|
|
301
|
-
/**
|
|
155
|
+
/**
|
|
156
|
+
Build success status fields from reduce progress, falling back to prior.
|
|
157
|
+
*/
|
|
302
158
|
function successStatusFields(progress, prior, now) {
|
|
303
159
|
const fromProgress = progress === void 0 ? {} : pickDefined(progress, PROGRESS_KEYS);
|
|
304
160
|
const generation = progress?.generation ?? prior?.generation;
|
|
@@ -313,7 +169,9 @@ function successStatusFields(progress, prior, now) {
|
|
|
313
169
|
...prior?.lastErrorAt !== void 0 && { lastErrorAt: prior.lastErrorAt }
|
|
314
170
|
};
|
|
315
171
|
}
|
|
316
|
-
/**
|
|
172
|
+
/**
|
|
173
|
+
Build failure status fields while preserving prior checkpoint progress.
|
|
174
|
+
*/
|
|
317
175
|
function failureStatusFields(prior, consecutiveFailures, error, now) {
|
|
318
176
|
return {
|
|
319
177
|
consecutiveFailures,
|
|
@@ -323,7 +181,7 @@ function failureStatusFields(prior, consecutiveFailures, error, now) {
|
|
|
323
181
|
};
|
|
324
182
|
}
|
|
325
183
|
//#endregion
|
|
326
|
-
//#region \0@oxc-project+runtime@0.
|
|
184
|
+
//#region \0@oxc-project+runtime@0.143.0/helpers/esm/decorate.js
|
|
327
185
|
function __decorate(decorators, target, key, desc) {
|
|
328
186
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
329
187
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -333,22 +191,6 @@ function __decorate(decorators, target, key, desc) {
|
|
|
333
191
|
//#endregion
|
|
334
192
|
//#region src/DappActor.ts
|
|
335
193
|
const DEFAULT_REDUCE_INTERVAL_MS = 5e3;
|
|
336
|
-
const DEFAULT_FIRST_RUN_DELAY_MS = 2e3;
|
|
337
|
-
const REDUCE_TIMER = "DappReduce";
|
|
338
|
-
function createDeferred() {
|
|
339
|
-
let resolve;
|
|
340
|
-
let reject;
|
|
341
|
-
const promise = new Promise((res, rej) => {
|
|
342
|
-
resolve = res;
|
|
343
|
-
reject = rej;
|
|
344
|
-
});
|
|
345
|
-
promise.catch(() => {});
|
|
346
|
-
return {
|
|
347
|
-
promise,
|
|
348
|
-
reject,
|
|
349
|
-
resolve
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
194
|
function withDefaultGenerationRoot(result) {
|
|
353
195
|
if (result === void 0) return;
|
|
354
196
|
if (result.generation === void 0 || result.generationRoot !== void 0) return result;
|
|
@@ -357,7 +199,7 @@ function withDefaultGenerationRoot(result) {
|
|
|
357
199
|
generationRoot: HEAD_KEY
|
|
358
200
|
};
|
|
359
201
|
}
|
|
360
|
-
let DappActor = class DappActor extends
|
|
202
|
+
let DappActor = class DappActor extends PeriodicActor {
|
|
361
203
|
static dependencies = [
|
|
362
204
|
DappDataStoreMoniker,
|
|
363
205
|
DappStateStoreMoniker,
|
|
@@ -366,12 +208,17 @@ let DappActor = class DappActor extends AbstractActor {
|
|
|
366
208
|
_data;
|
|
367
209
|
_index;
|
|
368
210
|
_state;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
211
|
+
/**
|
|
212
|
+
Dapp actors require a logger in the locator context (see {@link DappContext}).
|
|
213
|
+
*/
|
|
214
|
+
get logger() {
|
|
215
|
+
return assertEx(super.logger, () => `Logger is required in context for actor ${this.name}.`);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
Reduce cadence: `reduceIntervalMs` names the interval in dapp configs.
|
|
219
|
+
*/
|
|
220
|
+
get intervalMs() {
|
|
221
|
+
return this.params.reduceIntervalMs ?? DEFAULT_REDUCE_INTERVAL_MS;
|
|
375
222
|
}
|
|
376
223
|
async createHandler() {
|
|
377
224
|
await super.createHandler();
|
|
@@ -380,21 +227,27 @@ let DappActor = class DappActor extends AbstractActor {
|
|
|
380
227
|
this._state = await this.locator.getInstance(DappStateStoreMoniker);
|
|
381
228
|
this._index = await this.locator.getInstance(DappIndexStoreMoniker);
|
|
382
229
|
}
|
|
383
|
-
async readyHandler() {
|
|
384
|
-
await this._firstPass.promise;
|
|
385
|
-
}
|
|
386
230
|
async startHandler() {
|
|
387
231
|
await super.startHandler();
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
232
|
+
this.logger.info(`DappActor started: reducer '${this.params.reducer.name}' every ${this.intervalMs}ms (first run in ${this.firstRunDelayMs}ms)`);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
Failure side-channel: publish durable failure status (count already incremented).
|
|
236
|
+
*/
|
|
237
|
+
async onPassError(error) {
|
|
238
|
+
await this.safePublishStatus(void 0, error);
|
|
394
239
|
}
|
|
395
|
-
async
|
|
396
|
-
|
|
397
|
-
|
|
240
|
+
async runPass({ signal }) {
|
|
241
|
+
const result = await this.params.reducer.reduce({
|
|
242
|
+
data: this._data,
|
|
243
|
+
index: this._index,
|
|
244
|
+
logger: this.logger,
|
|
245
|
+
signal,
|
|
246
|
+
state: this._state
|
|
247
|
+
});
|
|
248
|
+
if (signal.aborted) return;
|
|
249
|
+
const progress = withDefaultGenerationRoot(result === void 0 ? void 0 : result);
|
|
250
|
+
await this.safePublishStatus(progress);
|
|
398
251
|
}
|
|
399
252
|
async publishStatusFromProgress(progress, error) {
|
|
400
253
|
if (this.params.publishStatus === false) return;
|
|
@@ -405,40 +258,9 @@ let DappActor = class DappActor extends AbstractActor {
|
|
|
405
258
|
prior = void 0;
|
|
406
259
|
}
|
|
407
260
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
408
|
-
const fields = error === void 0 ? successStatusFields(progress, prior, now) : failureStatusFields(prior, this.
|
|
261
|
+
const fields = error === void 0 ? successStatusFields(progress, prior, now) : failureStatusFields(prior, this.consecutiveFailures, error, now);
|
|
409
262
|
await writeIndexerStatus(this._state, fields);
|
|
410
263
|
}
|
|
411
|
-
async runReducePass() {
|
|
412
|
-
const signal = this.signal;
|
|
413
|
-
try {
|
|
414
|
-
const result = await this.params.reducer.reduce({
|
|
415
|
-
data: this._data,
|
|
416
|
-
index: this._index,
|
|
417
|
-
logger: this.logger,
|
|
418
|
-
signal,
|
|
419
|
-
state: this._state
|
|
420
|
-
});
|
|
421
|
-
if (signal.aborted) return;
|
|
422
|
-
const progress = withDefaultGenerationRoot(result === void 0 ? void 0 : result);
|
|
423
|
-
this._consecutiveFailures = 0;
|
|
424
|
-
await this.safePublishStatus(progress);
|
|
425
|
-
this.settleFirstPass();
|
|
426
|
-
} catch (error) {
|
|
427
|
-
if (signal.aborted) return;
|
|
428
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
429
|
-
this._consecutiveFailures += 1;
|
|
430
|
-
await this.safePublishStatus(void 0, err);
|
|
431
|
-
this.settleFirstPass(err);
|
|
432
|
-
this.logger.error(`Error in reduce pass for '${this.params.reducer.name}': ${err.message}`);
|
|
433
|
-
const max = this.params.maxConsecutiveFailures;
|
|
434
|
-
if (max !== void 0 && this._consecutiveFailures >= max) {
|
|
435
|
-
this.logger.error(`Reducer '${this.params.reducer.name}' failed ${this._consecutiveFailures} consecutive times; stopping actor`);
|
|
436
|
-
setTimeout(() => {
|
|
437
|
-
this.stop();
|
|
438
|
-
}, 0);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
264
|
async safePublishStatus(progress, error) {
|
|
443
265
|
try {
|
|
444
266
|
await this.publishStatusFromProgress(progress, error);
|
|
@@ -446,50 +268,9 @@ let DappActor = class DappActor extends AbstractActor {
|
|
|
446
268
|
this.logger.error(`Failed to publish indexer status: ${String(statusError)}`);
|
|
447
269
|
}
|
|
448
270
|
}
|
|
449
|
-
settleFirstPass(error) {
|
|
450
|
-
if (this._firstPassSettled) return;
|
|
451
|
-
this._firstPassSettled = true;
|
|
452
|
-
if (error === void 0) this._firstPass.resolve();
|
|
453
|
-
else this._firstPass.reject(error);
|
|
454
|
-
}
|
|
455
271
|
};
|
|
456
272
|
DappActor = __decorate([creatable()], DappActor);
|
|
457
273
|
//#endregion
|
|
458
|
-
//#region src/boot/bootDappActors.ts
|
|
459
|
-
/**
|
|
460
|
-
* Creates and starts one {@link DappActor} per spec, all sharing the single
|
|
461
|
-
* process-wide locator. On partial failure, actors already started are stopped
|
|
462
|
-
* before the error is rethrown. Returns them so the caller can stop them on
|
|
463
|
-
* shutdown.
|
|
464
|
-
*/
|
|
465
|
-
async function bootDappActors(locator, specs) {
|
|
466
|
-
const actors = [];
|
|
467
|
-
try {
|
|
468
|
-
for (const spec of specs) {
|
|
469
|
-
const params = {
|
|
470
|
-
locator,
|
|
471
|
-
name: spec.name,
|
|
472
|
-
reducer: spec.reducer,
|
|
473
|
-
...spec.reduceIntervalMs !== void 0 && { reduceIntervalMs: spec.reduceIntervalMs },
|
|
474
|
-
...spec.firstRunDelayMs !== void 0 && { firstRunDelayMs: spec.firstRunDelayMs },
|
|
475
|
-
...spec.maxConsecutiveFailures !== void 0 && { maxConsecutiveFailures: spec.maxConsecutiveFailures },
|
|
476
|
-
...spec.publishStatus !== void 0 && { publishStatus: spec.publishStatus },
|
|
477
|
-
...spec.shutdownTimeoutMs !== void 0 && { shutdownTimeoutMs: spec.shutdownTimeoutMs }
|
|
478
|
-
};
|
|
479
|
-
const actor = await DappActor.create(params);
|
|
480
|
-
await actor.start();
|
|
481
|
-
actors.push(actor);
|
|
482
|
-
if (spec.runReady !== false) await actor.runReadyHandler();
|
|
483
|
-
}
|
|
484
|
-
return actors;
|
|
485
|
-
} catch (error) {
|
|
486
|
-
for (const actor of [...actors].reverse()) try {
|
|
487
|
-
await actor.stop();
|
|
488
|
-
} catch {}
|
|
489
|
-
throw error;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
//#endregion
|
|
493
274
|
//#region src/providers/errors.ts
|
|
494
275
|
/**
|
|
495
276
|
* Thrown when a conditional put fails (object already exists under
|
|
@@ -517,7 +298,9 @@ function joinKey(prefix, relativeKey) {
|
|
|
517
298
|
if (cleanKey.length === 0) return cleanPrefix;
|
|
518
299
|
return `${cleanPrefix}/${cleanKey}`;
|
|
519
300
|
}
|
|
520
|
-
/**
|
|
301
|
+
/**
|
|
302
|
+
Strip a role prefix from a physical key, returning the relative key.
|
|
303
|
+
*/
|
|
521
304
|
function stripPrefix(prefix, physicalKey) {
|
|
522
305
|
const cleanPrefix = prefix.replaceAll(/^\/+|\/+$/g, "");
|
|
523
306
|
if (cleanPrefix.length === 0) return physicalKey;
|
|
@@ -526,7 +309,9 @@ function stripPrefix(prefix, physicalKey) {
|
|
|
526
309
|
if (physicalKey.startsWith(withSlash)) return physicalKey.slice(withSlash.length);
|
|
527
310
|
return physicalKey;
|
|
528
311
|
}
|
|
529
|
-
/**
|
|
312
|
+
/**
|
|
313
|
+
Normalize an optional public base URL (no trailing slash).
|
|
314
|
+
*/
|
|
530
315
|
function normalizePublicBaseUrl(url) {
|
|
531
316
|
if (url === void 0 || url.length === 0) return void 0;
|
|
532
317
|
return url.replace(/\/+$/, "");
|
|
@@ -942,28 +727,30 @@ async function main() {
|
|
|
942
727
|
});
|
|
943
728
|
process.env.DAPP_PUBLICATION_SAFETY ??= "unfenced";
|
|
944
729
|
process.env.DAPP_ENDPOINT ??= server.baseUrl;
|
|
945
|
-
const actors = await
|
|
730
|
+
const actors = [await DappActor.create({
|
|
731
|
+
firstRunDelayMs: FIRST_RUN_DELAY_MS,
|
|
732
|
+
locator,
|
|
946
733
|
name: "DappActor",
|
|
947
|
-
reducer,
|
|
734
|
+
publishStatus: reducer.name !== "noop",
|
|
948
735
|
reduceIntervalMs: REDUCE_INTERVAL_MS,
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
}]);
|
|
736
|
+
reducer
|
|
737
|
+
})];
|
|
952
738
|
const versionSuffix = reducer.version === void 0 ? "" : `@${reducer.version}`;
|
|
953
739
|
const reducerLine = REDUCER_SPEC === void 0 ? "\nreducer: noop (pass DAPP_REDUCER / --reducer for real logic)" : `\nreducer: ${REDUCER_SPEC}`;
|
|
954
|
-
|
|
955
|
-
const
|
|
956
|
-
|
|
740
|
+
const banner = `[dev-only] dapp server listening at ${server.baseUrl}\n` + DAPP_BUCKETS.map((bucket) => ` /${bucket.padEnd(5)} ${server.baseUrl}/${bucket}`).join("\n") + `\nbacking: ${backing.description}\nactors: ${actors.length} (reducer '${reducer.name}'${versionSuffix}, every ${REDUCE_INTERVAL_MS}ms)` + reducerLine;
|
|
741
|
+
const processHost = createNodeProcessHost({ signals: ["SIGINT", "SIGTERM"] });
|
|
742
|
+
try {
|
|
743
|
+
await runActorsService(processHost, {
|
|
744
|
+
actors,
|
|
745
|
+
onReady: () => {
|
|
746
|
+
console.log(banner);
|
|
747
|
+
},
|
|
748
|
+
supervisor: "parallel"
|
|
749
|
+
});
|
|
750
|
+
} finally {
|
|
957
751
|
locator.destroy();
|
|
958
752
|
await server.close();
|
|
959
|
-
|
|
960
|
-
};
|
|
961
|
-
process.on("SIGINT", () => {
|
|
962
|
-
shutdown();
|
|
963
|
-
});
|
|
964
|
-
process.on("SIGTERM", () => {
|
|
965
|
-
shutdown();
|
|
966
|
-
});
|
|
753
|
+
}
|
|
967
754
|
}
|
|
968
755
|
main().catch((error) => {
|
|
969
756
|
console.error(error);
|
package/dist/node/DappActor.d.ts
CHANGED
|
@@ -1,47 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { PeriodicActorParams, PeriodicPassContext } from '@ariestools/actor';
|
|
2
|
+
import { PeriodicActor } from '@ariestools/actor';
|
|
3
|
+
import type { Logger } from '@ariestools/sdk';
|
|
4
|
+
import type { DappProviderLocator } from './actor/types.ts';
|
|
3
5
|
import type { DappObjectReader, DappObjectWriter } from './providers/capabilities.ts';
|
|
4
6
|
import type { DappReducer } from './reducer/DappReducer.ts';
|
|
5
|
-
export interface DappActorParams extends
|
|
6
|
-
/** Delay before the first reduce pass. Defaults to 2000ms. */
|
|
7
|
-
firstRunDelayMs?: number;
|
|
8
|
-
/**
|
|
9
|
-
* When set, after this many consecutive reduce failures the actor stops so a
|
|
10
|
-
* supervisor can restart the process.
|
|
11
|
-
*/
|
|
12
|
-
maxConsecutiveFailures?: number;
|
|
7
|
+
export interface DappActorParams extends PeriodicActorParams<DappProviderLocator> {
|
|
13
8
|
/**
|
|
14
9
|
* When true (default), publish durable indexer status to the state store
|
|
15
10
|
* after each reduce pass (success or failure).
|
|
16
11
|
*/
|
|
17
12
|
publishStatus?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
Period between reduce passes. Defaults to 5000ms.
|
|
15
|
+
*/
|
|
18
16
|
reduceIntervalMs?: number;
|
|
19
17
|
reducer: DappReducer;
|
|
20
18
|
}
|
|
21
19
|
/**
|
|
22
20
|
* The stock dapp actor: resolves the three bucket stores from the shared
|
|
23
21
|
* locator, then drives its reducer on an interval to keep `state` and `index`
|
|
24
|
-
* derived from authoritative input.
|
|
25
|
-
*
|
|
26
|
-
* the
|
|
22
|
+
* derived from authoritative input. The loop policies (first-pass-gated
|
|
23
|
+
* readiness, non-overlap, consecutive-failure self-stop) come from
|
|
24
|
+
* `PeriodicActor`; this class contributes the reduce pass and durable status
|
|
25
|
+
* publication. Multiple actors (each with its own reducer) can share one
|
|
26
|
+
* locator; this is the default single-reducer instance the local daemon boots.
|
|
27
27
|
*/
|
|
28
|
-
export declare class DappActor extends
|
|
28
|
+
export declare class DappActor extends PeriodicActor<DappActorParams> {
|
|
29
29
|
static readonly dependencies: readonly ["DappDataStore", "DappStateStore", "DappIndexStore"];
|
|
30
30
|
protected _data: DappObjectReader;
|
|
31
31
|
protected _index: DappObjectWriter;
|
|
32
32
|
protected _state: DappObjectWriter;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
/**
|
|
34
|
+
Dapp actors require a logger in the locator context (see {@link DappContext}).
|
|
35
|
+
*/
|
|
36
|
+
get logger(): Logger;
|
|
37
|
+
/**
|
|
38
|
+
Reduce cadence: `reduceIntervalMs` names the interval in dapp configs.
|
|
39
|
+
*/
|
|
40
|
+
protected get intervalMs(): number;
|
|
38
41
|
createHandler(): Promise<void>;
|
|
39
|
-
readyHandler(): Promise<void>;
|
|
40
42
|
startHandler(): Promise<void>;
|
|
41
|
-
|
|
43
|
+
/**
|
|
44
|
+
Failure side-channel: publish durable failure status (count already incremented).
|
|
45
|
+
*/
|
|
46
|
+
protected onPassError(error: Error): Promise<void>;
|
|
47
|
+
protected runPass({ signal }: PeriodicPassContext): Promise<void>;
|
|
42
48
|
private publishStatusFromProgress;
|
|
43
|
-
private runReducePass;
|
|
44
49
|
private safePublishStatus;
|
|
45
|
-
private settleFirstPass;
|
|
46
50
|
}
|
|
47
51
|
//# sourceMappingURL=DappActor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DappActor.d.ts","sourceRoot":"","sources":["../../src/DappActor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DappActor.d.ts","sourceRoot":"","sources":["../../src/DappActor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAG7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AASrF,OAAO,KAAK,EAAsB,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE/E,MAAM,WAAW,eAAgB,SAAQ,mBAAmB,CAAC,mBAAmB,CAAC;IAC/E;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;MAEE;IACF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,EAAE,WAAW,CAAA;CACrB;AAYD;;;;;;;;GAQG;AACH,qBACa,SAAU,SAAQ,aAAa,CAAC,eAAe,CAAC;IAC3D,MAAM,CAAC,QAAQ,CAAC,YAAY,iEAIlB;IAEV,SAAS,CAAC,KAAK,EAAG,gBAAgB,CAAA;IAClC,SAAS,CAAC,MAAM,EAAG,gBAAgB,CAAA;IACnC,SAAS,CAAC,MAAM,EAAG,gBAAgB,CAAA;IAEnC;;MAEE;IACF,IAAa,MAAM,IAAI,MAAM,CAE5B;IAED;;MAEE;IACF,cAAuB,UAAU,IAAI,MAAM,CAE1C;IAEc,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5C;;MAEE;cACuB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;cAIxC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;YAclE,yBAAyB;YAkBzB,iBAAiB;CAUhC"}
|
|
@@ -1,37 +1,23 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { ActorContext, InstanceLocator, OwnedLocator, RegistrableLocator } from '@ariestools/actor-model';
|
|
2
|
+
import type { Logger } from '@ariestools/sdk';
|
|
3
|
+
/**
|
|
4
|
+
Identifier a provider is registered and resolved under in the locator.
|
|
5
|
+
*/
|
|
3
6
|
export type DappMoniker = string;
|
|
4
|
-
export type ReadyState = 'pending' | 'ready' | 'failed';
|
|
5
7
|
/**
|
|
6
|
-
* The shared context carried by the process-wide locator.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* The shared context carried by the process-wide locator. A `logger` is
|
|
9
|
+
* required for dapp actors; telemetry providers and a status reporter are
|
|
10
|
+
* available via the inherited {@link ActorContext} fields when wired.
|
|
9
11
|
*/
|
|
10
|
-
export interface DappContext {
|
|
12
|
+
export interface DappContext extends ActorContext {
|
|
11
13
|
logger: Logger;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* shares the same instance across every actor (see `bootDappActors`).
|
|
16
|
+
* The dapp locator contract: the actor-kit locator seam carrying the dapp
|
|
17
|
+
* context, with registration, ownership, and a `has` probe. The daemon builds
|
|
18
|
+
* one and shares the same instance across every actor (see `bootDappActors`).
|
|
18
19
|
*/
|
|
19
|
-
export
|
|
20
|
-
readonly context: DappContext;
|
|
21
|
-
/** Release owned resources (e.g. an S3 client constructed by the locator). */
|
|
22
|
-
destroy(): void;
|
|
23
|
-
getInstance<T>(moniker: DappMoniker): Promise<T>;
|
|
20
|
+
export type DappProviderLocator = InstanceLocator<DappContext> & OwnedLocator & RegistrableLocator & {
|
|
24
21
|
has(moniker: DappMoniker): boolean;
|
|
25
|
-
|
|
26
|
-
tryGetInstance<T>(moniker: DappMoniker): Promise<T | undefined>;
|
|
27
|
-
}
|
|
28
|
-
/** Base params every dapp actor takes: the shared, process-wide locator. */
|
|
29
|
-
export interface ActorParams extends CreatableParams {
|
|
30
|
-
locator: DappProviderLocator;
|
|
31
|
-
/**
|
|
32
|
-
* Max time to wait for in-flight timer work on stop after aborting the
|
|
33
|
-
* signal. When omitted, stop waits until in-flight work settles.
|
|
34
|
-
*/
|
|
35
|
-
shutdownTimeoutMs?: number;
|
|
36
|
-
}
|
|
22
|
+
};
|
|
37
23
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/actor/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/actor/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,kBAAkB,EACnB,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE7C;;EAEE;AACF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAA;AAEhC;;;;GAIG;AACH,MAAM,WAAW,WAAY,SAAQ,YAAY;IAC/C,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,eAAe,CAAC,WAAW,CAAC,GAAG,YAAY,GAAG,kBAAkB,GAAG;IACnG,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAA;CACnC,CAAA"}
|
|
@@ -5,7 +5,9 @@ export interface LoadReducerOptions {
|
|
|
5
5
|
* Defaults to trying `reducer`, then `default`.
|
|
6
6
|
*/
|
|
7
7
|
exportName?: string;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
Absolute or relative path to a `.mjs` file, or a resolvable package export.
|
|
10
|
+
*/
|
|
9
11
|
spec: string;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadReducer.d.ts","sourceRoot":"","sources":["../../../src/bin/loadReducer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAI5D,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB
|
|
1
|
+
{"version":3,"file":"loadReducer.d.ts","sourceRoot":"","sources":["../../../src/bin/loadReducer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAI5D,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;MAEE;IACF,IAAI,EAAE,MAAM,CAAA;CACb;AA6DD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAOnF"}
|
|
@@ -17,9 +17,10 @@ export interface DappActorSpec {
|
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Creates and starts one {@link DappActor} per spec, all sharing the single
|
|
20
|
-
* process-wide locator.
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* process-wide locator. A thin wrapper over actor-kit's `bootActors`: on
|
|
21
|
+
* partial failure, actors already started are stopped (with shutdown
|
|
22
|
+
* fallback) before the error is rethrown. Returns them so the caller can
|
|
23
|
+
* stop them on shutdown.
|
|
23
24
|
*/
|
|
24
25
|
export declare function bootDappActors(locator: DappProviderLocator, specs: readonly DappActorSpec[]): Promise<DappActor[]>;
|
|
25
26
|
//# sourceMappingURL=bootDappActors.d.ts.map
|