@toa.io/extensions.exposition 1.0.0-alpha.341 → 1.0.0-alpha.343
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 +3 -3
- package/transpiled/directives/auth/Transfer.d.ts +1 -0
- package/transpiled/directives/auth/Transfer.js +2 -1
- package/transpiled/directives/auth/Transfer.js.map +1 -1
- package/transpiled/directives/realtime/Hub.d.ts +14 -1
- package/transpiled/directives/realtime/Hub.js +57 -10
- package/transpiled/directives/realtime/Hub.js.map +1 -1
- package/transpiled/directives/realtime/Realtime.d.ts +13 -2
- package/transpiled/directives/realtime/Realtime.js +57 -13
- package/transpiled/directives/realtime/Realtime.js.map +1 -1
- package/transpiled/directives/realtime/Stream.d.ts +11 -0
- package/transpiled/directives/realtime/Stream.js +11 -0
- package/transpiled/directives/realtime/Stream.js.map +1 -1
- package/transpiled/directives/realtime/measurements.d.ts +2 -0
- package/transpiled/directives/realtime/measurements.js +11 -2
- package/transpiled/directives/realtime/measurements.js.map +1 -1
- package/transpiled/realtime/redis.d.ts +7 -1
- package/transpiled/realtime/redis.js +9 -3
- package/transpiled/realtime/redis.js.map +1 -1
- package/ui/dist/_app/version.json +1 -1
- package/ui/dist/index.html +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.exposition",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.343",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Toa Exposition",
|
|
6
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@toa.io/core": "1.0.0-alpha.333",
|
|
32
|
-
"@toa.io/definitions": "1.0.0-alpha.
|
|
32
|
+
"@toa.io/definitions": "1.0.0-alpha.343",
|
|
33
33
|
"@toa.io/generic": "1.0.0-alpha.332",
|
|
34
34
|
"@toa.io/pointer": "1.0.0-alpha.332",
|
|
35
35
|
"@toa.io/schemas": "1.0.0-alpha.332",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"lru-cache": "11.5.3",
|
|
76
76
|
"paseto": "4.0.1"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "820f07c0112820e70048f5304c9de200b6aa0788"
|
|
79
79
|
}
|
|
@@ -20,5 +20,6 @@ export declare class Transfer implements Directive {
|
|
|
20
20
|
describe(introspection: Introspection): Introspection;
|
|
21
21
|
/** What answers a credential is never the answer to another. */
|
|
22
22
|
settle(_: Context, response: OutgoingMessage): Promise<void>;
|
|
23
|
+
/** A body taken as it arrived (`map:buffer`, `map:stream`) is none here, as it is to `map`. */
|
|
23
24
|
private embed;
|
|
24
25
|
}
|
|
@@ -38,8 +38,9 @@ export class Transfer {
|
|
|
38
38
|
response.headers ??= new Headers();
|
|
39
39
|
response.headers.set('cache-control', 'no-store');
|
|
40
40
|
}
|
|
41
|
+
/** A body taken as it arrived (`map:buffer`, `map:stream`) is none here, as it is to `map`. */
|
|
41
42
|
embed(body, credential) {
|
|
42
|
-
if (body === undefined)
|
|
43
|
+
if (body === undefined || body === null)
|
|
43
44
|
body = {};
|
|
44
45
|
if (typeof body !== 'object' || body === null)
|
|
45
46
|
throw new BadRequest('Invalid request body');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Transfer.js","sourceRoot":"","sources":["../../../source/directives/auth/Transfer.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAK7C;;;;;GAKG;AACH,MAAM,OAAO,QAAQ;IACH,QAAQ,CAAQ;IAEhC,YAAmB,QAAiB;QAClC,MAAM,CAAC,EAAE,CACP,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EACnD,yEAAyE,CAC1E,CAAA;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,CAAkB,EAAE,OAAgB;QACnD,IAAI,OAAO,CAAC,UAAU;YAAE,OAAO,KAAK,CAAA;QAEpC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAA;QAExD,IAAI,UAAU,KAAK,SAAS;YAC1B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;QAErE,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,MAAM,CAAC,CAAkB,EAAE,OAAgB;QAChD,OAAO,CAAC,OAAO,CAAC,UAAU,CAAA;IAC5B,CAAC;IAED,0EAA0E;IACnE,QAAQ,CAAC,aAA4B;QAC1C,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAElC,OAAO,aAAa,CAAA;IACtB,CAAC;IAED,gEAAgE;IACzD,KAAK,CAAC,MAAM,CAAC,CAAU,EAAE,QAAyB;QACvD,QAAQ,CAAC,OAAO,KAAK,IAAI,OAAO,EAAE,CAAA;QAClC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAA;IACnD,CAAC;
|
|
1
|
+
{"version":3,"file":"Transfer.js","sourceRoot":"","sources":["../../../source/directives/auth/Transfer.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAK7C;;;;;GAKG;AACH,MAAM,OAAO,QAAQ;IACH,QAAQ,CAAQ;IAEhC,YAAmB,QAAiB;QAClC,MAAM,CAAC,EAAE,CACP,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EACnD,yEAAyE,CAC1E,CAAA;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;IAED;;;OAGG;IACI,SAAS,CAAC,CAAkB,EAAE,OAAgB;QACnD,IAAI,OAAO,CAAC,UAAU;YAAE,OAAO,KAAK,CAAA;QAEpC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAA;QAExD,IAAI,UAAU,KAAK,SAAS;YAC1B,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAA;QAErE,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,MAAM,CAAC,CAAkB,EAAE,OAAgB;QAChD,OAAO,CAAC,OAAO,CAAC,UAAU,CAAA;IAC5B,CAAC;IAED,0EAA0E;IACnE,QAAQ,CAAC,aAA4B;QAC1C,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAElC,OAAO,aAAa,CAAA;IACtB,CAAC;IAED,gEAAgE;IACzD,KAAK,CAAC,MAAM,CAAC,CAAU,EAAE,QAAyB;QACvD,QAAQ,CAAC,OAAO,KAAK,IAAI,OAAO,EAAE,CAAA;QAClC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAA;IACnD,CAAC;IAED,+FAA+F;IACvF,KAAK,CAAC,IAAa,EAAE,UAAkB;QAC7C,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI;YAAE,IAAI,GAAG,EAAE,CAAA;QAElD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAC3C,MAAM,IAAI,UAAU,CAAC,sBAAsB,CAAC,CAAA;QAE9C,MAAM,KAAK,GAAG,IAA+B,CAAA;QAE7C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAA;QAEjC,OAAO,KAAK,CAAA;IACd,CAAC;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Stream } from './Stream.ts';
|
|
1
|
+
import { Stream, type Push } from './Stream.ts';
|
|
2
2
|
/**
|
|
3
3
|
* The streams this gateway serves, by key.
|
|
4
4
|
*
|
|
@@ -10,24 +10,35 @@ import { Stream } from './Stream.ts';
|
|
|
10
10
|
* A channel keeps nothing for a subscriber that was away. Whenever the subscriber is back, what
|
|
11
11
|
* each key was written meanwhile is read from its stream, from the last event this gateway
|
|
12
12
|
* delivered of it; each reader skips what it was given already.
|
|
13
|
+
*
|
|
14
|
+
* A key has a second channel, of the events clients push to it, which are stored nowhere: what
|
|
15
|
+
* was pushed while the subscriber was away is gone.
|
|
13
16
|
*/
|
|
14
17
|
export declare class Hub {
|
|
15
18
|
private readonly keys;
|
|
16
19
|
private shards;
|
|
17
20
|
private subscribers;
|
|
21
|
+
private publishers;
|
|
18
22
|
private connecting;
|
|
19
23
|
private prefix;
|
|
24
|
+
private pushes;
|
|
20
25
|
/** Connects on the first stream it serves, not before: a gateway may serve none. */
|
|
21
26
|
connect(): Promise<void>;
|
|
22
27
|
close(): void;
|
|
23
28
|
private start;
|
|
24
29
|
open(key: string, token?: string): Promise<Stream>;
|
|
30
|
+
/**
|
|
31
|
+
* Publishes an event a client pushed to the readers of a key, wherever they are read. It is not
|
|
32
|
+
* delivered here but from the channel, as it is on every other gateway.
|
|
33
|
+
*/
|
|
34
|
+
push(key: string, { event, sender, data }: Push): Promise<void>;
|
|
25
35
|
private enter;
|
|
26
36
|
private leave;
|
|
27
37
|
/** Creates the stream where it is gone, and answers where it ends now. */
|
|
28
38
|
private marker;
|
|
29
39
|
private read;
|
|
30
40
|
private receive;
|
|
41
|
+
private pushed;
|
|
31
42
|
private broadcast;
|
|
32
43
|
/**
|
|
33
44
|
* What every key was written while the subscriber was away. Its channels are subscribed to
|
|
@@ -35,6 +46,8 @@ export declare class Hub {
|
|
|
35
46
|
* is missed.
|
|
36
47
|
*/
|
|
37
48
|
private recover;
|
|
49
|
+
/** The channel of a key's routed events, and the channel of its pushed events. */
|
|
50
|
+
private channels;
|
|
38
51
|
/** The connection a key's stream is kept on. */
|
|
39
52
|
private redis;
|
|
40
53
|
private subscriber;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { console } from 'openspan';
|
|
2
2
|
import { Stream, HEARTBEAT, decode, encode } from './Stream.js';
|
|
3
|
-
import { MAXLEN, Shards, expire, prefix, shard } from '../../realtime/redis.js';
|
|
3
|
+
import { MAXLEN, Shards, expire, prefix, pushes, shard } from '../../realtime/redis.js';
|
|
4
4
|
import * as measure from './measurements.js';
|
|
5
5
|
/**
|
|
6
6
|
* The streams this gateway serves, by key.
|
|
@@ -13,14 +13,21 @@ import * as measure from './measurements.js';
|
|
|
13
13
|
* A channel keeps nothing for a subscriber that was away. Whenever the subscriber is back, what
|
|
14
14
|
* each key was written meanwhile is read from its stream, from the last event this gateway
|
|
15
15
|
* delivered of it; each reader skips what it was given already.
|
|
16
|
+
*
|
|
17
|
+
* A key has a second channel, of the events clients push to it, which are stored nowhere: what
|
|
18
|
+
* was pushed while the subscriber was away is gone.
|
|
16
19
|
*/
|
|
17
20
|
export class Hub {
|
|
18
21
|
keys = new Map();
|
|
19
22
|
shards = null;
|
|
20
|
-
// a subscribing connection can do nothing else, so each Redis has one of its own
|
|
23
|
+
// a subscribing connection can do nothing else, so each Redis has one of its own; it
|
|
24
|
+
// subscribes to both channels of a key, so it names them in full
|
|
21
25
|
subscribers = null;
|
|
26
|
+
// pushed events are published under a prefix of their own
|
|
27
|
+
publishers = null;
|
|
22
28
|
connecting = null;
|
|
23
29
|
prefix = '';
|
|
30
|
+
pushes = '';
|
|
24
31
|
/** Connects on the first stream it serves, not before: a gateway may serve none. */
|
|
25
32
|
async connect() {
|
|
26
33
|
this.connecting ??= this.start();
|
|
@@ -34,23 +41,35 @@ export class Hub {
|
|
|
34
41
|
}
|
|
35
42
|
this.keys.clear();
|
|
36
43
|
this.subscribers?.disconnect();
|
|
44
|
+
this.publishers?.disconnect();
|
|
37
45
|
this.shards?.disconnect();
|
|
38
46
|
this.subscribers = null;
|
|
47
|
+
this.publishers = null;
|
|
39
48
|
this.shards = null;
|
|
40
49
|
this.connecting = null;
|
|
41
50
|
}
|
|
42
51
|
async start() {
|
|
43
52
|
this.prefix = prefix();
|
|
53
|
+
this.pushes = pushes();
|
|
44
54
|
const shards = new Shards();
|
|
45
|
-
const subscribers = new Shards();
|
|
46
|
-
|
|
55
|
+
const subscribers = new Shards('');
|
|
56
|
+
// connected by the first push, not before: a gateway may push nothing
|
|
57
|
+
const publishers = new Shards(this.pushes);
|
|
58
|
+
for (const connection of [
|
|
59
|
+
...shards.connections,
|
|
60
|
+
...subscribers.connections,
|
|
61
|
+
...publishers.connections
|
|
62
|
+
])
|
|
47
63
|
connection.on('error', (error) => console.debug('Realtime streams unreachable', {
|
|
48
64
|
error: error.code ?? error.message
|
|
49
65
|
}));
|
|
50
66
|
subscribers.connections.forEach((subscriber, i) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
subscriber.on('smessage', (channel, message) => {
|
|
68
|
+
if (channel.startsWith(this.prefix))
|
|
69
|
+
this.receive(channel.slice(this.prefix.length), message);
|
|
70
|
+
else if (channel.startsWith(this.pushes))
|
|
71
|
+
this.pushed(channel.slice(this.pushes.length), message);
|
|
72
|
+
});
|
|
54
73
|
// `ready` follows every reconnect too, and what was written meanwhile never arrives
|
|
55
74
|
let connected = false;
|
|
56
75
|
subscriber.on('ready', () => {
|
|
@@ -61,6 +80,7 @@ export class Hub {
|
|
|
61
80
|
});
|
|
62
81
|
this.shards = shards;
|
|
63
82
|
this.subscribers = subscribers;
|
|
83
|
+
this.publishers = publishers;
|
|
64
84
|
await Promise.all([shards.connect(), subscribers.connect()]);
|
|
65
85
|
}
|
|
66
86
|
async open(key, token) {
|
|
@@ -84,6 +104,16 @@ export class Hub {
|
|
|
84
104
|
stream.token(encode(marker));
|
|
85
105
|
return stream;
|
|
86
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Publishes an event a client pushed to the readers of a key, wherever they are read. It is not
|
|
109
|
+
* delivered here but from the channel, as it is on every other gateway.
|
|
110
|
+
*/
|
|
111
|
+
async push(key, { event, sender, data }) {
|
|
112
|
+
await this.connect();
|
|
113
|
+
const message = JSON.stringify([event, data, sender ?? null]);
|
|
114
|
+
await this.publishers.of(key).spublish(key, message);
|
|
115
|
+
measure.push(event);
|
|
116
|
+
}
|
|
87
117
|
async enter(key, stream) {
|
|
88
118
|
let entry = this.keys.get(key);
|
|
89
119
|
if (entry === undefined) {
|
|
@@ -92,7 +122,7 @@ export class Hub {
|
|
|
92
122
|
last: null,
|
|
93
123
|
timer: setInterval(() => this.renew(key), this.renewal()),
|
|
94
124
|
subscribed: this.subscriber(key)
|
|
95
|
-
.ssubscribe(key)
|
|
125
|
+
.ssubscribe(...this.channels(key))
|
|
96
126
|
.then(() => undefined)
|
|
97
127
|
};
|
|
98
128
|
entry.timer.unref();
|
|
@@ -115,7 +145,7 @@ export class Hub {
|
|
|
115
145
|
this.keys.delete(key);
|
|
116
146
|
this.renew(key);
|
|
117
147
|
this.subscriber(key)
|
|
118
|
-
.sunsubscribe(key)
|
|
148
|
+
.sunsubscribe(...this.channels(key))
|
|
119
149
|
.catch((error) => console.debug('Realtime key not unsubscribed', { key, error }));
|
|
120
150
|
}
|
|
121
151
|
/** Creates the stream where it is gone, and answers where it ends now. */
|
|
@@ -148,6 +178,17 @@ export class Hub {
|
|
|
148
178
|
const [id, event, data] = JSON.parse(message);
|
|
149
179
|
this.broadcast(entry, { id, event, data: JSON.parse(data) });
|
|
150
180
|
}
|
|
181
|
+
pushed(key, message) {
|
|
182
|
+
const entry = this.keys.get(key);
|
|
183
|
+
if (entry === undefined)
|
|
184
|
+
return;
|
|
185
|
+
const [event, data, sender] = JSON.parse(message);
|
|
186
|
+
const push = sender === null ? { event, data } : { event, sender, data };
|
|
187
|
+
for (const stream of entry.streams)
|
|
188
|
+
if (!stream.volatile(push))
|
|
189
|
+
measure.drop(event);
|
|
190
|
+
measure.deliver(event);
|
|
191
|
+
}
|
|
151
192
|
broadcast(entry, event) {
|
|
152
193
|
entry.last = event.id;
|
|
153
194
|
for (const stream of entry.streams)
|
|
@@ -163,7 +204,9 @@ export class Hub {
|
|
|
163
204
|
const n = this.shards?.connections.length ?? 1;
|
|
164
205
|
const keys = [...this.keys.keys()].filter((key) => shard(key, n) === i);
|
|
165
206
|
if (keys.length > 0)
|
|
166
|
-
await this.subscribers?.connections[i]
|
|
207
|
+
await this.subscribers?.connections[i]
|
|
208
|
+
.ssubscribe(...keys.flatMap((key) => this.channels(key)))
|
|
209
|
+
.catch((error) => {
|
|
167
210
|
console.warn('Realtime keys not subscribed again', { error });
|
|
168
211
|
});
|
|
169
212
|
for (const key of keys) {
|
|
@@ -181,6 +224,10 @@ export class Hub {
|
|
|
181
224
|
}
|
|
182
225
|
}
|
|
183
226
|
}
|
|
227
|
+
/** The channel of a key's routed events, and the channel of its pushed events. */
|
|
228
|
+
channels(key) {
|
|
229
|
+
return [this.prefix + key, this.pushes + key];
|
|
230
|
+
}
|
|
184
231
|
/** The connection a key's stream is kept on. */
|
|
185
232
|
redis(key) {
|
|
186
233
|
return this.shards.of(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Hub.js","sourceRoot":"","sources":["../../../source/directives/realtime/Hub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"Hub.js","sourceRoot":"","sources":["../../../source/directives/realtime/Hub.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +1,36 @@
|
|
|
1
|
+
import type { Schema } from '@toa.io/schemas';
|
|
1
2
|
import type { Context } from '../../HTTP/index.ts';
|
|
2
3
|
import type { DirectiveFamily, Parameter } from '../../RTD/index.ts';
|
|
3
4
|
import type { Output } from '../../io.ts';
|
|
4
5
|
/**
|
|
5
6
|
* `realtime:stream` answers with the stream of the key a route variable names, or of a literal
|
|
6
|
-
* key
|
|
7
|
+
* key, and `realtime:push` sends the request body to whoever reads one. Who may read or push is
|
|
8
|
+
* what the route's own directives say, as for anything else it serves.
|
|
7
9
|
*/
|
|
8
10
|
export declare class Realtime implements DirectiveFamily<Directive> {
|
|
9
11
|
readonly name = "realtime";
|
|
10
12
|
readonly mandatory = false;
|
|
11
13
|
private readonly hub;
|
|
12
14
|
create(name: string, value: unknown, _: unknown, route: string): Directive;
|
|
15
|
+
/** A method answers with a stream or pushes to one, and not both. */
|
|
16
|
+
arrange(directives: Directive[]): void;
|
|
13
17
|
precall(directives: Directive[], context: Context, parameters: Parameter[]): Promise<Output>;
|
|
14
18
|
dispose(): void;
|
|
15
19
|
/** The value of the route variable, which is never a literal: a literal is served by name. */
|
|
16
20
|
private variable;
|
|
21
|
+
private push;
|
|
17
22
|
}
|
|
18
|
-
export type Directive = Variable | Literal;
|
|
23
|
+
export type Directive = Variable | Literal | Push;
|
|
19
24
|
interface Variable {
|
|
20
25
|
variable: string;
|
|
21
26
|
}
|
|
22
27
|
interface Literal {
|
|
23
28
|
key: string;
|
|
24
29
|
}
|
|
30
|
+
type Push = (Variable | Literal) & {
|
|
31
|
+
push: {
|
|
32
|
+
event: string;
|
|
33
|
+
input: Schema;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
25
36
|
export {};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import * as schemas from '@toa.io/schemas';
|
|
1
2
|
import { literal } from '@toa.io/definitions/extensions.exposition/realtime';
|
|
2
|
-
import { NotFound } from '../../HTTP/index.js';
|
|
3
|
+
import { BadRequest, NotFound, RequestEntityTooLarge } from '../../HTTP/index.js';
|
|
3
4
|
import { configured } from '../../realtime/redis.js';
|
|
4
5
|
import { Hub } from './Hub.js';
|
|
5
6
|
/**
|
|
6
7
|
* `realtime:stream` answers with the stream of the key a route variable names, or of a literal
|
|
7
|
-
* key
|
|
8
|
+
* key, and `realtime:push` sends the request body to whoever reads one. Who may read or push is
|
|
9
|
+
* what the route's own directives say, as for anything else it serves.
|
|
8
10
|
*/
|
|
9
11
|
export class Realtime {
|
|
10
12
|
name = 'realtime';
|
|
@@ -13,17 +15,16 @@ export class Realtime {
|
|
|
13
15
|
// the arguments every family is given a directive with
|
|
14
16
|
// eslint-disable-next-line max-params
|
|
15
17
|
create(name, value, _, route) {
|
|
16
|
-
if (name
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return { variable: value };
|
|
18
|
+
if (name === 'stream')
|
|
19
|
+
return key(name, value, route);
|
|
20
|
+
if (name === 'push')
|
|
21
|
+
return push(value, route);
|
|
22
|
+
throw new Error(`Directive 'realtime:${name}' is not implemented`);
|
|
23
|
+
}
|
|
24
|
+
/** A method answers with a stream or pushes to one, and not both. */
|
|
25
|
+
arrange(directives) {
|
|
26
|
+
if (directives.length > 1)
|
|
27
|
+
throw new Error('A method declares one realtime directive, and no more');
|
|
27
28
|
}
|
|
28
29
|
async precall(directives, context, parameters) {
|
|
29
30
|
const [directive] = directives;
|
|
@@ -31,6 +32,8 @@ export class Realtime {
|
|
|
31
32
|
// nothing in the context declares realtime, so nothing is kept to be read
|
|
32
33
|
if (!configured())
|
|
33
34
|
throw new NotFound('Realtime streams are not configured');
|
|
35
|
+
if ('push' in directive)
|
|
36
|
+
return await this.push(directive.push, key, context);
|
|
34
37
|
const token = context.url.searchParams.get('token') ?? undefined;
|
|
35
38
|
return { body: await this.hub.open(key, token) };
|
|
36
39
|
}
|
|
@@ -46,5 +49,46 @@ export class Realtime {
|
|
|
46
49
|
throw new NotFound();
|
|
47
50
|
return key;
|
|
48
51
|
}
|
|
52
|
+
async push({ event, input }, key, context) {
|
|
53
|
+
const length = Number(context.request.headers['content-length']);
|
|
54
|
+
// what is pushed is sent to every reader of the key, so how much may be is bounded
|
|
55
|
+
if (length > LIMIT)
|
|
56
|
+
throw new RequestEntityTooLarge(`Size limit is ${LIMIT} bytes`);
|
|
57
|
+
const body = await context.body();
|
|
58
|
+
// a body sent without its length is measured once it is read
|
|
59
|
+
if (Number.isNaN(length) && Buffer.byteLength(JSON.stringify(body) ?? '') > LIMIT)
|
|
60
|
+
throw new RequestEntityTooLarge(`Size limit is ${LIMIT} bytes`);
|
|
61
|
+
const error = input.fit(body);
|
|
62
|
+
if (error !== null)
|
|
63
|
+
throw new BadRequest(error.message);
|
|
64
|
+
await this.hub.push(key, { event, sender: context.identity?.id, data: body });
|
|
65
|
+
return { status: 204 };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** The key a directive names: a route variable, or a literal. */
|
|
69
|
+
function key(name, value, route) {
|
|
70
|
+
if (typeof value === 'string' && literal(value)) {
|
|
71
|
+
if (value.length === 1)
|
|
72
|
+
throw new Error(`'realtime:${name}' literal '${value}' names no key, at '${route}'`);
|
|
73
|
+
return { key: value };
|
|
74
|
+
}
|
|
75
|
+
if (typeof value !== 'string' || !route.includes(`:${value}`))
|
|
76
|
+
throw new Error(`'realtime:${name}' names the route variable that is the key, or a literal key, and ` +
|
|
77
|
+
`'${String(value)}' is not one of '${route}'`);
|
|
78
|
+
return { variable: value };
|
|
79
|
+
}
|
|
80
|
+
function push(value, route) {
|
|
81
|
+
const { key: name, event, input } = (value ?? {});
|
|
82
|
+
if (typeof event !== 'string' || event === '')
|
|
83
|
+
throw new Error(`'realtime:push' names the event it is streamed as, at '${route}'`);
|
|
84
|
+
// a reader tells a token by its name, and a routed event by a name qualified by its component
|
|
85
|
+
if (event === 'token' || event.includes('.'))
|
|
86
|
+
throw new Error(`'realtime:push' event '${event}' would be read as a token or a routed event, at '${route}'`);
|
|
87
|
+
// whatever is pushed reaches every reader of the key, so what may be is stated
|
|
88
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input))
|
|
89
|
+
throw new Error(`'realtime:push' states the schema of what is pushed, at '${route}'`);
|
|
90
|
+
return { ...key('push', name, route), push: { event, input: schemas.schema(input) } };
|
|
49
91
|
}
|
|
92
|
+
/** Bytes a pushed body may take. */
|
|
93
|
+
const LIMIT = 65536;
|
|
50
94
|
//# sourceMappingURL=Realtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Realtime.js","sourceRoot":"","sources":["../../../source/directives/realtime/Realtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oDAAoD,CAAA;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"Realtime.js","sourceRoot":"","sources":["../../../source/directives/realtime/Realtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,10 @@ import { Readable } from 'node:stream';
|
|
|
5
5
|
* `cursor` is the id of the last event it was given. What arrives while it is being replayed to
|
|
6
6
|
* is held until the replay is done, and whatever it was given already is not given again: a replay
|
|
7
7
|
* and the channel may both carry the same event.
|
|
8
|
+
*
|
|
9
|
+
* A pushed event is stored nowhere and superseded by the next one, so it is neither held nor
|
|
10
|
+
* buffered: it is dropped while the replay is in flight, and where whoever reads this has not
|
|
11
|
+
* taken what it was sent already.
|
|
8
12
|
*/
|
|
9
13
|
export declare class Stream extends Readable {
|
|
10
14
|
cursor: string | null;
|
|
@@ -18,6 +22,8 @@ export declare class Stream extends Readable {
|
|
|
18
22
|
deliver(entry: Entry): void;
|
|
19
23
|
/** What the replay found is sent, then what was held back meanwhile, and from now on as it comes. */
|
|
20
24
|
ready(entries: Entry[]): void;
|
|
25
|
+
/** A pushed event: no token follows it, and it moves no cursor. Whether it was sent. */
|
|
26
|
+
volatile(push: Push): boolean;
|
|
21
27
|
token(token: string): void;
|
|
22
28
|
heartbeat(): void;
|
|
23
29
|
/** Ends it: whoever reads it gets the end, not a broken pipe. */
|
|
@@ -31,6 +37,11 @@ export interface Entry {
|
|
|
31
37
|
event: string;
|
|
32
38
|
data: unknown;
|
|
33
39
|
}
|
|
40
|
+
export interface Push {
|
|
41
|
+
event: string;
|
|
42
|
+
sender?: string;
|
|
43
|
+
data: unknown;
|
|
44
|
+
}
|
|
34
45
|
export declare function encode(id: string): string;
|
|
35
46
|
export declare function decode(token: string): string;
|
|
36
47
|
/** Stream ids are `<ms>-<seq>`, ordered as two numbers. */
|
|
@@ -5,6 +5,10 @@ import { Readable } from 'node:stream';
|
|
|
5
5
|
* `cursor` is the id of the last event it was given. What arrives while it is being replayed to
|
|
6
6
|
* is held until the replay is done, and whatever it was given already is not given again: a replay
|
|
7
7
|
* and the channel may both carry the same event.
|
|
8
|
+
*
|
|
9
|
+
* A pushed event is stored nowhere and superseded by the next one, so it is neither held nor
|
|
10
|
+
* buffered: it is dropped while the replay is in flight, and where whoever reads this has not
|
|
11
|
+
* taken what it was sent already.
|
|
8
12
|
*/
|
|
9
13
|
export class Stream extends Readable {
|
|
10
14
|
cursor = null;
|
|
@@ -39,6 +43,13 @@ export class Stream extends Readable {
|
|
|
39
43
|
for (const entry of held)
|
|
40
44
|
this.write(entry);
|
|
41
45
|
}
|
|
46
|
+
/** A pushed event: no token follows it, and it moves no cursor. Whether it was sent. */
|
|
47
|
+
volatile(push) {
|
|
48
|
+
if (this.held !== null || this.readableLength >= this.readableHighWaterMark)
|
|
49
|
+
return false;
|
|
50
|
+
this.send(push);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
42
53
|
token(token) {
|
|
43
54
|
this.send({ event: 'token', data: token });
|
|
44
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Stream.js","sourceRoot":"","sources":["../../../source/directives/realtime/Stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC
|
|
1
|
+
{"version":3,"file":"Stream.js","sourceRoot":"","sources":["../../../source/directives/realtime/Stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { registry } from 'openspan';
|
|
2
2
|
/**
|
|
3
|
-
* Counted where the gateway
|
|
4
|
-
* `toa.realtime.routed
|
|
3
|
+
* Counted where the gateway sends an event to the readers of a key it serves. Against
|
|
4
|
+
* `toa.realtime.routed` and `toa.realtime.pushed`, it says what arrived; `toa.realtime.dropped`
|
|
5
|
+
* is a pushed event a reader was not sent because it did not keep up.
|
|
5
6
|
*/
|
|
6
7
|
const meters = registry();
|
|
7
8
|
const delivered = meters.counter('toa.realtime.delivered', { event: null });
|
|
9
|
+
const pushed = meters.counter('toa.realtime.pushed', { event: null });
|
|
10
|
+
const dropped = meters.counter('toa.realtime.dropped', { event: null });
|
|
8
11
|
export function deliver(event) {
|
|
9
12
|
delivered.add(1, { event });
|
|
10
13
|
}
|
|
14
|
+
export function push(event) {
|
|
15
|
+
pushed.add(1, { event });
|
|
16
|
+
}
|
|
17
|
+
export function drop(event) {
|
|
18
|
+
dropped.add(1, { event });
|
|
19
|
+
}
|
|
11
20
|
//# sourceMappingURL=measurements.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measurements.js","sourceRoot":"","sources":["../../../source/directives/realtime/measurements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAEnC
|
|
1
|
+
{"version":3,"file":"measurements.js","sourceRoot":"","sources":["../../../source/directives/realtime/measurements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAEnC;;;;GAIG;AACH,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAA;AAEzB,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3E,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AACrE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAEvE,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;AAC3B,CAAC"}
|
|
@@ -6,7 +6,8 @@ import { Redis } from 'ioredis';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class Shards {
|
|
8
8
|
readonly connections: Redis[];
|
|
9
|
-
|
|
9
|
+
/** `keyPrefix` is the key's, and its channel's: it applies to a sharded channel as to a key. */
|
|
10
|
+
constructor(keyPrefix?: string);
|
|
10
11
|
/** The connection a key is kept on. */
|
|
11
12
|
of(key: string): Redis;
|
|
12
13
|
connect(): Promise<void>;
|
|
@@ -16,6 +17,11 @@ export declare class Shards {
|
|
|
16
17
|
export declare function configured(): boolean;
|
|
17
18
|
/** What a key is stored and published under: the scope, so contexts sharing a Redis do not meet. */
|
|
18
19
|
export declare function prefix(): string;
|
|
20
|
+
/**
|
|
21
|
+
* What the channel of a key's pushed events is published under. It differs from `prefix` before
|
|
22
|
+
* either ends, so no key's channel of pushed events is another key's channel, whatever a key is.
|
|
23
|
+
*/
|
|
24
|
+
export declare function pushes(): string;
|
|
19
25
|
/** Seconds a stream outlives its last reader: the window a reader reconnects in. */
|
|
20
26
|
export declare function expire(): number;
|
|
21
27
|
/**
|
|
@@ -8,9 +8,8 @@ import { EXPIRE, STREAMS } from '@toa.io/definitions/extensions.exposition/realt
|
|
|
8
8
|
*/
|
|
9
9
|
export class Shards {
|
|
10
10
|
connections;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const keyPrefix = prefix();
|
|
11
|
+
/** `keyPrefix` is the key's, and its channel's: it applies to a sharded channel as to a key. */
|
|
12
|
+
constructor(keyPrefix = prefix()) {
|
|
14
13
|
this.connections = addresses().map((address) => new Redis(address, { keyPrefix, lazyConnect: true }));
|
|
15
14
|
}
|
|
16
15
|
/** The connection a key is kept on. */
|
|
@@ -33,6 +32,13 @@ export function configured() {
|
|
|
33
32
|
export function prefix() {
|
|
34
33
|
return `${environment.scope()}:realtime:`;
|
|
35
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* What the channel of a key's pushed events is published under. It differs from `prefix` before
|
|
37
|
+
* either ends, so no key's channel of pushed events is another key's channel, whatever a key is.
|
|
38
|
+
*/
|
|
39
|
+
export function pushes() {
|
|
40
|
+
return `${environment.scope()}:realtime~:`;
|
|
41
|
+
}
|
|
36
42
|
/** Seconds a stream outlives its last reader: the window a reader reconnects in. */
|
|
37
43
|
export function expire() {
|
|
38
44
|
const value = Number(environment.get(EXPIRE));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../source/realtime/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,oDAAoD,CAAA;AAEpF;;;;GAIG;AACH,MAAM,OAAO,MAAM;IACD,WAAW,CAAS;IAEpC
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../source/realtime/redis.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"
|
|
1
|
+
{"version":"1793269037569"}
|
package/ui/dist/index.html
CHANGED
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
<div style="display: contents">
|
|
45
45
|
<script>
|
|
46
46
|
{
|
|
47
|
-
|
|
47
|
+
__sveltekit_ihd8a = {
|
|
48
48
|
base: "/.discovery",
|
|
49
|
-
version: "
|
|
49
|
+
version: "1793269037569",
|
|
50
50
|
assets: "/.discovery",
|
|
51
51
|
env: null
|
|
52
52
|
};
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
const element = document.currentScript.parentElement;
|
|
55
55
|
|
|
56
56
|
import("/.discovery/_app/env.js").then(({ env }) => {
|
|
57
|
-
|
|
57
|
+
__sveltekit_ihd8a.env = env;
|
|
58
58
|
|
|
59
59
|
import("/.discovery/_app/immutable/entry/start.BzTqgs51.js").then(async (kit) => {
|
|
60
|
-
kit.init(
|
|
60
|
+
kit.init(__sveltekit_ihd8a);
|
|
61
61
|
const app = await import("/.discovery/_app/immutable/entry/app.C3gvpmYY.js");
|
|
62
62
|
kit.start(app, element);
|
|
63
63
|
});
|