@toa.io/core 1.0.0-alpha.284 → 1.0.0-alpha.286
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 +19 -7
- package/source/assignment.ts +27 -0
- package/{src/call.js → source/call.ts} +16 -21
- package/{src/cascade.js → source/cascade.ts} +6 -8
- package/{src/component.js → source/component.ts} +27 -25
- package/{src/composition.js → source/composition.ts} +9 -3
- package/{src/connector.js → source/connector.ts} +36 -55
- package/source/context.ts +67 -0
- package/source/contract/contract.ts +23 -0
- package/{src/contract/reply.js → source/contract/reply.ts} +26 -19
- package/source/contract/request.ts +85 -0
- package/source/contract/schemas.ts +39 -0
- package/{src/discovery.js → source/discovery.ts} +15 -8
- package/source/effect.ts +14 -0
- package/{src/emission.js → source/emission.ts} +5 -3
- package/source/entities/changeset.ts +37 -0
- package/source/entities/entity.ts +137 -0
- package/source/entities/factory.ts +52 -0
- package/source/entities/index.ts +4 -0
- package/{src/entities/newid.js → source/entities/newid.ts} +1 -1
- package/{src/entities/set.js → source/entities/set.ts} +8 -5
- package/source/event.ts +57 -0
- package/{src/exceptions.js → source/exceptions.ts} +52 -33
- package/source/exposition.ts +33 -0
- package/source/guard.ts +16 -0
- package/{src/index.js → source/index.ts} +8 -0
- package/{src/locator.js → source/locator.ts} +17 -30
- package/source/observation.ts +16 -0
- package/source/operation.ts +138 -0
- package/{src/outbox/outbox.js → source/outbox/outbox.ts} +87 -53
- package/source/query/criteria.ts +90 -0
- package/source/query/options.ts +35 -0
- package/{src/query.js → source/query.ts} +14 -17
- package/source/receiver.ts +120 -0
- package/source/reflection.ts +20 -0
- package/source/remote.ts +20 -0
- package/source/state.ts +179 -0
- package/source/transition.ts +79 -0
- package/{src/transmission.js → source/transmission.ts} +8 -8
- package/source/types/atomicity.ts +63 -0
- package/source/types/bindings.ts +59 -0
- package/source/types/bridges.ts +54 -0
- package/source/types/extensions.ts +89 -0
- package/{types → source/types}/index.ts +9 -16
- package/{types/message.d.ts → source/types/message.ts} +2 -1
- package/source/types/operations.ts +31 -0
- package/source/types/outbox.ts +35 -0
- package/source/types/receiver.ts +10 -0
- package/{types/request.d.ts → source/types/request.ts} +8 -9
- package/source/types/state.ts +9 -0
- package/source/types/storages.ts +129 -0
- package/source/unmanaged.ts +8 -0
- package/test/call.fixtures.js +3 -1
- package/test/call.test.js +28 -7
- package/test/component.test.js +10 -5
- package/test/connector.fixtures.js +7 -7
- package/test/connector.test.js +15 -2
- package/test/context.fixtures.js +1 -1
- package/test/context.test.js +4 -4
- package/test/contract/conditions.test.js +6 -2
- package/test/contract/contract.fixtures.js +3 -4
- package/test/contract/request.test.js +68 -34
- package/test/discovery.test.js +10 -3
- package/test/emission.test.js +16 -8
- package/test/entities/entity.fixtures.js +5 -6
- package/test/entities/entity.test.js +54 -20
- package/test/entities/factory.fixtures.js +11 -10
- package/test/entities/factory.test.js +47 -10
- package/test/entities/set.test.js +1 -1
- package/test/event.test.js +29 -11
- package/test/locator.test.js +10 -4
- package/test/outbox.test.js +49 -15
- package/test/query.test.js +69 -7
- package/test/receiver.fixtures.js +2 -2
- package/test/receiver.test.js +53 -27
- package/test/reflection.test.js +3 -3
- package/test/state.fixtures.js +10 -3
- package/test/state.test.js +77 -14
- package/test/transmission.test.js +25 -12
- package/transpiled/assignment.d.ts +6 -0
- package/transpiled/assignment.js +20 -0
- package/transpiled/assignment.js.map +1 -0
- package/transpiled/call.d.ts +10 -0
- package/transpiled/call.js +52 -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 +61 -0
- package/transpiled/component.js.map +1 -0
- package/transpiled/composition.d.ts +6 -0
- package/transpiled/composition.js +23 -0
- package/transpiled/composition.js.map +1 -0
- package/transpiled/connector.d.ts +47 -0
- package/transpiled/connector.js +143 -0
- package/transpiled/connector.js.map +1 -0
- package/transpiled/context.d.ts +18 -0
- package/transpiled/context.js +41 -0
- package/transpiled/context.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 +2 -0
- package/transpiled/contract/index.js +3 -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 +24 -0
- package/transpiled/contract/request.js +59 -0
- package/transpiled/contract/request.js.map +1 -0
- package/transpiled/contract/schemas.d.ts +4 -0
- package/transpiled/contract/schemas.js +36 -0
- package/transpiled/contract/schemas.js.map +1 -0
- package/transpiled/discovery.d.ts +12 -0
- package/transpiled/discovery.js +34 -0
- package/transpiled/discovery.js.map +1 -0
- package/transpiled/effect.d.ts +5 -0
- package/transpiled/effect.js +11 -0
- package/transpiled/effect.js.map +1 -0
- package/transpiled/emission.d.ts +8 -0
- package/transpiled/emission.js +14 -0
- package/transpiled/emission.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 +109 -0
- package/transpiled/entities/entity.js.map +1 -0
- package/transpiled/entities/factory.d.ts +22 -0
- package/transpiled/entities/factory.js +34 -0
- package/transpiled/entities/factory.js.map +1 -0
- package/transpiled/entities/index.d.ts +4 -0
- package/transpiled/entities/index.js +5 -0
- package/transpiled/entities/index.js.map +1 -0
- package/transpiled/entities/newid.d.ts +1 -0
- package/transpiled/entities/newid.js +7 -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 +14 -0
- package/transpiled/event.js +38 -0
- package/transpiled/event.js.map +1 -0
- package/transpiled/exceptions.d.ts +61 -0
- package/transpiled/exceptions.js +93 -0
- package/transpiled/exceptions.js.map +1 -0
- package/transpiled/exposition.d.ts +18 -0
- package/transpiled/exposition.js +18 -0
- package/transpiled/exposition.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/index.d.ts +35 -0
- package/transpiled/index.js +29 -0
- package/transpiled/index.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/observation.d.ts +5 -0
- package/transpiled/observation.js +12 -0
- package/transpiled/observation.js.map +1 -0
- package/transpiled/operation.d.ts +49 -0
- package/transpiled/operation.js +77 -0
- package/transpiled/operation.js.map +1 -0
- package/transpiled/outbox/index.d.ts +1 -0
- package/transpiled/outbox/index.js +2 -0
- package/transpiled/outbox/index.js.map +1 -0
- package/transpiled/outbox/outbox.d.ts +46 -0
- package/transpiled/outbox/outbox.js +267 -0
- package/transpiled/outbox/outbox.js.map +1 -0
- package/transpiled/query/criteria.d.ts +6 -0
- package/transpiled/query/criteria.js +74 -0
- package/transpiled/query/criteria.js.map +1 -0
- package/transpiled/query/options.d.ts +3 -0
- package/transpiled/query/options.js +27 -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 +92 -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 +12 -0
- package/transpiled/remote.js.map +1 -0
- package/transpiled/state.d.ts +33 -0
- package/transpiled/state.js +126 -0
- package/transpiled/state.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 +56 -0
- package/transpiled/types/atomicity.js +2 -0
- package/transpiled/types/atomicity.js.map +1 -0
- package/transpiled/types/bindings.d.ts +42 -0
- package/transpiled/types/bindings.js +2 -0
- package/transpiled/types/bindings.js.map +1 -0
- package/transpiled/types/bridges.d.ts +38 -0
- package/transpiled/types/bridges.js +2 -0
- package/transpiled/types/bridges.js.map +1 -0
- package/transpiled/types/extensions.d.ts +62 -0
- package/transpiled/types/extensions.js +2 -0
- package/transpiled/types/extensions.js.map +1 -0
- package/transpiled/types/index.d.ts +13 -0
- package/transpiled/types/index.js +8 -0
- package/transpiled/types/index.js.map +1 -0
- package/transpiled/types/message.d.ts +5 -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 +28 -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 +55 -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 +106 -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/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/CHANGELOG.md +0 -192
- package/src/assignment.js +0 -28
- package/src/context.js +0 -57
- package/src/contract/contract.js +0 -18
- package/src/contract/request.js +0 -77
- package/src/contract/schemas/error.yaml +0 -9
- package/src/contract/schemas/index.js +0 -11
- package/src/contract/schemas/query.yaml +0 -43
- package/src/contract/schemas/source.yaml +0 -23
- package/src/effect.js +0 -15
- package/src/entities/changeset.js +0 -36
- package/src/entities/entity.js +0 -119
- package/src/entities/factory.js +0 -40
- package/src/entities/index.js +0 -1
- package/src/event.js +0 -54
- package/src/exposition.js +0 -24
- package/src/guard.js +0 -13
- package/src/observation.js +0 -8
- package/src/operation.js +0 -95
- package/src/query/criteria.js +0 -44
- package/src/query/options.js +0 -37
- package/src/receiver.js +0 -123
- package/src/reflection.js +0 -24
- package/src/remote.js +0 -14
- package/src/state.js +0 -138
- package/src/transition.js +0 -61
- package/src/unmanaged.js +0 -7
- package/types/atomicity.d.ts +0 -79
- package/types/bindings.d.ts +0 -42
- package/types/bridges.ts +0 -33
- package/types/call.d.ts +0 -13
- package/types/component.d.ts +0 -12
- package/types/connector.d.ts +0 -18
- package/types/context.d.ts +0 -24
- 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 -73
- package/types/guard.d.ts +0 -5
- package/types/locator.d.ts +0 -13
- package/types/operations.d.ts +0 -8
- package/types/outbox.d.ts +0 -53
- package/types/query.d.ts +0 -17
- package/types/receiver.d.ts +0 -12
- package/types/reflection.d.ts +0 -14
- package/types/remote.d.ts +0 -19
- package/types/state.d.ts +0 -38
- package/types/storages.d.ts +0 -96
- /package/{src/contract/index.js → source/contract/index.ts} +0 -0
- /package/{src/outbox/index.js → source/outbox/index.ts} +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Properties } from './query/criteria.js';
|
|
2
|
+
import type { Query as Parsed } from './types/storages.js';
|
|
3
|
+
import type { Query as Requested } from './types/request.js';
|
|
4
|
+
/** Translates the query a request carries into the one a storage is given. */
|
|
5
|
+
export declare class Query {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(properties: Properties);
|
|
8
|
+
parse(query: Requested): Parsed;
|
|
9
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { empty } from '@toa.io/generic';
|
|
2
|
+
import * as criteria from './query/criteria.js';
|
|
3
|
+
import * as options from './query/options.js';
|
|
4
|
+
const parse = { ...criteria, ...options };
|
|
5
|
+
/** Translates the query a request carries into the one a storage is given. */
|
|
6
|
+
export class Query {
|
|
7
|
+
#properties;
|
|
8
|
+
/** parsed criteria by their expression */
|
|
9
|
+
#asts = new Map();
|
|
10
|
+
constructor(properties) {
|
|
11
|
+
this.#properties = properties;
|
|
12
|
+
}
|
|
13
|
+
parse(query) {
|
|
14
|
+
const result = {};
|
|
15
|
+
const { id, ids, version, criteria, search, ...rest } = query;
|
|
16
|
+
const options = this.#options(rest);
|
|
17
|
+
if (id !== undefined)
|
|
18
|
+
result.id = id;
|
|
19
|
+
if (ids !== undefined)
|
|
20
|
+
result.ids = ids;
|
|
21
|
+
if (version !== undefined)
|
|
22
|
+
result.version = version;
|
|
23
|
+
if (criteria !== undefined)
|
|
24
|
+
result.criteria = this.#criteria(criteria);
|
|
25
|
+
if (search !== undefined)
|
|
26
|
+
result.search = search;
|
|
27
|
+
if (options !== undefined)
|
|
28
|
+
result.options = options;
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
#options(given) {
|
|
32
|
+
if (empty(given))
|
|
33
|
+
return undefined;
|
|
34
|
+
return parse.options(given, this.#properties);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Lexing an RSQL expression is the most expensive thing this class does, and the same
|
|
38
|
+
* expression arrives over and over: a route builds it from its own declaration and the
|
|
39
|
+
* request parameters. The tree is only read downstream — a storage builds a fresh query
|
|
40
|
+
* from it — so it is kept rather than parsed again.
|
|
41
|
+
*
|
|
42
|
+
* Expressions come from the client, hence the bound. An invalid one throws before it
|
|
43
|
+
* reaches the cache.
|
|
44
|
+
*/
|
|
45
|
+
#criteria(criteria) {
|
|
46
|
+
const known = this.#asts.get(criteria);
|
|
47
|
+
if (known !== undefined)
|
|
48
|
+
return known;
|
|
49
|
+
const ast = parse.criteria(criteria, this.#properties);
|
|
50
|
+
if (this.#asts.size >= LIMIT)
|
|
51
|
+
this.#asts.clear();
|
|
52
|
+
this.#asts.set(criteria, ast);
|
|
53
|
+
return ast;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const LIMIT = 1024;
|
|
57
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../source/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAK7C,MAAM,KAAK,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAA;AAEzC,8EAA8E;AAC9E,MAAM,OAAO,KAAK;IACP,WAAW,CAAY;IAEhC,0CAA0C;IACjC,KAAK,GAAG,IAAI,GAAG,EAAgB,CAAA;IAExC,YAAmB,UAAsB;QACvC,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;IAC/B,CAAC;IAEM,KAAK,CAAC,KAAgB;QAC3B,MAAM,MAAM,GAAW,EAAE,CAAA;QACzB,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAA;QAE7D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAEnC,IAAI,EAAE,KAAK,SAAS;YAAE,MAAM,CAAC,EAAE,GAAG,EAAE,CAAA;QACpC,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,GAAG,GAAG,CAAA;QACvC,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAA;QACnD,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACtE,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;QAChD,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAA;QAEnD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,QAAQ,CAAC,KAA0B;QACjC,IAAI,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAA;QAElC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC/C,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,CAAC,QAAgB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAEtC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAA;QAErC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QAEtD,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK;YAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QAEhD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;QAE7B,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAED,MAAM,KAAK,GAAG,IAAI,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Connector } from './connector.js';
|
|
2
|
+
import type { Component } from './component.js';
|
|
3
|
+
import type { Receiver as Bridge } from './types/bridges.js';
|
|
4
|
+
import type { Message } from './types/message.js';
|
|
5
|
+
import type { Source } from './types/request.js';
|
|
6
|
+
export interface Definition {
|
|
7
|
+
conditioned?: boolean;
|
|
8
|
+
adaptive?: boolean;
|
|
9
|
+
operation: string;
|
|
10
|
+
label?: string;
|
|
11
|
+
destination?: string;
|
|
12
|
+
arguments?: unknown[];
|
|
13
|
+
origin?: Source;
|
|
14
|
+
}
|
|
15
|
+
export declare class Receiver extends Connector {
|
|
16
|
+
#private;
|
|
17
|
+
constructor(definition: Definition, local: Component, bridge?: Bridge);
|
|
18
|
+
/** @hot */
|
|
19
|
+
receive(message: Message): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { console, decode, run } from 'openspan';
|
|
2
|
+
import { add } from '@toa.io/generic';
|
|
3
|
+
import { Connector } from './connector.js';
|
|
4
|
+
export class Receiver extends Connector {
|
|
5
|
+
#conditioned;
|
|
6
|
+
#adaptive;
|
|
7
|
+
#endpoint;
|
|
8
|
+
#label;
|
|
9
|
+
#destination;
|
|
10
|
+
#arguments;
|
|
11
|
+
#origin;
|
|
12
|
+
#local;
|
|
13
|
+
#bridge;
|
|
14
|
+
#delivery;
|
|
15
|
+
#processing;
|
|
16
|
+
constructor(definition, local, bridge) {
|
|
17
|
+
super();
|
|
18
|
+
const { conditioned, adaptive, operation } = definition;
|
|
19
|
+
this.#conditioned = conditioned;
|
|
20
|
+
this.#adaptive = adaptive;
|
|
21
|
+
this.#endpoint = operation;
|
|
22
|
+
this.#label = definition.label ?? operation;
|
|
23
|
+
this.#destination = definition.destination ?? this.#label;
|
|
24
|
+
this.#arguments = definition.arguments;
|
|
25
|
+
this.#origin = definition.origin;
|
|
26
|
+
this.#local = local;
|
|
27
|
+
this.#bridge = bridge;
|
|
28
|
+
this.depends(local);
|
|
29
|
+
if (bridge !== undefined)
|
|
30
|
+
this.depends(bridge);
|
|
31
|
+
/*
|
|
32
|
+
* The delivery span is created on behalf of the messaging destination, so that
|
|
33
|
+
* each consumer forms its own complete producer/consumer pair, and service graphs
|
|
34
|
+
* display fan-out correctly: producer -> destination -> each consumer
|
|
35
|
+
* (Tempo pairs spans one-to-one, thus multiple consumers can not pair
|
|
36
|
+
* with a single producer span, see grafana/tempo#5408)
|
|
37
|
+
*/
|
|
38
|
+
this.#delivery = {
|
|
39
|
+
name: `${this.#label} deliver`,
|
|
40
|
+
kind: 'producer',
|
|
41
|
+
service: this.#destination,
|
|
42
|
+
attributes: { 'messaging.destination.name': this.#destination }
|
|
43
|
+
};
|
|
44
|
+
this.#processing = {
|
|
45
|
+
name: `${this.#label} process`,
|
|
46
|
+
kind: 'consumer',
|
|
47
|
+
service: local.locator.id,
|
|
48
|
+
attributes: { 'messaging.destination.name': this.#destination }
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** @hot */
|
|
52
|
+
async receive(message) {
|
|
53
|
+
const { payload, telemetry, ...extensions } = message;
|
|
54
|
+
if (this.#conditioned === true && (await this.#bridge?.condition(payload)) === false)
|
|
55
|
+
return;
|
|
56
|
+
const request = await this.#request(payload);
|
|
57
|
+
add(request, extensions);
|
|
58
|
+
// set after `add`, so that a message field can not spoof the origin
|
|
59
|
+
if (this.#origin !== undefined)
|
|
60
|
+
request.source = this.#origin;
|
|
61
|
+
// continue the trace from the producer span
|
|
62
|
+
const remote = telemetry === undefined ? null : decode(telemetry);
|
|
63
|
+
const task = async () => {
|
|
64
|
+
await this.#process(request);
|
|
65
|
+
};
|
|
66
|
+
if (remote === null)
|
|
67
|
+
await task();
|
|
68
|
+
else
|
|
69
|
+
await run(remote, task);
|
|
70
|
+
}
|
|
71
|
+
async #process(request) {
|
|
72
|
+
return console.span(this.#delivery, async () => console.span(this.#processing, async () => {
|
|
73
|
+
try {
|
|
74
|
+
await this.#local.invoke(this.#endpoint, request);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('Receiver error', {
|
|
78
|
+
component: this.#local.locator.id,
|
|
79
|
+
endpoint: this.#endpoint,
|
|
80
|
+
error
|
|
81
|
+
});
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
async #request(payload) {
|
|
87
|
+
return this.#adaptive === true
|
|
88
|
+
? await this.#bridge.request(payload, ...(this.#arguments ?? []))
|
|
89
|
+
: { input: payload };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=receiver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receiver.js","sourceRoot":"","sources":["../source/receiver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Connector } from './connector.js';
|
|
2
|
+
/** What a reflection reads, once, as it connects. */
|
|
3
|
+
export type Source<T = any> = () => Promise<T>;
|
|
4
|
+
export declare class Reflection<T = any> extends Connector {
|
|
5
|
+
#private;
|
|
6
|
+
value: T | undefined;
|
|
7
|
+
constructor(source: Source<T>);
|
|
8
|
+
protected open(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Connector } from './connector.js';
|
|
2
|
+
export class Reflection extends Connector {
|
|
3
|
+
value;
|
|
4
|
+
#source;
|
|
5
|
+
constructor(source) {
|
|
6
|
+
super();
|
|
7
|
+
this.#source = source;
|
|
8
|
+
}
|
|
9
|
+
async open() {
|
|
10
|
+
this.value = await this.#source();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=reflection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflection.js","sourceRoot":"","sources":["../source/reflection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAK1C,MAAM,OAAO,UAAoB,SAAQ,SAAS;IACzC,KAAK,CAAe;IAElB,OAAO,CAAW;IAE3B,YAAmB,MAAiB;QAClC,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,IAAI,CAAC,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Component } from './component.js';
|
|
2
|
+
import type { Invocable } from './component.js';
|
|
3
|
+
/** A call knows what its endpoint declares, which is what an explanation is read from. */
|
|
4
|
+
export interface Explicable extends Invocable {
|
|
5
|
+
explain(): any;
|
|
6
|
+
}
|
|
7
|
+
export declare class Remote extends Component<Explicable> {
|
|
8
|
+
protected kind: 'client';
|
|
9
|
+
explain(endpoint: string): any;
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { Component } from './component.js';
|
|
3
|
+
export class Remote extends Component {
|
|
4
|
+
kind = 'client';
|
|
5
|
+
explain(endpoint) {
|
|
6
|
+
if (!(endpoint in this.operations))
|
|
7
|
+
// `assert.fail`, not `assert.ok`: the message is built only when it is needed
|
|
8
|
+
assert.fail(`Endpoint '${endpoint}' is not provided by '${this.locator.id}'`);
|
|
9
|
+
return this.operations[endpoint].explain();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../source/remote.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAQ1C,MAAM,OAAO,MAAO,SAAQ,SAAqB;IAC5B,IAAI,GAAG,QAAiB,CAAA;IAEpC,OAAO,CAAC,QAAgB;QAC7B,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC;YAChC,8EAA8E;YAC9E,MAAM,CAAC,IAAI,CAAC,aAAa,QAAQ,yBAAyB,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAA;QAE/E,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAA;IAC5C,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { EntitySet } from './entities/set.js';
|
|
2
|
+
import type { Readable } from 'node:stream';
|
|
3
|
+
import type { Factory } from './entities/factory.js';
|
|
4
|
+
import type { Entity } from './entities/entity.js';
|
|
5
|
+
import type { Changeset } from './entities/changeset.js';
|
|
6
|
+
import type { Outbox } from './outbox/outbox.js';
|
|
7
|
+
import type { Query, Record, Storage } from './types/storages.js';
|
|
8
|
+
/**
|
|
9
|
+
* What an operation acquires and commits. One method per scope a manifest may declare, which
|
|
10
|
+
* is how an operation reaches the one it was declared with.
|
|
11
|
+
*/
|
|
12
|
+
export declare class State {
|
|
13
|
+
#private;
|
|
14
|
+
readonly storage: Storage;
|
|
15
|
+
constructor(storage: Storage, entities: Factory, outbox: Outbox | undefined, associated?: boolean);
|
|
16
|
+
init(id?: string): Entity;
|
|
17
|
+
fit(values: object): void;
|
|
18
|
+
/** scope `object` */
|
|
19
|
+
object(query: Query, mutable?: boolean): Promise<Entity | null>;
|
|
20
|
+
/** scope `objects` */
|
|
21
|
+
objects(query: Query, mutable?: boolean): Promise<EntitySet>;
|
|
22
|
+
/** scope `stream` */
|
|
23
|
+
stream(query: Query): Promise<Readable>;
|
|
24
|
+
/** scope `changeset` */
|
|
25
|
+
changeset(query: Query): Changeset;
|
|
26
|
+
/** scope `none`: an operation that acquires nothing still asks for its scope */
|
|
27
|
+
none(): null;
|
|
28
|
+
/** get-or-create, in one indivisible step */
|
|
29
|
+
ensure(query: Query | undefined, properties: object, input?: object): Promise<Entity>;
|
|
30
|
+
commit(state: Entity | EntitySet, input?: object): Promise<boolean>;
|
|
31
|
+
massCommit(state: EntitySet, input?: object): Promise<boolean>;
|
|
32
|
+
apply(state: Changeset, input?: object): Promise<Record>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { EntitySet } from './entities/set.js';
|
|
2
|
+
import { StatePreconditionException, StateNotFoundException } from './exceptions.js';
|
|
3
|
+
/**
|
|
4
|
+
* What an operation acquires and commits. One method per scope a manifest may declare, which
|
|
5
|
+
* is how an operation reaches the one it was declared with.
|
|
6
|
+
*/
|
|
7
|
+
export class State {
|
|
8
|
+
storage;
|
|
9
|
+
#entities;
|
|
10
|
+
#outbox;
|
|
11
|
+
/** whether an entity exists by virtue of the identity it is looked up by */
|
|
12
|
+
#associated;
|
|
13
|
+
// eslint-disable-next-line max-params
|
|
14
|
+
constructor(storage, entities, outbox, associated) {
|
|
15
|
+
this.storage = storage;
|
|
16
|
+
this.#entities = entities;
|
|
17
|
+
this.#outbox = outbox;
|
|
18
|
+
this.#associated = associated === true;
|
|
19
|
+
}
|
|
20
|
+
init(id) {
|
|
21
|
+
return this.#entities.init(id);
|
|
22
|
+
}
|
|
23
|
+
fit(values) {
|
|
24
|
+
this.#entities.fit(values);
|
|
25
|
+
}
|
|
26
|
+
/** scope `object` */
|
|
27
|
+
async object(query, mutable = true) {
|
|
28
|
+
const record = await this.storage.get(query);
|
|
29
|
+
if (record !== null)
|
|
30
|
+
return this.#entities.object(record, mutable);
|
|
31
|
+
// an associated entity is whatever the identity it is looked up by names, so a miss on
|
|
32
|
+
// that identity alone is a blank rather than an absence
|
|
33
|
+
if (this.#associated &&
|
|
34
|
+
query.id !== undefined &&
|
|
35
|
+
query.criteria === undefined &&
|
|
36
|
+
query.version === undefined)
|
|
37
|
+
return this.init(query.id);
|
|
38
|
+
if (query.version !== undefined)
|
|
39
|
+
throw new StatePreconditionException();
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/** scope `objects` */
|
|
43
|
+
async objects(query, mutable = true) {
|
|
44
|
+
const recordset = await this.storage.find(query);
|
|
45
|
+
const ids = query.ids;
|
|
46
|
+
const missing = this.#associated && ids !== undefined && recordset.length < ids.length;
|
|
47
|
+
const init = missing
|
|
48
|
+
? ids.filter((id) => !recordset.some((record) => record.id === id))
|
|
49
|
+
: undefined;
|
|
50
|
+
return this.#entities.objects(recordset, init, mutable);
|
|
51
|
+
}
|
|
52
|
+
/** scope `stream` */
|
|
53
|
+
async stream(query) {
|
|
54
|
+
return this.storage.stream(query);
|
|
55
|
+
}
|
|
56
|
+
/** scope `changeset` */
|
|
57
|
+
changeset(query) {
|
|
58
|
+
return this.#entities.changeset(query);
|
|
59
|
+
}
|
|
60
|
+
/** scope `none`: an operation that acquires nothing still asks for its scope */
|
|
61
|
+
none() {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/** get-or-create, in one indivisible step */
|
|
65
|
+
async ensure(query, properties, input) {
|
|
66
|
+
const object = this.#entities.init();
|
|
67
|
+
const blank = object.get();
|
|
68
|
+
Object.assign(blank, properties);
|
|
69
|
+
object.set(blank);
|
|
70
|
+
const row = this.#outbox?.row(object.event(input));
|
|
71
|
+
const record = await this.storage.ensure(query, properties, object.get(), row);
|
|
72
|
+
// whatever came back under another id was already there, and an effect never commits it
|
|
73
|
+
if (record.id !== blank.id)
|
|
74
|
+
return this.#entities.object(record, NOT_MUTABLE);
|
|
75
|
+
await this.#publish(row);
|
|
76
|
+
return object;
|
|
77
|
+
}
|
|
78
|
+
async commit(state, input) {
|
|
79
|
+
if (state instanceof EntitySet)
|
|
80
|
+
return this.massCommit(state, input);
|
|
81
|
+
// the row is built before the write so that the storage can commit it in the same
|
|
82
|
+
// transaction, closing the window this used to have
|
|
83
|
+
const row = this.#outbox?.row(state.event(input));
|
|
84
|
+
const ok = await this.storage.store(state.get(), row);
|
|
85
|
+
if (ok)
|
|
86
|
+
await this.#publish(row);
|
|
87
|
+
return ok;
|
|
88
|
+
}
|
|
89
|
+
async massCommit(state, input) {
|
|
90
|
+
const outbox = this.#outbox;
|
|
91
|
+
const rows = outbox === undefined
|
|
92
|
+
? undefined
|
|
93
|
+
: state.events(input).map((event) => outbox.row(event));
|
|
94
|
+
const ok = await this.storage.massStore(state.get(), rows);
|
|
95
|
+
if (ok && rows !== undefined)
|
|
96
|
+
await Promise.all(rows.map(async (row) => this.#publish(row)));
|
|
97
|
+
return ok;
|
|
98
|
+
}
|
|
99
|
+
async apply(state, input) {
|
|
100
|
+
// an assignment's images are the write's own, so the storage fills them in
|
|
101
|
+
const row = this.#outbox?.row({ input });
|
|
102
|
+
const result = await this.storage.upsert(state.query, state.export(), row);
|
|
103
|
+
if (result === null)
|
|
104
|
+
throw state.query.version === undefined
|
|
105
|
+
? new StateNotFoundException()
|
|
106
|
+
: new StatePreconditionException();
|
|
107
|
+
if (row !== undefined) {
|
|
108
|
+
// a storage that does not know how leaves the event with what it was given
|
|
109
|
+
row.event.state ??= result;
|
|
110
|
+
row.event.origin ??= null;
|
|
111
|
+
await this.#publish(row);
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Without a durable outbox this is the emission itself, and the operation waits for it;
|
|
117
|
+
* with one the row is already committed and this returns at once.
|
|
118
|
+
*/
|
|
119
|
+
async #publish(row) {
|
|
120
|
+
if (row !== undefined)
|
|
121
|
+
await this.#outbox?.publish(row);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** an effect never commits what `ensure` hands it, see `Effect` */
|
|
125
|
+
const NOT_MUTABLE = false;
|
|
126
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../source/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Operation } from './operation.js';
|
|
2
|
+
import type { Contracts, Definition, Store } from './operation.js';
|
|
3
|
+
import type { Cascade } from './cascade.js';
|
|
4
|
+
import type { State } from './state.js';
|
|
5
|
+
import type { Query as Translator } from './query.js';
|
|
6
|
+
export declare class Transition extends Operation {
|
|
7
|
+
#private;
|
|
8
|
+
/** a transition is the only operation that commits */
|
|
9
|
+
protected mutable: boolean;
|
|
10
|
+
constructor(cascade: Cascade, scope: State, contract: Contracts, query: Translator, definition: Definition);
|
|
11
|
+
protected process(store: Store): Promise<any>;
|
|
12
|
+
protected acquire(store: Store): Promise<void>;
|
|
13
|
+
protected commit(store: Store): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { retry } from '@toa.io/generic';
|
|
2
|
+
import { Operation } from './operation.js';
|
|
3
|
+
import { StateConcurrencyException, StateNotFoundException } from './exceptions.js';
|
|
4
|
+
export class Transition extends Operation {
|
|
5
|
+
/** a transition is the only operation that commits */
|
|
6
|
+
mutable = true;
|
|
7
|
+
#concurrency;
|
|
8
|
+
// eslint-disable-next-line max-params
|
|
9
|
+
constructor(cascade, scope, contract, query, definition) {
|
|
10
|
+
super(cascade, scope, contract, query, definition);
|
|
11
|
+
this.#concurrency = definition.concurrency;
|
|
12
|
+
}
|
|
13
|
+
async process(store) {
|
|
14
|
+
return retry(async (retry) => this.#retry(store, retry), RETRY);
|
|
15
|
+
}
|
|
16
|
+
async acquire(store) {
|
|
17
|
+
const { request } = store;
|
|
18
|
+
store.scope =
|
|
19
|
+
request.query === undefined ? this.scope.init() : await this.query(request.query);
|
|
20
|
+
const entity = store.scope;
|
|
21
|
+
if (entity === null ||
|
|
22
|
+
(entity.deleted && request.query?.options?.deleted !== true))
|
|
23
|
+
throw new StateNotFoundException();
|
|
24
|
+
store.state = entity.get();
|
|
25
|
+
}
|
|
26
|
+
async commit(store) {
|
|
27
|
+
const { scope, state, reply, retry } = store;
|
|
28
|
+
if (reply.error !== undefined)
|
|
29
|
+
return;
|
|
30
|
+
const entity = scope;
|
|
31
|
+
entity.set(state);
|
|
32
|
+
const result = await this.scope.commit(entity, store.request.input);
|
|
33
|
+
if (result !== false)
|
|
34
|
+
return;
|
|
35
|
+
if (this.#concurrency === 'retry')
|
|
36
|
+
await retry?.();
|
|
37
|
+
else
|
|
38
|
+
throw new StateConcurrencyException();
|
|
39
|
+
}
|
|
40
|
+
async #retry(store, retry) {
|
|
41
|
+
store.retry = retry;
|
|
42
|
+
return super.process(store);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const RETRY = {
|
|
46
|
+
base: 10,
|
|
47
|
+
max: 5000,
|
|
48
|
+
dispersion: 1,
|
|
49
|
+
retries: 32
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=transition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transition.js","sourceRoot":"","sources":["../source/transition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAOnF,MAAM,OAAO,UAAW,SAAQ,SAAS;IACvC,sDAAsD;IACnC,OAAO,GAAG,IAAI,CAAA;IAExB,YAAY,CAAoB;IAEzC,sCAAsC;IACtC,YACE,OAAgB,EAChB,KAAY,EACZ,QAAmB,EACnB,KAAiB,EACjB,UAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;QAElD,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,WAAW,CAAA;IAC5C,CAAC;IAEkB,KAAK,CAAC,OAAO,CAAC,KAAY;QAC3C,OAAO,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAA;IACjE,CAAC;IAEkB,KAAK,CAAC,OAAO,CAAC,KAAY;QAC3C,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;QAEzB,KAAK,CAAC,KAAK;YACT,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAEnF,MAAM,MAAM,GAAG,KAAK,CAAC,KAAsB,CAAA;QAE3C,IACE,MAAM,KAAK,IAAI;YACf,CAAC,MAAM,CAAC,OAAO,IAAK,OAAO,CAAC,KAAa,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;YAErE,MAAM,IAAI,sBAAsB,EAAE,CAAA;QAEpC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,CAAA;IAC5B,CAAC;IAEkB,KAAK,CAAC,MAAM,CAAC,KAAY;QAC1C,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;QAE5C,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,OAAM;QAErC,MAAM,MAAM,GAAG,KAAe,CAAA;QAE9B,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAEjB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAEnE,IAAI,MAAM,KAAK,KAAK;YAAE,OAAM;QAE5B,IAAI,IAAI,CAAC,YAAY,KAAK,OAAO;YAAE,MAAM,KAAK,EAAE,EAAE,CAAA;;YAC7C,MAAM,IAAI,yBAAyB,EAAE,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAY,EAAE,KAAyB;QAClD,KAAK,CAAC,KAAK,GAAG,KAAK,CAAA;QAEnB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,EAAE;IACR,GAAG,EAAE,IAAI;IACT,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,EAAE;CACZ,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Connector } from './connector.js';
|
|
2
|
+
import type { Consumer } from './types/bindings.js';
|
|
3
|
+
import type { Request } from './types/request.js';
|
|
4
|
+
export declare class Transmission extends Connector {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(bindings: Consumer[]);
|
|
7
|
+
request(request: Request): Promise<any>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Connector } from './connector.js';
|
|
2
|
+
import { TransmissionException } from './exceptions.js';
|
|
3
|
+
export class Transmission extends Connector {
|
|
4
|
+
#bindings;
|
|
5
|
+
constructor(bindings) {
|
|
6
|
+
super();
|
|
7
|
+
this.#bindings = bindings;
|
|
8
|
+
this.depends(bindings);
|
|
9
|
+
}
|
|
10
|
+
async request(request) {
|
|
11
|
+
let reply = false;
|
|
12
|
+
let i = 0;
|
|
13
|
+
while (reply === false && i < this.#bindings.length) {
|
|
14
|
+
const binding = this.#bindings[i];
|
|
15
|
+
i++;
|
|
16
|
+
if (request?.task === true) {
|
|
17
|
+
if (binding.task === undefined)
|
|
18
|
+
continue;
|
|
19
|
+
await binding.task(request);
|
|
20
|
+
reply = null;
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
reply = await binding.request(request);
|
|
24
|
+
}
|
|
25
|
+
if (reply === false)
|
|
26
|
+
throw new TransmissionException(`All (${this.#bindings.length}) bindings rejected.`);
|
|
27
|
+
return reply;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=transmission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transmission.js","sourceRoot":"","sources":["../source/transmission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAIvD,MAAM,OAAO,YAAa,SAAQ,SAAS;IAChC,SAAS,CAAY;IAE9B,YAAmB,QAAoB;QACrC,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACxB,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,OAAgB;QACnC,IAAI,KAAK,GAAQ,KAAK,CAAA;QACtB,IAAI,CAAC,GAAG,CAAC,CAAA;QAET,OAAO,KAAK,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;YAEjC,CAAC,EAAE,CAAA;YAEH,IAAI,OAAO,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;gBAC3B,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;oBAAE,SAAQ;gBAExC,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC3B,KAAK,GAAG,IAAI,CAAA;YACd,CAAC;;gBAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC/C,CAAC;QAED,IAAI,KAAK,KAAK,KAAK;YACjB,MAAM,IAAI,qBAAqB,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,sBAAsB,CAAC,CAAA;QAEtF,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Connector } from '../connector.js';
|
|
2
|
+
/** Which of the group this replica is, and how many of them there are. */
|
|
3
|
+
export interface Assignment {
|
|
4
|
+
i: number;
|
|
5
|
+
n: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What one group of replicas decides together, in one place. The decisions here are the ones
|
|
9
|
+
* processes cannot arrange by talking to each other: they need a single arbiter and a step
|
|
10
|
+
* indivisible from its point of view.
|
|
11
|
+
*/
|
|
12
|
+
export interface Atom extends Connector {
|
|
13
|
+
/**
|
|
14
|
+
* An exclusive claim on slots of `0..total`: while this replica holds one, no other
|
|
15
|
+
* replica of the group does. Answered from memory, so it costs nothing to ask.
|
|
16
|
+
*
|
|
17
|
+
* `null` while this replica owns nothing — after a restart, during a rollout, or while
|
|
18
|
+
* coordination is unreachable. Whoever asks must be able to stand down: acting on a claim
|
|
19
|
+
* that cannot be supported is a different guarantee, not a degraded one.
|
|
20
|
+
*/
|
|
21
|
+
slots(total: number): number[] | null;
|
|
22
|
+
/**
|
|
23
|
+
* Calls `listener` with the assignment this replica holds, and again whenever it changes —
|
|
24
|
+
* one arrived, was lost, or the group resized. Answers with what removes the listener
|
|
25
|
+
* again.
|
|
26
|
+
*
|
|
27
|
+
* A change and not a heartbeat: a group that stays as it is never calls back. It is called
|
|
28
|
+
* once as it is added, with the claim as it stands.
|
|
29
|
+
*/
|
|
30
|
+
onassigned(listener: (assignment: Assignment | null) => void): () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Debt the group has run up under each key, in milliseconds. Every call adds its own deltas
|
|
33
|
+
* and reads back where the group stands, so a replica reports what it alone has spent and
|
|
34
|
+
* still decides on what all of them have.
|
|
35
|
+
*
|
|
36
|
+
* Rejects where there is nothing to arbitrate through.
|
|
37
|
+
*/
|
|
38
|
+
meter(keys: string[], deltas: number[]): Promise<number[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Runs `routine` holding `keys`, and while it holds them no other replica of the group
|
|
41
|
+
* does. Waits for as long as it takes to acquire them.
|
|
42
|
+
*
|
|
43
|
+
* The lease is extended for as long as the routine runs. An extension that fails aborts the
|
|
44
|
+
* signal the routine is given, which is the only way it learns it no longer holds what it
|
|
45
|
+
* is working under.
|
|
46
|
+
*
|
|
47
|
+
* Rejects where there is nothing to arbitrate through.
|
|
48
|
+
*/
|
|
49
|
+
lock<T>(keys: string | string[], routine: (signal: AbortSignal, context: unknown) => Promise<T>): Promise<T>;
|
|
50
|
+
}
|
|
51
|
+
export interface Factory {
|
|
52
|
+
/** @param group what the replicas deciding together have in common */
|
|
53
|
+
atom(group: string, options?: {
|
|
54
|
+
interval?: number;
|
|
55
|
+
}): Atom;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomicity.js","sourceRoot":"","sources":["../../source/types/atomicity.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
import type { Connector } from '../connector.js';
|
|
3
|
+
import type { Locator } from '../locator.js';
|
|
4
|
+
import type { Component } from '../component.js';
|
|
5
|
+
import type { Receiver } from './receiver.js';
|
|
6
|
+
import type { Message } from './message.js';
|
|
7
|
+
import type { Reply, Request } from './request.js';
|
|
8
|
+
/** What a binding module exports beside its factory. */
|
|
9
|
+
export interface Properties {
|
|
10
|
+
/** delivers asynchronously; an event's binding must */
|
|
11
|
+
async?: boolean;
|
|
12
|
+
/** in-process: its producers are connected first and torn down last */
|
|
13
|
+
local?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface Consumer extends Connector {
|
|
16
|
+
/**
|
|
17
|
+
* `false` says this binding does not carry the endpoint, and the transmission tries the
|
|
18
|
+
* next one. A `Readable` is a streamed reply.
|
|
19
|
+
*/
|
|
20
|
+
request(request: Request): Promise<Reply | Readable | false>;
|
|
21
|
+
/**
|
|
22
|
+
* Absent where the binding cannot enqueue — a transmission skips a binding that offers
|
|
23
|
+
* no `task` rather than failing over it.
|
|
24
|
+
*/
|
|
25
|
+
task?(request: Request): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface Emitter extends Connector {
|
|
28
|
+
emit(message: Message): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export interface Broadcast<L extends string = string> extends Connector {
|
|
31
|
+
transmit<T>(label: L, payload: T): Promise<void>;
|
|
32
|
+
receive<T>(label: L, callback: (payload: T) => void | Promise<void>): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface Factory {
|
|
35
|
+
producer(locator: Locator, endpoints: string[], component: Component): Connector;
|
|
36
|
+
consumer(locator: Locator, endpoint: string): Consumer;
|
|
37
|
+
/** only the binding an event declares is asked for one */
|
|
38
|
+
emitter?(locator: Locator, label: string): Emitter;
|
|
39
|
+
/** `group` is absent for an exclusive subscription */
|
|
40
|
+
receiver?(locator: Locator, label: string, group: string | undefined, receiver: Receiver): Connector;
|
|
41
|
+
broadcast?(name: string, group?: string): Broadcast;
|
|
42
|
+
}
|