From 68a24d5ded687b6eecbef148f73c58a08ee952da Mon Sep 17 00:00:00 2001 From: Mathias Buus Date: Wed, 27 Nov 2024 22:04:45 +0100 Subject: [PATCH] add weak session support (#603) --- index.js | 3 +++ lib/core.js | 12 ++++++++++-- lib/session-state.js | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index cfa0463b..5e9cd499 100644 --- a/index.js +++ b/index.js @@ -64,6 +64,7 @@ class Hypercore extends EventEmitter { this.exclusive = false this.opened = false this.closed = false + this.weak = !!opts.weak this.snapshotted = !!opts.snapshot this.draft = !!opts.draft this.onwait = opts.onwait || null @@ -206,6 +207,7 @@ class Hypercore extends EventEmitter { const writable = opts.writable === false ? false : !this._readonly const onwait = opts.onwait === undefined ? this.onwait : opts.onwait const timeout = opts.timeout === undefined ? this.timeout : opts.timeout + const weak = opts.weak === undefined ? this.weak : opts.weak const Clz = opts.class || Hypercore const s = new Clz(null, this.key, { ...opts, @@ -214,6 +216,7 @@ class Hypercore extends EventEmitter { onwait, timeout, writable, + weak, parent: this }) diff --git a/lib/core.js b/lib/core.js index ce9be63e..b3804721 100644 --- a/lib/core.js +++ b/lib/core.js @@ -22,6 +22,7 @@ module.exports = class Core { this.replicator = new Replicator(this, opts) this.sessionStates = [] this.monitors = [] + this.activeSessions = 0 this.id = opts.key ? z32.encode(opts.key) : null this.key = opts.key || null @@ -86,12 +87,14 @@ module.exports = class Core { allSessions () { const sessions = [] - for (const state of this.sessionStates) sessions.push(...state.sessions) + for (const state of this.sessionStates) { + if (state.sessions.length) sessions.push(...state.sessions) + } return sessions } hasSession () { - return this.sessionStates.length > 1 || (this.state !== null && this.state.sessions.length !== 0) + return this.activeSessions !== 0 } checkIfIdle () { @@ -719,8 +722,13 @@ module.exports = class Core { } destroy () { + if (this.hasSession() === true) throw new Error('Cannot destroy while sessions are open') if (this.replicator) this.replicator.destroy() if (this.state) this.state.destroy() + + // close all pending weak sessions... + const weakSessions = this.allSessions() + for (const s of weakSessions) s.close().catch(noop) } async _close () { diff --git a/lib/session-state.js b/lib/session-state.js index 41f35ba7..6585bb19 100644 --- a/lib/session-state.js +++ b/lib/session-state.js @@ -42,7 +42,9 @@ module.exports = class SessionState { } addSession (s) { + if (s._stateIndex !== -1) return s._stateIndex = this.sessions.push(s) - 1 + if (s.weak === false) this.core.activeSessions++ } removeSession (s) { @@ -50,6 +52,7 @@ module.exports = class SessionState { const head = this.sessions.pop() if (head !== s) this.sessions[(head._stateIndex = s._stateIndex)] = head s._stateIndex = -1 + if (s.weak === false) this.core.activeSessions-- this.core.checkIfIdle() }