braid-http 1.0.5 → 1.0.6

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.
@@ -169,6 +169,9 @@ async function braid_fetch (url, params = {}) {
169
169
  params.headers.set('subscribe', 'true')
170
170
  if (params.peer)
171
171
  params.headers.set('peer', params.peer)
172
+
173
+ if (params.heartbeats)
174
+ params.headers.set('heartbeats', typeof params.heartbeats === 'number' ? `${params.heartbeats}s` : params.heartbeats)
172
175
 
173
176
  // Prevent browsers from going to disk cache
174
177
  params.cache = 'no-cache'
@@ -225,8 +228,23 @@ async function braid_fetch (url, params = {}) {
225
228
  return await new Promise((done, fail) => {
226
229
  connect()
227
230
  async function connect() {
231
+ let on_error = e => {
232
+ on_error = () => {}
233
+
234
+ if (!params.retry || (e.name === "AbortError")) {
235
+ subscription_error?.(e)
236
+ return fail(e)
237
+ }
238
+
239
+ underlying_aborter.abort()
240
+
241
+ console.log(`retrying in ${waitTime}ms: ${url} after error: ${e}`)
242
+ setTimeout(connect, waitTime)
243
+ waitTime = Math.min(waitTime * 2, 3000)
244
+ }
245
+
228
246
  try {
229
- if (original_signal?.aborted) return fail(new Error('abort'))
247
+ if (original_signal?.aborted) throw new DOMException('already aborted', 'AbortError')
230
248
 
231
249
  // We need a fresh underlying abort controller each time we connect
232
250
  underlying_aborter = new AbortController()
@@ -257,6 +275,22 @@ async function braid_fetch (url, params = {}) {
257
275
  subscription_cb = cb
258
276
  subscription_error = error
259
277
 
278
+ // heartbeat
279
+ let on_heartbeat = () => {}
280
+ if (res.headers.get('heartbeats')) {
281
+ let heartbeats = parseFloat(res.headers.get('heartbeats'))
282
+ if (isFinite(heartbeats)) {
283
+ let timeout = null
284
+ on_heartbeat = () => {
285
+ clearTimeout(timeout)
286
+ timeout = setTimeout(() => {
287
+ on_error(new Error(`heartbeat not seen in ${(1.2 * heartbeats).toFixed(2)}s`))
288
+ }, 1.2 * heartbeats * 1000)
289
+ }
290
+ on_heartbeat()
291
+ }
292
+ }
293
+
260
294
  if (!res.ok)
261
295
  throw new Error('Request returned not ok status:', res.status)
262
296
 
@@ -274,20 +308,17 @@ async function braid_fetch (url, params = {}) {
274
308
  if (!err)
275
309
  // Yay! We got a new version! Tell the callback!
276
310
  cb(result)
277
- else {
311
+ else
278
312
  // This error handling code runs if the connection
279
313
  // closes, or if there is unparseable stuff in the
280
314
  // streamed response.
281
-
282
- // In any case, we want to be sure to abort the
283
- // underlying fetch.
284
- underlying_aborter.abort()
285
-
286
315
  on_error(err)
287
- }
288
316
  },
289
317
  !isTextContentType(res.headers.get('content-type')),
290
- params.onBytes
318
+ (...args) => {
319
+ on_heartbeat()
320
+ params.onBytes?.(...args)
321
+ }
291
322
  )
292
323
  }
293
324
 
@@ -366,16 +397,6 @@ async function braid_fetch (url, params = {}) {
366
397
  waitTime = 10
367
398
  } catch (e) { on_error(e) }
368
399
  }
369
- function on_error(e) {
370
- if (!params.retry || (e.name === "AbortError")) {
371
- subscription_error?.(e)
372
- return fail(e)
373
- }
374
-
375
- console.log(`retrying in ${waitTime}ms: ${url} after error: ${e}`)
376
- setTimeout(connect, waitTime)
377
- waitTime = Math.min(waitTime * 2, 3000)
378
- }
379
400
  })
380
401
  }
381
402
 
@@ -270,6 +270,22 @@ function braidify (req, res, next) {
270
270
  res.on('close', x => disconnected('close'))
271
271
  res.on('finish', x => disconnected('finish'))
272
272
  req.on('abort', x => disconnected('abort'))
273
+
274
+ // Heartbeats
275
+ if (req.headers['heartbeats']) {
276
+ let heartbeats = parseFloat(req.headers['heartbeats'])
277
+ if (isFinite(heartbeats)) {
278
+ res.setHeader('heartbeats', req.headers['heartbeats'])
279
+ let closed
280
+ res.on('close', () => closed = true)
281
+ loop()
282
+ function loop() {
283
+ if (res.writableEnded || closed) return
284
+ res.write("\r\n")
285
+ setTimeout(loop, 1000 * heartbeats)
286
+ }
287
+ }
288
+ }
273
289
  }
274
290
 
275
291
  // Check the Useragent to work around Firefox bugs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-http",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "An implementation of Braid-HTTP for Node.js and Browsers",
5
5
  "scripts": {
6
6
  "test": "node test/server.js"