@ariestools/aries-dapp-core 0.1.14 → 0.1.16

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.
@@ -11,163 +11,12 @@ var __decorateClass = (decorators, target, key, kind) => {
11
11
  };
12
12
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
13
 
14
- // src/actor/AbstractActor.ts
15
- import {
16
- AbstractCreatable,
17
- assertEx,
18
- IdLogger
19
- } from "@ariestools/sdk";
20
- function createDeferred() {
21
- let resolve;
22
- let reject;
23
- const promise = new Promise((res, rej) => {
24
- resolve = res;
25
- reject = rej;
26
- });
27
- void promise.catch(() => {
28
- });
29
- return {
30
- promise,
31
- reject,
32
- resolve
33
- };
34
- }
35
- var AbstractActor = class extends AbstractCreatable {
36
- _intervals = /* @__PURE__ */ new Map();
37
- _timeouts = /* @__PURE__ */ new Map();
38
- _abortController = new AbortController();
39
- _idLogger;
40
- _inFlight = /* @__PURE__ */ new Map();
41
- _readyDeferred = createDeferred();
42
- _readyError;
43
- _readyState = "pending";
44
- get logger() {
45
- this._idLogger ??= new IdLogger(
46
- assertEx(this.context.logger, () => `Logger is required in context for actor ${this.name}.`),
47
- () => this.name
48
- );
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({ ...inParams, name: inParams.name ?? "UnknownActor" });
70
- const locator = assertEx(inParams.locator, () => `params.locator is required for actor ${String(baseParams.name)}.`);
71
- return { ...baseParams, locator };
72
- }
73
- /** Override to prove the actor can do useful work. Default: no-op. */
74
- async readyHandler() {
75
- }
76
- /**
77
- * Register a recurring task. The first invocation fires after `dueTimeMs`
78
- * (the documented first-run delay); subsequent invocations fire every
79
- * `periodMs` while the actor is `started`. A run is skipped if the previous
80
- * one is still in flight, so a slow pass can never stack on top of itself.
81
- * Must be called from `startHandler` (guards on `starting` status).
82
- */
83
- registerTimer(timerName, callback, dueTimeMs, periodMs) {
84
- if (this.status !== "starting") {
85
- this.logger.warn(`Cannot register timer '${timerName}' because actor is not starting.`);
86
- return;
87
- }
88
- const tick = () => {
89
- if (this.status !== "started") return;
90
- if (this._inFlight.has(timerName)) {
91
- this.logger.warn(`Skipping timer '${this.name}:${timerName}' because the previous run is still in flight.`);
92
- return;
93
- }
94
- const run = (async () => {
95
- const startTime = Date.now();
96
- try {
97
- await callback();
98
- } catch (error) {
99
- const err = error instanceof Error ? error : new Error(String(error));
100
- this.logger.error(`Error in timer '${this.name}:${timerName}': ${err.message}`);
101
- } finally {
102
- const duration = Date.now() - startTime;
103
- if (duration > periodMs) {
104
- this.logger.warn(`Timer '${this.name}:${timerName}' took ${duration}ms, longer than its ${periodMs}ms period.`);
105
- }
106
- }
107
- })();
108
- this._inFlight.set(timerName, run.finally(() => {
109
- this._inFlight.delete(timerName);
110
- }));
111
- };
112
- const timeoutId = setTimeout(() => {
113
- if (this.status !== "started") return;
114
- this._intervals.set(timerName, setInterval(tick, periodMs));
115
- tick();
116
- }, dueTimeMs);
117
- this._timeouts.set(timerName, timeoutId);
118
- }
119
- /**
120
- * Run the warm-pass once. The standard boot path invokes this after
121
- * `start()` so readiness either resolves or rejects.
122
- */
123
- async runReadyHandler() {
124
- if (this._readyState !== "pending") return;
125
- try {
126
- await this.readyHandler();
127
- this._readyState = "ready";
128
- this._readyDeferred.resolve();
129
- } catch (error) {
130
- const err = error instanceof Error ? error : new Error(String(error));
131
- this._readyState = "failed";
132
- this._readyError = err;
133
- this._readyDeferred.reject(err);
134
- throw err;
135
- }
136
- }
137
- async startHandler() {
138
- if (this._abortController.signal.aborted) {
139
- this._abortController = new AbortController();
140
- }
141
- await super.startHandler();
142
- }
143
- async stopHandler() {
144
- await super.stopHandler();
145
- this._abortController.abort();
146
- for (const timeoutRef of this._timeouts.values()) clearTimeout(timeoutRef);
147
- this._timeouts.clear();
148
- for (const intervalRef of this._intervals.values()) clearInterval(intervalRef);
149
- this._intervals.clear();
150
- const inFlight = [...this._inFlight.values()];
151
- this._inFlight.clear();
152
- const timeoutMs = this.params.shutdownTimeoutMs;
153
- if (timeoutMs === void 0) {
154
- await Promise.allSettled(inFlight);
155
- return;
156
- }
157
- await Promise.race([
158
- Promise.allSettled(inFlight),
159
- new Promise((resolve) => {
160
- setTimeout(resolve, timeoutMs);
161
- })
162
- ]);
163
- }
164
- async whenReady() {
165
- await this._readyDeferred.promise;
166
- }
167
- };
14
+ // src/boot/bootDappActors.ts
15
+ import { bootActors } from "@ariestools/actor";
168
16
 
