@push-rpc/next 2.0.19 → 2.0.21
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/README.md +4 -3
- package/dist/client/RemoteSubscriptions.d.ts +0 -1
- package/dist/client/RemoteSubscriptions.js +3 -10
- package/dist/client/RemoteSubscriptions.js.map +1 -1
- package/dist/client/RpcClientImpl.js +5 -10
- package/dist/client/RpcClientImpl.js.map +1 -1
- package/dist/client/WebSocketConnection.d.ts +1 -0
- package/dist/client/WebSocketConnection.js +9 -1
- package/dist/client/WebSocketConnection.js.map +1 -1
- package/dist/server/ConnectionsServer.d.ts +1 -0
- package/dist/server/ConnectionsServer.js +4 -0
- package/dist/server/ConnectionsServer.js.map +1 -1
- package/dist/server/RpcServerImpl.d.ts +0 -1
- package/dist/server/RpcServerImpl.js +11 -13
- package/dist/server/RpcServerImpl.js.map +1 -1
- package/dist/utils/promises.d.ts +0 -4
- package/dist/utils/promises.js +1 -22
- package/dist/utils/promises.js.map +1 -1
- package/package.json +1 -1
- package/src/client/RemoteSubscriptions.ts +3 -11
- package/src/client/RpcClientImpl.ts +6 -11
- package/src/client/WebSocketConnection.ts +14 -4
- package/src/server/ConnectionsServer.ts +7 -1
- package/src/server/LocalSubscriptions.ts +4 -4
- package/src/server/RpcServerImpl.ts +24 -28
- package/src/utils/promises.ts +0 -22
- package/tests/calls.ts +1 -36
- package/tests/context.ts +22 -34
- package/tests/middleware.ts +8 -3
- package/tests/subscriptions.ts +118 -97
- package/tests/testUtils.ts +2 -2
- package/tests/triggers.ts +6 -2
|
@@ -2,7 +2,6 @@ import {PublishServicesOptions, RpcServer} from "./index.js"
|
|
|
2
2
|
import {LocalSubscriptions} from "./LocalSubscriptions.js"
|
|
3
3
|
import http from "http"
|
|
4
4
|
import type {ConnectionsServer} from "./ConnectionsServer.js"
|
|
5
|
-
import {PromiseCache} from "../utils/promises.js"
|
|
6
5
|
import {serveHttpRequest} from "./http.js"
|
|
7
6
|
import {
|
|
8
7
|
InvocationType,
|
|
@@ -21,7 +20,7 @@ import {safeParseJson, safeStringify} from "../utils/json.js"
|
|
|
21
20
|
export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implements RpcServer {
|
|
22
21
|
constructor(
|
|
23
22
|
private readonly services: S,
|
|
24
|
-
private readonly options: PublishServicesOptions<C
|
|
23
|
+
private readonly options: PublishServicesOptions<C>,
|
|
25
24
|
) {
|
|
26
25
|
if ("server" in this.options) {
|
|
27
26
|
this.httpServer = this.options.server
|
|
@@ -50,7 +49,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
50
49
|
res,
|
|
51
50
|
options.path,
|
|
52
51
|
options.createServerHooks ? options.createServerHooks(hooks, req) : hooks,
|
|
53
|
-
options.createConnectionContext
|
|
52
|
+
options.createConnectionContext,
|
|
54
53
|
).catch((e) => {
|
|
55
54
|
log.warn("Unhandled error serving HTTP request", e)
|
|
56
55
|
})
|
|
@@ -66,7 +65,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
66
65
|
(clientId) => {
|
|
67
66
|
this.localSubscriptions.unsubscribeAll(clientId)
|
|
68
67
|
},
|
|
69
|
-
!("server" in this.options)
|
|
68
|
+
!("server" in this.options),
|
|
70
69
|
)
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -114,14 +113,13 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
private readonly localSubscriptions = new LocalSubscriptions()
|
|
117
|
-
private readonly invocationCache = new PromiseCache()
|
|
118
116
|
private connectionsServer: ConnectionsServer | null = null
|
|
119
117
|
readonly httpServer
|
|
120
118
|
|
|
121
119
|
private call = async (
|
|
122
120
|
connectionContext: RpcConnectionContext,
|
|
123
121
|
itemName: string,
|
|
124
|
-
parameters: unknown[]
|
|
122
|
+
parameters: unknown[],
|
|
125
123
|
): Promise<unknown> => {
|
|
126
124
|
const item = this.getRemoteFunction(itemName)
|
|
127
125
|
|
|
@@ -135,7 +133,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
135
133
|
itemName,
|
|
136
134
|
item,
|
|
137
135
|
parameters,
|
|
138
|
-
InvocationType.Call
|
|
136
|
+
InvocationType.Call,
|
|
139
137
|
)
|
|
140
138
|
} catch (e) {
|
|
141
139
|
log.error(`Cannot call item ${itemName}.`, e)
|
|
@@ -146,7 +144,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
146
144
|
private subscribe = async (
|
|
147
145
|
connectionContext: RpcConnectionContext,
|
|
148
146
|
itemName: string,
|
|
149
|
-
parameters: unknown[]
|
|
147
|
+
parameters: unknown[],
|
|
150
148
|
) => {
|
|
151
149
|
const item = this.getRemoteFunction(itemName)
|
|
152
150
|
|
|
@@ -167,7 +165,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
167
165
|
itemName,
|
|
168
166
|
item,
|
|
169
167
|
parameters,
|
|
170
|
-
InvocationType.Trigger
|
|
168
|
+
InvocationType.Trigger,
|
|
171
169
|
)
|
|
172
170
|
|
|
173
171
|
const newDataJson = safeStringify(newData)
|
|
@@ -178,7 +176,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
178
176
|
connectionContext.clientId,
|
|
179
177
|
itemName,
|
|
180
178
|
parameters,
|
|
181
|
-
newData
|
|
179
|
+
newData,
|
|
182
180
|
)
|
|
183
181
|
}
|
|
184
182
|
} catch (e) {
|
|
@@ -186,14 +184,16 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
186
184
|
}
|
|
187
185
|
})
|
|
188
186
|
|
|
189
|
-
this.
|
|
187
|
+
if (this.connectionsServer?.isClientSubscribed(connectionContext.clientId)) {
|
|
188
|
+
this.localSubscriptions.subscribe(connectionContext.clientId, itemName, parameters, update)
|
|
189
|
+
}
|
|
190
190
|
|
|
191
191
|
const lastData = await this.invokeLocalFunction(
|
|
192
192
|
connectionContext,
|
|
193
193
|
itemName,
|
|
194
194
|
item,
|
|
195
195
|
parameters,
|
|
196
|
-
InvocationType.Subscribe
|
|
196
|
+
InvocationType.Subscribe,
|
|
197
197
|
)
|
|
198
198
|
lastDataJson = safeStringify(lastData)
|
|
199
199
|
|
|
@@ -209,7 +209,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
209
209
|
private unsubscribe = async (
|
|
210
210
|
connectionContext: RpcConnectionContext,
|
|
211
211
|
itemName: string,
|
|
212
|
-
parameters: unknown[]
|
|
212
|
+
parameters: unknown[],
|
|
213
213
|
) => {
|
|
214
214
|
try {
|
|
215
215
|
this.localSubscriptions.unsubscribe(connectionContext.clientId, itemName, parameters)
|
|
@@ -221,7 +221,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
221
221
|
|
|
222
222
|
private getRemoteFunction(
|
|
223
223
|
itemName: string,
|
|
224
|
-
root: any = this.services
|
|
224
|
+
root: any = this.services,
|
|
225
225
|
): {function: RemoteFunction; container: any} | undefined {
|
|
226
226
|
const parts = itemName.split("/")
|
|
227
227
|
|
|
@@ -248,22 +248,18 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
248
248
|
itemName: string,
|
|
249
249
|
item: {function: RemoteFunction; container: any},
|
|
250
250
|
parameters: unknown[],
|
|
251
|
-
invocationType: InvocationType
|
|
251
|
+
invocationType: InvocationType,
|
|
252
252
|
): Promise<unknown> {
|
|
253
|
-
|
|
254
|
-
{clientId: connectionContext.clientId, itemName, parameters},
|
|
255
|
-
() => {
|
|
256
|
-
const parametersCopy: unknown[] = safeParseJson(safeStringify(parameters))
|
|
253
|
+
const parametersCopy: unknown[] = safeParseJson(safeStringify(parameters))
|
|
257
254
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
255
|
+
const ctx = safeParseJson(safeStringify(connectionContext)) as C
|
|
256
|
+
ctx.itemName = itemName
|
|
257
|
+
ctx.invocationType = invocationType
|
|
261
258
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
)
|
|
259
|
+
const invokeItem = (...params: unknown[]) => {
|
|
260
|
+
return item.function.call(item.container, ...params, ctx)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return withMiddlewares<C>(ctx, this.options.middleware, invokeItem, ...parametersCopy)
|
|
268
264
|
}
|
|
269
265
|
}
|
package/src/utils/promises.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
export class PromiseCache {
|
|
2
|
-
invoke<T>(cacheKey: unknown, supplier: () => Promise<T>): Promise<T> {
|
|
3
|
-
const key = JSON.stringify(cacheKey)
|
|
4
|
-
|
|
5
|
-
if (!this.cache[key]) {
|
|
6
|
-
this.cache[key] = supplier()
|
|
7
|
-
.then((r) => {
|
|
8
|
-
delete this.cache[key]
|
|
9
|
-
return r
|
|
10
|
-
})
|
|
11
|
-
.catch((e) => {
|
|
12
|
-
delete this.cache[key]
|
|
13
|
-
throw e
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return this.cache[key]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
private cache: {[key: string]: Promise<any>} = {}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
1
|
export async function adelay(ms: number) {
|
|
24
2
|
return new Promise((r) => setTimeout(r, ms))
|
|
25
3
|
}
|
package/tests/calls.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {assert} from "chai"
|
|
2
2
|
import {createTestClient, startTestServer} from "./testUtils.js"
|
|
3
|
-
import {CallOptions,
|
|
3
|
+
import {CallOptions, RpcErrors} from "../src/index.js"
|
|
4
4
|
import {adelay} from "../src/utils/promises.js"
|
|
5
5
|
|
|
6
6
|
describe("calls", () => {
|
|
@@ -169,41 +169,6 @@ describe("calls", () => {
|
|
|
169
169
|
const r = await client.obj.hello()
|
|
170
170
|
assert.equal("yes", r)
|
|
171
171
|
})
|
|
172
|
-
|
|
173
|
-
it("concurrent call cache", async () => {
|
|
174
|
-
const item = {r: "1"}
|
|
175
|
-
let supplied = 0
|
|
176
|
-
|
|
177
|
-
const server = {
|
|
178
|
-
test: {
|
|
179
|
-
item: async () => {
|
|
180
|
-
await adelay(1)
|
|
181
|
-
supplied++
|
|
182
|
-
return item
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
await startTestServer(server)
|
|
188
|
-
|
|
189
|
-
const client = await createTestClient<typeof server>()
|
|
190
|
-
|
|
191
|
-
let item1
|
|
192
|
-
client.test.item().then((item) => {
|
|
193
|
-
item1 = item
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
let item2
|
|
197
|
-
client.test.item().then((item) => {
|
|
198
|
-
item2 = item
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
await adelay(50)
|
|
202
|
-
assert.deepEqual(item1, item)
|
|
203
|
-
assert.deepEqual(item2, item)
|
|
204
|
-
|
|
205
|
-
assert.equal(supplied, 1)
|
|
206
|
-
})
|
|
207
172
|
})
|
|
208
173
|
|
|
209
174
|
abstract class A {
|
package/tests/context.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {createTestClient, startTestServer} from "./testUtils.js"
|
|
1
|
+
import {createTestClient, startTestServer, testClient, testServer} from "./testUtils.js"
|
|
2
2
|
import {assert} from "chai"
|
|
3
3
|
import {adelay} from "../src/utils/promises.js"
|
|
4
4
|
import {RpcContext} from "../src/index.js"
|
|
@@ -41,7 +41,7 @@ describe("context", () => {
|
|
|
41
41
|
async createConnectionContext() {
|
|
42
42
|
return {clientId: "test", newKey: "bla"}
|
|
43
43
|
},
|
|
44
|
-
}
|
|
44
|
+
},
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
const client = await createTestClient<typeof services>()
|
|
@@ -75,30 +75,25 @@ describe("context", () => {
|
|
|
75
75
|
it("available in trigger", async () => {
|
|
76
76
|
let ctx = null
|
|
77
77
|
|
|
78
|
-
const services = await startTestServer(
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
ctx = passedCtx
|
|
83
|
-
},
|
|
78
|
+
const services = await startTestServer({
|
|
79
|
+
test: {
|
|
80
|
+
async call(passedCtx?: any) {
|
|
81
|
+
ctx = passedCtx
|
|
84
82
|
},
|
|
85
83
|
},
|
|
86
|
-
|
|
87
|
-
async createConnectionContext() {
|
|
88
|
-
return {clientId: "test"}
|
|
89
|
-
},
|
|
90
|
-
}
|
|
91
|
-
)
|
|
84
|
+
})
|
|
92
85
|
|
|
93
|
-
const client = await createTestClient<typeof services>(
|
|
86
|
+
const client = await createTestClient<typeof services>({
|
|
87
|
+
connectOnCreate: true,
|
|
88
|
+
})
|
|
94
89
|
|
|
95
90
|
await client.test.call.subscribe(() => {})
|
|
96
|
-
assert.equal(ctx!.clientId,
|
|
91
|
+
assert.equal(ctx!.clientId, testClient?.clientId)
|
|
97
92
|
|
|
98
93
|
ctx = null
|
|
99
94
|
services.test.call.trigger()
|
|
100
95
|
await adelay(20)
|
|
101
|
-
assert.equal(ctx!.clientId,
|
|
96
|
+
assert.equal(ctx!.clientId, testClient?.clientId)
|
|
102
97
|
assert.equal(ctx!.invocationType, InvocationType.Trigger)
|
|
103
98
|
})
|
|
104
99
|
|
|
@@ -107,26 +102,19 @@ describe("context", () => {
|
|
|
107
102
|
|
|
108
103
|
let count = 0
|
|
109
104
|
|
|
110
|
-
const services = await startTestServer(
|
|
111
|
-
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
ctx = passedCtx
|
|
105
|
+
const services = await startTestServer({
|
|
106
|
+
test: {
|
|
107
|
+
async call(passedCtx?: any) {
|
|
108
|
+
ctx = passedCtx
|
|
115
109
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
if (!count) {
|
|
111
|
+
ctx.modified = true
|
|
112
|
+
}
|
|
119
113
|
|
|
120
|
-
|
|
121
|
-
},
|
|
114
|
+
count++
|
|
122
115
|
},
|
|
123
116
|
},
|
|
124
|
-
|
|
125
|
-
async createConnectionContext() {
|
|
126
|
-
return {clientId: "test"}
|
|
127
|
-
},
|
|
128
|
-
}
|
|
129
|
-
)
|
|
117
|
+
})
|
|
130
118
|
|
|
131
119
|
const client = await createTestClient<typeof services>()
|
|
132
120
|
|
|
@@ -160,7 +148,7 @@ describe("context", () => {
|
|
|
160
148
|
return next(ctx)
|
|
161
149
|
},
|
|
162
150
|
],
|
|
163
|
-
}
|
|
151
|
+
},
|
|
164
152
|
)
|
|
165
153
|
|
|
166
154
|
const client = await createTestClient<typeof services>()
|
package/tests/middleware.ts
CHANGED
|
@@ -44,7 +44,7 @@ describe("middleware", () => {
|
|
|
44
44
|
return next()
|
|
45
45
|
},
|
|
46
46
|
],
|
|
47
|
-
}
|
|
47
|
+
},
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
const remote = await createTestClient<typeof services>()
|
|
@@ -128,6 +128,7 @@ describe("middleware", () => {
|
|
|
128
128
|
return next((r as number) + 1)
|
|
129
129
|
},
|
|
130
130
|
],
|
|
131
|
+
connectOnCreate: true,
|
|
131
132
|
})
|
|
132
133
|
|
|
133
134
|
let response
|
|
@@ -135,9 +136,12 @@ describe("middleware", () => {
|
|
|
135
136
|
(r) => {
|
|
136
137
|
response = r
|
|
137
138
|
},
|
|
138
|
-
{param: 1}
|
|
139
|
+
{param: 1},
|
|
139
140
|
)
|
|
140
141
|
|
|
142
|
+
assert.equal(response, 1)
|
|
143
|
+
assert.equal(count, 2)
|
|
144
|
+
|
|
141
145
|
services.remote.trigger({param: 1})
|
|
142
146
|
|
|
143
147
|
await adelay(20)
|
|
@@ -172,6 +176,7 @@ describe("middleware", () => {
|
|
|
172
176
|
throw new Error("Test error")
|
|
173
177
|
},
|
|
174
178
|
],
|
|
179
|
+
connectOnCreate: true,
|
|
175
180
|
})
|
|
176
181
|
|
|
177
182
|
await client.remote.subscribe((r) => {
|
|
@@ -227,7 +232,7 @@ describe("middleware", () => {
|
|
|
227
232
|
throw new Error("Error")
|
|
228
233
|
},
|
|
229
234
|
],
|
|
230
|
-
}
|
|
235
|
+
},
|
|
231
236
|
)
|
|
232
237
|
|
|
233
238
|
const client = await createTestClient<typeof services>({})
|
package/tests/subscriptions.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {assert} from "chai"
|
|
2
2
|
import {createTestClient, startTestServer, testClient, testServer} from "./testUtils.js"
|
|
3
3
|
import {adelay} from "../src/utils/promises.js"
|
|
4
|
-
import {CallOptions,
|
|
5
|
-
import {
|
|
6
|
-
import {CLIENT_ID_HEADER} from "../src/rpc.js"
|
|
7
|
-
import WebSocket from "ws"
|
|
4
|
+
import {CallOptions, RpcErrors} from "../src/index.js"
|
|
5
|
+
import {setTestWebSocketConnectionDelay} from "../src/client/WebSocketConnection.js"
|
|
8
6
|
|
|
9
7
|
describe("Subscriptions", () => {
|
|
10
8
|
it("subscribe delivers data", async () => {
|
|
@@ -140,41 +138,6 @@ describe("Subscriptions", () => {
|
|
|
140
138
|
assert.equal(testServer?._allSubscriptions()[0][0], "test/item")
|
|
141
139
|
})
|
|
142
140
|
|
|
143
|
-
it("concurrent subscribe cache", async () => {
|
|
144
|
-
const item = {r: "1"}
|
|
145
|
-
let supplied = 0
|
|
146
|
-
|
|
147
|
-
const server = {
|
|
148
|
-
test: {
|
|
149
|
-
item: async () => {
|
|
150
|
-
await adelay(20)
|
|
151
|
-
supplied++
|
|
152
|
-
return item
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
await startTestServer(server)
|
|
158
|
-
|
|
159
|
-
const client = await createTestClient<typeof server>()
|
|
160
|
-
|
|
161
|
-
let item1
|
|
162
|
-
client.test.item.subscribe((item) => {
|
|
163
|
-
item1 = item
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
let item2
|
|
167
|
-
client.test.item.subscribe((item) => {
|
|
168
|
-
item2 = item
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
await adelay(50)
|
|
172
|
-
assert.deepEqual(item1, item)
|
|
173
|
-
assert.deepEqual(item2, item)
|
|
174
|
-
|
|
175
|
-
assert.equal(supplied, 1)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
141
|
it("subscribe use client cached value", async () => {
|
|
179
142
|
const item = {r: "1"}
|
|
180
143
|
|
|
@@ -482,23 +445,7 @@ describe("Subscriptions", () => {
|
|
|
482
445
|
})
|
|
483
446
|
|
|
484
447
|
// delay client connection open by 10ms
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
oldAddEL = WebSocket.prototype.addEventListener
|
|
488
|
-
WebSocket.prototype.addEventListener = function (eventName: any, callback: any) {
|
|
489
|
-
if (eventName == "open") {
|
|
490
|
-
oldAddEL.apply(this, [
|
|
491
|
-
eventName,
|
|
492
|
-
() => {
|
|
493
|
-
setTimeout(callback, 10)
|
|
494
|
-
},
|
|
495
|
-
])
|
|
496
|
-
|
|
497
|
-
return
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
return oldAddEL.apply(this, [eventName, callback])
|
|
501
|
-
}
|
|
448
|
+
delayWebsocketConnection(10)
|
|
502
449
|
|
|
503
450
|
const client = await createTestClient<typeof services>()
|
|
504
451
|
|
|
@@ -514,7 +461,7 @@ describe("Subscriptions", () => {
|
|
|
514
461
|
assert.equal(testClient!._allSubscriptions().length, 0)
|
|
515
462
|
assert.equal(testServer!._allSubscriptions().length, 0)
|
|
516
463
|
|
|
517
|
-
|
|
464
|
+
cancelWebsocketConnectionDelay()
|
|
518
465
|
})
|
|
519
466
|
|
|
520
467
|
it("skip unchanged data", async () => {
|
|
@@ -587,6 +534,7 @@ describe("Subscriptions", () => {
|
|
|
587
534
|
|
|
588
535
|
const client = await createTestClient<typeof services>({
|
|
589
536
|
callTimeout: 2 * delay,
|
|
537
|
+
connectOnCreate: true,
|
|
590
538
|
})
|
|
591
539
|
|
|
592
540
|
let received = 0
|
|
@@ -605,6 +553,8 @@ describe("Subscriptions", () => {
|
|
|
605
553
|
assert.equal(received, 2)
|
|
606
554
|
})
|
|
607
555
|
|
|
556
|
+
// Currently not working, b/c paused is boolean
|
|
557
|
+
// To implement it, need to replace it with counter
|
|
608
558
|
it.skip("two concurrent subscribes and trigger", async () => {
|
|
609
559
|
const delay = 50
|
|
610
560
|
|
|
@@ -694,62 +644,133 @@ describe("Subscriptions", () => {
|
|
|
694
644
|
assert.equal(received, 1)
|
|
695
645
|
})
|
|
696
646
|
|
|
697
|
-
it("subscribe
|
|
698
|
-
const
|
|
647
|
+
it("can subscribe while disconnected", async () => {
|
|
648
|
+
const item = {r: "1"}
|
|
699
649
|
|
|
700
|
-
|
|
701
|
-
let serverCalled = 0
|
|
650
|
+
delayWebsocketConnection(50)
|
|
702
651
|
|
|
703
|
-
const services = await startTestServer(
|
|
704
|
-
{
|
|
705
|
-
|
|
706
|
-
async op(params: {key: number}): Promise<number> {
|
|
707
|
-
serverCalled++
|
|
708
|
-
return 1
|
|
709
|
-
},
|
|
710
|
-
},
|
|
652
|
+
const services = await startTestServer({
|
|
653
|
+
test: {
|
|
654
|
+
item: async () => item,
|
|
711
655
|
},
|
|
712
|
-
|
|
713
|
-
async createConnectionContext(req: IncomingMessage): Promise<RpcConnectionContext> {
|
|
714
|
-
const header = req.headers[CLIENT_ID_HEADER]
|
|
656
|
+
})
|
|
715
657
|
|
|
716
|
-
|
|
658
|
+
const remote = await createTestClient<typeof services>()
|
|
717
659
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
660
|
+
let receivedItem
|
|
661
|
+
await remote.test.item.subscribe((item) => {
|
|
662
|
+
receivedItem = item
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
assert.deepEqual(receivedItem, item)
|
|
666
|
+
|
|
667
|
+
// trigger sends item
|
|
668
|
+
item.r = "2"
|
|
669
|
+
services.test.item.trigger()
|
|
670
|
+
await adelay(60)
|
|
671
|
+
assert.deepEqual(receivedItem, item)
|
|
672
|
+
|
|
673
|
+
cancelWebsocketConnectionDelay()
|
|
674
|
+
})
|
|
675
|
+
|
|
676
|
+
it("connect during subscribe", async () => {
|
|
677
|
+
const item = {r: "1"}
|
|
678
|
+
|
|
679
|
+
delayWebsocketConnection(30)
|
|
680
|
+
|
|
681
|
+
const services = await startTestServer({
|
|
682
|
+
test: {
|
|
683
|
+
item: async () => {
|
|
684
|
+
await adelay(50)
|
|
685
|
+
return item
|
|
721
686
|
},
|
|
722
687
|
},
|
|
723
|
-
)
|
|
688
|
+
})
|
|
724
689
|
|
|
725
|
-
const
|
|
726
|
-
|
|
690
|
+
const remote = await createTestClient<typeof services>()
|
|
691
|
+
|
|
692
|
+
let receivedItem
|
|
693
|
+
await remote.test.item.subscribe((item) => {
|
|
694
|
+
receivedItem = item
|
|
727
695
|
})
|
|
728
696
|
|
|
729
|
-
|
|
730
|
-
|
|
697
|
+
assert.deepEqual(receivedItem, item)
|
|
698
|
+
|
|
699
|
+
// trigger sends item
|
|
700
|
+
item.r = "2"
|
|
701
|
+
services.test.item.trigger()
|
|
702
|
+
await adelay(100)
|
|
703
|
+
assert.deepEqual(receivedItem, item)
|
|
704
|
+
|
|
705
|
+
cancelWebsocketConnectionDelay()
|
|
706
|
+
})
|
|
707
|
+
|
|
708
|
+
it("disconnect during subscribe", async () => {
|
|
709
|
+
const item = {r: "1"}
|
|
731
710
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
711
|
+
const services = await startTestServer({
|
|
712
|
+
test: {
|
|
713
|
+
item: async () => item,
|
|
735
714
|
},
|
|
736
|
-
|
|
737
|
-
)
|
|
715
|
+
})
|
|
738
716
|
|
|
739
|
-
await
|
|
717
|
+
const consume1 = await createTestClient<typeof services>({
|
|
718
|
+
connectOnCreate: true,
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
let received = null
|
|
740
722
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
723
|
+
// disconnect WS
|
|
724
|
+
testClient!._webSocket()!.close()
|
|
725
|
+
|
|
726
|
+
await consume1.test.item.subscribe((item) => {
|
|
727
|
+
received = item
|
|
728
|
+
})
|
|
729
|
+
|
|
730
|
+
assert.deepEqual(received, item)
|
|
731
|
+
|
|
732
|
+
item.r = "2"
|
|
733
|
+
services.test.item.trigger()
|
|
734
|
+
await adelay(100)
|
|
735
|
+
|
|
736
|
+
// still getting the update b/c on WS reconnect client will resubscribe
|
|
737
|
+
assert.deepEqual(received, item)
|
|
738
|
+
})
|
|
739
|
+
|
|
740
|
+
it("do not add subscriptions without connection", async () => {
|
|
741
|
+
const item = {r: "1"}
|
|
742
|
+
|
|
743
|
+
delayWebsocketConnection(100)
|
|
744
|
+
|
|
745
|
+
const services = await startTestServer({
|
|
746
|
+
test: {
|
|
747
|
+
item: async () => {
|
|
748
|
+
return item
|
|
749
|
+
},
|
|
744
750
|
},
|
|
745
|
-
|
|
746
|
-
)
|
|
751
|
+
})
|
|
747
752
|
|
|
748
|
-
await
|
|
753
|
+
const remote = await createTestClient<typeof services>()
|
|
749
754
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
755
|
+
let receivedItem
|
|
756
|
+
await remote.test.item.subscribe((item) => {
|
|
757
|
+
receivedItem = item
|
|
758
|
+
})
|
|
759
|
+
|
|
760
|
+
assert.deepEqual(receivedItem, item)
|
|
761
|
+
|
|
762
|
+
const length = testServer!._allSubscriptions().length
|
|
763
|
+
|
|
764
|
+
assert.equal(length, 0)
|
|
765
|
+
|
|
766
|
+
cancelWebsocketConnectionDelay()
|
|
754
767
|
})
|
|
755
768
|
})
|
|
769
|
+
|
|
770
|
+
function delayWebsocketConnection(ms: number) {
|
|
771
|
+
setTestWebSocketConnectionDelay(ms)
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function cancelWebsocketConnectionDelay() {
|
|
775
|
+
setTestWebSocketConnectionDelay(0)
|
|
776
|
+
}
|
package/tests/testUtils.ts
CHANGED
|
@@ -20,7 +20,7 @@ export let testServer: RpcServer | null = null
|
|
|
20
20
|
|
|
21
21
|
export async function startTestServer<S extends Services<S>, C extends RpcContext>(
|
|
22
22
|
local: S,
|
|
23
|
-
options: Partial<PublishServicesOptions<C>> = {}
|
|
23
|
+
options: Partial<PublishServicesOptions<C>> = {},
|
|
24
24
|
): Promise<ServicesWithTriggers<S>> {
|
|
25
25
|
const r = await publishServices<S, C>(local, {
|
|
26
26
|
port: TEST_PORT,
|
|
@@ -34,7 +34,7 @@ export async function startTestServer<S extends Services<S>, C extends RpcContex
|
|
|
34
34
|
export let testClient: RpcClient | null = null
|
|
35
35
|
|
|
36
36
|
export async function createTestClient<S extends Services<S>>(
|
|
37
|
-
options?: Partial<ConsumeServicesOptions
|
|
37
|
+
options?: Partial<ConsumeServicesOptions>,
|
|
38
38
|
): Promise<ServicesWithSubscriptions<S>> {
|
|
39
39
|
if (!options) options = {}
|
|
40
40
|
if (!options.middleware) options.middleware = []
|
package/tests/triggers.ts
CHANGED
|
@@ -22,7 +22,9 @@ describe("Subscription triggers", () => {
|
|
|
22
22
|
timeout: 0,
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
const remote = await createTestClient<typeof services>(
|
|
25
|
+
const remote = await createTestClient<typeof services>({
|
|
26
|
+
connectOnCreate: true,
|
|
27
|
+
})
|
|
26
28
|
|
|
27
29
|
let item1
|
|
28
30
|
let item2
|
|
@@ -68,7 +70,9 @@ describe("Subscription triggers", () => {
|
|
|
68
70
|
timeout: throttleTimeout,
|
|
69
71
|
})
|
|
70
72
|
|
|
71
|
-
const remote = await createTestClient<typeof services>(
|
|
73
|
+
const remote = await createTestClient<typeof services>({
|
|
74
|
+
connectOnCreate: true,
|
|
75
|
+
})
|
|
72
76
|
|
|
73
77
|
let count = 0
|
|
74
78
|
let item = null
|