@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
package/src/receiver.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { console, decode, run } from 'openspan'
|
|
2
|
-
import { add } from '@toa.io/generic'
|
|
3
|
-
import { Connector } from './connector.js'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @implements {toa.core.Receiver}
|
|
7
|
-
*/
|
|
8
|
-
export class Receiver extends Connector {
|
|
9
|
-
/** @type {boolean} */
|
|
10
|
-
#conditioned
|
|
11
|
-
|
|
12
|
-
/** @type {boolean} */
|
|
13
|
-
#adaptive
|
|
14
|
-
|
|
15
|
-
/** @type {string} */
|
|
16
|
-
#endpoint
|
|
17
|
-
|
|
18
|
-
/** @type {string} */
|
|
19
|
-
#label
|
|
20
|
-
|
|
21
|
-
/** @type {string} */
|
|
22
|
-
#destination
|
|
23
|
-
|
|
24
|
-
/** @type {unknown[]} */
|
|
25
|
-
#arguments
|
|
26
|
-
|
|
27
|
-
/** @type {toa.core.Source} */
|
|
28
|
-
#origin
|
|
29
|
-
|
|
30
|
-
#local
|
|
31
|
-
|
|
32
|
-
#bridge
|
|
33
|
-
|
|
34
|
-
/** @type {object} */
|
|
35
|
-
#delivery
|
|
36
|
-
|
|
37
|
-
/** @type {object} */
|
|
38
|
-
#processing
|
|
39
|
-
|
|
40
|
-
constructor (definition, local, bridge) {
|
|
41
|
-
super()
|
|
42
|
-
|
|
43
|
-
const { conditioned, adaptive, operation } = definition
|
|
44
|
-
|
|
45
|
-
this.#conditioned = conditioned
|
|
46
|
-
this.#adaptive = adaptive
|
|
47
|
-
this.#endpoint = operation
|
|
48
|
-
this.#label = definition.label ?? operation
|
|
49
|
-
this.#destination = definition.destination ?? this.#label
|
|
50
|
-
this.#arguments = definition.arguments
|
|
51
|
-
this.#origin = definition.origin
|
|
52
|
-
|
|
53
|
-
this.#local = local
|
|
54
|
-
this.#bridge = bridge
|
|
55
|
-
|
|
56
|
-
this.depends(local)
|
|
57
|
-
if (bridge !== undefined) this.depends(bridge)
|
|
58
|
-
|
|
59
|
-
/*
|
|
60
|
-
* The delivery span is created on behalf of the messaging destination, so that
|
|
61
|
-
* each consumer forms its own complete producer/consumer pair, and service graphs
|
|
62
|
-
* display fan-out correctly: producer -> destination -> each consumer
|
|
63
|
-
* (Tempo pairs spans one-to-one, thus multiple consumers can not pair
|
|
64
|
-
* with a single producer span, see grafana/tempo#5408)
|
|
65
|
-
*/
|
|
66
|
-
this.#delivery = {
|
|
67
|
-
name: `${this.#label} deliver`,
|
|
68
|
-
kind: 'producer',
|
|
69
|
-
service: this.#destination,
|
|
70
|
-
attributes: { 'messaging.destination.name': this.#destination }
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
this.#processing = {
|
|
74
|
-
name: `${this.#label} process`,
|
|
75
|
-
kind: 'consumer',
|
|
76
|
-
service: local.locator.id,
|
|
77
|
-
attributes: { 'messaging.destination.name': this.#destination }
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** @hot */
|
|
82
|
-
async receive (message) {
|
|
83
|
-
const { payload, telemetry, ...extensions } = message
|
|
84
|
-
|
|
85
|
-
if (this.#conditioned && await this.#bridge.condition(payload) === false) return
|
|
86
|
-
|
|
87
|
-
const request = await this.#request(payload)
|
|
88
|
-
|
|
89
|
-
add(request, extensions)
|
|
90
|
-
|
|
91
|
-
// set after `add`, so that a message field can not spoof the origin
|
|
92
|
-
if (this.#origin !== undefined) request.source = this.#origin
|
|
93
|
-
|
|
94
|
-
// continue the trace from the producer span
|
|
95
|
-
const remote = telemetry === undefined ? null : decode(telemetry)
|
|
96
|
-
const task = () => this.#process(request)
|
|
97
|
-
|
|
98
|
-
if (remote === null)
|
|
99
|
-
await task()
|
|
100
|
-
else
|
|
101
|
-
await run(remote, task)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async #process (request) {
|
|
105
|
-
return console.span(this.#delivery, async () => console.span(this.#processing, async () => {
|
|
106
|
-
try {
|
|
107
|
-
await this.#local.invoke(this.#endpoint, request)
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error('Receiver error', {
|
|
110
|
-
component: this.#local.locator.id,
|
|
111
|
-
endpoint: this.#endpoint,
|
|
112
|
-
error
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
throw error
|
|
116
|
-
}
|
|
117
|
-
}))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async #request (payload) {
|
|
121
|
-
return this.#adaptive ? await this.#bridge.request(payload, ...(this.#arguments ?? [])) : { input: payload }
|
|
122
|
-
}
|
|
123
|
-
}
|
package/src/reflection.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Connector } from './connector.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @implements {toa.core.Reflection}
|
|
5
|
-
*/
|
|
6
|
-
export class Reflection extends Connector {
|
|
7
|
-
/** @type {toa.core.reflection.Source} */
|
|
8
|
-
#source
|
|
9
|
-
|
|
10
|
-
value
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param {toa.core.reflection.Source} source
|
|
14
|
-
*/
|
|
15
|
-
constructor (source) {
|
|
16
|
-
super()
|
|
17
|
-
|
|
18
|
-
this.#source = source
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async open () {
|
|
22
|
-
this.value = await this.#source()
|
|
23
|
-
}
|
|
24
|
-
}
|
package/src/remote.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Component } from './component.js'
|
|
3
|
-
|
|
4
|
-
export class Remote extends Component {
|
|
5
|
-
kind = 'client'
|
|
6
|
-
|
|
7
|
-
explain (endpoint) {
|
|
8
|
-
if (!(endpoint in this.operations))
|
|
9
|
-
// `assert.fail`, not `assert.ok`: the message is built only when it is needed
|
|
10
|
-
assert.fail(`Endpoint '${endpoint}' is not provided by '${this.locator.id}'`)
|
|
11
|
-
|
|
12
|
-
return this.operations[endpoint].explain()
|
|
13
|
-
}
|
|
14
|
-
}
|
package/src/state.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { StatePreconditionException, StateNotFoundException } from './exceptions.js'
|
|
2
|
-
|
|
3
|
-
export class State {
|
|
4
|
-
storage
|
|
5
|
-
|
|
6
|
-
#associated
|
|
7
|
-
#entities
|
|
8
|
-
#outbox
|
|
9
|
-
|
|
10
|
-
constructor (storage, entity, outbox, associated) {
|
|
11
|
-
this.storage = storage
|
|
12
|
-
this.#entities = entity
|
|
13
|
-
this.#outbox = outbox
|
|
14
|
-
this.#associated = associated === true
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
init (id) {
|
|
18
|
-
return this.#entities.init(id)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
fit (values) {
|
|
22
|
-
return this.#entities.fit(values)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async object (query, mutable = true) {
|
|
26
|
-
const record = await this.storage.get(query)
|
|
27
|
-
|
|
28
|
-
if (record === null) {
|
|
29
|
-
if (this.#associated && query.id !== undefined && query.criteria === undefined && query.version === undefined)
|
|
30
|
-
return this.init(query.id)
|
|
31
|
-
else if (query.version !== undefined)
|
|
32
|
-
throw new StatePreconditionException()
|
|
33
|
-
|
|
34
|
-
return null
|
|
35
|
-
} else
|
|
36
|
-
return this.#entities.object(record, mutable)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async objects (query, mutable = true) {
|
|
40
|
-
const recordset = await this.storage.find(query)
|
|
41
|
-
const missing = this.#associated && query.ids !== undefined && recordset.length < query.ids.length
|
|
42
|
-
const init = missing ? query.ids.filter((id) => !recordset.some((record) => record.id === id)) : undefined
|
|
43
|
-
|
|
44
|
-
return this.#entities.objects(recordset, init, mutable)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async stream (query) {
|
|
48
|
-
return this.storage.stream(query)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
changeset (query) {
|
|
52
|
-
return this.#entities.changeset(query)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
none () {
|
|
56
|
-
return null
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async ensure (query, properties, input) {
|
|
60
|
-
const object = this.#entities.init()
|
|
61
|
-
const blank = object.get()
|
|
62
|
-
|
|
63
|
-
Object.assign(blank, properties)
|
|
64
|
-
|
|
65
|
-
object.set(blank)
|
|
66
|
-
|
|
67
|
-
const row = this.#outbox?.row(object.event(input))
|
|
68
|
-
const record = await this.storage.ensure(query, properties, object.get(), row)
|
|
69
|
-
|
|
70
|
-
if (record.id !== blank.id) // exists
|
|
71
|
-
return this.#entities.object(record, NOT_MUTABLE)
|
|
72
|
-
|
|
73
|
-
if (row !== undefined)
|
|
74
|
-
await this.#outbox.publish(row)
|
|
75
|
-
|
|
76
|
-
return object
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async commit (state, input) {
|
|
80
|
-
if (state.constructor.name === 'EntitySet')
|
|
81
|
-
return this.massCommit(state, input)
|
|
82
|
-
|
|
83
|
-
const data = state.get()
|
|
84
|
-
|
|
85
|
-
// the row is built before the write so that the storage can commit it in the same
|
|
86
|
-
// transaction, closing the window this used to have
|
|
87
|
-
const row = this.#outbox?.row(state.event(input))
|
|
88
|
-
const ok = await this.storage.store(data, row)
|
|
89
|
-
|
|
90
|
-
if (ok === true && row !== undefined)
|
|
91
|
-
await this.#outbox.publish(row)
|
|
92
|
-
|
|
93
|
-
return ok
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async massCommit (state, input) {
|
|
97
|
-
const data = state.get()
|
|
98
|
-
const rows = this.#outbox === undefined
|
|
99
|
-
? undefined
|
|
100
|
-
: state.events(input).map((event) => this.#outbox.row(event))
|
|
101
|
-
|
|
102
|
-
const ok = await this.storage.massStore(data, rows)
|
|
103
|
-
|
|
104
|
-
if (ok === true && rows !== undefined)
|
|
105
|
-
await Promise.all(rows.map((row) => this.#outbox.publish(row)))
|
|
106
|
-
|
|
107
|
-
return ok
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async apply (state, input) {
|
|
111
|
-
const changeset = state.export()
|
|
112
|
-
|
|
113
|
-
// an assignment's event is the write's own images, so the storage fills them in;
|
|
114
|
-
// see `apply` in the outbox design
|
|
115
|
-
const row = this.#outbox?.row({ input })
|
|
116
|
-
const result = await this.storage.upsert(state.query, changeset, row)
|
|
117
|
-
|
|
118
|
-
if (result === null) {
|
|
119
|
-
if (state.query.version !== undefined) {
|
|
120
|
-
throw new StatePreconditionException()
|
|
121
|
-
} else {
|
|
122
|
-
throw new StateNotFoundException()
|
|
123
|
-
}
|
|
124
|
-
} else if (row !== undefined) {
|
|
125
|
-
// the storage fills `origin` and `state` from its own write; a storage that does not
|
|
126
|
-
// know how leaves the event with what it was given
|
|
127
|
-
row.event.state ??= result
|
|
128
|
-
row.event.origin ??= null
|
|
129
|
-
|
|
130
|
-
await this.#outbox.publish(row)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return result
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** an effect never commits what `ensure` hands it, see `Effect` */
|
|
138
|
-
const NOT_MUTABLE = false
|
package/src/transition.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { retry } from '@toa.io/generic'
|
|
2
|
-
import { Operation } from './operation.js'
|
|
3
|
-
import { StateConcurrencyException, StateNotFoundException } from './exceptions.js'
|
|
4
|
-
|
|
5
|
-
export class Transition extends Operation {
|
|
6
|
-
/** a transition is the only operation that commits */
|
|
7
|
-
mutable = true
|
|
8
|
-
|
|
9
|
-
#concurrency
|
|
10
|
-
|
|
11
|
-
constructor (cascade, scope, contract, query, definition) {
|
|
12
|
-
super(cascade, scope, contract, query, definition)
|
|
13
|
-
|
|
14
|
-
this.#concurrency = definition.concurrency
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async process (store) {
|
|
18
|
-
return retry((retry) => this.#retry(store, retry), RETRY)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async acquire (store) {
|
|
22
|
-
const { request } = store
|
|
23
|
-
|
|
24
|
-
store.scope = request.query ? await this.query(request.query) : this.scope.init()
|
|
25
|
-
|
|
26
|
-
if (store.scope === null || (store.scope.deleted === true && request.query?.options?.deleted !== true))
|
|
27
|
-
throw new StateNotFoundException()
|
|
28
|
-
|
|
29
|
-
store.state = store.scope.get()
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async commit (store) {
|
|
33
|
-
const { scope, state, reply, retry } = store
|
|
34
|
-
|
|
35
|
-
if (reply.error !== undefined) return
|
|
36
|
-
|
|
37
|
-
scope.set(state)
|
|
38
|
-
|
|
39
|
-
const result = await this.scope.commit(scope, store.request.input)
|
|
40
|
-
|
|
41
|
-
if (result === false) {
|
|
42
|
-
if (this.#concurrency === 'retry')
|
|
43
|
-
return retry()
|
|
44
|
-
else
|
|
45
|
-
throw new StateConcurrencyException()
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async #retry (store, retry) {
|
|
50
|
-
store.retry = retry
|
|
51
|
-
|
|
52
|
-
return super.process(store)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const RETRY = {
|
|
57
|
-
base: 10,
|
|
58
|
-
max: 5000,
|
|
59
|
-
dispersion: 1,
|
|
60
|
-
retries: 32
|
|
61
|
-
}
|
package/src/unmanaged.js
DELETED
package/types/atomicity.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// noinspection ES6UnusedImports
|
|
2
|
-
|
|
3
|
-
import { Connector } from './connector.js'
|
|
4
|
-
|
|
5
|
-
declare namespace toa.core {
|
|
6
|
-
|
|
7
|
-
namespace atomicity {
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* What one group of replicas decides together, in one place. The decisions here are the
|
|
11
|
-
* ones processes cannot arrange by talking to each other: they need a single arbiter and a
|
|
12
|
-
* step indivisible from its point of view.
|
|
13
|
-
*/
|
|
14
|
-
interface Atom extends Connector {
|
|
15
|
-
/**
|
|
16
|
-
* An exclusive claim on slots of `0..total`: while this replica holds one, no other
|
|
17
|
-
* replica of the group does. Answered from memory, so it costs nothing to ask.
|
|
18
|
-
*
|
|
19
|
-
* `null` while this replica owns nothing — after a restart, during a rollout, or while
|
|
20
|
-
* coordination is unreachable. Whoever asks must be able to stand down: acting on a
|
|
21
|
-
* claim that cannot be supported is a different guarantee, not a degraded one.
|
|
22
|
-
*/
|
|
23
|
-
slots (total: number): number[] | null
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Calls `listener` with the assignment this replica holds, and again whenever it
|
|
27
|
-
* changes — one arrived, was lost, or the group resized. Answers with what removes the
|
|
28
|
-
* listener again.
|
|
29
|
-
*
|
|
30
|
-
* A change and not a heartbeat: a group that stays as it is never calls back. It is
|
|
31
|
-
* called once as it is added, with the claim as it stands.
|
|
32
|
-
*
|
|
33
|
-
* What `slots` cannot say. Reading serves a consumer that asks often, where a stale
|
|
34
|
-
* answer costs it one cycle; a consumer that asks rarely has to be told, or it samples
|
|
35
|
-
* the one moment a rollout was passing through and stands down for a whole cycle.
|
|
36
|
-
*/
|
|
37
|
-
onassigned (listener: (assignment: Assignment | null) => void): () => void
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Debt the group has run up under each key, in milliseconds. Every call adds its own
|
|
41
|
-
* deltas and reads back where the group stands, so a replica reports what it alone has
|
|
42
|
-
* spent and still decides on what all of them have.
|
|
43
|
-
*
|
|
44
|
-
* Rejects where there is nothing to arbitrate through.
|
|
45
|
-
*/
|
|
46
|
-
meter (keys: string[], deltas: number[]): Promise<number[]>
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Runs `routine` holding `keys`, and while it holds them no other replica of the group
|
|
50
|
-
* does. Waits for as long as it takes to acquire them.
|
|
51
|
-
*
|
|
52
|
-
* The lease is extended for as long as the routine runs. An extension that fails aborts
|
|
53
|
-
* the signal the routine is given, which is the only way it learns it no longer holds
|
|
54
|
-
* what it is working under.
|
|
55
|
-
*
|
|
56
|
-
* Rejects where there is nothing to arbitrate through.
|
|
57
|
-
*/
|
|
58
|
-
lock<T> (keys: string | string[],
|
|
59
|
-
routine: (signal: AbortSignal, context: unknown) => Promise<T>): Promise<T>
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Which of the group this replica is, and how many of them there are. */
|
|
63
|
-
interface Assignment {
|
|
64
|
-
i: number
|
|
65
|
-
n: number
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
interface Factory {
|
|
69
|
-
/** @param group what the replicas deciding together have in common */
|
|
70
|
-
atom (group: string, options?: object): Atom
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export type Atom = toa.core.atomicity.Atom
|
|
78
|
-
export type Assignment = toa.core.atomicity.Assignment
|
|
79
|
-
export type Factory = toa.core.atomicity.Factory
|
package/types/bindings.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import * as _core from './index.js'
|
|
2
|
-
|
|
3
|
-
declare namespace toa.core.bindings {
|
|
4
|
-
|
|
5
|
-
type Properties = {
|
|
6
|
-
async?: boolean
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface Consumer extends _core.Connector {
|
|
10
|
-
request (request: Request): Promise<_core.Reply>
|
|
11
|
-
|
|
12
|
-
task (request: Request): Promise<void>
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface Emitter extends _core.Connector {
|
|
16
|
-
emit (message: _core.Message): Promise<void>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface Broadcast<L> extends _core.Connector {
|
|
20
|
-
transmit<T> (label: L, payload: T): Promise<void>
|
|
21
|
-
|
|
22
|
-
receive<T> (label: L, callback: (payload: T) => void | Promise<void>): Promise<void>
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface Factory {
|
|
26
|
-
producer? (locator: _core.Locator, endpoints: Array<string>, producer: _core.Component): _core.Connector
|
|
27
|
-
|
|
28
|
-
consumer? (locator: _core.Locator, endpoint: string): Consumer
|
|
29
|
-
|
|
30
|
-
emitter? (locator: _core.Locator, label: string): Emitter
|
|
31
|
-
|
|
32
|
-
receiver? (locator: _core.Locator, label: string, group: string, receiver: _core.Receiver): _core.Connector
|
|
33
|
-
|
|
34
|
-
broadcast? (name: string, group?: string): Broadcast
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type Emitter = toa.core.bindings.Emitter
|
|
40
|
-
export type Factory = toa.core.bindings.Factory
|
|
41
|
-
export type Properties = toa.core.bindings.Properties
|
|
42
|
-
export type Broadcast<L = any> = toa.core.bindings.Broadcast<L>
|
package/types/bridges.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { Request, Reply } from './request.js'
|
|
2
|
-
import type { Context } from './context.js'
|
|
3
|
-
import type { Connector } from './connector.js'
|
|
4
|
-
|
|
5
|
-
export interface Algorithm {
|
|
6
|
-
mount: (context?: Context) => Promise<void>
|
|
7
|
-
|
|
8
|
-
execute: ((input: any, scope: object | object[]) => Promise<Reply>) |
|
|
9
|
-
((input: any) => Promise<Reply>) |
|
|
10
|
-
(() => Promise<Reply>)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface Event {
|
|
14
|
-
condition: (object: object) => Promise<boolean>
|
|
15
|
-
|
|
16
|
-
payload: (object: object) => Promise<object>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface Receiver {
|
|
20
|
-
condition: (object: object) => Promise<boolean>
|
|
21
|
-
|
|
22
|
-
request: (object: object) => Promise<Request>
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface Factory {
|
|
26
|
-
algorithm?: (path: string, name: string, context: Context) => Algorithm
|
|
27
|
-
|
|
28
|
-
event?: (path: string, label: string) => Event
|
|
29
|
-
|
|
30
|
-
receiver?: (path: string, label: string) => Receiver
|
|
31
|
-
|
|
32
|
-
rc?: (path: string, context: Context) => Promise<{ preflight?: Connector, settle?: Connector, dispose?: Connector } | undefined>
|
|
33
|
-
}
|
package/types/call.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Request } from './request.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* How an endpoint is called. What it resolves to is what the operation declares — `toa types`
|
|
5
|
-
* writes that per operation, and these are what a hand-written context says instead.
|
|
6
|
-
*/
|
|
7
|
-
export type Call<Output = any, Input = any> = (request: Request<Input>) => Promise<Output>
|
|
8
|
-
|
|
9
|
-
export type Observation<Output = any, Input = never, Entity = unknown> =
|
|
10
|
-
(request: Request<Input, Entity>) => Promise<Output extends unknown[] ? Output : Output | null>
|
|
11
|
-
|
|
12
|
-
export type Transition<Output = any, Input = never, Entity = unknown> =
|
|
13
|
-
(request: Request<Input, Entity>) => Promise<Output | null>
|
package/types/component.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Connector } from './connector.js'
|
|
2
|
-
import { Locator } from './locator.js'
|
|
3
|
-
import { Request } from './request.js'
|
|
4
|
-
import { Operation } from './operations.js'
|
|
5
|
-
|
|
6
|
-
export class Component extends Connector {
|
|
7
|
-
locator: Locator
|
|
8
|
-
|
|
9
|
-
constructor (locator: Locator, operations: Record<string, Operation>)
|
|
10
|
-
|
|
11
|
-
invoke<T = any> (endpoint: string, request: Request): Promise<T>
|
|
12
|
-
}
|
package/types/connector.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export class Connector {
|
|
2
|
-
public id: string
|
|
3
|
-
public connected: boolean
|
|
4
|
-
|
|
5
|
-
public connect (): Promise<void>
|
|
6
|
-
|
|
7
|
-
public disconnect (interrupt?: boolean): Promise<void>
|
|
8
|
-
|
|
9
|
-
public depends (connector: Connector | Connector[]): Connector
|
|
10
|
-
|
|
11
|
-
link (connector: Connector): void
|
|
12
|
-
|
|
13
|
-
protected open (): Promise<void> | void
|
|
14
|
-
|
|
15
|
-
protected close (): Promise<void> | void
|
|
16
|
-
|
|
17
|
-
protected dispose (): Promise<void> | void
|
|
18
|
-
}
|
package/types/context.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as _request from './request.js'
|
|
2
|
-
import { Locator } from './locator.js'
|
|
3
|
-
import * as _reply from './reply'
|
|
4
|
-
import * as _extensions from './extensions.js'
|
|
5
|
-
import * as _connector from './connector.js'
|
|
6
|
-
|
|
7
|
-
export interface Context extends _connector.Connector{
|
|
8
|
-
aspects: _extensions.Aspect[]
|
|
9
|
-
|
|
10
|
-
locator: Locator
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Calls local endpoint
|
|
14
|
-
*/
|
|
15
|
-
apply (endpoint: string, request: _request.Request): Promise<_reply.Reply>
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Calls remote endpoint
|
|
19
|
-
*/
|
|
20
|
-
call (namespace: string, name: string, endpoint: string, request: _request.Request): Promise<_reply.Reply>
|
|
21
|
-
|
|
22
|
-
// shortcuts
|
|
23
|
-
[key: string]: any
|
|
24
|
-
}
|
package/types/entity.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import * as _event from './event.js'
|
|
2
|
-
import * as _storages from './storages.js'
|
|
3
|
-
|
|
4
|
-
declare namespace toa.core {
|
|
5
|
-
|
|
6
|
-
namespace entity {
|
|
7
|
-
|
|
8
|
-
interface Factory {
|
|
9
|
-
init(id: string): Entity
|
|
10
|
-
|
|
11
|
-
object(record: Object, mutable?: boolean): Entity
|
|
12
|
-
|
|
13
|
-
objects(recordset: Object[], init?: string[], mutable?: boolean): Entity[]
|
|
14
|
-
|
|
15
|
-
changeset(query: _storages.Query): Changeset
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface Entity {
|
|
21
|
-
get(): _storages.Record
|
|
22
|
-
|
|
23
|
-
set(value: _storages.Record): void
|
|
24
|
-
|
|
25
|
-
event(): _event.Event
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
type Upsert = {
|
|
29
|
-
changeset: Object
|
|
30
|
-
insert: Object
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface Changeset {
|
|
34
|
-
query: _storages.Query
|
|
35
|
-
|
|
36
|
-
get(): Object
|
|
37
|
-
|
|
38
|
-
set(value: Object): void
|
|
39
|
-
|
|
40
|
-
export(): Upsert
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type Entity = toa.core.Entity
|
|
46
|
-
export type Changeset = toa.core.Changeset
|
package/types/event.d.ts
DELETED
package/types/exception.d.ts
DELETED