bare-rpc 1.3.5 → 1.3.7

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/index.js CHANGED
@@ -2,6 +2,7 @@ const safetyCatch = require('safety-catch')
2
2
  const b4a = require('b4a')
3
3
  const c = require('compact-encoding')
4
4
  const m = require('./lib/messages')
5
+ const errors = require('./lib/errors')
5
6
  const { type: t, stream: s } = require('./lib/constants')
6
7
  const IncomingEvent = require('./lib/incoming-event')
7
8
  const IncomingRequest = require('./lib/incoming-request')
@@ -36,10 +37,15 @@ module.exports = exports = class RPC {
36
37
 
37
38
  this._onrequest = onrequest
38
39
  this._onerror = this._onerror.bind(this)
40
+ this._onclose = this._onclose.bind(this)
39
41
  this._ondata = this._ondata.bind(this)
40
42
  this._ondrain = this._ondrain.bind(this)
41
43
 
42
- this._stream.on('error', this._onerror).on('data', this._ondata).on('drain', this._ondrain)
44
+ this._stream
45
+ .on('error', this._onerror)
46
+ .on('close', this._onclose)
47
+ .on('data', this._ondata)
48
+ .on('drain', this._ondrain)
43
49
  }
44
50
 
45
51
  // Whether there are no requests or responses currently in flight. Useful for
@@ -64,6 +70,14 @@ module.exports = exports = class RPC {
64
70
  }
65
71
 
66
72
  _sendMessage(message, cb) {
73
+ // Once the underlying stream is being torn down there is nowhere left to
74
+ // write, so drop the message and settle the callback immediately. This
75
+ // keeps stream teardown from stalling on a drain that will never arrive.
76
+ if (this._stream.destroying) {
77
+ if (cb) cb(null)
78
+ return
79
+ }
80
+
67
81
  const header = c.encode(m.header, message)
68
82
 
69
83
  let flushed = this._stream.write(header)
@@ -167,9 +181,53 @@ module.exports = exports = class RPC {
167
181
  }
168
182
 
169
183
  _onerror(err) {
184
+ this._teardown(err)
185
+ }
186
+
187
+ _onclose() {
188
+ // A clean close of the underlying stream leaves in-flight requests and
189
+ // responses with nowhere to complete, so tear them down as if the channel
190
+ // had errored.
191
+ this._teardown(errors.CHANNEL_CLOSED('Channel closed'))
192
+ }
193
+
194
+ _teardown(err) {
170
195
  this._ondrain(err)
171
196
 
172
- // TODO Destroy pending requests and responses
197
+ // Reject any request awaiting a plain reply. Requests whose response is
198
+ // delivered over a stream are torn down through that stream below.
199
+ for (const request of this._outgoingRequests.values()) {
200
+ if (request.received && request._responseStream === null) request._reject(err)
201
+ }
202
+
203
+ // Collect the streams first, deduplicating as a single request may appear
204
+ // in more than one map, then destroy them once the maps have been cleared.
205
+ const streams = new Set()
206
+
207
+ for (const request of this._outgoingRequests.values()) {
208
+ if (request._requestStream !== null) streams.add(request._requestStream)
209
+ }
210
+
211
+ for (const request of this._incomingRequests.values()) {
212
+ if (request._requestStream !== null) streams.add(request._requestStream)
213
+ }
214
+
215
+ for (const request of this._outgoingResponses.values()) {
216
+ if (request._responseStream !== null) streams.add(request._responseStream)
217
+ }
218
+
219
+ for (const request of this._incomingResponses.values()) {
220
+ if (request._responseStream !== null) streams.add(request._responseStream)
221
+ }
222
+
223
+ this._outgoingRequests.clear()
224
+ this._outgoingResponses.clear()
225
+ this._incomingRequests.clear()
226
+ this._incomingResponses.clear()
227
+ this._pendingRequests.clear()
228
+ this._pendingResponses.clear()
229
+
230
+ for (const stream of streams) stream.destroy(err)
173
231
  }
174
232
 
175
233
  _ondata(data) {
package/lib/errors.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  declare class RPCError extends Error {
2
2
  static UNKNOWN_MESSAGE(msg: string): RPCError
3
3
  static ALREADY_SENT(msg: string): RPCError
4
+ static ALREADY_RECEIVED(msg: string): RPCError
5
+ static CHANNEL_CLOSED(msg: string): RPCError
4
6
  }
5
7
 
6
8
  export = RPCError
package/lib/errors.js CHANGED
@@ -23,4 +23,8 @@ module.exports = class RPCError extends Error {
23
23
  static ALREADY_RECEIVED(msg) {
24
24
  return new RPCError(msg, 'ALREADY_RECEIVED', RPCError.ALREADY_RECEIVED)
25
25
  }
26
+
27
+ static CHANNEL_CLOSED(msg) {
28
+ return new RPCError(msg, 'CHANNEL_CLOSED', RPCError.CHANNEL_CLOSED)
29
+ }
26
30
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-rpc",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "librpc ABI compatible RPC for Bare",
5
5
  "exports": {
6
6
  ".": {