@design.estate/dees-comms 2.0.0 → 2.1.0
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/dist_bundle/bundle.js +11 -8
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_bundle/bundle.js.third-party-notices.json +1 -1
- package/dist_bundle/bundle.js.third-party-notices.txt +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/dees-comms.classes.deescomms.d.ts +35 -3
- package/dist_ts/dees-comms.classes.deescomms.js +44 -8
- package/package.json +7 -7
- package/readme.md +77 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/dees-comms.classes.deescomms.ts +81 -13
|
@@ -6,7 +6,7 @@ the license and notice files the package ships, or the license text the project
|
|
|
6
6
|
or a bundled package supplied for it.
|
|
7
7
|
|
|
8
8
|
================================================================================
|
|
9
|
-
@api.global/typedrequest@9.
|
|
9
|
+
@api.global/typedrequest@9.1.2
|
|
10
10
|
License: MIT
|
|
11
11
|
|
|
12
12
|
--- license.md ---
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-comms',
|
|
6
|
-
version: '2.
|
|
6
|
+
version: '2.1.0',
|
|
7
7
|
description: 'A communications module for enabling DOM-based messaging and synchronization across browser tabs and workers.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSwyQkFBMkI7SUFDakMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLCtHQUErRztDQUM3SCxDQUFBIn0=
|
|
@@ -7,6 +7,34 @@ export interface IDeesCommsOptions {
|
|
|
7
7
|
* used before names existed.
|
|
8
8
|
*/
|
|
9
9
|
channelName?: string;
|
|
10
|
+
/**
|
|
11
|
+
* How long a typed request this instance fires waits for its answer, in
|
|
12
|
+
* milliseconds. Defaults to 30 seconds. A request fired with its own
|
|
13
|
+
* `timeoutMs` ends at the earlier of the two.
|
|
14
|
+
*/
|
|
15
|
+
responseTimeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* What a typed request fired on a DeesComms instance throws when a handler
|
|
19
|
+
* refuses it, and what a handler throws to refuse one. These are the classes
|
|
20
|
+
* of the `@api.global/typedrequest` the instance routes with, so `instanceof`
|
|
21
|
+
* holds whichever version the application itself depends on.
|
|
22
|
+
*/
|
|
23
|
+
export type TypedResponseError = plugins.typedrequest.TypedResponseError;
|
|
24
|
+
export declare const TypedResponseError: typeof plugins.typedrequest.TypedResponseError;
|
|
25
|
+
/**
|
|
26
|
+
* What a typed request fired with `timeoutMs` throws when no answer came in
|
|
27
|
+
* time.
|
|
28
|
+
*/
|
|
29
|
+
export type TypedRequestTimeoutError = plugins.typedrequest.TypedRequestTimeoutError;
|
|
30
|
+
export declare const TypedRequestTimeoutError: typeof plugins.typedrequest.TypedRequestTimeoutError;
|
|
31
|
+
export interface IDeesCommsTypedHandler {
|
|
32
|
+
/**
|
|
33
|
+
* Stops answering. A request that arrives from then on is left to the
|
|
34
|
+
* other instances, as if this one never had the handler; one it is
|
|
35
|
+
* answering right now still gets its answer. Calling it again does nothing.
|
|
36
|
+
*/
|
|
37
|
+
remove(): void;
|
|
10
38
|
}
|
|
11
39
|
/**
|
|
12
40
|
* Receives the payload of one typed event, and the event itself.
|
|
@@ -32,7 +60,7 @@ export declare class DeesComms {
|
|
|
32
60
|
readonly channelName: string;
|
|
33
61
|
private readonly channel;
|
|
34
62
|
private readonly eventHandlers;
|
|
35
|
-
private
|
|
63
|
+
private typedHandlerCount;
|
|
36
64
|
private closed;
|
|
37
65
|
private closing;
|
|
38
66
|
typedrouter: plugins.typedrequest.TypedRouter<plugins.typedrequestInterfaces.ITypedRequest>;
|
|
@@ -47,9 +75,13 @@ export declare class DeesComms {
|
|
|
47
75
|
*/
|
|
48
76
|
postMessage<T = plugins.typedrequestInterfaces.ITypedRequest>(messageArg: T): Promise<void>;
|
|
49
77
|
/**
|
|
50
|
-
*
|
|
78
|
+
* Answers the typed requests of a method that other instances on this
|
|
79
|
+
* channel fire. The handler answers with what it returns; one that throws a
|
|
80
|
+
* `TypedResponseError` refuses the request, and its caller gets that error
|
|
81
|
+
* at once instead of waiting for its timeout. An instance has at most one
|
|
82
|
+
* handler per method.
|
|
51
83
|
*/
|
|
52
|
-
createTypedHandler<T extends plugins.typedrequestInterfaces.ITypedRequest>(methodArg: T['method'], handlerFunction: plugins.typedrequest.THandlerFunction<T>): Promise<
|
|
84
|
+
createTypedHandler<T extends plugins.typedrequestInterfaces.ITypedRequest>(methodArg: T['method'], handlerFunction: plugins.typedrequest.THandlerFunction<T>): Promise<IDeesCommsTypedHandler>;
|
|
53
85
|
/**
|
|
54
86
|
* Sends a typed event to every other instance on this channel and expects
|
|
55
87
|
* no answer. The instance that sends it does not receive it; any other
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as plugins from './dees-comms.plugins.js';
|
|
2
|
+
export const TypedResponseError = plugins.typedrequest.TypedResponseError;
|
|
3
|
+
export const TypedRequestTimeoutError = plugins.typedrequest.TypedRequestTimeoutError;
|
|
2
4
|
const isProcessHolding = (channelArg) => 'ref' in channelArg &&
|
|
3
5
|
typeof channelArg.ref === 'function' &&
|
|
4
6
|
'unref' in channelArg &&
|
|
@@ -83,18 +85,22 @@ export class DeesComms {
|
|
|
83
85
|
// receiving messages
|
|
84
86
|
constructor(optionsArg = {}) {
|
|
85
87
|
this.eventHandlers = new Map();
|
|
86
|
-
this.
|
|
88
|
+
this.typedHandlerCount = 0;
|
|
87
89
|
this.closed = false;
|
|
88
90
|
this.closing = null;
|
|
89
91
|
// sending messages
|
|
90
92
|
this.typedrouter = new plugins.typedrequest.TypedRouter();
|
|
93
|
+
this.channelName = optionsArg.channelName ?? DeesComms.defaultChannelName;
|
|
91
94
|
this.typedtarget = new plugins.typedrequest.TypedTarget({
|
|
95
|
+
// posting is done once it returns, so a request aborted later has no
|
|
96
|
+
// transport work left to release; the target stops its wait
|
|
92
97
|
postMethodWithTypedRouter: async (messageArg) => {
|
|
93
98
|
await this.postMessage(messageArg);
|
|
94
99
|
},
|
|
95
100
|
typedRouterRef: this.typedrouter,
|
|
101
|
+
supportsAbortSignal: true,
|
|
102
|
+
responseTimeoutMs: optionsArg.responseTimeoutMs,
|
|
96
103
|
});
|
|
97
|
-
this.channelName = optionsArg.channelName ?? DeesComms.defaultChannelName;
|
|
98
104
|
this.channel = openChannel(this.channelName, (messageArg) => {
|
|
99
105
|
void this.receive(messageArg);
|
|
100
106
|
});
|
|
@@ -114,12 +120,32 @@ export class DeesComms {
|
|
|
114
120
|
await this.channel.post(messageArg);
|
|
115
121
|
}
|
|
116
122
|
/**
|
|
117
|
-
*
|
|
123
|
+
* Answers the typed requests of a method that other instances on this
|
|
124
|
+
* channel fire. The handler answers with what it returns; one that throws a
|
|
125
|
+
* `TypedResponseError` refuses the request, and its caller gets that error
|
|
126
|
+
* at once instead of waiting for its timeout. An instance has at most one
|
|
127
|
+
* handler per method.
|
|
118
128
|
*/
|
|
119
129
|
async createTypedHandler(methodArg, handlerFunction) {
|
|
120
|
-
|
|
121
|
-
|
|
130
|
+
// each handler sits in a router of its own, so that removing it detaches
|
|
131
|
+
// that router from the instance's
|
|
132
|
+
const handlerRouter = new plugins.typedrequest.TypedRouter();
|
|
133
|
+
handlerRouter.addTypedHandler(new plugins.typedrequest.TypedHandler(methodArg, handlerFunction));
|
|
134
|
+
const detach = this.typedrouter.addTypedRouter(handlerRouter);
|
|
135
|
+
this.typedHandlerCount++;
|
|
122
136
|
this.holdProcessWhileListened();
|
|
137
|
+
let removed = false;
|
|
138
|
+
return {
|
|
139
|
+
remove: () => {
|
|
140
|
+
if (removed) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
removed = true;
|
|
144
|
+
detach();
|
|
145
|
+
this.typedHandlerCount--;
|
|
146
|
+
this.holdProcessWhileListened();
|
|
147
|
+
},
|
|
148
|
+
};
|
|
123
149
|
}
|
|
124
150
|
/**
|
|
125
151
|
* Sends a typed event to every other instance on this channel and expects
|
|
@@ -191,7 +217,7 @@ export class DeesComms {
|
|
|
191
217
|
if (this.closed) {
|
|
192
218
|
return;
|
|
193
219
|
}
|
|
194
|
-
this.channel.holdProcess(this.
|
|
220
|
+
this.channel.holdProcess(this.typedHandlerCount > 0 || this.eventHandlers.size > 0);
|
|
195
221
|
}
|
|
196
222
|
assertOpen() {
|
|
197
223
|
if (this.closed) {
|
|
@@ -211,11 +237,21 @@ export class DeesComms {
|
|
|
211
237
|
this.dispatch(event);
|
|
212
238
|
return;
|
|
213
239
|
}
|
|
240
|
+
// Every instance on the channel hears a request; only one with a handler
|
|
241
|
+
// for its method answers it, so the others do not refuse it in its place.
|
|
242
|
+
if (isObject(messageArg) &&
|
|
243
|
+
isObject(messageArg.correlation) &&
|
|
244
|
+
messageArg.correlation.phase === 'request' &&
|
|
245
|
+
typeof messageArg.method === 'string' &&
|
|
246
|
+
!this.typedrouter.checkForTypedHandler(messageArg.method)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
214
249
|
// Skip hooks for broadcast-received messages to prevent infinite loops
|
|
215
250
|
// when traffic logging hooks are set up globally. The router validates
|
|
216
251
|
// the shape of what it is given.
|
|
217
252
|
const response = await this.typedrouter.routeAndAddResponse(messageArg, { skipHooks: true });
|
|
218
|
-
|
|
253
|
+
// a refusal travels like an answer
|
|
254
|
+
if (response && !this.closed) {
|
|
219
255
|
await this.postMessage(response);
|
|
220
256
|
}
|
|
221
257
|
}
|
|
@@ -240,4 +276,4 @@ export class DeesComms {
|
|
|
240
276
|
}
|
|
241
277
|
}
|
|
242
278
|
}
|
|
243
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1jb21tcy5jbGFzc2VzLmRlZXNjb21tcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2RlZXMtY29tbXMuY2xhc3Nlcy5kZWVzY29tbXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx5QkFBeUIsQ0FBQztBQWdFbkQsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLFVBQWtCLEVBQXdDLEVBQUUsQ0FDcEYsS0FBSyxJQUFJLFVBQVU7SUFDbkIsT0FBTyxVQUFVLENBQUMsR0FBRyxLQUFLLFVBQVU7SUFDcEMsT0FBTyxJQUFJLFVBQVU7SUFDckIsT0FBTyxVQUFVLENBQUMsS0FBSyxLQUFLLFVBQVUsQ0FBQztBQUV6Qzs7OztHQUlHO0FBQ0gsTUFBTSxXQUFXLEdBQUcsQ0FDbEIsT0FBZSxFQUNmLFVBQXlDLEVBQ3RCLEVBQUU7SUFDckIsSUFBSSxPQUFPLFVBQVUsQ0FBQyxnQkFBZ0IsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUN0RCxNQUFNLE9BQU8sR0FBRyxJQUFJLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6RCxPQUFPLENBQUMsU0FBUyxHQUFHLENBQUMsUUFBK0IsRUFBRSxFQUFFO1lBQ3RELFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxjQUFjLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ2xFLGdFQUFnRTtRQUNoRSxjQUFjLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDeEIsT0FBTztZQUNMLElBQUksRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQUU7Z0JBQ3pCLE9BQU8sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDbEMsQ0FBQztZQUNELEtBQUssRUFBRSxLQUFLLElBQUksRUFBRTtn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
|
|
279
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1jb21tcy5jbGFzc2VzLmRlZXNjb21tcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2RlZXMtY29tbXMuY2xhc3Nlcy5kZWVzY29tbXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx5QkFBeUIsQ0FBQztBQXlCbkQsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQztBQU8xRSxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLHdCQUF3QixDQUFDO0FBK0R0RixNQUFNLGdCQUFnQixHQUFHLENBQUMsVUFBa0IsRUFBd0MsRUFBRSxDQUNwRixLQUFLLElBQUksVUFBVTtJQUNuQixPQUFPLFVBQVUsQ0FBQyxHQUFHLEtBQUssVUFBVTtJQUNwQyxPQUFPLElBQUksVUFBVTtJQUNyQixPQUFPLFVBQVUsQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDO0FBRXpDOzs7O0dBSUc7QUFDSCxNQUFNLFdBQVcsR0FBRyxDQUNsQixPQUFlLEVBQ2YsVUFBeUMsRUFDdEIsRUFBRTtJQUNyQixJQUFJLE9BQU8sVUFBVSxDQUFDLGdCQUFnQixLQUFLLFVBQVUsRUFBRSxDQUFDO1FBQ3RELE1BQU0sT0FBTyxHQUFHLElBQUksVUFBVSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pELE9BQU8sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxRQUErQixFQUFFLEVBQUU7WUFDdEQsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixDQUFDLENBQUM7UUFDRixNQUFNLGNBQWMsR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDbEUsZ0VBQWdFO1FBQ2hFLGNBQWMsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUN4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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design.estate/dees-comms",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A communications module for enabling DOM-based messaging and synchronization across browser tabs and workers.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
"author": "Lossless GmbH",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@git.zone/tsbuild": "^
|
|
13
|
-
"@git.zone/tsbundle": "^3.1
|
|
14
|
-
"@git.zone/tsrun": "^3.0.
|
|
15
|
-
"@git.zone/tstest": "^7.
|
|
16
|
-
"@types/node": "^26.6.
|
|
12
|
+
"@git.zone/tsbuild": "^6.0.2",
|
|
13
|
+
"@git.zone/tsbundle": "^3.2.1",
|
|
14
|
+
"@git.zone/tsrun": "^3.0.3",
|
|
15
|
+
"@git.zone/tstest": "^7.2.1",
|
|
16
|
+
"@types/node": "^26.6.4"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@api.global/typedrequest": "^9.
|
|
19
|
+
"@api.global/typedrequest": "^9.1.2",
|
|
20
20
|
"@api.global/typedrequest-interfaces": "^7.1.0",
|
|
21
21
|
"broadcast-channel": "^7.2.0"
|
|
22
22
|
},
|
package/readme.md
CHANGED
|
@@ -67,6 +67,81 @@ console.log(response.reply); // 'Hello Alice, nice to meet you!'
|
|
|
67
67
|
|
|
68
68
|
`postMessage()` posts a typed request object as it is; `typedrouter` and `typedtarget` are the `@api.global/typedrequest` 9 router and target the instance routes with. A handler answers with what it returns, `false`, `0` and `''` included; a handler that returns nothing answers `response: null`.
|
|
69
69
|
|
|
70
|
+
- Every other instance on the channel hears a request, but only one with a handler for its method answers it; the others stay silent. When several instances have a handler for it, the first answer to arrive is the response and the later ones are dropped.
|
|
71
|
+
- An instance has at most one handler per method: `createTypedHandler()` rejects a second one.
|
|
72
|
+
- The instance that fires a request does not answer it itself, even when it has a handler for its method.
|
|
73
|
+
|
|
74
|
+
#### Waiting for the answer
|
|
75
|
+
|
|
76
|
+
A request waits 30 seconds for its answer by default. `responseTimeoutMs` sets that limit for every request an instance fires; it must be a whole number of milliseconds from 1 to 2147483647, or the constructor throws a `RangeError`. A request that reaches the limit rejects with an `Error` (`TypedTarget response timed out after …ms`).
|
|
77
|
+
|
|
78
|
+
A single request can wait less with `timeoutMs`, and its caller can cancel it with an `AbortSignal`:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { DeesComms, TypedRequestTimeoutError } from '@design.estate/dees-comms';
|
|
82
|
+
|
|
83
|
+
const asking = new DeesComms({ channelName: 'my-app', responseTimeoutMs: 10_000 });
|
|
84
|
+
const greet = asking.createTypedRequest<IGreetRequest>('greet');
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
await greet.fire({ name: 'Alice' }, { timeoutMs: 1_000 });
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error instanceof TypedRequestTimeoutError) {
|
|
90
|
+
console.log(`nobody answered within ${error.timeoutMs} ms`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const controller = new AbortController();
|
|
95
|
+
const pending = greet.fire({ name: 'Bob' }, { abortSignal: controller.signal });
|
|
96
|
+
controller.abort(new Error('the tab is closing'));
|
|
97
|
+
await pending.catch((reason) => console.log(reason.message)); // 'the tab is closing'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- A request with its own `timeoutMs` ends at the earlier of its own deadline and the instance's `responseTimeoutMs`, and rejects with a `TypedRequestTimeoutError` (carrying `timeoutMs`) when its own deadline comes first.
|
|
101
|
+
- An aborted request rejects with the signal's reason at once. A request fired with a signal that is already aborted is never sent. A handler that is already working on an aborted request still finishes; its answer is dropped.
|
|
102
|
+
|
|
103
|
+
#### Refusing a request
|
|
104
|
+
|
|
105
|
+
A handler refuses a request by throwing a `TypedResponseError`. Its caller rejects with that error at once, with its `errorText` and `errorData`, instead of waiting for its timeout:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { DeesComms, TypedResponseError } from '@design.estate/dees-comms';
|
|
109
|
+
|
|
110
|
+
answering.createTypedHandler<IGreetRequest>('greet', async (request) => {
|
|
111
|
+
if (request.name === '') {
|
|
112
|
+
throw new TypedResponseError('name-required', { field: 'name' });
|
|
113
|
+
}
|
|
114
|
+
return { reply: `Hello ${request.name}, nice to meet you!` };
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
await asking.createTypedRequest<IGreetRequest>('greet').fire({ name: '' });
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (error instanceof TypedResponseError) {
|
|
121
|
+
console.log(error.errorText, error.errorData); // 'name-required' { field: 'name' }
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- A handler that throws any other error answers with a `TypedResponseError` whose `errorText` is `Internal server error`; the error itself does not travel.
|
|
127
|
+
- A refusal is an answer: when several instances have a handler for the method, the first answer wins, whether it is a response or a refusal. An instance that cannot help but wants to leave the request to the others removes its handler instead of refusing.
|
|
128
|
+
- `TypedResponseError` and `TypedRequestTimeoutError` are exported by `@design.estate/dees-comms` and are the classes of the `@api.global/typedrequest` it routes with. Use these exports for `instanceof`: an application that depends on another version of `@api.global/typedrequest` has classes of its own that the errors are not instances of.
|
|
129
|
+
|
|
130
|
+
#### Removing a handler
|
|
131
|
+
|
|
132
|
+
`createTypedHandler()` resolves with a handle whose `remove()` stops the handler:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const handler = await answering.createTypedHandler<IGreetRequest>('greet', async (request) => {
|
|
136
|
+
return { reply: `Hello ${request.name}!` };
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// later: the requests are left to the other instances
|
|
140
|
+
handler.remove();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
A request that arrives after `remove()` is left to the other instances, as if this one never had the handler; one the handler is working on still gets its answer. The method can be handled again with a new `createTypedHandler()`. Calling `remove()` again does nothing.
|
|
144
|
+
|
|
70
145
|
### Typed events
|
|
71
146
|
|
|
72
147
|
A typed event is sent to every other instance on the channel and expects no answer. It is declared as an `ITypedEvent` of `@api.global/typedrequest-interfaces`: its `name` is the contract, its `payload` is what travels.
|
|
@@ -109,9 +184,9 @@ subscription.unsubscribe();
|
|
|
109
184
|
await comms.close();
|
|
110
185
|
```
|
|
111
186
|
|
|
112
|
-
A closed instance receives nothing: its subscriptions end and its typed handlers are no longer asked. `postMessage()`, `broadcast()` and the typed requests it fires reject, and `subscribe()` throws. A typed request that is still waiting for its response when the channel closes cannot receive it and ends with its
|
|
187
|
+
A closed instance receives nothing: its subscriptions end and its typed handlers are no longer asked. `postMessage()`, `broadcast()` and the typed requests it fires reject, and `subscribe()` throws. A typed request that is still waiting for its response when the channel closes cannot receive it and ends at its timeout; abort it with its `AbortSignal` to end it at once. Closing again does nothing.
|
|
113
188
|
|
|
114
|
-
In Node.js an instance keeps the process alive only while something listens on it, as a `MessagePort` with a message listener does: while it has a subscription
|
|
189
|
+
In Node.js an instance keeps the process alive only while something listens on it, as a `MessagePort` with a message listener does: while it has a subscription or a typed handler. An instance nobody listens on, such as the one `@design.estate/dees-domtools` opens on import, lets the process end. An instance whose subscriptions ended and whose handlers were removed lets it end too, as a closed one does, so remove every typed handler or close every instance with one that a test or a script opens. In browsers and workers nothing changes.
|
|
115
190
|
|
|
116
191
|
### What travels
|
|
117
192
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -8,6 +8,37 @@ export interface IDeesCommsOptions {
|
|
|
8
8
|
* used before names existed.
|
|
9
9
|
*/
|
|
10
10
|
channelName?: string;
|
|
11
|
+
/**
|
|
12
|
+
* How long a typed request this instance fires waits for its answer, in
|
|
13
|
+
* milliseconds. Defaults to 30 seconds. A request fired with its own
|
|
14
|
+
* `timeoutMs` ends at the earlier of the two.
|
|
15
|
+
*/
|
|
16
|
+
responseTimeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* What a typed request fired on a DeesComms instance throws when a handler
|
|
21
|
+
* refuses it, and what a handler throws to refuse one. These are the classes
|
|
22
|
+
* of the `@api.global/typedrequest` the instance routes with, so `instanceof`
|
|
23
|
+
* holds whichever version the application itself depends on.
|
|
24
|
+
*/
|
|
25
|
+
export type TypedResponseError = plugins.typedrequest.TypedResponseError;
|
|
26
|
+
export const TypedResponseError = plugins.typedrequest.TypedResponseError;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* What a typed request fired with `timeoutMs` throws when no answer came in
|
|
30
|
+
* time.
|
|
31
|
+
*/
|
|
32
|
+
export type TypedRequestTimeoutError = plugins.typedrequest.TypedRequestTimeoutError;
|
|
33
|
+
export const TypedRequestTimeoutError = plugins.typedrequest.TypedRequestTimeoutError;
|
|
34
|
+
|
|
35
|
+
export interface IDeesCommsTypedHandler {
|
|
36
|
+
/**
|
|
37
|
+
* Stops answering. A request that arrives from then on is left to the
|
|
38
|
+
* other instances, as if this one never had the handler; one it is
|
|
39
|
+
* answering right now still gets its answer. Calling it again does nothing.
|
|
40
|
+
*/
|
|
41
|
+
remove(): void;
|
|
11
42
|
}
|
|
12
43
|
|
|
13
44
|
/**
|
|
@@ -162,22 +193,27 @@ export class DeesComms {
|
|
|
162
193
|
public readonly channelName: string;
|
|
163
194
|
private readonly channel: IDeesCommsChannel;
|
|
164
195
|
private readonly eventHandlers = new Map<string, Set<TStoredEventHandler>>();
|
|
165
|
-
private
|
|
196
|
+
private typedHandlerCount = 0;
|
|
166
197
|
private closed = false;
|
|
167
198
|
private closing: Promise<void> | null = null;
|
|
168
199
|
|
|
169
200
|
// sending messages
|
|
170
201
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
|
171
|
-
public typedtarget
|
|
172
|
-
postMethodWithTypedRouter: async (messageArg) => {
|
|
173
|
-
await this.postMessage(messageArg);
|
|
174
|
-
},
|
|
175
|
-
typedRouterRef: this.typedrouter,
|
|
176
|
-
});
|
|
202
|
+
public typedtarget: plugins.typedrequest.TypedTarget;
|
|
177
203
|
|
|
178
204
|
// receiving messages
|
|
179
205
|
constructor(optionsArg: IDeesCommsOptions = {}) {
|
|
180
206
|
this.channelName = optionsArg.channelName ?? DeesComms.defaultChannelName;
|
|
207
|
+
this.typedtarget = new plugins.typedrequest.TypedTarget({
|
|
208
|
+
// posting is done once it returns, so a request aborted later has no
|
|
209
|
+
// transport work left to release; the target stops its wait
|
|
210
|
+
postMethodWithTypedRouter: async (messageArg) => {
|
|
211
|
+
await this.postMessage(messageArg);
|
|
212
|
+
},
|
|
213
|
+
typedRouterRef: this.typedrouter,
|
|
214
|
+
supportsAbortSignal: true,
|
|
215
|
+
responseTimeoutMs: optionsArg.responseTimeoutMs,
|
|
216
|
+
});
|
|
181
217
|
this.channel = openChannel(this.channelName, (messageArg) => {
|
|
182
218
|
void this.receive(messageArg);
|
|
183
219
|
});
|
|
@@ -204,17 +240,37 @@ export class DeesComms {
|
|
|
204
240
|
}
|
|
205
241
|
|
|
206
242
|
/**
|
|
207
|
-
*
|
|
243
|
+
* Answers the typed requests of a method that other instances on this
|
|
244
|
+
* channel fire. The handler answers with what it returns; one that throws a
|
|
245
|
+
* `TypedResponseError` refuses the request, and its caller gets that error
|
|
246
|
+
* at once instead of waiting for its timeout. An instance has at most one
|
|
247
|
+
* handler per method.
|
|
208
248
|
*/
|
|
209
249
|
public async createTypedHandler<T extends plugins.typedrequestInterfaces.ITypedRequest>(
|
|
210
250
|
methodArg: T['method'],
|
|
211
251
|
handlerFunction: plugins.typedrequest.THandlerFunction<T>
|
|
212
|
-
) {
|
|
213
|
-
|
|
252
|
+
): Promise<IDeesCommsTypedHandler> {
|
|
253
|
+
// each handler sits in a router of its own, so that removing it detaches
|
|
254
|
+
// that router from the instance's
|
|
255
|
+
const handlerRouter = new plugins.typedrequest.TypedRouter();
|
|
256
|
+
handlerRouter.addTypedHandler(
|
|
214
257
|
new plugins.typedrequest.TypedHandler<T>(methodArg, handlerFunction)
|
|
215
258
|
);
|
|
216
|
-
|
|
259
|
+
const detach = this.typedrouter.addTypedRouter(handlerRouter);
|
|
260
|
+
this.typedHandlerCount++;
|
|
217
261
|
this.holdProcessWhileListened();
|
|
262
|
+
let removed = false;
|
|
263
|
+
return {
|
|
264
|
+
remove: () => {
|
|
265
|
+
if (removed) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
removed = true;
|
|
269
|
+
detach();
|
|
270
|
+
this.typedHandlerCount--;
|
|
271
|
+
this.holdProcessWhileListened();
|
|
272
|
+
},
|
|
273
|
+
};
|
|
218
274
|
}
|
|
219
275
|
|
|
220
276
|
/**
|
|
@@ -297,7 +353,7 @@ export class DeesComms {
|
|
|
297
353
|
if (this.closed) {
|
|
298
354
|
return;
|
|
299
355
|
}
|
|
300
|
-
this.channel.holdProcess(this.
|
|
356
|
+
this.channel.holdProcess(this.typedHandlerCount > 0 || this.eventHandlers.size > 0);
|
|
301
357
|
}
|
|
302
358
|
|
|
303
359
|
private assertOpen(): void {
|
|
@@ -319,6 +375,17 @@ export class DeesComms {
|
|
|
319
375
|
this.dispatch(event);
|
|
320
376
|
return;
|
|
321
377
|
}
|
|
378
|
+
// Every instance on the channel hears a request; only one with a handler
|
|
379
|
+
// for its method answers it, so the others do not refuse it in its place.
|
|
380
|
+
if (
|
|
381
|
+
isObject(messageArg) &&
|
|
382
|
+
isObject(messageArg.correlation) &&
|
|
383
|
+
messageArg.correlation.phase === 'request' &&
|
|
384
|
+
typeof messageArg.method === 'string' &&
|
|
385
|
+
!this.typedrouter.checkForTypedHandler(messageArg.method)
|
|
386
|
+
) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
322
389
|
// Skip hooks for broadcast-received messages to prevent infinite loops
|
|
323
390
|
// when traffic logging hooks are set up globally. The router validates
|
|
324
391
|
// the shape of what it is given.
|
|
@@ -326,7 +393,8 @@ export class DeesComms {
|
|
|
326
393
|
messageArg as plugins.typedrequestInterfaces.ITypedRequest,
|
|
327
394
|
{ skipHooks: true }
|
|
328
395
|
);
|
|
329
|
-
|
|
396
|
+
// a refusal travels like an answer
|
|
397
|
+
if (response && !this.closed) {
|
|
330
398
|
await this.postMessage(response);
|
|
331
399
|
}
|
|
332
400
|
}
|