Expand collab, network-stack, messaging, storage, pear, and experimental modules
Add manual helpers: overlay topology neighbor management, stream chunker drainAll, whiteboard and line-lock clear, fork picker and cursor presence bulk ops, anycast unregister, bandwidth broker reset, log gossip filtering, bee tombstone clear, gossip mesh clearSeen, update gossip unsubscribeAll, congestion throttled peers, histogram reset, preflight cancelAll, sticky session clearAll, gravity well and collab room bulk helpers, stream resume reset, stream transform clearPending, entropy spiral advanceBatch, and related list/clear utilities. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -130,6 +130,20 @@ class HyperP2PCollabRoom extends EventEmitter {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaveAll () {
|
||||||
|
let n = 0
|
||||||
|
for (const roomId of this.listRooms()) {
|
||||||
|
if (this.leave(roomId)) n++
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAllRooms () {
|
||||||
|
const ids = this.listRooms()
|
||||||
|
for (const id of ids) this.closeRoom(id)
|
||||||
|
return ids.length
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (!data || !data.type) return
|
if (!data || !data.type) return
|
||||||
this._stats.gossipIn++
|
this._stats.gossipIn++
|
||||||
|
|||||||
@@ -91,6 +91,16 @@ class HyperP2PCursorPresence extends EventEmitter {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listDocIds () {
|
||||||
|
return [...new Set([...this._cursors.values()].map((c) => c.docId))]
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._cursors.size
|
||||||
|
this._cursors.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
this._stats.gossipIn++
|
this._stats.gossipIn++
|
||||||
|
|||||||
@@ -84,6 +84,16 @@ class HyperP2PDocumentLineLock extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listDocIds () {
|
||||||
|
return [...new Set([...this._locks.values()].map((l) => l.docId))]
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._locks.size
|
||||||
|
this._locks.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
this._stats.gossipIn++
|
this._stats.gossipIn++
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ class HyperP2PWhiteboardOp extends EventEmitter {
|
|||||||
return before - this._log.length
|
return before - this._log.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._log.length
|
||||||
|
this._log = []
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (data && data.type === 'wb-op' && data.entry) this.mergeRemote(data.entry)
|
if (data && data.type === 'wb-op' && data.entry) this.mergeRemote(data.entry)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ class HyperP2PEntropySpiral extends EventEmitter {
|
|||||||
return removed
|
return removed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
advanceBatch (count = 1) {
|
||||||
|
const n = Math.max(0, count | 0)
|
||||||
|
const out = []
|
||||||
|
for (let i = 0; i < n; i++) out.push(this.advance())
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
_gossip (data) {
|
_gossip (data) {
|
||||||
if (!this._peerMsgs) return
|
if (!this._peerMsgs) return
|
||||||
gossipSend(this, data)
|
gossipSend(this, data)
|
||||||
|
|||||||
@@ -91,6 +91,22 @@ class HyperP2PGravityWell extends EventEmitter {
|
|||||||
return this._sink.slice(0, Math.max(0, n | 0))
|
return this._sink.slice(0, Math.max(0, n | 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wellIds () {
|
||||||
|
return [...this._wells.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSink () {
|
||||||
|
const n = this._sink.length
|
||||||
|
this._sink = []
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
clearWells () {
|
||||||
|
const n = this._wells.size
|
||||||
|
this._wells.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
async ready () {
|
async ready () {
|
||||||
if (this.swarm || !this.topic) return this
|
if (this.swarm || !this.topic) return this
|
||||||
await initModuleSwarm(this, {
|
await initModuleSwarm(this, {
|
||||||
|
|||||||
@@ -96,6 +96,16 @@ class HyperP2PHistogramGossip extends EventEmitter {
|
|||||||
return [...this._metrics.keys()].sort()
|
return [...this._metrics.keys()].sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetMetric (metric) {
|
||||||
|
return this._metrics.delete(String(metric))
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._metrics.size
|
||||||
|
this._metrics.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_mergeBuckets (local, remote) {
|
_mergeBuckets (local, remote) {
|
||||||
if (!remote || !remote.counts) return
|
if (!remote || !remote.counts) return
|
||||||
if (remote.min < local.min) local.min = remote.min
|
if (remote.min < local.min) local.min = remote.min
|
||||||
|
|||||||
@@ -134,6 +134,13 @@ class HyperP2PGossipMesh extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearSeen () {
|
||||||
|
const n = this._seen.size
|
||||||
|
this._seen.clear()
|
||||||
|
this._seenAt.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
publishBatch (messages, opts = {}) {
|
publishBatch (messages, opts = {}) {
|
||||||
if (!Array.isArray(messages)) throw new Error('messages array required')
|
if (!Array.isArray(messages)) throw new Error('messages array required')
|
||||||
return messages.map((msg) => this.publish(msg, opts))
|
return messages.map((msg) => this.publish(msg, opts))
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ class HyperP2PStreamChunker extends EventEmitter {
|
|||||||
return this._stats.chunks
|
return this._stats.chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drainAll () {
|
||||||
|
const tail = this.flush()
|
||||||
|
const out = this.reassemble()
|
||||||
|
this.reset()
|
||||||
|
return { tail, data: out }
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return {
|
return {
|
||||||
...this._stats,
|
...this._stats,
|
||||||
|
|||||||
@@ -95,6 +95,14 @@ class HyperP2PStreamResumeToken extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset () {
|
||||||
|
this._chunks = []
|
||||||
|
this._offset = 0
|
||||||
|
this._tokens.clear()
|
||||||
|
this._stats.bytes = 0
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return {
|
return {
|
||||||
...this._stats,
|
...this._stats,
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ class HyperP2PStreamTransform extends EventEmitter {
|
|||||||
return this._out.length
|
return this._out.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearPending () {
|
||||||
|
const n = this._out.length
|
||||||
|
this._out = []
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return { ...this._stats, pending: this._out.length, protocol: PROTOCOL }
|
return { ...this._stats, pending: this._out.length, protocol: PROTOCOL }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,22 @@ class HyperP2PAnycastSelector extends EventEmitter {
|
|||||||
return best
|
return best
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unregisterCapability (tag, peerId = null) {
|
||||||
|
if (!tag) throw new Error('tag required')
|
||||||
|
const pid = peerId || this.peerId
|
||||||
|
const s = this._tags.get(tag)
|
||||||
|
if (!s) return false
|
||||||
|
const ok = s.delete(pid)
|
||||||
|
if (s.size === 0) this._tags.delete(tag)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
clearLatencies () {
|
||||||
|
const n = this._latency.size
|
||||||
|
this._latency.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return { ...this._stats, tags: this._tags.size, latencyPeers: this._latency.size, protocol: PROTOCOL }
|
return { ...this._stats, tags: this._tags.size, latencyPeers: this._latency.size, protocol: PROTOCOL }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,21 @@ class HyperP2PBandwidthBroker extends EventEmitter {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerIds () {
|
||||||
|
return [...this._balances.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPeer (peerId) {
|
||||||
|
if (!peerId) throw new Error('peerId required')
|
||||||
|
return this._balances.delete(peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
clearBalances () {
|
||||||
|
const n = this._balances.size
|
||||||
|
this._balances.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return { ...this._stats, peers: this._balances.size, protocol: PROTOCOL }
|
return { ...this._stats, peers: this._balances.size, protocol: PROTOCOL }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,16 @@ class HyperP2PCongestionSignal extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throttledPeers () {
|
||||||
|
return this.listPeerIds().filter((id) => this.shouldThrottle(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._samples.size
|
||||||
|
this._samples.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return { ...this._stats, peers: this._samples.size, protocol: PROTOCOL }
|
return { ...this._stats, peers: this._samples.size, protocol: PROTOCOL }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,24 @@ class HyperP2POverlayTopology extends EventEmitter {
|
|||||||
|
|
||||||
neighborCount () { return this._neighbors.size }
|
neighborCount () { return this._neighbors.size }
|
||||||
|
|
||||||
|
neighborIds () {
|
||||||
|
return [...this._neighbors.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._neighbors.size
|
||||||
|
this._neighbors.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
lightestNeighbor () {
|
||||||
|
let best = null
|
||||||
|
for (const n of this._neighbors.values()) {
|
||||||
|
if (!best || n.weight < best.weight) best = n
|
||||||
|
}
|
||||||
|
return best
|
||||||
|
}
|
||||||
|
|
||||||
suggestReplacement (failedPeer) {
|
suggestReplacement (failedPeer) {
|
||||||
if (!failedPeer) throw new Error('failedPeer required')
|
if (!failedPeer) throw new Error('failedPeer required')
|
||||||
let best = null
|
let best = null
|
||||||
|
|||||||
@@ -40,6 +40,23 @@ class HyperP2PLogGossip extends EventEmitter {
|
|||||||
return this._logs.slice(-limit)
|
return this._logs.slice(-limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear () {
|
||||||
|
const n = this._logs.length
|
||||||
|
this._logs = []
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
filterByLevel (level, limit = 50) {
|
||||||
|
const idx = this._levelIndex(level)
|
||||||
|
return this._logs.filter((e) => this._levelIndex(e.level) >= idx).slice(-limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
countByLevel () {
|
||||||
|
const out = {}
|
||||||
|
for (const e of this._logs) out[e.level] = (out[e.level] || 0) + 1
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (data) {
|
_onGossip (data) {
|
||||||
if (!data || data.type !== 'log' || !data.entry) return
|
if (!data || data.type !== 'log' || !data.entry) return
|
||||||
this._stats.gossipIn++
|
this._stats.gossipIn++
|
||||||
|
|||||||
@@ -110,6 +110,18 @@ class HyperPearPreflightSync extends EventEmitter {
|
|||||||
return [...this._jobs.values()].reduce((s, j) => s + (j.bytes || 0), 0)
|
return [...this._jobs.values()].reduce((s, j) => s + (j.bytes || 0), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelAll () {
|
||||||
|
let n = 0
|
||||||
|
for (const job of this.listPending()) {
|
||||||
|
if (this.cancel(job.id)) n++
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
jobIds () {
|
||||||
|
return [...this._jobs.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return platformStats(this._stats, PROTOCOL, {
|
return platformStats(this._stats, PROTOCOL, {
|
||||||
jobs: this._jobs.size,
|
jobs: this._jobs.size,
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ class HyperPearUpdateGossip extends EventEmitter {
|
|||||||
return () => this._subs.delete(fn)
|
return () => this._subs.delete(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsubscribeAll () {
|
||||||
|
const n = this._subs.size
|
||||||
|
this._subs.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_notify (update) {
|
_notify (update) {
|
||||||
for (const fn of this._subs) {
|
for (const fn of this._subs) {
|
||||||
try { fn(update) } catch (_) { /* ignore */ }
|
try { fn(update) } catch (_) { /* ignore */ }
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ class HyperP2PStickySession extends EventEmitter {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._bindings.size
|
||||||
|
this._bindings.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
_onGossip (d) {
|
_onGossip (d) {
|
||||||
if (!d || d.type !== 'sticky-session-sync' || !d.sessionId) return
|
if (!d || d.type !== 'sticky-session-sync' || !d.sessionId) return
|
||||||
this._stats.gossipIn++
|
this._stats.gossipIn++
|
||||||
|
|||||||
@@ -71,6 +71,20 @@ class HyperP2PBeeTombstoneGc extends EventEmitter {
|
|||||||
return this.gcSweep(olderThanMs).length
|
return this.gcSweep(olderThanMs).length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._tombstones.size
|
||||||
|
this._tombstones.clear()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
oldestTombstone () {
|
||||||
|
let oldest = null
|
||||||
|
for (const entry of this._tombstones.values()) {
|
||||||
|
if (!oldest || entry.at < oldest.at) oldest = entry
|
||||||
|
}
|
||||||
|
return oldest
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return beeStats(this._stats, PROTOCOL, { pending: this._tombstones.size })
|
return beeStats(this._stats, PROTOCOL, { pending: this._tombstones.size })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,17 @@ class HyperP2PCoreForkPicker extends EventEmitter {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forkIds () {
|
||||||
|
return [...this._forks.keys()]
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAll () {
|
||||||
|
const n = this._forks.size
|
||||||
|
this._forks.clear()
|
||||||
|
this._chosen = null
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
getStats () {
|
getStats () {
|
||||||
return coreStats(this._stats, PROTOCOL, {
|
return coreStats(this._stats, PROTOCOL, {
|
||||||
forkCount: this._forks.size,
|
forkCount: this._forks.size,
|
||||||
|
|||||||
Reference in New Issue
Block a user