@delight-rpc/child-process 0.7.2 → 0.7.3
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/lib/client.js +33 -26
- package/lib/client.js.map +1 -1
- package/lib/server.js +11 -8
- package/lib/server.js.map +1 -1
- package/package.json +2 -1
- package/src/client.ts +45 -36
- package/src/server.ts +15 -8
package/lib/client.js
CHANGED
|
@@ -3,46 +3,50 @@ import { Deferred } from 'extra-promise';
|
|
|
3
3
|
import { CustomError } from '@blackglory/errors';
|
|
4
4
|
import { raceAbortSignals, timeoutSignal, withAbortSignal } from 'extra-abort';
|
|
5
5
|
import { isntUndefined } from '@blackglory/prelude';
|
|
6
|
+
import { SyncDestructor } from 'extra-defer';
|
|
6
7
|
export function createClient(process, { parameterValidators, expectedVersion, channel, timeout } = {}) {
|
|
8
|
+
const destructor = new SyncDestructor();
|
|
7
9
|
const pendings = new Map();
|
|
8
|
-
|
|
10
|
+
destructor.defer(abortAllPendings);
|
|
11
|
+
process.on('message', receive);
|
|
12
|
+
destructor.defer(() => process.off('message', receive));
|
|
9
13
|
process.on('disconnect', abortAllPendings);
|
|
14
|
+
destructor.defer(() => process.off('disconnect', abortAllPendings));
|
|
10
15
|
const client = DelightRPC.createClient(async function send(request, signal) {
|
|
16
|
+
const destructor = new SyncDestructor();
|
|
11
17
|
const res = new Deferred();
|
|
12
18
|
pendings.set(request.id, res);
|
|
19
|
+
destructor.defer(() => pendings.delete(request.id));
|
|
13
20
|
try {
|
|
14
21
|
process.send(request);
|
|
15
22
|
const mergedSignal = raceAbortSignals([
|
|
16
23
|
isntUndefined(timeout) && timeoutSignal(timeout),
|
|
17
24
|
signal
|
|
18
25
|
]);
|
|
19
|
-
mergedSignal.addEventListener('abort',
|
|
20
|
-
|
|
21
|
-
process.send(abort);
|
|
22
|
-
});
|
|
26
|
+
mergedSignal.addEventListener('abort', sendAbort);
|
|
27
|
+
destructor.defer(() => mergedSignal.removeEventListener('abort', sendAbort));
|
|
23
28
|
return await withAbortSignal(mergedSignal, () => res);
|
|
24
29
|
}
|
|
25
30
|
finally {
|
|
26
|
-
|
|
31
|
+
destructor.execute();
|
|
32
|
+
}
|
|
33
|
+
function sendAbort() {
|
|
34
|
+
const abort = DelightRPC.createAbort(request.id, channel);
|
|
35
|
+
process.send(abort);
|
|
27
36
|
}
|
|
28
37
|
}, {
|
|
29
38
|
parameterValidators,
|
|
30
39
|
expectedVersion,
|
|
31
40
|
channel
|
|
32
41
|
});
|
|
33
|
-
return [client,
|
|
34
|
-
function close() {
|
|
35
|
-
process.off('message', handleMessage);
|
|
36
|
-
process.off('disconnect', abortAllPendings);
|
|
37
|
-
abortAllPendings();
|
|
38
|
-
}
|
|
42
|
+
return [client, () => destructor.execute()];
|
|
39
43
|
function abortAllPendings() {
|
|
40
44
|
for (const deferred of pendings.values()) {
|
|
41
45
|
deferred.reject(new ClientClosed());
|
|
42
46
|
}
|
|
43
47
|
pendings.clear();
|
|
44
48
|
}
|
|
45
|
-
function
|
|
49
|
+
function receive(res) {
|
|
46
50
|
var _a;
|
|
47
51
|
if (DelightRPC.isResult(res) || DelightRPC.isError(res)) {
|
|
48
52
|
(_a = pendings.get(res.id)) === null || _a === void 0 ? void 0 : _a.resolve(res);
|
|
@@ -50,43 +54,46 @@ export function createClient(process, { parameterValidators, expectedVersion, ch
|
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
export function createBatchClient(process, { expectedVersion, channel, timeout } = {}) {
|
|
57
|
+
const destructor = new SyncDestructor();
|
|
53
58
|
const pendings = new Map();
|
|
54
|
-
|
|
59
|
+
destructor.defer(abortAllPendings);
|
|
60
|
+
process.on('message', receive);
|
|
61
|
+
destructor.defer(() => process.off('message', receive));
|
|
55
62
|
process.on('disconnect', abortAllPendings);
|
|
63
|
+
destructor.defer(() => process.off('disconnect', abortAllPendings));
|
|
56
64
|
const client = new DelightRPC.BatchClient(async function send(request) {
|
|
65
|
+
const destructor = new SyncDestructor();
|
|
57
66
|
const res = new Deferred();
|
|
58
67
|
pendings.set(request.id, res);
|
|
68
|
+
destructor.defer(() => pendings.delete(request.id));
|
|
59
69
|
try {
|
|
60
70
|
process.send(request);
|
|
61
71
|
const mergedSignal = raceAbortSignals([
|
|
62
72
|
isntUndefined(timeout) && timeoutSignal(timeout)
|
|
63
73
|
]);
|
|
64
|
-
mergedSignal.addEventListener('abort',
|
|
65
|
-
|
|
66
|
-
process.send(abort);
|
|
67
|
-
});
|
|
74
|
+
mergedSignal.addEventListener('abort', sendAbort);
|
|
75
|
+
destructor.defer(() => mergedSignal.removeEventListener('abort', sendAbort));
|
|
68
76
|
return await withAbortSignal(mergedSignal, () => res);
|
|
69
77
|
}
|
|
70
78
|
finally {
|
|
71
|
-
|
|
79
|
+
destructor.execute();
|
|
80
|
+
}
|
|
81
|
+
function sendAbort() {
|
|
82
|
+
const abort = DelightRPC.createAbort(request.id, channel);
|
|
83
|
+
process.send(abort);
|
|
72
84
|
}
|
|
73
85
|
}, {
|
|
74
86
|
expectedVersion,
|
|
75
87
|
channel
|
|
76
88
|
});
|
|
77
|
-
return [client,
|
|
78
|
-
function close() {
|
|
79
|
-
process.off('message', handleMessage);
|
|
80
|
-
process.off('disconnect', abortAllPendings);
|
|
81
|
-
abortAllPendings();
|
|
82
|
-
}
|
|
89
|
+
return [client, () => destructor.execute()];
|
|
83
90
|
function abortAllPendings() {
|
|
84
91
|
for (const deferred of pendings.values()) {
|
|
85
92
|
deferred.reject(new ClientClosed());
|
|
86
93
|
}
|
|
87
94
|
pendings.clear();
|
|
88
95
|
}
|
|
89
|
-
function
|
|
96
|
+
function receive(res) {
|
|
90
97
|
var _a;
|
|
91
98
|
if (DelightRPC.isError(res) || DelightRPC.isBatchResponse(res)) {
|
|
92
99
|
(_a = pendings.get(res.id)) === null || _a === void 0 ? void 0 : _a.resolve(res);
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/lib/server.js
CHANGED
|
@@ -2,26 +2,29 @@ import * as DelightRPC from 'delight-rpc';
|
|
|
2
2
|
import { isntNull, pass } from '@blackglory/prelude';
|
|
3
3
|
import { AbortController } from 'extra-abort';
|
|
4
4
|
import { HashMap } from '@blackglory/structures';
|
|
5
|
+
import { SyncDestructor } from 'extra-defer';
|
|
5
6
|
export function createServer(api, process, { parameterValidators, version, channel, ownPropsOnly } = {}) {
|
|
7
|
+
const destructor = new SyncDestructor();
|
|
6
8
|
const channelIdToController = new HashMap(({ channel, id }) => JSON.stringify([channel, id]));
|
|
7
|
-
|
|
9
|
+
destructor.defer(abortAllPendings);
|
|
10
|
+
process.on('message', receive);
|
|
11
|
+
destructor.defer(() => process.off('message', receive));
|
|
8
12
|
process.on('disconnect', abortAllPendings);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
process.off('disconnect', abortAllPendings);
|
|
12
|
-
abortAllPendings();
|
|
13
|
-
};
|
|
13
|
+
destructor.defer(() => process.off('disconnect', abortAllPendings));
|
|
14
|
+
return () => destructor.execute();
|
|
14
15
|
function abortAllPendings() {
|
|
15
16
|
for (const controller of channelIdToController.values()) {
|
|
16
17
|
controller.abort();
|
|
17
18
|
}
|
|
18
19
|
channelIdToController.clear();
|
|
19
20
|
}
|
|
20
|
-
async function
|
|
21
|
+
async function receive(message) {
|
|
21
22
|
var _a;
|
|
22
23
|
if (DelightRPC.isRequest(message) || DelightRPC.isBatchRequest(message)) {
|
|
24
|
+
const destructor = new SyncDestructor();
|
|
23
25
|
const controller = new AbortController();
|
|
24
26
|
channelIdToController.set(message, controller);
|
|
27
|
+
destructor.defer(() => channelIdToController.delete(message));
|
|
25
28
|
try {
|
|
26
29
|
const result = await DelightRPC.createResponse(api, message, {
|
|
27
30
|
parameterValidators,
|
|
@@ -44,7 +47,7 @@ export function createServer(api, process, { parameterValidators, version, chann
|
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
finally {
|
|
47
|
-
|
|
50
|
+
destructor.execute();
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
else if (DelightRPC.isAbort(message)) {
|
package/lib/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delight-rpc/child-process",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"files": [
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"@blackglory/structures": "^0.14.13",
|
|
59
59
|
"@delight-rpc/protocol": "^4.0.0",
|
|
60
60
|
"extra-abort": "^0.4.1",
|
|
61
|
+
"extra-defer": "^0.3.1",
|
|
61
62
|
"extra-promise": "^7.1.1"
|
|
62
63
|
},
|
|
63
64
|
"peerDependencies": {
|
package/src/client.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { CustomError } from '@blackglory/errors'
|
|
|
5
5
|
import { IResponse, IError, IBatchRequest, IBatchResponse } from '@delight-rpc/protocol'
|
|
6
6
|
import { raceAbortSignals, timeoutSignal, withAbortSignal } from 'extra-abort'
|
|
7
7
|
import { isntUndefined } from '@blackglory/prelude'
|
|
8
|
+
import { SyncDestructor } from 'extra-defer'
|
|
8
9
|
|
|
9
10
|
export function createClient<IAPI extends object>(
|
|
10
11
|
process: ChildProcess | NodeJS.Process
|
|
@@ -15,15 +16,25 @@ export function createClient<IAPI extends object>(
|
|
|
15
16
|
timeout?: number
|
|
16
17
|
} = {}
|
|
17
18
|
): [client: DelightRPC.ClientProxy<IAPI>, close: () => void] {
|
|
19
|
+
const destructor = new SyncDestructor()
|
|
20
|
+
|
|
18
21
|
const pendings: Map<string, Deferred<IResponse<unknown>>> = new Map()
|
|
22
|
+
destructor.defer(abortAllPendings)
|
|
23
|
+
|
|
24
|
+
process.on('message', receive)
|
|
25
|
+
destructor.defer(() => process.off('message', receive))
|
|
19
26
|
|
|
20
|
-
process.on('message', handleMessage)
|
|
21
27
|
process.on('disconnect', abortAllPendings)
|
|
28
|
+
destructor.defer(() => process.off('disconnect', abortAllPendings))
|
|
22
29
|
|
|
23
30
|
const client = DelightRPC.createClient<IAPI>(
|
|
24
31
|
async function send(request, signal) {
|
|
32
|
+
const destructor = new SyncDestructor()
|
|
33
|
+
|
|
25
34
|
const res = new Deferred<IResponse<unknown>>()
|
|
26
35
|
pendings.set(request.id, res)
|
|
36
|
+
destructor.defer(() => pendings.delete(request.id))
|
|
37
|
+
|
|
27
38
|
try {
|
|
28
39
|
process.send!(request)
|
|
29
40
|
|
|
@@ -31,14 +42,17 @@ export function createClient<IAPI extends object>(
|
|
|
31
42
|
isntUndefined(timeout) && timeoutSignal(timeout)
|
|
32
43
|
, signal
|
|
33
44
|
])
|
|
34
|
-
mergedSignal.addEventListener('abort',
|
|
35
|
-
|
|
36
|
-
process.send!(abort)
|
|
37
|
-
})
|
|
45
|
+
mergedSignal.addEventListener('abort', sendAbort)
|
|
46
|
+
destructor.defer(() => mergedSignal.removeEventListener('abort', sendAbort))
|
|
38
47
|
|
|
39
48
|
return await withAbortSignal(mergedSignal, () => res)
|
|
40
49
|
} finally {
|
|
41
|
-
|
|
50
|
+
destructor.execute()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sendAbort(): void {
|
|
54
|
+
const abort = DelightRPC.createAbort(request.id, channel)
|
|
55
|
+
process.send!(abort)
|
|
42
56
|
}
|
|
43
57
|
}
|
|
44
58
|
, {
|
|
@@ -48,13 +62,7 @@ export function createClient<IAPI extends object>(
|
|
|
48
62
|
}
|
|
49
63
|
)
|
|
50
64
|
|
|
51
|
-
return [client,
|
|
52
|
-
|
|
53
|
-
function close(): void {
|
|
54
|
-
process.off('message', handleMessage)
|
|
55
|
-
process.off('disconnect', abortAllPendings)
|
|
56
|
-
abortAllPendings()
|
|
57
|
-
}
|
|
65
|
+
return [client, () => destructor.execute()]
|
|
58
66
|
|
|
59
67
|
function abortAllPendings(): void {
|
|
60
68
|
for (const deferred of pendings.values()) {
|
|
@@ -64,7 +72,7 @@ export function createClient<IAPI extends object>(
|
|
|
64
72
|
pendings.clear()
|
|
65
73
|
}
|
|
66
74
|
|
|
67
|
-
function
|
|
75
|
+
function receive(res: unknown): void {
|
|
68
76
|
if (DelightRPC.isResult(res) || DelightRPC.isError(res)) {
|
|
69
77
|
pendings.get(res.id)?.resolve(res)
|
|
70
78
|
}
|
|
@@ -79,35 +87,42 @@ export function createBatchClient<DataType>(
|
|
|
79
87
|
timeout?: number
|
|
80
88
|
} = {}
|
|
81
89
|
): [client: DelightRPC.BatchClient<DataType>, close: () => void] {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
, Deferred<IError | IBatchResponse<unknown
|
|
85
|
-
|
|
90
|
+
const destructor = new SyncDestructor()
|
|
91
|
+
|
|
92
|
+
const pendings: Map<string, Deferred<IError | IBatchResponse<unknown>>> = new Map()
|
|
93
|
+
destructor.defer(abortAllPendings)
|
|
94
|
+
|
|
95
|
+
process.on('message', receive)
|
|
96
|
+
destructor.defer(() => process.off('message', receive))
|
|
86
97
|
|
|
87
|
-
process.on('message', handleMessage)
|
|
88
98
|
process.on('disconnect', abortAllPendings)
|
|
99
|
+
destructor.defer(() => process.off('disconnect', abortAllPendings))
|
|
89
100
|
|
|
90
101
|
const client = new DelightRPC.BatchClient(
|
|
91
102
|
async function send(request: IBatchRequest<unknown>) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
| IBatchResponse<unknown
|
|
95
|
-
>()
|
|
103
|
+
const destructor = new SyncDestructor()
|
|
104
|
+
|
|
105
|
+
const res = new Deferred<IError | IBatchResponse<unknown>>()
|
|
96
106
|
pendings.set(request.id, res)
|
|
107
|
+
destructor.defer(() => pendings.delete(request.id))
|
|
108
|
+
|
|
97
109
|
try {
|
|
98
110
|
process.send!(request)
|
|
99
111
|
|
|
100
112
|
const mergedSignal = raceAbortSignals([
|
|
101
113
|
isntUndefined(timeout) && timeoutSignal(timeout)
|
|
102
114
|
])
|
|
103
|
-
mergedSignal.addEventListener('abort',
|
|
104
|
-
|
|
105
|
-
process.send!(abort)
|
|
106
|
-
})
|
|
115
|
+
mergedSignal.addEventListener('abort', sendAbort)
|
|
116
|
+
destructor.defer(() => mergedSignal.removeEventListener('abort', sendAbort))
|
|
107
117
|
|
|
108
118
|
return await withAbortSignal(mergedSignal, () => res)
|
|
109
119
|
} finally {
|
|
110
|
-
|
|
120
|
+
destructor.execute()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function sendAbort(): void {
|
|
124
|
+
const abort = DelightRPC.createAbort(request.id, channel)
|
|
125
|
+
process.send!(abort)
|
|
111
126
|
}
|
|
112
127
|
}
|
|
113
128
|
, {
|
|
@@ -116,13 +131,7 @@ export function createBatchClient<DataType>(
|
|
|
116
131
|
}
|
|
117
132
|
)
|
|
118
133
|
|
|
119
|
-
return [client,
|
|
120
|
-
|
|
121
|
-
function close(): void {
|
|
122
|
-
process.off('message', handleMessage)
|
|
123
|
-
process.off('disconnect', abortAllPendings)
|
|
124
|
-
abortAllPendings()
|
|
125
|
-
}
|
|
134
|
+
return [client, () => destructor.execute()]
|
|
126
135
|
|
|
127
136
|
function abortAllPendings(): void {
|
|
128
137
|
for (const deferred of pendings.values()) {
|
|
@@ -132,7 +141,7 @@ export function createBatchClient<DataType>(
|
|
|
132
141
|
pendings.clear()
|
|
133
142
|
}
|
|
134
143
|
|
|
135
|
-
function
|
|
144
|
+
function receive(res: unknown): void {
|
|
136
145
|
if (DelightRPC.isError(res) || DelightRPC.isBatchResponse(res)) {
|
|
137
146
|
pendings.get(res.id)?.resolve(res)
|
|
138
147
|
}
|
package/src/server.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ChildProcess } from 'child_process'
|
|
|
3
3
|
import { isntNull, pass } from '@blackglory/prelude'
|
|
4
4
|
import { AbortController } from 'extra-abort'
|
|
5
5
|
import { HashMap } from '@blackglory/structures'
|
|
6
|
+
import { SyncDestructor } from 'extra-defer'
|
|
6
7
|
|
|
7
8
|
export function createServer<IAPI extends object>(
|
|
8
9
|
api: DelightRPC.ImplementationOf<IAPI>
|
|
@@ -14,6 +15,8 @@ export function createServer<IAPI extends object>(
|
|
|
14
15
|
ownPropsOnly?: boolean
|
|
15
16
|
} = {}
|
|
16
17
|
): () => void {
|
|
18
|
+
const destructor = new SyncDestructor()
|
|
19
|
+
|
|
17
20
|
const channelIdToController: HashMap<
|
|
18
21
|
{
|
|
19
22
|
channel?: string
|
|
@@ -21,14 +24,15 @@ export function createServer<IAPI extends object>(
|
|
|
21
24
|
}
|
|
22
25
|
, AbortController
|
|
23
26
|
> = new HashMap(({ channel, id }) => JSON.stringify([channel, id]))
|
|
27
|
+
destructor.defer(abortAllPendings)
|
|
28
|
+
|
|
29
|
+
process.on('message', receive)
|
|
30
|
+
destructor.defer(() => process.off('message', receive))
|
|
24
31
|
|
|
25
|
-
process.on('message', handleMessage)
|
|
26
32
|
process.on('disconnect', abortAllPendings)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
abortAllPendings()
|
|
31
|
-
}
|
|
33
|
+
destructor.defer(() => process.off('disconnect', abortAllPendings))
|
|
34
|
+
|
|
35
|
+
return () => destructor.execute()
|
|
32
36
|
|
|
33
37
|
function abortAllPendings(): void {
|
|
34
38
|
for (const controller of channelIdToController.values()) {
|
|
@@ -38,10 +42,13 @@ export function createServer<IAPI extends object>(
|
|
|
38
42
|
channelIdToController.clear()
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
async function
|
|
45
|
+
async function receive(message: unknown): Promise<void> {
|
|
42
46
|
if (DelightRPC.isRequest(message) || DelightRPC.isBatchRequest(message)) {
|
|
47
|
+
const destructor = new SyncDestructor()
|
|
48
|
+
|
|
43
49
|
const controller = new AbortController()
|
|
44
50
|
channelIdToController.set(message, controller)
|
|
51
|
+
destructor.defer(() => channelIdToController.delete(message))
|
|
45
52
|
|
|
46
53
|
try {
|
|
47
54
|
const result = await DelightRPC.createResponse(
|
|
@@ -69,7 +76,7 @@ export function createServer<IAPI extends object>(
|
|
|
69
76
|
})
|
|
70
77
|
}
|
|
71
78
|
} finally {
|
|
72
|
-
|
|
79
|
+
destructor.execute()
|
|
73
80
|
}
|
|
74
81
|
} else if (DelightRPC.isAbort(message)) {
|
|
75
82
|
if (DelightRPC.matchChannel(message, channel)) {
|