169
17
  // src/DappActor.ts
170
- import { creatable } from "@ariestools/sdk";
18
+ import { PeriodicActor } from "@ariestools/actor";
19
+ import { assertEx, creatable } from "@ariestools/sdk";
171
20
 
172
21
  // src/providers/capabilities.ts
173
22
  var ReadOnlyStoreError = class extends Error {
@@ -324,38 +173,22 @@ function failureStatusFields(prior, consecutiveFailures, error, now) {
324
173
 
325
174
  // src/DappActor.ts
326
175
  var DEFAULT_REDUCE_INTERVAL_MS = 5e3;
327
- var DEFAULT_FIRST_RUN_DELAY_MS = 2e3;
328
- var REDUCE_TIMER = "DappReduce";
329
- function createDeferred2() {
330
- let resolve;
331
- let reject;
332
- const promise = new Promise((res, rej) => {
333
- resolve = res;
334
- reject = rej;
335
- });
336
- void promise.catch(() => {
337
- });
338
- return {
339
- promise,
340
- reject,
341
- resolve
342
- };
343
- }
344
176
  function withDefaultGenerationRoot(result) {
345
177
  if (result === void 0) return;
346
178
  if (result.generation === void 0 || result.generationRoot !== void 0) return result;
347
179
  return { ...result, generationRoot: HEAD_KEY };
348
180
  }
349
- var DappActor = class extends AbstractActor {
181
+ var DappActor = class extends PeriodicActor {
350
182
  _data;
351
183
  _index;
352
184
  _state;
353
- _consecutiveFailures = 0;
354
- _firstPass = createDeferred2();
355
- _firstPassSettled = false;
356
- /** Consecutive reduce failures since the last success. */
357
- get consecutiveFailures() {
358
- return this._consecutiveFailures;
185
+ /** Dapp actors require a logger in the locator context (see {@link DappContext}). */
186
+ get logger() {
187
+ return assertEx(super.logger, () => `Logger is required in context for actor ${this.name}.`);
188
+ }
189
+ /** Reduce cadence: `reduceIntervalMs` names the interval in dapp configs. */
190
+ get intervalMs() {
191
+ return this.params.reduceIntervalMs ?? DEFAULT_REDUCE_INTERVAL_MS;
359
192
  }
360
193
  async createHandler() {
361
194
  await super.createHandler();
@@ -364,23 +197,27 @@ var DappActor = class extends AbstractActor {
364
197
  this._state = await this.locator.getInstance(DappStateStoreMoniker);
365
198
  this._index = await this.locator.getInstance(DappIndexStoreMoniker);
366
199
  }
367
- async readyHandler() {
368
- await this._firstPass.promise;
369
- }
370
200
  async startHandler() {
371
201
  await super.startHandler();
372
- const interval = this.params.reduceIntervalMs ?? DEFAULT_REDUCE_INTERVAL_MS;
373
- const firstRunDelay = this.params.firstRunDelayMs ?? DEFAULT_FIRST_RUN_DELAY_MS;
374
- this.registerTimer(REDUCE_TIMER, async () => {
375
- await this.runReducePass();
376
- }, firstRunDelay, interval);
377
202
  this.logger.info(
378
- `DappActor started: reducer '${this.params.reducer.name}' every ${interval}ms (first run in ${firstRunDelay}ms)`
203
+ `DappActor started: reducer '${this.params.reducer.name}' every ${this.intervalMs}ms (first run in ${this.firstRunDelayMs}ms)`
379
204
  );
380
205
  }
381
- async stopHandler() {
382
- this.settleFirstPass(new Error("Actor stopped before first reduce pass completed"));
383
- await super.stopHandler();
206
+ /** Failure side-channel: publish durable failure status (count already incremented). */
207
+ async onPassError(error) {
208
+ await this.safePublishStatus(void 0, error);
209
+ }
210
+ async runPass({ signal }) {
211
+ const result = await this.params.reducer.reduce({
212
+ data: this._data,
213
+ index: this._index,
214
+ logger: this.logger,
215
+ signal,
216
+ state: this._state
217
+ });
218
+ if (signal.aborted) return;
219
+ const progress = withDefaultGenerationRoot(result === void 0 ? void 0 : result);
220
+ await this.safePublishStatus(progress);
384
221
  }
385
222
  async publishStatusFromProgress(progress, error) {
386
223
  if (this.params.publishStatus === false) return;
@@ -391,44 +228,9 @@ var DappActor = class extends AbstractActor {
391
228
  prior = void 0;
392
229
  }
393
230
  const now = (/* @__PURE__ */ new Date()).toISOString();
394
- const fields = error === void 0 ? successStatusFields(progress, prior, now) : failureStatusFields(prior, this._consecutiveFailures, error, now);
231
+ const fields = error === void 0 ? successStatusFields(progress, prior, now) : failureStatusFields(prior, this.consecutiveFailures, error, now);
395
232
  await writeIndexerStatus(this._state, fields);
396
233
  }
397
- async runReducePass() {
398
- const signal = this.signal;
399
- try {
400
- const result = await this.params.reducer.reduce({
401
- data: this._data,
402
- index: this._index,
403
- logger: this.logger,
404
- signal,
405
- state: this._state
406
- });
407
- if (signal.aborted) return;
408
- const progress = withDefaultGenerationRoot(result === void 0 ? void 0 : result);
409
- this._consecutiveFailures = 0;
410
- await this.safePublishStatus(progress);
411
- this.settleFirstPass();
412
- } catch (error) {
413
- if (signal.aborted) return;
414
- const err = error instanceof Error ? error : new Error(String(error));
415
- this._consecutiveFailures += 1;
416
- await this.safePublishStatus(void 0, err);
417
- this.settleFirstPass(err);
418
- this.logger.error(
419
- `Error in reduce pass for '${this.params.reducer.name}': ${err.message}`
420
- );
421
- const max = this.params.maxConsecutiveFailures;
422
- if (max !== void 0 && this._consecutiveFailures >= max) {
423
- this.logger.error(
424
- `Reducer '${this.params.reducer.name}' failed ${this._consecutiveFailures} consecutive times; stopping actor`
425
- );
426
- setTimeout(() => {
427
- void this.stop();
428
- }, 0);
429
- }
430
- }
431
- }
432
234
  async safePublishStatus(progress, error) {
433
235
  try {
434
236
  await this.publishStatusFromProgress(progress, error);
@@ -436,12 +238,6 @@ var DappActor = class extends AbstractActor {
436
238
  this.logger.error(`Failed to publish indexer status: ${String(statusError)}`);
437
239
  }
438
240
  }
439
- settleFirstPass(error) {
440
- if (this._firstPassSettled) return;
441
- this._firstPassSettled = true;
442
- if (error === void 0) this._firstPass.resolve();
443
- else this._firstPass.reject(error);
444
- }
445
241
  };
446
242
  __publicField(DappActor, "dependencies", [
447
243
  DappDataStoreMoniker,
@@ -454,36 +250,22 @@ DappActor = __decorateClass([
454
250
 
455
251
  // src/boot/bootDappActors.ts
456
252
  async function bootDappActors(locator, specs) {
457
- const actors = [];
458
- try {
459
- for (const spec of specs) {
460
- const params = {
461
- locator,
462
- name: spec.name,
463
- reducer: spec.reducer,
464
- ...spec.reduceIntervalMs !== void 0 && { reduceIntervalMs: spec.reduceIntervalMs },
465
- ...spec.firstRunDelayMs !== void 0 && { firstRunDelayMs: spec.firstRunDelayMs },
466
- ...spec.maxConsecutiveFailures !== void 0 && { maxConsecutiveFailures: spec.maxConsecutiveFailures },
467
- ...spec.publishStatus !== void 0 && { publishStatus: spec.publishStatus },
468
- ...spec.shutdownTimeoutMs !== void 0 && { shutdownTimeoutMs: spec.shutdownTimeoutMs }
469
- };
470
- const actor = await DappActor.create(params);
471
- await actor.start();
472
- actors.push(actor);
473
- if (spec.runReady !== false) {
474
- await actor.runReadyHandler();
475
- }
476
- }
477
- return actors;
478
- } catch (error) {
479
- for (const actor of [...actors].reverse()) {
480
- try {
481
- await actor.stop();
482
- } catch {
483
- }
484
- }
485
- throw error;
486
- }
253
+ return await bootActors(specs.map((spec) => {
254
+ const params = {
255
+ locator,
256
+ name: spec.name,
257
+ reducer: spec.reducer,
258
+ ...spec.reduceIntervalMs !== void 0 && { reduceIntervalMs: spec.reduceIntervalMs },
259
+ ...spec.firstRunDelayMs !== void 0 && { firstRunDelayMs: spec.firstRunDelayMs },
260
+ ...spec.maxConsecutiveFailures !== void 0 && { maxConsecutiveFailures: spec.maxConsecutiveFailures },
261
+ ...spec.publishStatus !== void 0 && { publishStatus: spec.publishStatus },
262
+ ...spec.shutdownTimeoutMs !== void 0 && { shutdownTimeoutMs: spec.shutdownTimeoutMs }
263
+ };
264
+ return {
265
+ create: () => DappActor.create(params),
266
+ ...spec.runReady !== void 0 && { runReady: spec.runReady }
267
+ };
268
+ }));
487
269
  }
488
270
 
489
271
  // src/locator/createDappLocator.ts
@@ -1923,7 +1705,6 @@ var noopReducer = {
1923
1705
  }
1924
1706
  };
1925
1707
  export {
1926
- AbstractActor,
1927
1708
  CACHE_CONTROL_IMMUTABLE,
1928
1709
  CACHE_CONTROL_REVALIDATE,
1929
1710
  CAS_PREFIX,