Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libp2p events #1574

Closed
achingbrain opened this issue Feb 1, 2023 · 5 comments · Fixed by #1693
Closed

libp2p events #1574

achingbrain opened this issue Feb 1, 2023 · 5 comments · Fixed by #1693
Assignees
Labels
exploration kind/enhancement A net-new feature or improvement to an existing feature need/analysis Needs further analysis before proceeding P2 Medium: Good to have, but can wait until someone steps up

Comments

@achingbrain
Copy link
Member

The libp2p object returned from createLibp2p is an EventTarget that emits a few different events.

These events are really useful for observing the inner workings of libp2p without having to tie your code to the internal structure of libp2p.

They also open the door to real-time monitoring of libp2p with better observability and debugging possibilities.

The event list should be expanded to encompass more events. Some (non-exhausive) suggestions:

  • peer:dial - when we dial a peer, the event should hold the peer id and which multiaddrs are being dialled
  • peer:dial:success - the event should hold the peer id and the multiaddr that succeeded
  • peer:dial:error - the event should hold the peer id and the multiaddr that failed and an Error object
  • identify:success - the identify protocol competed for a peer - the event should hold the peer id
  • identify:error - the identify protocol failed for a peer - the event should hold the peer id and an Error object
  • identify:push:success - the identify push protocol competed for a peer - the event should hold the peer id
  • identify:push:error - the identify push protocol failed for a peer - the event should hold the peer id and an Error object
  • connection:prune - we pruned a connection, the event should have the peer id of the connection that was closed
  • connection:upgrade - a connection was upgraded, the event should have the connection that was upgraded
  • ...other things?

It would be good to establish a naming convention for events, the above hasn't had a whole lot of thought applied to it.

@achingbrain achingbrain added need/triage Needs initial labeling and prioritization kind/enhancement A net-new feature or improvement to an existing feature exploration need/analysis Needs further analysis before proceeding and removed need/triage Needs initial labeling and prioritization labels Feb 1, 2023
@maschad
Copy link
Member

maschad commented Feb 2, 2023

Great idea @achingbrain this would be very helpful, I would also add the following to this list:

  • peer:dial:pending when a dial is pending, the event the event should hold the peer id and which multiaddrs are being dialled
  • connection:${status} when a peer's status has changed, the event should have the peer id and the multiaddr and the status.

@wemeetagain can you think of other events that might be useful?

@achingbrain
Copy link
Member Author

We may not need a peer:dial:pending event - it is pending after the peer:dial event and before the peer:dial:success/peer:dial:error events.

@wemeetagain
Copy link
Member

More events would definitely be nice. Would be nice for the success events to include as much relevant data as possible. Eg: have identify:success also emit the Identify object.

As far as being a substitute to access to the underlying implementation, I disagree that it works for all cases.

For example, Lodestar currently inspects the dialer to avoid redialing peers with pending dials. This ensures we dial enough peers with the right properties and don't underdial.

We could track the libp2p dial/dial:success/dial:error events and build our own map of pending dials.
Or we could just use the existing map in the dialer and not do the extra work, maintain the extra code, etc.

For us, the tradeoffs pretty clearly point to us doing something like this:

function isPending(libp2p: Libp2p, peerIdStr: string): boolean {
  return (libp2p as unknown as {dialer: DefaultDialer}).dialer.pendingDials.has(peerIdStr);
}

rather than something like this:

class PendingDialTracker {
  public pendingDials = new Set<string>()
  libp2p: Libp2p
  constructor(libp2p: Libp2p) {
    this.libp2p = libp2p
    this.libp2p.addEventListener('peer:dial', this.onPeerDial)
    this.libp2p.addEventListener('peer:dial:success', this.onPeerDialFinish)
    this.libp2p.addEventListener('peer:dial:error', this.onPeerDialFinish)
  }
  close() {
    this.libp2p.removeEventListener('peer:dial', this.onPeerDial)
    this.libp2p.removeEventListener('peer:dial:success', this.onPeerDialFinish)
    this.libp2p.removeEventListener('peer:dial:error', this.onPeerDialFinish)
  }
  onPeerDial = (peerId: PeerId) => {
    this.pendingDials.add(peerId.toString())
  }
  onPeerDialFinish = (peerId: PeerId) => {
    this.pendingDials.delete(peerId.toString())
  }
}

@p-shahi p-shahi added the P2 Medium: Good to have, but can wait until someone steps up label Feb 7, 2023
@maschad
Copy link
Member

maschad commented Feb 7, 2023

As discussed with @achingbrain we could structure these events as Progress Events which would allow us to create union types that represent a variety of custom events that are emitted from a particular Libp2p process at various stages in it's progress.

We can begin working on this once ipfs/helia-ipns#1 is merged and we see how performant this is.

@achingbrain
Copy link
Member Author

The problem with that particular ProgressEvent is that it's very specific to loading resources via some sort of asynchronous request.

The properties, things like .lengthComputable, .loaded and .total are not generic enough to be relevant to all operations so I don't think it's a natural fit here.

The progress events used by @helia/ipns are usable as union types though, and seem to work well so all good there.

achingbrain added a commit that referenced this issue Apr 16, 2023
Adds an event emitter as a libp2p component that will echo every
emitted event on the main libp2p object.

Fixes #1574
@maschad maschad assigned achingbrain and unassigned maschad Apr 19, 2023
achingbrain added a commit that referenced this issue Apr 25, 2023
Adds an event emitter as a libp2p component that will echo every emitted event on the main libp2p object.

Closes #1574
Fixes  #1630
achingbrain added a commit to libp2p/js-libp2p-kad-dht that referenced this issue May 5, 2023
Send DHT query events to the onProgress callback if one is passed to
allow operation-specific progress events to pass up the stack.

Refs: libp2p/js-libp2p#1574
achingbrain added a commit to libp2p/js-libp2p-kad-dht that referenced this issue May 5, 2023
Send DHT query events to the onProgress callback if one is passed to
allow operation-specific progress events to pass up the stack.

Refs: libp2p/js-libp2p#1574
achingbrain added a commit that referenced this issue Aug 16, 2023
Allow passing an `onProgress` callback to the peer/content routers that can receive DHT query events.

Refs #1574
achingbrain added a commit that referenced this issue Nov 2, 2023
Allow passing an `onProgress` callback to the peer/content routers that can receive DHT query events.

Refs #1574
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exploration kind/enhancement A net-new feature or improvement to an existing feature need/analysis Needs further analysis before proceeding P2 Medium: Good to have, but can wait until someone steps up
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants