Expand economy, autobase, network, observability, and scheduling modules.
Add auction withdraw/cancel, marketplace search helpers, update gossip history, autobase fork/lease/indexer/view APIs, link-probe and circuit-loom utilities, trace trees, pheromone ranking, and scheduling/measurement helpers with tests. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -31,6 +31,14 @@ Public API on `HyperPearUpdateGossip`. See [`index.js`](../index.js) for paramet
|
||||
|
||||
Public API on `HyperPearUpdateGossip`. See [`index.js`](../index.js) for parameters and return types.
|
||||
|
||||
### `isNewerThan(version) → boolean`
|
||||
|
||||
`true` when `latestUpdate().version` is newer than `version` (numeric or string compare).
|
||||
|
||||
### `updateHistory(limit = 10) → object[]`
|
||||
|
||||
Recent published updates (ring buffer, `maxHistory` constructor option, default 32).
|
||||
|
||||
### `getStats() → object`
|
||||
|
||||
Metrics plus `protocol: 'pear-update-gossip/v1'`.
|
||||
|
||||
@@ -11,6 +11,8 @@ class HyperPearUpdateGossip extends EventEmitter {
|
||||
this.topic = opts.topic || null
|
||||
this.keyPair = opts.keyPair || require('hypercore-crypto').keyPair()
|
||||
this._latest = null
|
||||
this._history = []
|
||||
this.maxHistory = opts.maxHistory ?? 32
|
||||
this._subs = new Set()
|
||||
this._stats = { published: 0, gossipIn: 0, gossipOut: 0 }
|
||||
this.swarm = null
|
||||
@@ -23,19 +25,37 @@ class HyperPearUpdateGossip extends EventEmitter {
|
||||
throw new Error('manifest must be an object')
|
||||
}
|
||||
const update = { version, manifest, publishedAt: Date.now() }
|
||||
if (!this._latest || version > this._latest.version) {
|
||||
if (!this._latest || this._isNewer(version, this._latest.version)) {
|
||||
this._latest = update
|
||||
}
|
||||
this._history.push(update)
|
||||
if (this._history.length > this.maxHistory) this._history.shift()
|
||||
this._stats.published++
|
||||
this._gossip({ type: 'update-publish', version, manifest, publishedAt: update.publishedAt })
|
||||
this._notify(update)
|
||||
return update
|
||||
}
|
||||
|
||||
_isNewer (a, b) {
|
||||
const na = Number(a)
|
||||
const nb = Number(b)
|
||||
if (!Number.isNaN(na) && !Number.isNaN(nb)) return na > nb
|
||||
return String(a) > String(b)
|
||||
}
|
||||
|
||||
latestUpdate () {
|
||||
return this._latest ? { ...this._latest } : null
|
||||
}
|
||||
|
||||
isNewerThan (version) {
|
||||
if (!this._latest) return false
|
||||
return this._isNewer(this._latest.version, version)
|
||||
}
|
||||
|
||||
updateHistory (limit = 10) {
|
||||
return this._history.slice(-Math.max(0, limit | 0))
|
||||
}
|
||||
|
||||
subscribe (fn) {
|
||||
if (typeof fn !== 'function') throw new Error('fn must be a function')
|
||||
this._subs.add(fn)
|
||||
@@ -59,12 +79,14 @@ class HyperPearUpdateGossip extends EventEmitter {
|
||||
_onGossip (d) {
|
||||
if (!d || d.type !== 'update-publish' || !d.version) return
|
||||
this._stats.gossipIn++
|
||||
if (!this._latest || d.version > this._latest.version) {
|
||||
if (!this._latest || this._isNewer(d.version, this._latest.version)) {
|
||||
this._latest = {
|
||||
version: d.version,
|
||||
manifest: d.manifest,
|
||||
publishedAt: d.publishedAt || Date.now()
|
||||
}
|
||||
this._history.push(this._latest)
|
||||
if (this._history.length > this.maxHistory) this._history.shift()
|
||||
this._notify(this._latest)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,3 +35,12 @@ test('getStats', async (t) => {
|
||||
t.is(m.getStats().published, 1)
|
||||
await m.close()
|
||||
})
|
||||
|
||||
test('history and isNewer', async (t) => {
|
||||
const m = new HyperPearUpdateGossip()
|
||||
m.publishUpdate('1.0.0', {})
|
||||
m.publishUpdate('2.0.0', {})
|
||||
t.ok(m.isNewerThan('1.5.0'))
|
||||
t.is(m.updateHistory(2).length, 2)
|
||||
await m.close()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user