Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,10 +470,14 @@ Emitted when the core has been appended to (i.e. has a new length / byteLength),

Emitted when the core has been truncated, either locally or remotely.

#### `core.on('peer-add')`
#### `core.on('peer-add', peer)`

Emitted when a new connection has been established with a peer.

#### `core.on('peer-remove')`
#### `core.on('peer-update', peer)`

Emitted when a peer updates its properties like `peer.remoteContiguousLength`.

#### `core.on('peer-remove', peer)`

Emitted when a peer's connection has been closed.
7 changes: 7 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ module.exports = class Hypercore extends EventEmitter {
eagerUpgrade: true,
allowFork: opts.allowFork !== false,
onpeerupdate: this._onpeerupdate.bind(this),
onpeerchange: this._onpeerchange.bind(this),
onupload: this._onupload.bind(this)
})

Expand Down Expand Up @@ -732,6 +733,12 @@ module.exports = class Hypercore extends EventEmitter {
}
}

_onpeerchange (peer) {
for (let i = 0; i < this.sessions.length; i++) {
this.sessions[i].emit('peer-update', peer)
}
}

async setUserData (key, value, { flush = false } = {}) {
if (this.opened === false) await this.opening
return this.core.userData(key, value, flush)
Expand Down
6 changes: 5 additions & 1 deletion lib/replicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ class Peer {
onbitfield ({ start, bitfield }) {
if (this.remoteBitfield.insert(start, bitfield)) {
this.skipList.setRange(start, bitfield.byteLength * 8, false)
this.replicator.onpeerchange(this)
this._update()
}
}
Expand All @@ -729,13 +730,15 @@ class Peer {
if (length === 1) {
this.remoteBitfield.setRange(start, length, has)
this.skipList.set(start, false)
this.replicator.onpeerchange(this)
} else {
const rangeStart = this.remoteBitfield.findFirst(!has, start)
const rangeLength = length - (rangeStart - start)

if (rangeLength > 0) {
this.remoteBitfield.setRange(rangeStart, rangeLength, has)
this.skipList.setRange(rangeStart, rangeLength, false)
this.replicator.onpeerchange(this)
}
}

Expand Down Expand Up @@ -1081,13 +1084,14 @@ class Peer {
}

module.exports = class Replicator {
constructor (core, key, { eagerUpgrade = true, allowFork = true, onpeerupdate = noop, onupload = noop } = {}) {
constructor (core, key, { eagerUpgrade = true, allowFork = true, onpeerupdate = noop, onpeerchange = noop, onupload = noop } = {}) {
this.key = key
this.discoveryKey = core.crypto.discoveryKey(key)
this.core = core
this.eagerUpgrade = eagerUpgrade
this.allowFork = allowFork
this.onpeerupdate = onpeerupdate
this.onpeerchange = onpeerchange
this.onupload = onupload
this.ondownloading = null // optional external hook for monitoring downloading status
this.peers = []
Expand Down
19 changes: 19 additions & 0 deletions test/remote-length.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,25 @@ test('peer truncates the remote contiguous length', async function (t) {
t.is(getPeer(a, b).remoteContiguousLength, 1)
})

test('peer-update event is emitted when remote contiguous length changes', async function (t) {
t.plan(2)

const a = await create()
const b = await create(a.key)

replicate(a, b, t)

await a.append('a')

b.download()

t.is(getPeer(a, b).remoteContiguousLength, 0)

a.once('peer-update', function (peer) {
t.is(getPeer(a, b).remoteContiguousLength, 1)
})
})

// "A" wants to know if "B" is finished syncing, so find the corresponding peer
function getPeer (a, b) {
return a.replicator.peers.find(peer => b4a.equals(peer.remotePublicKey, b.replicator.peers[0].stream.publicKey))
Expand Down