apcore-js 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -9
- package/dist/acl-handlers.d.ts +14 -0
- package/dist/acl-handlers.d.ts.map +1 -1
- package/dist/acl-handlers.js +37 -4
- package/dist/acl-handlers.js.map +1 -1
- package/dist/acl.d.ts +22 -1
- package/dist/acl.d.ts.map +1 -1
- package/dist/acl.js +90 -34
- package/dist/acl.js.map +1 -1
- package/dist/async-task.d.ts +70 -16
- package/dist/async-task.d.ts.map +1 -1
- package/dist/async-task.js +212 -72
- package/dist/async-task.js.map +1 -1
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js +113 -11
- package/dist/bindings.js.map +1 -1
- package/dist/builtin-steps.d.ts +33 -8
- package/dist/builtin-steps.d.ts.map +1 -1
- package/dist/builtin-steps.js +119 -47
- package/dist/builtin-steps.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +163 -33
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +34 -7
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +108 -40
- package/dist/context.js.map +1 -1
- package/dist/decorator.d.ts +3 -0
- package/dist/decorator.d.ts.map +1 -1
- package/dist/decorator.js +3 -0
- package/dist/decorator.js.map +1 -1
- package/dist/errors.d.ts +88 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +231 -56
- package/dist/errors.js.map +1 -1
- package/dist/events/circuit-breaker.d.ts +45 -0
- package/dist/events/circuit-breaker.d.ts.map +1 -0
- package/dist/events/circuit-breaker.js +115 -0
- package/dist/events/circuit-breaker.js.map +1 -0
- package/dist/events/emitter.d.ts +24 -1
- package/dist/events/emitter.d.ts.map +1 -1
- package/dist/events/emitter.js +86 -12
- package/dist/events/emitter.js.map +1 -1
- package/dist/events/index.d.ts +4 -2
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +3 -2
- package/dist/events/index.js.map +1 -1
- package/dist/events/subscribers.d.ts +33 -1
- package/dist/events/subscribers.d.ts.map +1 -1
- package/dist/events/subscribers.js +124 -1
- package/dist/events/subscribers.js.map +1 -1
- package/dist/executor.d.ts +14 -3
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +155 -48
- package/dist/executor.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +47 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -18
- package/dist/index.js.map +1 -1
- package/dist/middleware/base.d.ts +25 -3
- package/dist/middleware/base.d.ts.map +1 -1
- package/dist/middleware/base.js +24 -0
- package/dist/middleware/base.js.map +1 -1
- package/dist/middleware/circuit-breaker.d.ts +54 -0
- package/dist/middleware/circuit-breaker.d.ts.map +1 -0
- package/dist/middleware/circuit-breaker.js +168 -0
- package/dist/middleware/circuit-breaker.js.map +1 -0
- package/dist/middleware/context-namespace.d.ts +30 -0
- package/dist/middleware/context-namespace.d.ts.map +1 -0
- package/dist/middleware/context-namespace.js +38 -0
- package/dist/middleware/context-namespace.js.map +1 -0
- package/dist/middleware/index.d.ts +8 -2
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +5 -2
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/logging.d.ts +6 -0
- package/dist/middleware/logging.d.ts.map +1 -1
- package/dist/middleware/logging.js +13 -3
- package/dist/middleware/logging.js.map +1 -1
- package/dist/middleware/manager.d.ts +11 -4
- package/dist/middleware/manager.d.ts.map +1 -1
- package/dist/middleware/manager.js +26 -9
- package/dist/middleware/manager.js.map +1 -1
- package/dist/middleware/platform-notify.d.ts +8 -4
- package/dist/middleware/platform-notify.d.ts.map +1 -1
- package/dist/middleware/platform-notify.js +15 -7
- package/dist/middleware/platform-notify.js.map +1 -1
- package/dist/middleware/retry.d.ts +16 -7
- package/dist/middleware/retry.d.ts.map +1 -1
- package/dist/middleware/retry.js +21 -15
- package/dist/middleware/retry.js.map +1 -1
- package/dist/middleware/tracing.d.ts +50 -0
- package/dist/middleware/tracing.d.ts.map +1 -0
- package/dist/middleware/tracing.js +89 -0
- package/dist/middleware/tracing.js.map +1 -0
- package/dist/observability/batch-span-processor.d.ts +48 -0
- package/dist/observability/batch-span-processor.d.ts.map +1 -0
- package/dist/observability/batch-span-processor.js +89 -0
- package/dist/observability/batch-span-processor.js.map +1 -0
- package/dist/observability/context-logger.d.ts +54 -1
- package/dist/observability/context-logger.d.ts.map +1 -1
- package/dist/observability/context-logger.js +287 -10
- package/dist/observability/context-logger.js.map +1 -1
- package/dist/observability/error-history.d.ts +36 -7
- package/dist/observability/error-history.d.ts.map +1 -1
- package/dist/observability/error-history.js +169 -50
- package/dist/observability/error-history.js.map +1 -1
- package/dist/observability/index.d.ts +16 -5
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +8 -3
- package/dist/observability/index.js.map +1 -1
- package/dist/observability/metrics-utils.d.ts.map +1 -1
- package/dist/observability/metrics-utils.js +3 -5
- package/dist/observability/metrics-utils.js.map +1 -1
- package/dist/observability/metrics.d.ts +15 -1
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/metrics.js +37 -3
- package/dist/observability/metrics.js.map +1 -1
- package/dist/observability/prometheus-exporter.d.ts +37 -0
- package/dist/observability/prometheus-exporter.d.ts.map +1 -0
- package/dist/observability/prometheus-exporter.js +135 -0
- package/dist/observability/prometheus-exporter.js.map +1 -0
- package/dist/observability/storage.d.ts +43 -0
- package/dist/observability/storage.d.ts.map +1 -0
- package/dist/observability/storage.js +58 -0
- package/dist/observability/storage.js.map +1 -0
- package/dist/observability/store.d.ts +29 -0
- package/dist/observability/store.d.ts.map +1 -0
- package/dist/observability/store.js +36 -0
- package/dist/observability/store.js.map +1 -0
- package/dist/observability/tracing.d.ts +2 -0
- package/dist/observability/tracing.d.ts.map +1 -1
- package/dist/observability/tracing.js +12 -2
- package/dist/observability/tracing.js.map +1 -1
- package/dist/observability/usage-exporter.d.ts +58 -0
- package/dist/observability/usage-exporter.d.ts.map +1 -0
- package/dist/observability/usage-exporter.js +86 -0
- package/dist/observability/usage-exporter.js.map +1 -0
- package/dist/observability/usage.d.ts +18 -1
- package/dist/observability/usage.d.ts.map +1 -1
- package/dist/observability/usage.js +35 -4
- package/dist/observability/usage.js.map +1 -1
- package/dist/pipeline-config.d.ts +24 -7
- package/dist/pipeline-config.d.ts.map +1 -1
- package/dist/pipeline-config.js +113 -19
- package/dist/pipeline-config.js.map +1 -1
- package/dist/pipeline.d.ts +123 -2
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +249 -50
- package/dist/pipeline.js.map +1 -1
- package/dist/registry/conflicts.d.ts +2 -2
- package/dist/registry/conflicts.d.ts.map +1 -1
- package/dist/registry/conflicts.js +10 -11
- package/dist/registry/conflicts.js.map +1 -1
- package/dist/registry/dependencies.d.ts +1 -1
- package/dist/registry/dependencies.d.ts.map +1 -1
- package/dist/registry/dependencies.js +69 -20
- package/dist/registry/dependencies.js.map +1 -1
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/multi-class.d.ts +57 -0
- package/dist/registry/multi-class.d.ts.map +1 -0
- package/dist/registry/multi-class.js +120 -0
- package/dist/registry/multi-class.js.map +1 -0
- package/dist/registry/registry.d.ts +99 -4
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +291 -33
- package/dist/registry/registry.js.map +1 -1
- package/dist/registry/scanner.d.ts.map +1 -1
- package/dist/registry/scanner.js +6 -0
- package/dist/registry/scanner.js.map +1 -1
- package/dist/registry/version.d.ts +1 -0
- package/dist/registry/version.d.ts.map +1 -1
- package/dist/registry/version.js +33 -4
- package/dist/registry/version.js.map +1 -1
- package/dist/schema/constants.d.ts +9 -0
- package/dist/schema/constants.d.ts.map +1 -0
- package/dist/schema/constants.js +9 -0
- package/dist/schema/constants.js.map +1 -0
- package/dist/schema/extractor.d.ts +69 -0
- package/dist/schema/extractor.d.ts.map +1 -0
- package/dist/schema/extractor.js +142 -0
- package/dist/schema/extractor.js.map +1 -0
- package/dist/schema/index.d.ts +3 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +2 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/loader.d.ts +27 -3
- package/dist/schema/loader.d.ts.map +1 -1
- package/dist/schema/loader.js +137 -32
- package/dist/schema/loader.js.map +1 -1
- package/dist/schema/ref-resolver.d.ts.map +1 -1
- package/dist/schema/ref-resolver.js +10 -1
- package/dist/schema/ref-resolver.js.map +1 -1
- package/dist/schema/types.d.ts +4 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js.map +1 -1
- package/dist/schema/validator.d.ts +9 -0
- package/dist/schema/validator.d.ts.map +1 -1
- package/dist/schema/validator.js +153 -4
- package/dist/schema/validator.js.map +1 -1
- package/dist/sys-modules/audit.d.ts +50 -0
- package/dist/sys-modules/audit.d.ts.map +1 -0
- package/dist/sys-modules/audit.js +89 -0
- package/dist/sys-modules/audit.js.map +1 -0
- package/dist/sys-modules/control.d.ts +32 -4
- package/dist/sys-modules/control.d.ts.map +1 -1
- package/dist/sys-modules/control.js +197 -23
- package/dist/sys-modules/control.js.map +1 -1
- package/dist/sys-modules/index.d.ts +7 -2
- package/dist/sys-modules/index.d.ts.map +1 -1
- package/dist/sys-modules/index.js +3 -1
- package/dist/sys-modules/index.js.map +1 -1
- package/dist/sys-modules/overrides.d.ts +58 -0
- package/dist/sys-modules/overrides.d.ts.map +1 -0
- package/dist/sys-modules/overrides.js +106 -0
- package/dist/sys-modules/overrides.js.map +1 -0
- package/dist/sys-modules/registration.d.ts +18 -1
- package/dist/sys-modules/registration.d.ts.map +1 -1
- package/dist/sys-modules/registration.js +115 -11
- package/dist/sys-modules/registration.js.map +1 -1
- package/dist/sys-modules/toggle.d.ts +7 -2
- package/dist/sys-modules/toggle.d.ts.map +1 -1
- package/dist/sys-modules/toggle.js +61 -5
- package/dist/sys-modules/toggle.js.map +1 -1
- package/dist/trace-context.d.ts +47 -9
- package/dist/trace-context.d.ts.map +1 -1
- package/dist/trace-context.js +139 -16
- package/dist/trace-context.js.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/middleware/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
export { Middleware } from './base.js';
|
|
1
|
+
export { Middleware, RetrySignal } from './base.js';
|
|
2
2
|
export { MiddlewareManager, MiddlewareChainError } from './manager.js';
|
|
3
3
|
export { BeforeMiddleware, AfterMiddleware } from './adapters.js';
|
|
4
4
|
export { LoggingMiddleware } from './logging.js';
|
|
5
|
-
export { RetryMiddleware, CTX_RETRY_COUNT_PREFIX, CTX_RETRY_DELAY_PREFIX } from './retry.js';
|
|
5
|
+
export { RetryHintMiddleware, RetryMiddleware, CTX_RETRY_COUNT_PREFIX, CTX_RETRY_DELAY_PREFIX } from './retry.js';
|
|
6
6
|
export { ErrorHistoryMiddleware } from './error-history.js';
|
|
7
7
|
export { PlatformNotifyMiddleware } from './platform-notify.js';
|
|
8
|
+
export { CircuitBreakerMiddleware, CircuitState as MiddlewareCircuitState, CTX_CIRCUIT_STATE, } from './circuit-breaker.js';
|
|
9
|
+
export { TracingMiddleware, CTX_TRACING_SPAN_ID } from './tracing.js';
|
|
10
|
+
export { validateContextKey, isAsyncHandler } from './context-namespace.js';
|
|
8
11
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAElH,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EACL,wBAAwB,EACxB,YAAY,IAAI,sBAAsB,EACtC,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LoggingMiddleware for structured module call logging.
|
|
3
|
+
*
|
|
4
|
+
* @deprecated Use `ObsLoggingMiddleware` from `apcore/observability` instead.
|
|
5
|
+
* `ObsLoggingMiddleware` provides the same functionality with structured JSON
|
|
6
|
+
* output, configurable log levels, and `_secret_`-key redaction via
|
|
7
|
+
* `ContextLogger`. `LoggingMiddleware` will be removed in a future major version.
|
|
3
8
|
*/
|
|
4
9
|
import type { Context } from '../context.js';
|
|
5
10
|
import { Middleware } from './base.js';
|
|
@@ -7,6 +12,7 @@ export interface Logger {
|
|
|
7
12
|
info(message: string, extra?: Record<string, unknown>): void;
|
|
8
13
|
error(message: string, extra?: Record<string, unknown>): void;
|
|
9
14
|
}
|
|
15
|
+
/** @deprecated Use `ObsLoggingMiddleware` from `apcore/observability`. */
|
|
10
16
|
export declare class LoggingMiddleware extends Middleware {
|
|
11
17
|
private _logger;
|
|
12
18
|
private _logInputs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/middleware/logging.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/middleware/logging.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC/D;AAWD,0EAA0E;AAC1E,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,UAAU,CAAU;gBAEhB,OAAO,CAAC,EAAE;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB;IAQQ,MAAM,CACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,IAAI;IAgBE,KAAK,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,IAAI;IAuBE,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,GACf,IAAI;CAaR"}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LoggingMiddleware for structured module call logging.
|
|
3
|
+
*
|
|
4
|
+
* @deprecated Use `ObsLoggingMiddleware` from `apcore/observability` instead.
|
|
5
|
+
* `ObsLoggingMiddleware` provides the same functionality with structured JSON
|
|
6
|
+
* output, configurable log levels, and `_secret_`-key redaction via
|
|
7
|
+
* `ContextLogger`. `LoggingMiddleware` will be removed in a future major version.
|
|
3
8
|
*/
|
|
4
9
|
import { Middleware } from './base.js';
|
|
5
10
|
const defaultLogger = {
|
|
6
11
|
info(message, extra) {
|
|
7
|
-
console.info(message
|
|
12
|
+
console.info(`[apcore:middleware.logging] ${message}`, extra ?? '');
|
|
8
13
|
},
|
|
9
14
|
error(message, extra) {
|
|
10
|
-
console.error(message
|
|
15
|
+
console.error(`[apcore:middleware.logging] ${message}`, extra ?? '');
|
|
11
16
|
},
|
|
12
17
|
};
|
|
18
|
+
/** @deprecated Use `ObsLoggingMiddleware` from `apcore/observability`. */
|
|
13
19
|
export class LoggingMiddleware extends Middleware {
|
|
14
20
|
_logger;
|
|
15
21
|
_logInputs;
|
|
@@ -39,11 +45,15 @@ export class LoggingMiddleware extends Middleware {
|
|
|
39
45
|
const startTime = context.data['_apcore.mw.logging.start_time'] ?? performance.now();
|
|
40
46
|
const durationMs = performance.now() - startTime;
|
|
41
47
|
if (this._logOutputs) {
|
|
48
|
+
// Use the schema-aware redacted output when the executor produced one;
|
|
49
|
+
// the executor's redaction only ran on context.redactedOutput and not
|
|
50
|
+
// on the raw `output` argument.
|
|
51
|
+
const redactedOutput = context.redactedOutput ?? output;
|
|
42
52
|
this._logger.info(`[${context.traceId}] END ${moduleId} (${durationMs.toFixed(2)}ms)`, {
|
|
43
53
|
traceId: context.traceId,
|
|
44
54
|
moduleId,
|
|
45
55
|
durationMs,
|
|
46
|
-
output,
|
|
56
|
+
output: redactedOutput,
|
|
47
57
|
});
|
|
48
58
|
}
|
|
49
59
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/middleware/logging.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/middleware/logging.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { Context } from '../context.js';
|
|
5
5
|
import { ModuleError } from '../errors.js';
|
|
6
|
-
import { Middleware } from './base.js';
|
|
6
|
+
import { Middleware, RetrySignal } from './base.js';
|
|
7
7
|
export declare class MiddlewareChainError extends ModuleError {
|
|
8
8
|
static readonly DEFAULT_RETRYABLE: boolean | null;
|
|
9
9
|
readonly original: Error;
|
|
@@ -15,8 +15,15 @@ export declare class MiddlewareManager {
|
|
|
15
15
|
add(middleware: Middleware): void;
|
|
16
16
|
remove(middleware: Middleware): boolean;
|
|
17
17
|
snapshot(): Middleware[];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Run all `before` hooks in priority-descending order, awaiting any Promise
|
|
20
|
+
* a middleware returns.
|
|
21
|
+
*
|
|
22
|
+
* Always-async (sync finding A-D-403) — matches apcore-rust's design and
|
|
23
|
+
* removes the silent-Promise-into-currentInputs trap.
|
|
24
|
+
*/
|
|
25
|
+
executeBefore(moduleId: string, inputs: Record<string, unknown>, context: Context): Promise<[Record<string, unknown>, Middleware[]]>;
|
|
26
|
+
executeAfter(moduleId: string, inputs: Record<string, unknown>, output: Record<string, unknown>, context: Context): Promise<Record<string, unknown>>;
|
|
27
|
+
executeOnError(moduleId: string, inputs: Record<string, unknown>, error: Error, context: Context, executedMiddlewares: Middleware[]): Promise<Record<string, unknown> | RetrySignal | null>;
|
|
21
28
|
}
|
|
22
29
|
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEpD,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,gBAAyB,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAS;IAEnE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzB,QAAQ,CAAC,mBAAmB,EAAE,UAAU,EAAE,CAAC;gBAE/B,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE;CAM/D;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,YAAY,CAAoB;IAExC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAcjC,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO;IAUvC,QAAQ,IAAI,UAAU,EAAE;IAIxB;;;;;;OAMG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAoB7C,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAe7B,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAE,UAAU,EAAE,GAChC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,IAAI,CAAC;CAwBzD"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* MiddlewareManager -- onion model execution engine for the middleware pipeline.
|
|
3
3
|
*/
|
|
4
4
|
import { ModuleError } from '../errors.js';
|
|
5
|
+
import { RetrySignal } from './base.js';
|
|
5
6
|
export class MiddlewareChainError extends ModuleError {
|
|
6
7
|
static DEFAULT_RETRYABLE = false;
|
|
7
8
|
original;
|
|
@@ -40,15 +41,22 @@ export class MiddlewareManager {
|
|
|
40
41
|
snapshot() {
|
|
41
42
|
return [...this._middlewares];
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Run all `before` hooks in priority-descending order, awaiting any Promise
|
|
46
|
+
* a middleware returns.
|
|
47
|
+
*
|
|
48
|
+
* Always-async (sync finding A-D-403) — matches apcore-rust's design and
|
|
49
|
+
* removes the silent-Promise-into-currentInputs trap.
|
|
50
|
+
*/
|
|
51
|
+
async executeBefore(moduleId, inputs, context) {
|
|
44
52
|
let currentInputs = inputs;
|
|
45
53
|
const executedMiddlewares = [];
|
|
46
54
|
const middlewares = this.snapshot();
|
|
47
55
|
for (const mw of middlewares) {
|
|
48
56
|
executedMiddlewares.push(mw);
|
|
49
57
|
try {
|
|
50
|
-
const result = mw.before(moduleId, currentInputs, context);
|
|
51
|
-
if (result !== null) {
|
|
58
|
+
const result = await mw.before(moduleId, currentInputs, context);
|
|
59
|
+
if (result !== null && result !== undefined) {
|
|
52
60
|
currentInputs = result;
|
|
53
61
|
}
|
|
54
62
|
}
|
|
@@ -58,22 +66,31 @@ export class MiddlewareManager {
|
|
|
58
66
|
}
|
|
59
67
|
return [currentInputs, executedMiddlewares];
|
|
60
68
|
}
|
|
61
|
-
executeAfter(moduleId, inputs, output, context) {
|
|
69
|
+
async executeAfter(moduleId, inputs, output, context) {
|
|
62
70
|
let currentOutput = output;
|
|
63
71
|
const middlewares = this.snapshot();
|
|
72
|
+
// Fail-fast: propagate the first error immediately (matches Python/Rust behaviour).
|
|
64
73
|
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
65
|
-
const result = middlewares[i].after(moduleId, inputs, currentOutput, context);
|
|
66
|
-
if (result !== null) {
|
|
74
|
+
const result = await middlewares[i].after(moduleId, inputs, currentOutput, context);
|
|
75
|
+
if (result !== null && result !== undefined) {
|
|
67
76
|
currentOutput = result;
|
|
68
77
|
}
|
|
69
78
|
}
|
|
70
79
|
return currentOutput;
|
|
71
80
|
}
|
|
72
|
-
executeOnError(moduleId, inputs, error, context, executedMiddlewares) {
|
|
81
|
+
async executeOnError(moduleId, inputs, error, context, executedMiddlewares) {
|
|
73
82
|
for (let i = executedMiddlewares.length - 1; i >= 0; i--) {
|
|
74
83
|
try {
|
|
75
|
-
const result = executedMiddlewares[i].onError(moduleId, inputs, error, context);
|
|
76
|
-
|
|
84
|
+
const result = await executedMiddlewares[i].onError(moduleId, inputs, error, context);
|
|
85
|
+
// Strict recovery type check (sync finding A-D-404):
|
|
86
|
+
// only a non-null object or a RetrySignal counts as recovery.
|
|
87
|
+
// `undefined` (typical of arrow functions without a return) does NOT trigger recovery.
|
|
88
|
+
if (result !== null
|
|
89
|
+
&& result !== undefined
|
|
90
|
+
&& (result instanceof RetrySignal || (typeof result === 'object'))) {
|
|
91
|
+
// RetrySignal short-circuits and propagates up to the executor's
|
|
92
|
+
// call() loop, which re-runs the pipeline with new inputs.
|
|
93
|
+
// Plain objects become the recovery output. (sync finding A-D-017)
|
|
77
94
|
return result;
|
|
78
95
|
}
|
|
79
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/middleware/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* PlatformNotifyMiddleware -- threshold sensor with hysteresis.
|
|
3
3
|
*
|
|
4
4
|
* Monitors error rates and latency, emits threshold events with hysteresis.
|
|
5
|
-
* Emits error_threshold_exceeded when a module's error rate
|
|
6
|
-
* configured threshold, latency_threshold_exceeded
|
|
7
|
-
* exceeds the limit, and apcore.health.recovered when a
|
|
8
|
-
* module recovers below threshold * 0.5.
|
|
5
|
+
* Emits apcore.health.error_threshold_exceeded when a module's error rate
|
|
6
|
+
* crosses the configured threshold, apcore.health.latency_threshold_exceeded
|
|
7
|
+
* when p99 latency exceeds the limit, and apcore.health.recovered when a
|
|
8
|
+
* previously alerted module recovers below threshold * 0.5.
|
|
9
|
+
*
|
|
10
|
+
* During the deprecation window legacy aliases (`error_threshold_exceeded`,
|
|
11
|
+
* `latency_threshold_exceeded`) are emitted alongside the canonical names
|
|
12
|
+
* with `deprecated: true` in the payload (Issue #36).
|
|
9
13
|
*/
|
|
10
14
|
import type { Context } from '../context.js';
|
|
11
15
|
import type { EventEmitter } from '../events/emitter.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-notify.d.ts","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"platform-notify.d.ts","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,qBAAa,wBAAyB,SAAQ,UAAU;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAC5D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;gBAG9D,YAAY,EAAE,YAAY,EAC1B,gBAAgB,GAAE,gBAAgB,GAAG,IAAW,EAChD,kBAAkB,GAAE,MAAY,EAChC,qBAAqB,GAAE,MAAa;IAS7B,KAAK,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMxB,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,OAAO,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IASjC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,sBAAsB;IAmB9B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,mBAAmB;CAe5B"}
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
* PlatformNotifyMiddleware -- threshold sensor with hysteresis.
|
|
3
3
|
*
|
|
4
4
|
* Monitors error rates and latency, emits threshold events with hysteresis.
|
|
5
|
-
* Emits error_threshold_exceeded when a module's error rate
|
|
6
|
-
* configured threshold, latency_threshold_exceeded
|
|
7
|
-
* exceeds the limit, and apcore.health.recovered when a
|
|
8
|
-
* module recovers below threshold * 0.5.
|
|
5
|
+
* Emits apcore.health.error_threshold_exceeded when a module's error rate
|
|
6
|
+
* crosses the configured threshold, apcore.health.latency_threshold_exceeded
|
|
7
|
+
* when p99 latency exceeds the limit, and apcore.health.recovered when a
|
|
8
|
+
* previously alerted module recovers below threshold * 0.5.
|
|
9
|
+
*
|
|
10
|
+
* During the deprecation window legacy aliases (`error_threshold_exceeded`,
|
|
11
|
+
* `latency_threshold_exceeded`) are emitted alongside the canonical names
|
|
12
|
+
* with `deprecated: true` in the payload (Issue #36).
|
|
9
13
|
*/
|
|
10
|
-
import { createEvent } from '../events/emitter.js';
|
|
14
|
+
import { createEvent, emitWithLegacy } from '../events/emitter.js';
|
|
11
15
|
import { computeModuleErrorRate, estimateP99FromHistogram } from '../observability/metrics-utils.js';
|
|
12
16
|
import { Middleware } from './base.js';
|
|
13
17
|
export class PlatformNotifyMiddleware extends Middleware {
|
|
@@ -30,6 +34,10 @@ export class PlatformNotifyMiddleware extends Middleware {
|
|
|
30
34
|
}
|
|
31
35
|
onError(moduleId, _inputs, _error, _context) {
|
|
32
36
|
this._checkErrorRateThreshold(moduleId);
|
|
37
|
+
// Also check recovery on error paths so a module whose error rate is
|
|
38
|
+
// falling (e.g., because the histogram window is decaying) can clear
|
|
39
|
+
// the alert state even when no successful call arrives.
|
|
40
|
+
this._checkErrorRecovery(moduleId);
|
|
33
41
|
return null;
|
|
34
42
|
}
|
|
35
43
|
_getAlerted(moduleId) {
|
|
@@ -49,7 +57,7 @@ export class PlatformNotifyMiddleware extends Middleware {
|
|
|
49
57
|
const errorRate = this._computeErrorRate(moduleId);
|
|
50
58
|
const alerted = this._getAlerted(moduleId);
|
|
51
59
|
if (errorRate >= this._errorRateThreshold && !alerted.has('error_rate')) {
|
|
52
|
-
this._emitter.
|
|
60
|
+
emitWithLegacy(this._emitter, 'apcore.health.error_threshold_exceeded', 'error_threshold_exceeded', moduleId, 'error', { error_rate: errorRate, threshold: this._errorRateThreshold });
|
|
53
61
|
alerted.add('error_rate');
|
|
54
62
|
}
|
|
55
63
|
}
|
|
@@ -61,7 +69,7 @@ export class PlatformNotifyMiddleware extends Middleware {
|
|
|
61
69
|
return;
|
|
62
70
|
const p99Ms = this._estimateP99Ms(moduleId);
|
|
63
71
|
if (p99Ms >= this._latencyP99ThresholdMs) {
|
|
64
|
-
this._emitter.
|
|
72
|
+
emitWithLegacy(this._emitter, 'apcore.health.latency_threshold_exceeded', 'latency_threshold_exceeded', moduleId, 'warn', { p99_latency_ms: p99Ms, threshold: this._latencyP99ThresholdMs });
|
|
65
73
|
alerted.add('latency');
|
|
66
74
|
}
|
|
67
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-notify.js","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"platform-notify.js","sourceRoot":"","sources":["../../src/middleware/platform-notify.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,18 +14,27 @@ export interface RetryConfig {
|
|
|
14
14
|
jitter: boolean;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Advisory retry-hint middleware.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* error
|
|
19
|
+
* This middleware does NOT re-invoke the failed module. It records retry
|
|
20
|
+
* state and advisory delay hints in `context.data` for outer retry loops,
|
|
21
|
+
* then returns null so the original error always propagates to the caller.
|
|
22
|
+
*
|
|
23
|
+
* Context keys written on a retryable error:
|
|
24
|
+
* - `CTX_RETRY_COUNT_PREFIX + moduleId` — number of attempts so far
|
|
25
|
+
* - `CTX_RETRY_DELAY_PREFIX + moduleId` — suggested delay in ms before retry
|
|
26
|
+
*
|
|
27
|
+
* If you need real retries, wrap `Executor.call` in an outer retry loop
|
|
28
|
+
* that inspects `error.retryable` and the hint values above.
|
|
24
29
|
*/
|
|
25
|
-
export declare class
|
|
30
|
+
export declare class RetryHintMiddleware extends Middleware {
|
|
26
31
|
private _config;
|
|
27
32
|
constructor(config?: Partial<RetryConfig>);
|
|
28
33
|
onError(moduleId: string, inputs: Record<string, unknown>, error: Error, context: Context): Record<string, unknown> | null;
|
|
29
34
|
private _calculateDelay;
|
|
30
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Use {@link RetryHintMiddleware} instead. Will be removed in 1.0.0.
|
|
38
|
+
*/
|
|
39
|
+
export declare const RetryMiddleware: typeof RetryHintMiddleware;
|
|
31
40
|
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/middleware/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,4BAA4B,CAAC;AAChE,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAUD
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/middleware/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,4BAA4B,CAAC;AAChE,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAUD;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IACjD,OAAO,CAAC,OAAO,CAAc;gBAEjB,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAKhC,OAAO,CACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA4BjC,OAAO,CAAC,eAAe;CAkBxB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,4BAAsB,CAAC"}
|
package/dist/middleware/retry.js
CHANGED
|
@@ -13,15 +13,20 @@ const DEFAULT_RETRY_CONFIG = {
|
|
|
13
13
|
jitter: true,
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Advisory retry-hint middleware.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* error
|
|
18
|
+
* This middleware does NOT re-invoke the failed module. It records retry
|
|
19
|
+
* state and advisory delay hints in `context.data` for outer retry loops,
|
|
20
|
+
* then returns null so the original error always propagates to the caller.
|
|
21
|
+
*
|
|
22
|
+
* Context keys written on a retryable error:
|
|
23
|
+
* - `CTX_RETRY_COUNT_PREFIX + moduleId` — number of attempts so far
|
|
24
|
+
* - `CTX_RETRY_DELAY_PREFIX + moduleId` — suggested delay in ms before retry
|
|
25
|
+
*
|
|
26
|
+
* If you need real retries, wrap `Executor.call` in an outer retry loop
|
|
27
|
+
* that inspects `error.retryable` and the hint values above.
|
|
23
28
|
*/
|
|
24
|
-
export class
|
|
29
|
+
export class RetryHintMiddleware extends Middleware {
|
|
25
30
|
_config;
|
|
26
31
|
constructor(config) {
|
|
27
32
|
super();
|
|
@@ -39,15 +44,12 @@ export class RetryMiddleware extends Middleware {
|
|
|
39
44
|
}
|
|
40
45
|
const delayMs = this._calculateDelay(retryCount);
|
|
41
46
|
context.data[retryKey] = retryCount + 1;
|
|
42
|
-
console.warn(`[apcore:retry] Retrying module '${moduleId}' (attempt ${retryCount + 1}/${this._config.maxRetries}) after ${Math.round(delayMs)}ms`);
|
|
43
|
-
// Synchronous onError cannot await -- schedule sleep externally.
|
|
44
|
-
// In JS, the MiddlewareManager runs onError synchronously, so we block
|
|
45
|
-
// via a busy wait only if strictly needed, but the better approach is
|
|
46
|
-
// to return the inputs immediately and let the pipeline handle retry.
|
|
47
|
-
// For compatibility with the sync Middleware base class, we return
|
|
48
|
-
// inputs directly. The delay is handled via context.data hint.
|
|
49
47
|
context.data[`${CTX_RETRY_DELAY_PREFIX}${moduleId}`] = delayMs;
|
|
50
|
-
|
|
48
|
+
console.warn(`[apcore:retry] Retryable error in '${moduleId}' (attempt ${retryCount + 1}/${this._config.maxRetries}). ` +
|
|
49
|
+
`Hint written to context.data for outer retry loop (delay: ${Math.round(delayMs)}ms).`);
|
|
50
|
+
// Return null so the error propagates. Returning inputs here would cause
|
|
51
|
+
// the executor to treat them as the recovered output — a silent footgun.
|
|
52
|
+
return null;
|
|
51
53
|
}
|
|
52
54
|
_calculateDelay(attempt) {
|
|
53
55
|
let delay;
|
|
@@ -64,4 +66,8 @@ export class RetryMiddleware extends Middleware {
|
|
|
64
66
|
return delay;
|
|
65
67
|
}
|
|
66
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* @deprecated Use {@link RetryHintMiddleware} instead. Will be removed in 1.0.0.
|
|
71
|
+
*/
|
|
72
|
+
export const RetryMiddleware = RetryHintMiddleware;
|
|
67
73
|
//# sourceMappingURL=retry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/middleware/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAChE,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AAUnE,MAAM,oBAAoB,GAAgB;IACxC,UAAU,EAAE,CAAC;IACb,QAAQ,EAAE,aAAa;IACvB,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/middleware/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAChE,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AAUnE,MAAM,oBAAoB,GAAgB;IACxC,UAAU,EAAE,CAAC;IACb,QAAQ,EAAE,aAAa;IACvB,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,mBAAoB,SAAQ,UAAU;IACzC,OAAO,CAAc;IAE7B,YAAY,MAA6B;QACvC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,oBAAoB,EAAE,GAAG,MAAM,EAAE,CAAC;IACxD,CAAC;IAEQ,OAAO,CACd,QAAgB,EAChB,MAA+B,EAC/B,KAAY,EACZ,OAAgB;QAEhB,MAAM,SAAS,GAAI,KAAqB,CAAC,SAAS,CAAC;QACnD,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,QAAQ,GAAG,GAAG,sBAAsB,GAAG,QAAQ,EAAE,CAAC;QACxD,MAAM,UAAU,GAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAY,IAAI,CAAC,CAAC;QAE3D,IAAI,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAC1C,OAAO,CAAC,IAAI,CACV,+BAA+B,IAAI,CAAC,OAAO,CAAC,UAAU,0BAA0B,QAAQ,GAAG,CAC5F,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,GAAG,sBAAsB,GAAG,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC;QAE/D,OAAO,CAAC,IAAI,CACV,sCAAsC,QAAQ,cAAc,UAAU,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,KAAK;YACxG,6DAA6D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CACzF,CAAC;QAEF,yEAAyE;QACzE,yEAAyE;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,eAAe,CAAC,OAAe;QACrC,IAAI,KAAa,CAAC;QAClB,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACtC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,6DAA6D;YAC7D,KAAK,GAAG,IAAI,CAAC,GAAG,CACd,IAAI,CAAC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAC/C,IAAI,CAAC,OAAO,CAAC,UAAU,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,cAAc;QAC9C,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TracingMiddleware — OpenTelemetry-compatible span lifecycle management (Issue #42).
|
|
3
|
+
*
|
|
4
|
+
* Behaviour:
|
|
5
|
+
* - before(): creates a span named after the module_id, sets apcore.* attributes,
|
|
6
|
+
* and stores the span_id in context.data["_apcore.mw.tracing.span_id"].
|
|
7
|
+
* - after(): ends the span with status OK.
|
|
8
|
+
* - onError(): ends the span with status ERROR.
|
|
9
|
+
* - If @opentelemetry/api is not installed (and no tracer is injected), all methods
|
|
10
|
+
* are silent no-ops.
|
|
11
|
+
*/
|
|
12
|
+
import type { Context } from '../context.js';
|
|
13
|
+
import { Middleware } from './base.js';
|
|
14
|
+
export declare const CTX_TRACING_SPAN_ID = "_apcore.mw.tracing.span_id";
|
|
15
|
+
export interface OtelSpan {
|
|
16
|
+
spanContext(): {
|
|
17
|
+
spanId: string;
|
|
18
|
+
};
|
|
19
|
+
setAttribute(key: string, value: string): void;
|
|
20
|
+
setStatus(status: {
|
|
21
|
+
code: number;
|
|
22
|
+
message?: string;
|
|
23
|
+
}): void;
|
|
24
|
+
end(): void;
|
|
25
|
+
}
|
|
26
|
+
export interface OtelTracer {
|
|
27
|
+
startSpan(name: string, options?: Record<string, unknown>): OtelSpan;
|
|
28
|
+
}
|
|
29
|
+
export interface TracingMiddlewareOptions {
|
|
30
|
+
/** OTel service name used when initialising the default tracer. Default: 'apcore' */
|
|
31
|
+
serviceName?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Inject a custom tracer (primarily for testing).
|
|
34
|
+
* When provided this takes precedence over auto-detected OTel.
|
|
35
|
+
* Pass `null` to force no-op mode even if OTel is installed.
|
|
36
|
+
*/
|
|
37
|
+
tracer?: OtelTracer | null;
|
|
38
|
+
/** Middleware priority (0–1000). Default: 800 */
|
|
39
|
+
priority?: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class TracingMiddleware extends Middleware {
|
|
42
|
+
private readonly _tracer;
|
|
43
|
+
constructor(options?: TracingMiddlewareOptions);
|
|
44
|
+
/** Type-safe accessor for the active span stored by before(). */
|
|
45
|
+
private _activeSpan;
|
|
46
|
+
before(moduleId: string, _inputs: Record<string, unknown>, context: Context): Record<string, unknown> | null;
|
|
47
|
+
after(_moduleId: string, _inputs: Record<string, unknown>, _output: Record<string, unknown>, context: Context): Record<string, unknown> | null;
|
|
48
|
+
onError(_moduleId: string, _inputs: Record<string, unknown>, error: Error, context: Context): Record<string, unknown> | null;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../../src/middleware/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAUhE,MAAM,WAAW,QAAQ;IACvB,WAAW,IAAI;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,GAAG,IAAI,IAAI,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC;CACtE;AAaD,MAAM,WAAW,wBAAwB;IACvC,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;gBAEhC,OAAO,GAAE,wBAA6B;IAWlD,iEAAiE;IACjE,OAAO,CAAC,WAAW;IAUV,MAAM,CACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAkBxB,KAAK,CACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IASxB,OAAO,CACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAQlC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TracingMiddleware — OpenTelemetry-compatible span lifecycle management (Issue #42).
|
|
3
|
+
*
|
|
4
|
+
* Behaviour:
|
|
5
|
+
* - before(): creates a span named after the module_id, sets apcore.* attributes,
|
|
6
|
+
* and stores the span_id in context.data["_apcore.mw.tracing.span_id"].
|
|
7
|
+
* - after(): ends the span with status OK.
|
|
8
|
+
* - onError(): ends the span with status ERROR.
|
|
9
|
+
* - If @opentelemetry/api is not installed (and no tracer is injected), all methods
|
|
10
|
+
* are silent no-ops.
|
|
11
|
+
*/
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
import { Middleware } from './base.js';
|
|
14
|
+
export const CTX_TRACING_SPAN_ID = '_apcore.mw.tracing.span_id';
|
|
15
|
+
// Internal key — stores the live Span object for retrieval in after()/onError().
|
|
16
|
+
// Not part of the public spec; not serialised; prefixed with _ to signal internal use.
|
|
17
|
+
const CTX_TRACING_SPAN = '_apcore.mw.tracing._active_span';
|
|
18
|
+
// OTel SpanStatusCode values (from @opentelemetry/api):
|
|
19
|
+
// UNSET = 0, OK = 1, ERROR = 2
|
|
20
|
+
const SPAN_STATUS_OK = 1;
|
|
21
|
+
const SPAN_STATUS_ERROR = 2;
|
|
22
|
+
// Attempt to load @opentelemetry/api synchronously via Node.js require.
|
|
23
|
+
// If the package is absent, _defaultTrace remains null and TracingMiddleware
|
|
24
|
+
// silently becomes a no-op unless a tracer is explicitly injected.
|
|
25
|
+
const _nodeRequire = createRequire(import.meta.url);
|
|
26
|
+
let _defaultTrace = null;
|
|
27
|
+
try {
|
|
28
|
+
_defaultTrace = _nodeRequire('@opentelemetry/api').trace;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
_defaultTrace = null;
|
|
32
|
+
}
|
|
33
|
+
export class TracingMiddleware extends Middleware {
|
|
34
|
+
_tracer;
|
|
35
|
+
constructor(options = {}) {
|
|
36
|
+
super(options.priority ?? 800);
|
|
37
|
+
if ('tracer' in options) {
|
|
38
|
+
this._tracer = options.tracer ?? null;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const name = options.serviceName ?? 'apcore';
|
|
42
|
+
this._tracer = _defaultTrace ? _defaultTrace.getTracer(name) : null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Type-safe accessor for the active span stored by before(). */
|
|
46
|
+
_activeSpan(context) {
|
|
47
|
+
const val = context.data[CTX_TRACING_SPAN];
|
|
48
|
+
if (val == null)
|
|
49
|
+
return null;
|
|
50
|
+
// Minimal shape check: any valid OtelSpan must expose an `end` method.
|
|
51
|
+
if (typeof val === 'object' && typeof val.end === 'function') {
|
|
52
|
+
return val;
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
before(moduleId, _inputs, context) {
|
|
57
|
+
if (!this._tracer)
|
|
58
|
+
return null;
|
|
59
|
+
try {
|
|
60
|
+
const span = this._tracer.startSpan(moduleId);
|
|
61
|
+
span.setAttribute('apcore.trace_id', context.traceId);
|
|
62
|
+
span.setAttribute('apcore.caller_id', context.callerId ?? '');
|
|
63
|
+
span.setAttribute('apcore.module_id', moduleId);
|
|
64
|
+
context.data[CTX_TRACING_SPAN_ID] = span.spanContext().spanId;
|
|
65
|
+
context.data[CTX_TRACING_SPAN] = span;
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
console.warn(`[apcore:middleware] TracingMiddleware: span creation failed for '${moduleId}':`, err);
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
after(_moduleId, _inputs, _output, context) {
|
|
73
|
+
const span = this._activeSpan(context);
|
|
74
|
+
if (span) {
|
|
75
|
+
span.setStatus({ code: SPAN_STATUS_OK });
|
|
76
|
+
span.end();
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
onError(_moduleId, _inputs, error, context) {
|
|
81
|
+
const span = this._activeSpan(context);
|
|
82
|
+
if (span) {
|
|
83
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: String(error) });
|
|
84
|
+
span.end();
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../src/middleware/tracing.ts"],"names":[],"mappings":"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"}
|