@toa.io/extensions.configuration 1.0.0-alpha.30 → 1.0.0-alpha.300
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/components/configuration.values/manifest.toa.yaml +151 -0
- package/components/configuration.values/migrations/0002-indexes.yaml +7 -0
- package/components/configuration.values/operations/create.js +32 -0
- package/components/configuration.values/operations/fetch.js +13 -0
- package/components/configuration.values/operations/get.js +19 -0
- package/components/configuration.values/operations/lib/map.js +22 -0
- package/components/configuration.values/operations/lib/resolve.js +24 -0
- package/components/configuration.values/operations/list.js +11 -0
- package/components/configuration.values/source/create.ts +56 -0
- package/components/configuration.values/source/fetch.ts +26 -0
- package/components/configuration.values/source/get.ts +32 -0
- package/components/configuration.values/source/lib/map.ts +36 -0
- package/components/configuration.values/source/lib/resolve.ts +57 -0
- package/components/configuration.values/source/list.ts +21 -0
- package/components/configuration.values/tsconfig.json +10 -0
- package/components/configuration.values/types/index.d.ts +3 -0
- package/components/configuration.values/types/toa.d.ts +69 -0
- package/package.json +21 -10
- package/readme.md +178 -50
- package/transpiled/Aspect.d.ts +19 -4
- package/transpiled/Aspect.js +62 -9
- package/transpiled/Aspect.js.map +1 -1
- package/transpiled/Client.d.ts +59 -0
- package/transpiled/Client.js +171 -0
- package/transpiled/Client.js.map +1 -0
- package/transpiled/Composition.d.ts +14 -0
- package/transpiled/Composition.js +38 -0
- package/transpiled/Composition.js.map +1 -0
- package/transpiled/Factory.d.ts +9 -2
- package/transpiled/Factory.js +20 -9
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Secret.d.ts +15 -0
- package/transpiled/Secret.js +26 -0
- package/transpiled/Secret.js.map +1 -0
- package/transpiled/UI.d.ts +25 -0
- package/transpiled/UI.js +173 -0
- package/transpiled/UI.js.map +1 -0
- package/transpiled/configuration.d.ts +7 -2
- package/transpiled/configuration.js +33 -43
- package/transpiled/configuration.js.map +1 -1
- package/transpiled/index.d.ts +3 -3
- package/transpiled/index.js +4 -9
- package/transpiled/index.js.map +1 -1
- package/ui/dist/_app/env.js +1 -0
- package/ui/dist/_app/immutable/assets/0.BGFdDICE.css +2 -0
- package/ui/dist/_app/immutable/assets/ui.BghF56l_.css +1 -0
- package/ui/dist/_app/immutable/chunks/BO-bVeya.js +1 -0
- package/ui/dist/_app/immutable/chunks/Bjy-W4x2.js +81 -0
- package/ui/dist/_app/immutable/chunks/CcD_ISxM.js +3 -0
- package/ui/dist/_app/immutable/chunks/ChuJmltc.js +1 -0
- package/ui/dist/_app/immutable/chunks/DLExbVxt.js +6 -0
- package/ui/dist/_app/immutable/chunks/DNBIBZfd.js +8 -0
- package/ui/dist/_app/immutable/chunks/DcYrQeF9.js +50 -0
- package/ui/dist/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/ui/dist/_app/immutable/entry/app.C_BoZFMH.js +2 -0
- package/ui/dist/_app/immutable/entry/start.DGqZJFG-.js +1 -0
- package/ui/dist/_app/immutable/nodes/0.kGp6jAon.js +1 -0
- package/ui/dist/_app/immutable/nodes/1.B6GdKFoh.js +1 -0
- package/ui/dist/_app/immutable/nodes/2.B1yjjJQp.js +1 -0
- package/ui/dist/_app/immutable/nodes/3.Djrl0t8X.js +1 -0
- package/ui/dist/_app/immutable/nodes/4.DU-VoYDI.js +1 -0
- package/ui/dist/_app/version.json +1 -0
- package/ui/dist/apple-touch-icon.png +0 -0
- package/ui/dist/favicon-96x96.png +0 -0
- package/ui/dist/favicon.ico +0 -0
- package/ui/dist/index.html +57 -0
- package/ui/dist/robots.txt +3 -0
- package/notes/consistency.md +0 -69
- package/schemas/annotation.cos.yaml +0 -1
- package/schemas/manifest.cos.yaml +0 -2
- package/source/Aspect.test.ts +0 -15
- package/source/Aspect.ts +0 -23
- package/source/Factory.ts +0 -12
- package/source/configuration.test.ts +0 -90
- package/source/configuration.ts +0 -59
- package/source/deployment.test.ts +0 -21
- package/source/deployment.ts +0 -86
- package/source/index.ts +0 -3
- package/source/manifest.test.ts +0 -15
- package/source/manifest.ts +0 -15
- package/source/schemas.ts +0 -9
- package/transpiled/Aspect.test.d.ts +0 -1
- package/transpiled/Aspect.test.js +0 -15
- package/transpiled/Aspect.test.js.map +0 -1
- package/transpiled/configuration.test.d.ts +0 -1
- package/transpiled/configuration.test.js +0 -64
- package/transpiled/configuration.test.js.map +0 -1
- package/transpiled/deployment.d.ts +0 -8
- package/transpiled/deployment.js +0 -88
- package/transpiled/deployment.js.map +0 -1
- package/transpiled/deployment.test.d.ts +0 -1
- package/transpiled/deployment.test.js +0 -18
- package/transpiled/deployment.test.js.map +0 -1
- package/transpiled/manifest.d.ts +0 -6
- package/transpiled/manifest.js +0 -35
- package/transpiled/manifest.js.map +0 -1
- package/transpiled/manifest.test.d.ts +0 -1
- package/transpiled/manifest.test.js +0 -14
- package/transpiled/manifest.test.js.map +0 -1
- package/transpiled/schemas.d.ts +0 -3
- package/transpiled/schemas.js +0 -33
- package/transpiled/schemas.js.map +0 -1
- package/transpiled/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.json +0 -9
package/readme.md
CHANGED
|
@@ -11,8 +11,12 @@ namespace: dummies
|
|
|
11
11
|
|
|
12
12
|
configuration:
|
|
13
13
|
schema:
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
type: object
|
|
15
|
+
properties:
|
|
16
|
+
foo:
|
|
17
|
+
type: string
|
|
18
|
+
bar:
|
|
19
|
+
type: number
|
|
16
20
|
defaults:
|
|
17
21
|
foo: bar
|
|
18
22
|
bar: 1
|
|
@@ -21,7 +25,7 @@ configuration:
|
|
|
21
25
|
### Use
|
|
22
26
|
|
|
23
27
|
```javascript
|
|
24
|
-
function transition
|
|
28
|
+
function transition(input, entity, context) {
|
|
25
29
|
const { foo, bar } = context.configuration
|
|
26
30
|
|
|
27
31
|
// ...
|
|
@@ -34,9 +38,9 @@ function transition (input, entity, context) {
|
|
|
34
38
|
# context.toa.yaml
|
|
35
39
|
configuration:
|
|
36
40
|
dummies.dummy:
|
|
37
|
-
foo: qux
|
|
41
|
+
foo: qux # override default value
|
|
38
42
|
foo@staging: quux # deployment environment discriminator
|
|
39
|
-
bar: $BAZ_VALUE
|
|
43
|
+
bar: $BAZ_VALUE # secret
|
|
40
44
|
```
|
|
41
45
|
|
|
42
46
|
### Deploy secrets
|
|
@@ -45,22 +49,28 @@ configuration:
|
|
|
45
49
|
$ toa conceal configuration BAZ_VALUE=$ecr3t
|
|
46
50
|
```
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
### Change at runtime
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
```http
|
|
55
|
+
POST /configuration/values/dummies.dummy/ HTTP/1.1
|
|
56
|
+
authorization: Token ...
|
|
57
|
+
content-type: application/yaml
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
configuration:
|
|
60
|
+
foo: quux
|
|
61
|
+
bar: 2
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
55
65
|
|
|
56
66
|
## Manifest
|
|
57
67
|
|
|
58
|
-
Component's configuration is declared using `configuration` manifest,
|
|
59
|
-
|
|
68
|
+
Component's configuration is declared using the `configuration` manifest, containing `schema`
|
|
69
|
+
and optionally `defaults` properties.
|
|
60
70
|
|
|
61
71
|
### Schema
|
|
62
72
|
|
|
63
|
-
Configuration schema is declared with [
|
|
73
|
+
Configuration schema is declared with [JSON Schema](https://json-schema.org).
|
|
64
74
|
|
|
65
75
|
```yaml
|
|
66
76
|
# manifest.toa.yaml
|
|
@@ -69,30 +79,24 @@ namespace: dummies
|
|
|
69
79
|
|
|
70
80
|
configuration:
|
|
71
81
|
schema:
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
type: object
|
|
83
|
+
properties:
|
|
84
|
+
foo:
|
|
85
|
+
type: string
|
|
86
|
+
bar:
|
|
87
|
+
type: number
|
|
88
|
+
token:
|
|
89
|
+
type: string
|
|
90
|
+
format: secret
|
|
74
91
|
```
|
|
75
92
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
> Therefore, configuration schema changes are subject to component versioning.
|
|
79
|
-
|
|
80
|
-
If `configuration` object doesn't contain property `schema`, then it is considered to be schema.
|
|
81
|
-
|
|
82
|
-
```yaml
|
|
83
|
-
# manifest.toa.yaml
|
|
84
|
-
name: dummy
|
|
85
|
-
namespace: dummies
|
|
86
|
-
|
|
87
|
-
configuration:
|
|
88
|
-
foo: string
|
|
89
|
-
bar: number
|
|
90
|
-
```
|
|
93
|
+
A string the component reads as a secret is declared `format: secret`. It is a `Secret`
|
|
94
|
+
on the context, and is given as a `$NAME` reference — see [Secrets](#secrets).
|
|
91
95
|
|
|
92
96
|
### Defaults
|
|
93
97
|
|
|
94
|
-
The default configuration value can be provided using the `defaults` property, which should
|
|
95
|
-
to the configuration schema.
|
|
98
|
+
The default configuration value can be provided using the `defaults` property, which should
|
|
99
|
+
conform to the configuration schema.
|
|
96
100
|
|
|
97
101
|
```yaml
|
|
98
102
|
# manifest.toa.yaml
|
|
@@ -101,27 +105,22 @@ namespace: dummies
|
|
|
101
105
|
|
|
102
106
|
configuration:
|
|
103
107
|
schema:
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
type: object
|
|
109
|
+
properties:
|
|
110
|
+
foo:
|
|
111
|
+
type: string
|
|
112
|
+
bar:
|
|
113
|
+
type: number
|
|
106
114
|
defaults:
|
|
107
115
|
foo: hello
|
|
108
116
|
bar: 0
|
|
109
117
|
```
|
|
110
118
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
The configuration schema itself can contain default primitive values using the COS syntax.
|
|
119
|
+
### Epoch
|
|
114
120
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
namespace: dummies
|
|
119
|
-
|
|
120
|
-
configuration:
|
|
121
|
-
schema:
|
|
122
|
-
foo: hello
|
|
123
|
-
bar: 0
|
|
124
|
-
```
|
|
121
|
+
The configuration epoch of a component is the SHA-256 of its configuration schema, as
|
|
122
|
+
canonical JSON. A configuration object belongs to the epoch of the schema it was validated
|
|
123
|
+
against. A schema change is a new epoch.
|
|
125
124
|
|
|
126
125
|
## Annotation
|
|
127
126
|
|
|
@@ -136,9 +135,37 @@ configuration:
|
|
|
136
135
|
bar@staging: 2
|
|
137
136
|
```
|
|
138
137
|
|
|
138
|
+
The annotated object is deployed as the defaults of the component for its epoch, in place of
|
|
139
|
+
the manifest `defaults`.
|
|
140
|
+
|
|
141
|
+
Every key names a component except `resources`, which is the values service's own: it deploys
|
|
142
|
+
like any other and states what it may take. A component actually named `resources` is written
|
|
143
|
+
with its namespace, `default.resources` — the bare form is only shorthand for that.
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
# context.toa.yaml
|
|
147
|
+
configuration:
|
|
148
|
+
resources:
|
|
149
|
+
cpu: [200m, 1000m]
|
|
150
|
+
memory: [200Mi, 500Mi]
|
|
151
|
+
dummies.dummy:
|
|
152
|
+
foo: bye
|
|
153
|
+
```
|
|
154
|
+
|
|
139
155
|
## Secrets
|
|
140
156
|
|
|
141
|
-
|
|
157
|
+
A property declared `format: secret` is given as an uppercase name prefixed with `$`.
|
|
158
|
+
A plain string in its place is refused.
|
|
159
|
+
|
|
160
|
+
```yaml
|
|
161
|
+
# manifest.toa.yaml
|
|
162
|
+
configuration:
|
|
163
|
+
schema:
|
|
164
|
+
properties:
|
|
165
|
+
api-key:
|
|
166
|
+
type: string
|
|
167
|
+
format: secret
|
|
168
|
+
```
|
|
142
169
|
|
|
143
170
|
```yaml
|
|
144
171
|
# context.toa.yaml
|
|
@@ -158,14 +185,115 @@ Deployed kubernetes secret's name is predefined as `configuration`.
|
|
|
158
185
|
$ toa conceal configuration STRIPE_API_KEY=xxxxxxxx
|
|
159
186
|
```
|
|
160
187
|
|
|
188
|
+
A secret is substituted in the component's process, from the variable
|
|
189
|
+
`TOA_CONFIGURATION__<NAME>` deployed to it — a variable the component's code cannot read.
|
|
190
|
+
The values service holds and returns the reference.
|
|
191
|
+
|
|
192
|
+
In the component, a secret is a `Secret` object: `unwrap()` returns the string, while
|
|
193
|
+
`toString()`, JSON and `util.inspect` give `<REDACTED>`.
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
function transition(input, entity, context) {
|
|
197
|
+
const key = context.configuration.apiKey.unwrap()
|
|
198
|
+
|
|
199
|
+
// ...
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Values
|
|
204
|
+
|
|
205
|
+
Configuration values are held by the `configuration.values` component, deployed as the
|
|
206
|
+
`configuration-values` service. The service is deployed with the variable
|
|
207
|
+
`TOA_CONFIGURATION_VALUES`: the epoch, the schema and the defaults of every component
|
|
208
|
+
declaring configuration.
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"dummies.dummy": {
|
|
213
|
+
"epoch": "3f2a…",
|
|
214
|
+
"schema": { "type": "object", "properties": { "foo": { "type": "string" } } },
|
|
215
|
+
"defaults": { "foo": "bye" }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Configuration objects are immutable. Creating a configuration is creating a new object for
|
|
221
|
+
the component's current epoch; the latest object for a component and an epoch is the last
|
|
222
|
+
created one. Each object records its `originator`.
|
|
223
|
+
|
|
224
|
+
The configuration of a component for an epoch is:
|
|
225
|
+
|
|
226
|
+
1. The latest object created for the component and the epoch;
|
|
227
|
+
2. Otherwise, the deployed defaults, if the epoch is the deployed one;
|
|
228
|
+
3. Otherwise, none.
|
|
229
|
+
|
|
230
|
+
### Operations
|
|
231
|
+
|
|
232
|
+
- `get({ component, epoch? })`: the configuration with the schema it is checked against, as
|
|
233
|
+
`{ configuration, schema, epoch }`, or `null` when there is none. The epoch is the deployed
|
|
234
|
+
one when omitted; an epoch the deployment does not know has no `schema`.
|
|
235
|
+
- `fetch([{ component, epoch }])`: the same for several pairs at once, as
|
|
236
|
+
`[{ component, epoch, configuration }]`.
|
|
237
|
+
- `list()`: every component's configuration for its deployed epoch, by component name, as
|
|
238
|
+
`[{ component, epoch, schema, configuration }]`.
|
|
239
|
+
- `create({ component, configuration, originator })`: a new object for the component's
|
|
240
|
+
deployed epoch. The configuration must satisfy the schema. Errors: `UNKNOWN_COMPONENT`,
|
|
241
|
+
`INVALID_CONFIGURATION`.
|
|
242
|
+
|
|
243
|
+
Creating a configuration publishes the `configuration.values.created` event with the
|
|
244
|
+
object as stored.
|
|
245
|
+
|
|
246
|
+
### Resources
|
|
247
|
+
|
|
248
|
+
| Method | Path | Role |
|
|
249
|
+
| ------ | ----------------------------------- | ----------------------------- |
|
|
250
|
+
| `GET` | `/configuration/values/` | `system:configuration:get` |
|
|
251
|
+
| `GET` | `/configuration/values/:component/` | `system:configuration:get` |
|
|
252
|
+
| `POST` | `/configuration/values/:component/` | `system:configuration:create` |
|
|
253
|
+
|
|
254
|
+
`GET /configuration/values/` lists every component's configuration for its deployed epoch, by
|
|
255
|
+
component name, as `[{ component, epoch, schema, configuration }]`.
|
|
256
|
+
|
|
257
|
+
`GET /configuration/values/:component/` returns `{ configuration, schema, epoch }` for the
|
|
258
|
+
deployed epoch, `404` when there is none.
|
|
259
|
+
|
|
260
|
+
`POST` takes `{ configuration }`, records the Identity as the `originator`, and returns
|
|
261
|
+
`{ id, epoch }`. A configuration not satisfying the schema, or an unknown component, is
|
|
262
|
+
`422`.
|
|
263
|
+
|
|
264
|
+
## UI
|
|
265
|
+
|
|
266
|
+
The values service serves a page listing the configured components and creating
|
|
267
|
+
configurations, mounted at `/.configuration` on port `8003`. Reading it needs the
|
|
268
|
+
`system:configuration:get` role, creating needs `system:configuration:create`.
|
|
269
|
+
|
|
270
|
+
The page is always published: unlike the introspection annotation, the configuration
|
|
271
|
+
annotation is the per-component values map and has nowhere to carry a switch.
|
|
272
|
+
|
|
161
273
|
## Aspect
|
|
162
274
|
|
|
163
275
|
Component's configuration values are available as a well-known Aspect `configuration`.
|
|
164
276
|
|
|
165
277
|
```javascript
|
|
166
|
-
function transition
|
|
167
|
-
const foo = context.
|
|
278
|
+
function transition(input, entity, context) {
|
|
279
|
+
const foo = context.configuration.foo
|
|
168
280
|
|
|
169
281
|
// ...
|
|
170
282
|
}
|
|
171
283
|
```
|
|
284
|
+
|
|
285
|
+
On start, a component requests its configuration for its epoch from the values service and
|
|
286
|
+
waits until there is one, reporting every fifth attempt. The schema is applied, and secrets
|
|
287
|
+
are substituted. What is served is what was stored, whole: a `default` written into the schema
|
|
288
|
+
fills nothing, so a value every component is to have is declared in `defaults`. After a configuration is created, the running component receives the new
|
|
289
|
+
object and takes it when its `CREATED` is later than that of the value it holds.
|
|
290
|
+
|
|
291
|
+
### Local override
|
|
292
|
+
|
|
293
|
+
When the variable `TOA_CONFIGURATION_<NAMESPACE>_<NAME>` is set, the component's
|
|
294
|
+
configuration is the variable's value with the manifest `defaults` filled in and the schema
|
|
295
|
+
applied, and the values service is not used.
|
|
296
|
+
|
|
297
|
+
```shell
|
|
298
|
+
$ TOA_CONFIGURATION_DUMMIES_DUMMY='{"foo":"local"}' toa run components/dummy
|
|
299
|
+
```
|
package/transpiled/Aspect.d.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
|
-
import { Connector, type
|
|
1
|
+
import { Connector, type Locator } from '@toa.io/core';
|
|
2
|
+
import type { extensions } from '@toa.io/core/types';
|
|
3
|
+
import type { Client } from './Client.js';
|
|
4
|
+
import type { Manifest } from '@toa.io/definitions/extensions.configuration';
|
|
2
5
|
export declare class Aspect extends Connector implements extensions.Aspect {
|
|
3
6
|
readonly name = "configuration";
|
|
4
|
-
private readonly
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
private readonly locator;
|
|
8
|
+
private readonly manifest;
|
|
9
|
+
private readonly client;
|
|
10
|
+
private readonly epoch;
|
|
11
|
+
private value;
|
|
12
|
+
private created;
|
|
13
|
+
/**
|
|
14
|
+
* Without a client the value is local: the variable, the defaults and the schema.
|
|
15
|
+
* With one, the value is what the service holds, and it follows the service.
|
|
16
|
+
*/
|
|
17
|
+
constructor(locator: Locator, manifest: Manifest, client: Client | null);
|
|
18
|
+
invoke(path?: string[]): any;
|
|
19
|
+
protected open(): Promise<void>;
|
|
20
|
+
protected close(): Promise<void>;
|
|
21
|
+
private readonly listener;
|
|
7
22
|
}
|
package/transpiled/Aspect.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Aspect extends
|
|
1
|
+
import { console } from 'openspan';
|
|
2
|
+
import { Connector } from '@toa.io/core';
|
|
3
|
+
import { fit, local } from './configuration.js';
|
|
4
|
+
import { epoch } from '@toa.io/definitions/extensions.configuration';
|
|
5
|
+
export class Aspect extends Connector {
|
|
6
6
|
name = 'configuration';
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
locator;
|
|
8
|
+
manifest;
|
|
9
|
+
client;
|
|
10
|
+
epoch;
|
|
11
|
+
value = {};
|
|
12
|
+
created = 0;
|
|
13
|
+
/**
|
|
14
|
+
* Without a client the value is local: the variable, the defaults and the schema.
|
|
15
|
+
* With one, the value is what the service holds, and it follows the service.
|
|
16
|
+
*/
|
|
17
|
+
constructor(locator, manifest, client) {
|
|
9
18
|
super();
|
|
10
|
-
this.
|
|
19
|
+
this.locator = locator;
|
|
20
|
+
this.manifest = manifest;
|
|
21
|
+
this.client = client;
|
|
22
|
+
this.epoch = epoch(manifest.schema);
|
|
23
|
+
if (client !== null)
|
|
24
|
+
this.depends(client);
|
|
11
25
|
}
|
|
12
26
|
invoke(path) {
|
|
13
27
|
let cursor = this.value;
|
|
@@ -16,6 +30,45 @@ class Aspect extends core_1.Connector {
|
|
|
16
30
|
cursor = cursor[segment];
|
|
17
31
|
return cursor;
|
|
18
32
|
}
|
|
33
|
+
async open() {
|
|
34
|
+
if (this.client === null) {
|
|
35
|
+
this.value = local(this.locator, this.manifest);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const { configuration, created } = await this.client.fetch(this.locator.id, this.epoch);
|
|
39
|
+
this.value = fit(configuration, this.manifest);
|
|
40
|
+
this.created = created;
|
|
41
|
+
this.client.subscribe(this.locator.id, this.epoch, this.listener);
|
|
42
|
+
console.trace('Configuration resolved', {
|
|
43
|
+
component: this.locator.id,
|
|
44
|
+
epoch: this.epoch,
|
|
45
|
+
created
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async close() {
|
|
49
|
+
this.client?.unsubscribe(this.locator.id, this.epoch, this.listener);
|
|
50
|
+
}
|
|
51
|
+
listener = ({ configuration, created }) => {
|
|
52
|
+
// deliveries may repeat or cross: only what is newer than the held value replaces it
|
|
53
|
+
if (created <= this.created)
|
|
54
|
+
return;
|
|
55
|
+
try {
|
|
56
|
+
this.value = fit(configuration, this.manifest);
|
|
57
|
+
this.created = created;
|
|
58
|
+
console.info('Configuration updated', {
|
|
59
|
+
component: this.locator.id,
|
|
60
|
+
epoch: this.epoch,
|
|
61
|
+
created
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// the service validated it against the schema of its epoch, so the two schemas differ
|
|
66
|
+
console.error('Configuration value does not match the schema', {
|
|
67
|
+
component: this.locator.id,
|
|
68
|
+
epoch: this.epoch,
|
|
69
|
+
error
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
19
73
|
}
|
|
20
|
-
exports.Aspect = Aspect;
|
|
21
74
|
//# sourceMappingURL=Aspect.js.map
|
package/transpiled/Aspect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Aspect.js","sourceRoot":"","sources":["../source/Aspect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Aspect.js","sourceRoot":"","sources":["../source/Aspect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Connector } from '@toa.io/core';
|
|
2
|
+
import type { Host } from './Factory.js';
|
|
3
|
+
/**
|
|
4
|
+
* One per process: one remote to the values service and one subscription to its events,
|
|
5
|
+
* shared by every Aspect. What the Aspects ask for is collected and sent as one call;
|
|
6
|
+
* what the service creates afterwards is handed to whoever subscribed.
|
|
7
|
+
*/
|
|
8
|
+
export declare class Client extends Connector {
|
|
9
|
+
/** Disconnected once, a connector keeps what it depended on, so a gone client is not reused. */
|
|
10
|
+
private readonly host;
|
|
11
|
+
private readonly options;
|
|
12
|
+
private readonly pending;
|
|
13
|
+
private readonly listeners;
|
|
14
|
+
private remote;
|
|
15
|
+
private timer;
|
|
16
|
+
private flushing;
|
|
17
|
+
private fresh;
|
|
18
|
+
private round;
|
|
19
|
+
constructor(host: Host, options?: Partial<Options>);
|
|
20
|
+
/** The configuration of a component for an epoch, once the service has one. */
|
|
21
|
+
fetch(component: string, epoch: string): Promise<Value>;
|
|
22
|
+
subscribe(component: string, epoch: string, listener: Listener): void;
|
|
23
|
+
unsubscribe(component: string, epoch: string, listener: Listener): void;
|
|
24
|
+
protected open(): Promise<void>;
|
|
25
|
+
protected close(): Promise<void>;
|
|
26
|
+
private schedule;
|
|
27
|
+
private flush;
|
|
28
|
+
/** Those the service has served are told; the rest stay for the next round. */
|
|
29
|
+
private settle;
|
|
30
|
+
private report;
|
|
31
|
+
private backoff;
|
|
32
|
+
/** A created object goes to the subscribers of its component and epoch, as it is. */
|
|
33
|
+
private deliver;
|
|
34
|
+
}
|
|
35
|
+
export interface Options {
|
|
36
|
+
base: number;
|
|
37
|
+
max: number;
|
|
38
|
+
/** Every n-th round of waiting is reported. */
|
|
39
|
+
warn: number;
|
|
40
|
+
}
|
|
41
|
+
/** A configuration and when it was created; `0` for the deployed defaults. */
|
|
42
|
+
export interface Value {
|
|
43
|
+
configuration: object;
|
|
44
|
+
created: number;
|
|
45
|
+
}
|
|
46
|
+
export interface Fetched {
|
|
47
|
+
component: string;
|
|
48
|
+
epoch: string;
|
|
49
|
+
configuration: object | null;
|
|
50
|
+
created: number;
|
|
51
|
+
}
|
|
52
|
+
/** The `configuration.values.created` payload: the object as stored. */
|
|
53
|
+
export interface Created {
|
|
54
|
+
component: string;
|
|
55
|
+
epoch: string;
|
|
56
|
+
configuration: object;
|
|
57
|
+
CREATED: number;
|
|
58
|
+
}
|
|
59
|
+
export type Listener = (value: Value) => void;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { console } from 'openspan';
|
|
2
|
+
import { Connector, Locator } from '@toa.io/core';
|
|
3
|
+
import { EVENT, SOURCE } from '@toa.io/definitions/extensions.configuration';
|
|
4
|
+
/**
|
|
5
|
+
* One per process: one remote to the values service and one subscription to its events,
|
|
6
|
+
* shared by every Aspect. What the Aspects ask for is collected and sent as one call;
|
|
7
|
+
* what the service creates afterwards is handed to whoever subscribed.
|
|
8
|
+
*/
|
|
9
|
+
export class Client extends Connector {
|
|
10
|
+
/** Disconnected once, a connector keeps what it depended on, so a gone client is not reused. */
|
|
11
|
+
host;
|
|
12
|
+
options;
|
|
13
|
+
pending = new Map();
|
|
14
|
+
listeners = new Map();
|
|
15
|
+
remote = null;
|
|
16
|
+
timer = null;
|
|
17
|
+
flushing = false;
|
|
18
|
+
fresh = false;
|
|
19
|
+
round = 0;
|
|
20
|
+
constructor(host, options = {}) {
|
|
21
|
+
super();
|
|
22
|
+
this.host = host;
|
|
23
|
+
this.options = { ...DEFAULTS, ...options };
|
|
24
|
+
}
|
|
25
|
+
/** The configuration of a component for an epoch, once the service has one. */
|
|
26
|
+
async fetch(component, epoch) {
|
|
27
|
+
const key = id(component, epoch);
|
|
28
|
+
let entry = this.pending.get(key);
|
|
29
|
+
if (entry === undefined) {
|
|
30
|
+
entry = { component, epoch, waiters: [] };
|
|
31
|
+
this.pending.set(key, entry);
|
|
32
|
+
}
|
|
33
|
+
const promise = new Promise((resolve) => {
|
|
34
|
+
entry.waiters.push(resolve);
|
|
35
|
+
});
|
|
36
|
+
if (this.flushing)
|
|
37
|
+
this.fresh = true;
|
|
38
|
+
else
|
|
39
|
+
this.schedule(0);
|
|
40
|
+
return await promise;
|
|
41
|
+
}
|
|
42
|
+
subscribe(component, epoch, listener) {
|
|
43
|
+
const key = id(component, epoch);
|
|
44
|
+
if (!this.listeners.has(key))
|
|
45
|
+
this.listeners.set(key, new Set());
|
|
46
|
+
this.listeners.get(key).add(listener);
|
|
47
|
+
}
|
|
48
|
+
unsubscribe(component, epoch, listener) {
|
|
49
|
+
this.listeners.get(id(component, epoch))?.delete(listener);
|
|
50
|
+
}
|
|
51
|
+
async open() {
|
|
52
|
+
this.remote = await this.host.remote(LOCATOR, SOURCE);
|
|
53
|
+
this.depends(this.remote);
|
|
54
|
+
await this.remote.connect();
|
|
55
|
+
const subscription = new Subscription(this.deliver.bind(this));
|
|
56
|
+
const consumer = await this.host.receive(EVENT, subscription);
|
|
57
|
+
this.depends(consumer);
|
|
58
|
+
await consumer.connect();
|
|
59
|
+
}
|
|
60
|
+
async close() {
|
|
61
|
+
if (this.timer !== null) {
|
|
62
|
+
clearTimeout(this.timer);
|
|
63
|
+
this.timer = null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
schedule(delay) {
|
|
67
|
+
if (this.flushing)
|
|
68
|
+
return;
|
|
69
|
+
if (this.timer !== null) {
|
|
70
|
+
// a request that has just arrived does not wait for the round already planned
|
|
71
|
+
if (delay > 0)
|
|
72
|
+
return;
|
|
73
|
+
clearTimeout(this.timer);
|
|
74
|
+
}
|
|
75
|
+
this.timer = setTimeout(() => {
|
|
76
|
+
void this.flush();
|
|
77
|
+
}, delay);
|
|
78
|
+
}
|
|
79
|
+
async flush() {
|
|
80
|
+
this.timer = null;
|
|
81
|
+
this.flushing = true;
|
|
82
|
+
this.fresh = false;
|
|
83
|
+
const batch = [...this.pending.values()];
|
|
84
|
+
const input = batch.map(({ component, epoch }) => ({ component, epoch }));
|
|
85
|
+
try {
|
|
86
|
+
const output = await this.remote.invoke('fetch', { input });
|
|
87
|
+
if (output instanceof Error)
|
|
88
|
+
throw output;
|
|
89
|
+
this.settle(output);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.warn('Configuration fetch failed', { error });
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
this.flushing = false;
|
|
96
|
+
}
|
|
97
|
+
this.report(batch);
|
|
98
|
+
if (this.pending.size === 0)
|
|
99
|
+
return;
|
|
100
|
+
if (this.fresh)
|
|
101
|
+
this.schedule(0);
|
|
102
|
+
else
|
|
103
|
+
this.schedule(this.backoff());
|
|
104
|
+
}
|
|
105
|
+
/** Those the service has served are told; the rest stay for the next round. */
|
|
106
|
+
settle(output) {
|
|
107
|
+
for (const { component, epoch, configuration, created } of output) {
|
|
108
|
+
if (configuration === null)
|
|
109
|
+
continue;
|
|
110
|
+
const key = id(component, epoch);
|
|
111
|
+
const entry = this.pending.get(key);
|
|
112
|
+
if (entry === undefined)
|
|
113
|
+
continue;
|
|
114
|
+
this.pending.delete(key);
|
|
115
|
+
for (const resolve of entry.waiters)
|
|
116
|
+
resolve({ configuration, created });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
report(batch) {
|
|
120
|
+
const waiting = batch
|
|
121
|
+
.filter(({ component, epoch }) => this.pending.has(id(component, epoch)))
|
|
122
|
+
.map(({ component }) => component);
|
|
123
|
+
if (waiting.length === 0) {
|
|
124
|
+
this.round = 0;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
this.round++;
|
|
128
|
+
if (this.round % this.options.warn === 1)
|
|
129
|
+
console.warn('Waiting for configuration', {
|
|
130
|
+
components: waiting,
|
|
131
|
+
round: this.round
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
backoff() {
|
|
135
|
+
return Math.min(this.options.base * Math.pow(FACTOR, this.round), this.options.max);
|
|
136
|
+
}
|
|
137
|
+
/** A created object goes to the subscribers of its component and epoch, as it is. */
|
|
138
|
+
deliver(created) {
|
|
139
|
+
const listeners = this.listeners.get(id(created.component, created.epoch));
|
|
140
|
+
if (listeners === undefined)
|
|
141
|
+
return;
|
|
142
|
+
const value = {
|
|
143
|
+
configuration: created.configuration,
|
|
144
|
+
created: created.CREATED
|
|
145
|
+
};
|
|
146
|
+
for (const listener of listeners)
|
|
147
|
+
listener(value);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** What the event consumer hands deliveries to. */
|
|
151
|
+
class Subscription extends Connector {
|
|
152
|
+
handler;
|
|
153
|
+
constructor(handler) {
|
|
154
|
+
super();
|
|
155
|
+
this.handler = handler;
|
|
156
|
+
}
|
|
157
|
+
async receive(message) {
|
|
158
|
+
this.handler(message.payload);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function id(component, epoch) {
|
|
162
|
+
return component + '\0' + epoch;
|
|
163
|
+
}
|
|
164
|
+
const LOCATOR = new Locator('values', 'configuration');
|
|
165
|
+
const FACTOR = 1.5;
|
|
166
|
+
const DEFAULTS = {
|
|
167
|
+
base: 1000,
|
|
168
|
+
max: 10000,
|
|
169
|
+
warn: 5
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=Client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.js","sourceRoot":"","sources":["../source/Client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Connector } from '@toa.io/core';
|
|
2
|
+
import type { Host } from './Factory.js';
|
|
3
|
+
/** Hosts the values component in the service process. */
|
|
4
|
+
export declare class Composition extends Connector {
|
|
5
|
+
private readonly host;
|
|
6
|
+
constructor(host: Host);
|
|
7
|
+
protected open(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export declare function components(): Components;
|
|
10
|
+
interface Components {
|
|
11
|
+
labels: string[];
|
|
12
|
+
paths: string[];
|
|
13
|
+
}
|
|
14
|
+
export {};
|