@toa.io/core 1.0.0-alpha.32 → 1.0.0-alpha.320
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +28 -12
- package/transpiled/abandon.d.ts +9 -0
- package/transpiled/abandon.js +37 -0
- package/transpiled/abandon.js.map +1 -0
- package/transpiled/assignment.d.ts +6 -0
- package/transpiled/assignment.js +25 -0
- package/transpiled/assignment.js.map +1 -0
- package/transpiled/call.d.ts +10 -0
- package/transpiled/call.js +187 -0
- package/transpiled/call.js.map +1 -0
- package/transpiled/cascade.d.ts +7 -0
- package/transpiled/cascade.js +28 -0
- package/transpiled/cascade.js.map +1 -0
- package/transpiled/component.d.ts +15 -0
- package/transpiled/component.js +148 -0
- package/transpiled/component.js.map +1 -0
- package/transpiled/composition.d.ts +6 -0
- package/transpiled/composition.js +20 -0
- package/transpiled/composition.js.map +1 -0
- package/transpiled/connector.d.ts +71 -0
- package/transpiled/connector.js +248 -0
- package/transpiled/connector.js.map +1 -0
- package/transpiled/context.d.ts +25 -0
- package/transpiled/context.js +55 -0
- package/transpiled/context.js.map +1 -0
- package/transpiled/contract/component.d.ts +37 -0
- package/transpiled/contract/component.js +94 -0
- package/transpiled/contract/component.js.map +1 -0
- package/transpiled/contract/contract.d.ts +10 -0
- package/transpiled/contract/contract.js +14 -0
- package/transpiled/contract/contract.js.map +1 -0
- package/transpiled/contract/index.d.ts +4 -0
- package/transpiled/contract/index.js +5 -0
- package/transpiled/contract/index.js.map +1 -0
- package/transpiled/contract/reply.d.ts +7 -0
- package/transpiled/contract/reply.js +48 -0
- package/transpiled/contract/reply.js.map +1 -0
- package/transpiled/contract/request.d.ts +49 -0
- package/transpiled/contract/request.js +152 -0
- package/transpiled/contract/request.js.map +1 -0
- package/transpiled/contract/schemas.d.ts +4 -0
- package/transpiled/contract/schemas.js +38 -0
- package/transpiled/contract/schemas.js.map +1 -0
- package/transpiled/contract/system.d.ts +33 -0
- package/transpiled/contract/system.js +76 -0
- package/transpiled/contract/system.js.map +1 -0
- package/transpiled/deliveries.d.ts +22 -0
- package/transpiled/deliveries.js +31 -0
- package/transpiled/deliveries.js.map +1 -0
- package/transpiled/effect.d.ts +7 -0
- package/transpiled/effect.js +13 -0
- package/transpiled/effect.js.map +1 -0
- package/transpiled/emission.d.ts +10 -0
- package/transpiled/emission.js +16 -0
- package/transpiled/emission.js.map +1 -0
- package/transpiled/encoded.d.ts +16 -0
- package/transpiled/encoded.js +25 -0
- package/transpiled/encoded.js.map +1 -0
- package/transpiled/entities/changeset.d.ts +10 -0
- package/transpiled/entities/changeset.js +27 -0
- package/transpiled/entities/changeset.js.map +1 -0
- package/transpiled/entities/entity.d.ts +19 -0
- package/transpiled/entities/entity.js +137 -0
- package/transpiled/entities/entity.js.map +1 -0
- package/transpiled/entities/factory.d.ts +27 -0
- package/transpiled/entities/factory.js +38 -0
- package/transpiled/entities/factory.js.map +1 -0
- package/transpiled/entities/index.d.ts +5 -0
- package/transpiled/entities/index.js +6 -0
- package/transpiled/entities/index.js.map +1 -0
- package/transpiled/entities/newid.d.ts +11 -0
- package/transpiled/entities/newid.js +41 -0
- package/transpiled/entities/newid.js.map +1 -0
- package/transpiled/entities/set.d.ts +10 -0
- package/transpiled/entities/set.js +19 -0
- package/transpiled/entities/set.js.map +1 -0
- package/transpiled/event.d.ts +20 -0
- package/transpiled/event.js +65 -0
- package/transpiled/event.js.map +1 -0
- package/transpiled/exceptions.d.ts +110 -0
- package/transpiled/exceptions.js +215 -0
- package/transpiled/exceptions.js.map +1 -0
- package/transpiled/gate.d.ts +40 -0
- package/transpiled/gate.js +84 -0
- package/transpiled/gate.js.map +1 -0
- package/transpiled/guard.d.ts +7 -0
- package/transpiled/guard.js +12 -0
- package/transpiled/guard.js.map +1 -0
- package/transpiled/halting.d.ts +16 -0
- package/transpiled/halting.js +25 -0
- package/transpiled/halting.js.map +1 -0
- package/transpiled/index.d.ts +44 -0
- package/transpiled/index.js +36 -0
- package/transpiled/index.js.map +1 -0
- package/transpiled/instance.d.ts +10 -0
- package/transpiled/instance.js +30 -0
- package/transpiled/instance.js.map +1 -0
- package/transpiled/locator.d.ts +12 -0
- package/transpiled/locator.js +32 -0
- package/transpiled/locator.js.map +1 -0
- package/transpiled/measurements.d.ts +20 -0
- package/transpiled/measurements.js +40 -0
- package/transpiled/measurements.js.map +1 -0
- package/transpiled/observation.d.ts +7 -0
- package/transpiled/observation.js +14 -0
- package/transpiled/observation.js.map +1 -0
- package/transpiled/operation.d.ts +73 -0
- package/transpiled/operation.js +213 -0
- package/transpiled/operation.js.map +1 -0
- package/transpiled/outbox.d.ts +45 -0
- package/transpiled/outbox.js +448 -0
- package/transpiled/outbox.js.map +1 -0
- package/transpiled/outbox.measurements.d.ts +4 -0
- package/transpiled/outbox.measurements.js +38 -0
- package/transpiled/outbox.measurements.js.map +1 -0
- package/transpiled/parts.d.ts +20 -0
- package/transpiled/parts.js +23 -0
- package/transpiled/parts.js.map +1 -0
- package/transpiled/query/criteria.d.ts +6 -0
- package/transpiled/query/criteria.js +177 -0
- package/transpiled/query/criteria.js.map +1 -0
- package/transpiled/query/options.d.ts +3 -0
- package/transpiled/query/options.js +34 -0
- package/transpiled/query/options.js.map +1 -0
- package/transpiled/query.d.ts +9 -0
- package/transpiled/query.js +57 -0
- package/transpiled/query.js.map +1 -0
- package/transpiled/receiver.d.ts +20 -0
- package/transpiled/receiver.js +113 -0
- package/transpiled/receiver.js.map +1 -0
- package/transpiled/reflection.d.ts +9 -0
- package/transpiled/reflection.js +13 -0
- package/transpiled/reflection.js.map +1 -0
- package/transpiled/remote.d.ts +10 -0
- package/transpiled/remote.js +11 -0
- package/transpiled/remote.js.map +1 -0
- package/transpiled/rendering.d.ts +13 -0
- package/transpiled/rendering.js +21 -0
- package/transpiled/rendering.js.map +1 -0
- package/transpiled/safety.d.ts +5 -0
- package/transpiled/safety.js +26 -0
- package/transpiled/safety.js.map +1 -0
- package/transpiled/state.d.ts +36 -0
- package/transpiled/state.js +131 -0
- package/transpiled/state.js.map +1 -0
- package/transpiled/trail.d.ts +78 -0
- package/transpiled/trail.js +112 -0
- package/transpiled/trail.js.map +1 -0
- package/transpiled/transition.d.ts +14 -0
- package/transpiled/transition.js +51 -0
- package/transpiled/transition.js.map +1 -0
- package/transpiled/transmission.d.ts +8 -0
- package/transpiled/transmission.js +30 -0
- package/transpiled/transmission.js.map +1 -0
- package/transpiled/types/atomicity.d.ts +58 -0
- package/transpiled/types/atomicity.js +2 -0
- package/transpiled/types/atomicity.js.map +1 -0
- package/transpiled/types/bindings.d.ts +82 -0
- package/transpiled/types/bindings.js +2 -0
- package/transpiled/types/bindings.js.map +1 -0
- package/transpiled/types/bridges.d.ts +41 -0
- package/transpiled/types/bridges.js +2 -0
- package/transpiled/types/bridges.js.map +1 -0
- package/transpiled/types/extensions.d.ts +121 -0
- package/transpiled/types/extensions.js +2 -0
- package/transpiled/types/extensions.js.map +1 -0
- package/transpiled/types/inbox.d.ts +27 -0
- package/transpiled/types/inbox.js +2 -0
- package/transpiled/types/inbox.js.map +1 -0
- package/transpiled/types/index.d.ts +14 -0
- package/transpiled/types/index.js +9 -0
- package/transpiled/types/index.js.map +1 -0
- package/transpiled/types/message.d.ts +16 -0
- package/transpiled/types/message.js +2 -0
- package/transpiled/types/message.js.map +1 -0
- package/transpiled/types/operations.d.ts +15 -0
- package/transpiled/types/operations.js +2 -0
- package/transpiled/types/operations.js.map +1 -0
- package/transpiled/types/outbox.d.ts +68 -0
- package/transpiled/types/outbox.js +2 -0
- package/transpiled/types/outbox.js.map +1 -0
- package/transpiled/types/receiver.d.ts +9 -0
- package/transpiled/types/receiver.js +2 -0
- package/transpiled/types/receiver.js.map +1 -0
- package/transpiled/types/request.d.ts +119 -0
- package/transpiled/types/request.js +2 -0
- package/transpiled/types/request.js.map +1 -0
- package/transpiled/types/state.d.ts +9 -0
- package/transpiled/types/state.js +2 -0
- package/transpiled/types/state.js.map +1 -0
- package/transpiled/types/storages.d.ts +154 -0
- package/transpiled/types/storages.js +2 -0
- package/transpiled/types/storages.js.map +1 -0
- package/transpiled/unmanaged.d.ts +5 -0
- package/transpiled/unmanaged.js +7 -0
- package/transpiled/unmanaged.js.map +1 -0
- package/src/assignment.js +0 -31
- package/src/call.js +0 -42
- package/src/cascade.js +0 -35
- package/src/component.js +0 -41
- package/src/composition.js +0 -25
- package/src/connector.js +0 -183
- package/src/context.js +0 -55
- package/src/contract/conditions.js +0 -21
- package/src/contract/index.js +0 -7
- package/src/contract/reply.js +0 -25
- package/src/contract/request.js +0 -67
- package/src/contract/schemas/error.yaml +0 -9
- package/src/contract/schemas/index.js +0 -7
- package/src/contract/schemas/query.yaml +0 -30
- package/src/discovery.js +0 -44
- package/src/emission.js +0 -23
- package/src/entities/changeset.js +0 -38
- package/src/entities/entity.js +0 -74
- package/src/entities/factory.js +0 -33
- package/src/entities/index.js +0 -5
- package/src/entities/set.js +0 -15
- package/src/event.js +0 -40
- package/src/exceptions.js +0 -100
- package/src/exposition.js +0 -27
- package/src/index.js +0 -47
- package/src/locator.js +0 -54
- package/src/observation.js +0 -20
- package/src/operation.js +0 -69
- package/src/query/criteria.js +0 -41
- package/src/query/options.js +0 -40
- package/src/query.js +0 -41
- package/src/receiver.js +0 -61
- package/src/reflection.js +0 -28
- package/src/remote.js +0 -17
- package/src/state.js +0 -99
- package/src/transition.js +0 -67
- package/src/transmission.js +0 -33
- package/test/call.fixtures.js +0 -27
- package/test/call.test.js +0 -46
- package/test/component.fixtures.js +0 -21
- package/test/component.test.js +0 -40
- package/test/connector.fixtures.js +0 -40
- package/test/connector.test.js +0 -176
- package/test/context.fixtures.js +0 -18
- package/test/context.test.js +0 -29
- package/test/contract/conditions.test.js +0 -26
- package/test/contract/contract.fixtures.js +0 -33
- package/test/contract/request.test.js +0 -112
- package/test/emission.fixtures.js +0 -17
- package/test/emission.test.js +0 -35
- package/test/entities/entity.fixtures.js +0 -29
- package/test/entities/entity.test.js +0 -65
- package/test/entities/factory.fixtures.js +0 -18
- package/test/entities/factory.test.js +0 -48
- package/test/entities/set.fixtures.js +0 -11
- package/test/entities/set.test.js +0 -12
- package/test/event.fixtures.js +0 -29
- package/test/event.test.js +0 -118
- package/test/locator.test.js +0 -113
- package/test/query.fixtures.js +0 -100
- package/test/query.test.js +0 -86
- package/test/receiver.fixtures.js +0 -23
- package/test/receiver.test.js +0 -95
- package/test/reflection.test.js +0 -30
- package/test/state.fixtures.js +0 -47
- package/test/state.test.js +0 -46
- package/test/transmission.fixtures.js +0 -15
- package/test/transmission.test.js +0 -46
- package/types/bindings.d.ts +0 -40
- package/types/bridges.ts +0 -30
- package/types/component.d.ts +0 -9
- package/types/connector.d.ts +0 -18
- package/types/context.d.ts +0 -21
- package/types/entity.d.ts +0 -46
- package/types/event.d.ts +0 -11
- package/types/exception.d.ts +0 -4
- package/types/extensions.d.ts +0 -29
- package/types/index.ts +0 -14
- package/types/locator.d.ts +0 -13
- package/types/message.d.ts +0 -3
- package/types/operations.d.ts +0 -2
- package/types/query.d.ts +0 -15
- package/types/receiver.d.ts +0 -12
- package/types/reflection.d.ts +0 -14
- package/types/request.d.ts +0 -23
- package/types/state.d.ts +0 -35
- package/types/storages.d.ts +0 -71
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { registry } from 'openspan';
|
|
2
|
+
/**
|
|
3
|
+
* What core measures, declared once for the process.
|
|
4
|
+
*
|
|
5
|
+
* An invocation and a call are two metrics rather than one with a `kind` label: a `Remote` is a
|
|
6
|
+
* `Component` too and names the very endpoint the callee does, so a single name would hold two
|
|
7
|
+
* quantities — the callee's own work, and the caller's round trip with the transport in it — and
|
|
8
|
+
* would count every remote call twice, once in each process.
|
|
9
|
+
*/
|
|
10
|
+
const meters = registry();
|
|
11
|
+
const COMPONENT = { component: null };
|
|
12
|
+
const ENDPOINT = { component: null, operation: null };
|
|
13
|
+
/** Prometheus' own ladder, in seconds: from five milliseconds to ten seconds. */
|
|
14
|
+
export const DURATIONS = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10];
|
|
15
|
+
export const operation = {
|
|
16
|
+
duration: meters.histogram('toa.operation.duration', { buckets: DURATIONS, unit: 's' }, ENDPOINT),
|
|
17
|
+
/** a refusal the operation chose: the operation working */
|
|
18
|
+
errors: meters.counter('toa.operation.errors', {
|
|
19
|
+
...ENDPOINT,
|
|
20
|
+
code: null
|
|
21
|
+
}),
|
|
22
|
+
/** a failure nobody chose; `outcome` says whether another attempt could pass */
|
|
23
|
+
exceptions: meters.counter('toa.operation.exceptions', {
|
|
24
|
+
...ENDPOINT,
|
|
25
|
+
code: null,
|
|
26
|
+
outcome: null
|
|
27
|
+
}),
|
|
28
|
+
inflight: meters.gauge('toa.operation.inflight', COMPONENT)
|
|
29
|
+
};
|
|
30
|
+
export const call = {
|
|
31
|
+
duration: meters.histogram('toa.call.duration', { buckets: DURATIONS, unit: 's' }, ENDPOINT),
|
|
32
|
+
/** only what the transmission raised: what the callee sent back is counted where it happened */
|
|
33
|
+
exceptions: meters.counter('toa.call.exceptions', { ...ENDPOINT, code: null }),
|
|
34
|
+
/** callers waiting, which is held for the whole round trip and not only while one runs */
|
|
35
|
+
inflight: meters.gauge('toa.call.inflight', COMPONENT)
|
|
36
|
+
};
|
|
37
|
+
export const event = {
|
|
38
|
+
publish: meters.histogram('toa.event.publish.duration', { buckets: DURATIONS, unit: 's' }, { event: null })
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=measurements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measurements.js","sourceRoot":"","sources":["../source/measurements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAEnC;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAA;AAEzB,MAAM,SAAS,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AACrC,MAAM,QAAQ,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AAErD,iFAAiF;AACjF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AAElF,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC,SAAS,CACxB,wBAAwB,EACxB,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EACjC,QAAQ,CACT;IAED,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE;QAC7C,GAAG,QAAQ;QACX,IAAI,EAAE,IAAI;KACX,CAAC;IAEF,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,0BAA0B,EAAE;QACrD,GAAG,QAAQ;QACX,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,IAAI;KACd,CAAC;IAEF,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,SAAS,CAAC;CAC5D,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC,SAAS,CACxB,mBAAmB,EACnB,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EACjC,QAAQ,CACT;IAED,gGAAgG;IAChG,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAE9E,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,SAAS,CAAC;CACvD,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO,EAAE,MAAM,CAAC,SAAS,CACvB,4BAA4B,EAC5B,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EACjC,EAAE,KAAK,EAAE,IAAI,EAAE,CAChB;CACF,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Operation } from './operation.ts';
|
|
2
|
+
import type { Store } from './operation.ts';
|
|
3
|
+
export declare class Observation extends Operation {
|
|
4
|
+
/** an observation answers what it read, and writes none of it back */
|
|
5
|
+
protected projects: boolean;
|
|
6
|
+
protected run(store: Store): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Operation } from './operation.js';
|
|
2
|
+
export class Observation extends Operation {
|
|
3
|
+
/** an observation answers what it read, and writes none of it back */
|
|
4
|
+
projects = true;
|
|
5
|
+
async run(store) {
|
|
6
|
+
const scope = store.scope;
|
|
7
|
+
if (scope === null ||
|
|
8
|
+
(scope?.deleted === true && store.request.query?.options?.deleted !== true))
|
|
9
|
+
store.reply = null;
|
|
10
|
+
else
|
|
11
|
+
await super.run(store);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=observation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation.js","sourceRoot":"","sources":["../source/observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI1C,MAAM,OAAO,WAAY,SAAQ,SAAS;IACxC,sEAAsE;IACnD,QAAQ,GAAY,IAAI,CAAA;IAExB,KAAK,CAAC,GAAG,CAAC,KAAY;QACvC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAsB,CAAA;QAE1C,IACE,KAAK,KAAK,IAAI;YACd,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,IAAK,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;YAEpF,KAAK,CAAC,KAAK,GAAG,IAAI,CAAA;;YACf,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { Connector } from './connector.ts';
|
|
3
|
+
import type { Cascade } from './cascade.ts';
|
|
4
|
+
import type { State } from './state.ts';
|
|
5
|
+
import type { Query as Translator } from './query.ts';
|
|
6
|
+
import type { Contract } from './contract/contract.ts';
|
|
7
|
+
import type { Entity } from './entities/entity.ts';
|
|
8
|
+
import type { EntitySet } from './entities/set.ts';
|
|
9
|
+
import type { Changeset } from './entities/changeset.ts';
|
|
10
|
+
import type { scope as Scope } from './types/operations.ts';
|
|
11
|
+
import type { Call } from './types/inbox.ts';
|
|
12
|
+
import type { Envelope, Query } from './types/request.ts';
|
|
13
|
+
/** What an operation acquires for the algorithm to run against. */
|
|
14
|
+
export type Scoped = Entity | EntitySet | Changeset | Readable | null;
|
|
15
|
+
/** What one invocation carries from step to step. */
|
|
16
|
+
export interface Store {
|
|
17
|
+
request: Envelope;
|
|
18
|
+
scope?: Scoped;
|
|
19
|
+
state?: any;
|
|
20
|
+
reply?: any;
|
|
21
|
+
/** set by a transition, which is the only operation that runs its steps again */
|
|
22
|
+
retry?: () => Promise<any>;
|
|
23
|
+
}
|
|
24
|
+
export interface Contracts {
|
|
25
|
+
request: Contract;
|
|
26
|
+
reply: Contract;
|
|
27
|
+
}
|
|
28
|
+
export interface Definition {
|
|
29
|
+
scope: Scope;
|
|
30
|
+
concurrency?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the same call arriving twice changes state once; see `documentation/inbox.md`. A
|
|
33
|
+
* number is how many seconds a call is remembered, where the deployment's window is not the
|
|
34
|
+
* one its callers retry within.
|
|
35
|
+
*/
|
|
36
|
+
once?: boolean | number;
|
|
37
|
+
}
|
|
38
|
+
export declare class Operation extends Connector {
|
|
39
|
+
#private;
|
|
40
|
+
scope: State;
|
|
41
|
+
/**
|
|
42
|
+
* Whether what this operation acquires may be modified and committed. Only a
|
|
43
|
+
* transition commits, and only a commit needs the pre-image an entity keeps
|
|
44
|
+
* to diff the new state against.
|
|
45
|
+
*
|
|
46
|
+
* @protected
|
|
47
|
+
*/
|
|
48
|
+
protected mutable: boolean;
|
|
49
|
+
/** whether a query of this operation may name the properties its storage reads */
|
|
50
|
+
protected projects: boolean;
|
|
51
|
+
constructor(cascade: Cascade, scope: State, contracts: Contracts, query: Translator, definition: Definition);
|
|
52
|
+
invoke(request: Envelope): Promise<any>;
|
|
53
|
+
/**
|
|
54
|
+
* The call, once. What it answered is recorded with what it changed, in one transaction, so a
|
|
55
|
+
* second arrival of the same identity finds the key taken, changes nothing, and is answered
|
|
56
|
+
* with what the first one answered.
|
|
57
|
+
*
|
|
58
|
+
* The read in front of it is not what makes that true — the key is — but it is what keeps the
|
|
59
|
+
* ordinary duplicate from running the algorithm at all, and the ordinary duplicate is a
|
|
60
|
+
* retransmission that arrives after the first call has finished.
|
|
61
|
+
*/
|
|
62
|
+
protected once(store: Store): Promise<any>;
|
|
63
|
+
/**
|
|
64
|
+
* What is recorded with the write. Read where the write is made, which is after the algorithm
|
|
65
|
+
* has run, because the reply is what a duplicate is answered with.
|
|
66
|
+
*/
|
|
67
|
+
protected call(store: Store): Call | undefined;
|
|
68
|
+
protected process(store: Store): Promise<any>;
|
|
69
|
+
protected acquire(store: Store): Promise<void>;
|
|
70
|
+
protected run(store: Store): Promise<void>;
|
|
71
|
+
protected commit(_store: Store): Promise<void>;
|
|
72
|
+
protected query(query?: Query): Promise<Scoped>;
|
|
73
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { Readable, Transform, pipeline } from 'node:stream';
|
|
2
|
+
import { Connector } from './connector.js';
|
|
3
|
+
import { codes, SystemException, RequestContractException } from './exceptions.js';
|
|
4
|
+
import * as parts from './parts.js';
|
|
5
|
+
import { environment } from '@toa.io/generic';
|
|
6
|
+
export class Operation extends Connector {
|
|
7
|
+
scope;
|
|
8
|
+
/**
|
|
9
|
+
* Whether what this operation acquires may be modified and committed. Only a
|
|
10
|
+
* transition commits, and only a commit needs the pre-image an entity keeps
|
|
11
|
+
* to diff the new state against.
|
|
12
|
+
*
|
|
13
|
+
* @protected
|
|
14
|
+
*/
|
|
15
|
+
mutable = false;
|
|
16
|
+
/** whether a query of this operation may name the properties its storage reads */
|
|
17
|
+
projects = false;
|
|
18
|
+
#cascade;
|
|
19
|
+
#contracts;
|
|
20
|
+
#query;
|
|
21
|
+
#scope;
|
|
22
|
+
#once;
|
|
23
|
+
/** what this operation states of how long a call is remembered; the deployment's where absent */
|
|
24
|
+
#retention;
|
|
25
|
+
/** a reply is validated only on local environments, which are set before an operation is built */
|
|
26
|
+
#local;
|
|
27
|
+
// eslint-disable-next-line max-params
|
|
28
|
+
constructor(cascade, scope, contracts, query, definition) {
|
|
29
|
+
super();
|
|
30
|
+
this.scope = scope;
|
|
31
|
+
this.#cascade = cascade;
|
|
32
|
+
this.#contracts = contracts;
|
|
33
|
+
this.#query = query;
|
|
34
|
+
this.#scope = definition.scope;
|
|
35
|
+
this.#once = definition.once === true || typeof definition.once === 'number';
|
|
36
|
+
this.#retention = typeof definition.once === 'number' ? definition.once : undefined;
|
|
37
|
+
this.#local = environment.get('TOA_ENV') === 'local';
|
|
38
|
+
this.depends(cascade);
|
|
39
|
+
}
|
|
40
|
+
async invoke(request) {
|
|
41
|
+
try {
|
|
42
|
+
/*
|
|
43
|
+
* A projection is what a storage reads, and only an observation's read is never written
|
|
44
|
+
* back: a transition replaces the record it read, an assignment's event carries the record
|
|
45
|
+
* it changed, and an effect reads for what it does next. Refused here rather than by the
|
|
46
|
+
* contract alone, because an authentic request skips the contract.
|
|
47
|
+
*/
|
|
48
|
+
if (!this.projects && request.query?.projection !== undefined)
|
|
49
|
+
throw new RequestContractException('`projection` is read by an observation alone');
|
|
50
|
+
if (request.authentic !== true)
|
|
51
|
+
this.#contracts.request.fit(request);
|
|
52
|
+
// the request carries the query onward in its parsed form: what a storage is given,
|
|
53
|
+
// not what the caller sent
|
|
54
|
+
if ('query' in request)
|
|
55
|
+
request.query = this.#query.parse(request.query);
|
|
56
|
+
// validate entity
|
|
57
|
+
if ('entity' in request)
|
|
58
|
+
this.scope.fit(request.entity);
|
|
59
|
+
const store = { request };
|
|
60
|
+
const reply = this.#once ? await this.once(store) : await this.process(store);
|
|
61
|
+
return restrict(reply, request.output);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
const exception = e instanceof Error ? new SystemException(e) : e;
|
|
65
|
+
return { exception };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The call, once. What it answered is recorded with what it changed, in one transaction, so a
|
|
70
|
+
* second arrival of the same identity finds the key taken, changes nothing, and is answered
|
|
71
|
+
* with what the first one answered.
|
|
72
|
+
*
|
|
73
|
+
* The read in front of it is not what makes that true — the key is — but it is what keeps the
|
|
74
|
+
* ordinary duplicate from running the algorithm at all, and the ordinary duplicate is a
|
|
75
|
+
* retransmission that arrives after the first call has finished.
|
|
76
|
+
*/
|
|
77
|
+
async once(store) {
|
|
78
|
+
const { id } = store.request;
|
|
79
|
+
if (id === undefined)
|
|
80
|
+
throw new RequestContractException('a request to an operation declared `once` carries no id');
|
|
81
|
+
const recalled = await this.scope.recall(id);
|
|
82
|
+
if (recalled !== null)
|
|
83
|
+
return recalled;
|
|
84
|
+
try {
|
|
85
|
+
return await this.process(store);
|
|
86
|
+
}
|
|
87
|
+
catch (exception) {
|
|
88
|
+
if (exception?.code !== codes.DuplicateCall)
|
|
89
|
+
throw exception;
|
|
90
|
+
/*
|
|
91
|
+
* It was made between the read and the write — a duplicate that arrived while the first
|
|
92
|
+
* was still running, and lost. Nothing of this one was committed, so what is answered is
|
|
93
|
+
* the other one's reply. Absent only if the record expired in between, which is the
|
|
94
|
+
* window closing on a call nobody is waiting on any more.
|
|
95
|
+
*/
|
|
96
|
+
return (await this.scope.recall(id)) ?? { exception };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* What is recorded with the write. Read where the write is made, which is after the algorithm
|
|
101
|
+
* has run, because the reply is what a duplicate is answered with.
|
|
102
|
+
*/
|
|
103
|
+
call(store) {
|
|
104
|
+
if (!this.#once)
|
|
105
|
+
return undefined;
|
|
106
|
+
/*
|
|
107
|
+
* A copy: an assignment fills its output in after the write it is recorded by returns, and
|
|
108
|
+
* what is recorded must be what was known when the record was made rather than whatever the
|
|
109
|
+
* reply became afterwards.
|
|
110
|
+
*/
|
|
111
|
+
const call = { id: store.request.id, reply: { ...store.reply } };
|
|
112
|
+
if (this.#retention !== undefined)
|
|
113
|
+
call.retention = this.#retention;
|
|
114
|
+
return call;
|
|
115
|
+
}
|
|
116
|
+
async process(store) {
|
|
117
|
+
await this.acquire(store);
|
|
118
|
+
await this.run(store);
|
|
119
|
+
await this.commit(store);
|
|
120
|
+
return store.reply;
|
|
121
|
+
}
|
|
122
|
+
async acquire(store) {
|
|
123
|
+
if (this.#scope === 'none')
|
|
124
|
+
return;
|
|
125
|
+
const scope = await this.query(store.request.query);
|
|
126
|
+
const raw = scope === null || scope instanceof Readable;
|
|
127
|
+
store.scope = scope;
|
|
128
|
+
store.state = raw ? scope : scope.get();
|
|
129
|
+
}
|
|
130
|
+
async run(store) {
|
|
131
|
+
const { request, state } = store;
|
|
132
|
+
const reply = await this.#cascade.run(request.input, state);
|
|
133
|
+
if (this.#local && !(reply instanceof Readable))
|
|
134
|
+
this.#contracts.reply.fit(reply);
|
|
135
|
+
store.reply = reply;
|
|
136
|
+
}
|
|
137
|
+
async commit(_store) { }
|
|
138
|
+
async query(query) {
|
|
139
|
+
if (query === undefined)
|
|
140
|
+
throw new RequestContractException('Request query is required');
|
|
141
|
+
const acquire = this.scope[this.#scope];
|
|
142
|
+
return acquire.call(this.scope, query, this.mutable);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* What a caller receives of the output it asked for: each object of it keeps the properties the
|
|
147
|
+
* request named, in the order the object holds them, and an empty list leaves no output at all.
|
|
148
|
+
* A system property is one of them: a caller that reads `VERSION` asks for it. An object is one
|
|
149
|
+
* the output is, one of an array it is, or one a stream it is yields. An error, an exception and
|
|
150
|
+
* a value that is not an object are answered as they are.
|
|
151
|
+
*/
|
|
152
|
+
function restrict(reply, output) {
|
|
153
|
+
if (output === undefined || reply === null || typeof reply !== 'object')
|
|
154
|
+
return reply;
|
|
155
|
+
// a stream is answered bare, where anything else is answered in `output`
|
|
156
|
+
if (reply instanceof Readable)
|
|
157
|
+
return restrict({ output: reply }, output).output ?? {};
|
|
158
|
+
const answered = reply.output;
|
|
159
|
+
if (answered === undefined || answered === null)
|
|
160
|
+
return reply;
|
|
161
|
+
if (output.length === 0) {
|
|
162
|
+
// nobody reads it, and what it holds open — a cursor, a reply pipe — is let go now
|
|
163
|
+
if (answered instanceof Readable)
|
|
164
|
+
answered.destroy();
|
|
165
|
+
delete reply.output;
|
|
166
|
+
return reply;
|
|
167
|
+
}
|
|
168
|
+
if (typeof answered !== 'object')
|
|
169
|
+
return reply;
|
|
170
|
+
const allowed = new Set(output);
|
|
171
|
+
// a stream of bytes is a value, as a primitive is: there is no property of it to leave out
|
|
172
|
+
if (answered instanceof Readable)
|
|
173
|
+
reply.output = answered.readableObjectMode ? restricted(answered, allowed) : answered;
|
|
174
|
+
else if (Array.isArray(answered))
|
|
175
|
+
reply.output = answered.map((value) => fitted(value, allowed));
|
|
176
|
+
else
|
|
177
|
+
reply.output = fit(answered, allowed);
|
|
178
|
+
return reply;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* A stream of what `fitted` makes of each value. Joined by `pipeline`, so that a failure of
|
|
182
|
+
* either side reaches the other: the source's error is the reader's, and a reader that stops
|
|
183
|
+
* reading closes the source.
|
|
184
|
+
*/
|
|
185
|
+
function restricted(source, allowed) {
|
|
186
|
+
const transform = new Transform({
|
|
187
|
+
objectMode: true,
|
|
188
|
+
transform(value, _, callback) {
|
|
189
|
+
callback(null, fitted(value, allowed));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return pipeline(source, transform, noop);
|
|
193
|
+
}
|
|
194
|
+
function fitted(value, allowed) {
|
|
195
|
+
// what a part carries of the set is its entry; a removal and a token are not the entity's
|
|
196
|
+
if (parts.is(value))
|
|
197
|
+
return 'entry' in value ? { entry: fit(value.entry, allowed) } : value;
|
|
198
|
+
return value !== null && typeof value === 'object' && !ArrayBuffer.isView(value)
|
|
199
|
+
? fit(value, allowed)
|
|
200
|
+
: value;
|
|
201
|
+
}
|
|
202
|
+
// what `pipeline` reports is what each stream already carries to its reader
|
|
203
|
+
function noop() { }
|
|
204
|
+
/** Runs per entity of a collection, hence the set and the absence of intermediates. */
|
|
205
|
+
function fit(entity, allowed) {
|
|
206
|
+
const output = {};
|
|
207
|
+
// the entity's own keys, so that what is answered keeps the order it was built in
|
|
208
|
+
for (const key of Object.keys(entity))
|
|
209
|
+
if (allowed.has(key))
|
|
210
|
+
output[key] = entity[key];
|
|
211
|
+
return output;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=operation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation.js","sourceRoot":"","sources":["../source/operation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Connector } from './connector.ts';
|
|
2
|
+
import type { Atom } from './types/atomicity.ts';
|
|
3
|
+
import type { Storage } from './types/storages.ts';
|
|
4
|
+
import type { Destination, Row } from './types/outbox.ts';
|
|
5
|
+
import type { Event } from './types/state.ts';
|
|
6
|
+
export interface Options {
|
|
7
|
+
interval?: number;
|
|
8
|
+
batch?: number;
|
|
9
|
+
gap?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Owns the intent to publish. A row is built before the write so that the storage can commit
|
|
13
|
+
* it in the same transaction as the entity; publication then happens off the operation's path,
|
|
14
|
+
* and anything that fails to publish is recovered from the row.
|
|
15
|
+
*
|
|
16
|
+
* The mechanism is a safety net: in a healthy system the row is written, published within
|
|
17
|
+
* milliseconds by the same process, and marked published on that process's next tick.
|
|
18
|
+
*
|
|
19
|
+
* A storage that cannot commit a row atomically has no outbox, and this degrades to the
|
|
20
|
+
* inline emission it replaces.
|
|
21
|
+
*/
|
|
22
|
+
export declare class Outbox extends Connector {
|
|
23
|
+
#private;
|
|
24
|
+
constructor(destinations: Destination[], storage: Storage | undefined, atom: Atom, options?: Options);
|
|
25
|
+
/** whether the storage can commit a row atomically with the entity */
|
|
26
|
+
get durable(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* An assignment's images are the write's own, so it hands over an event with neither, and
|
|
29
|
+
* the storage fills them in.
|
|
30
|
+
*/
|
|
31
|
+
row(event: Partial<Event>): Row;
|
|
32
|
+
/**
|
|
33
|
+
* Hands a committed row over. Awaited by the caller only on the legacy path — with an
|
|
34
|
+
* outbox this returns at once and the broker leaves the operation's path.
|
|
35
|
+
*/
|
|
36
|
+
publish(row: Row): Promise<void> | void;
|
|
37
|
+
protected open(): Promise<void>;
|
|
38
|
+
protected close(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Constant, never configuration: rows carry their lane, so lowering this would leave rows in
|
|
42
|
+
* lanes nobody reads any more. It is also the ceiling on replicas of one component, and a
|
|
43
|
+
* power of two so that the common replica counts divide evenly.
|
|
44
|
+
*/
|
|
45
|
+
export declare const LANES = 128;
|