Skip to content
This repository has been archived by the owner on Jul 21, 2023. It is now read-only.

Commit

Permalink
fix!: remove @libp2p/components (#146)
Browse files Browse the repository at this point in the history
`@libp2p/components` is a choke-point for our dependency graph as it depends on every interface, meaning when one interface revs a major `@libp2p/components` major has to change too which means every module depending on it also needs a major.

Switch instead to constructor injection of simple objects that let modules declare their dependencies on interfaces directly instead of indirectly via `@libp2p/components`

Refs libp2p/js-libp2p-components#6

BREAKING CHANGE: modules no longer implement `Initializable` instead switching to constructor injection
  • Loading branch information
achingbrain committed Oct 12, 2022
1 parent 4c3160d commit 36d68fc
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 155 deletions.
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@
"release": "aegir release"
},
"dependencies": {
"@libp2p/components": "^3.0.0",
"@libp2p/interface-peer-discovery": "^1.0.1",
"@libp2p/interface-peer-id": "^1.0.4",
"@libp2p/interface-peer-info": "^1.0.3",
Expand All @@ -144,11 +143,11 @@
"@multiformats/multiaddr": "^11.0.0",
"@types/multicast-dns": "^7.2.1",
"multicast-dns": "^7.2.0",
"multiformats": "^9.6.3"
"multiformats": "^10.0.0"
},
"devDependencies": {
"@libp2p/interface-address-manager": "^1.0.3",
"@libp2p/interface-peer-discovery-compliance-tests": "^1.0.2",
"@libp2p/interface-address-manager": "^2.0.0",
"@libp2p/interface-peer-discovery-compliance-tests": "^2.0.0",
"@libp2p/peer-id-factory": "^1.0.18",
"aegir": "^37.5.3",
"delay": "^5.0.0",
Expand Down
15 changes: 5 additions & 10 deletions src/compat/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events'
import { Responder } from './responder.js'
import { Querier } from './querier.js'
import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery'
import type { Components, Initializable } from '@libp2p/components'
import { symbol } from '@libp2p/interface-peer-discovery'
import type { MulticastDNSComponents } from '../index.js'

export interface GoMulticastDNSInit {
queryPeriod?: number
queryInterval?: number
}

export class GoMulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Initializable {
export class GoMulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
private _started: boolean
private readonly _responder: Responder
private readonly _querier: Querier

constructor (options: GoMulticastDNSInit = {}) {
constructor (components: MulticastDNSComponents, options: GoMulticastDNSInit = {}) {
super()
const { queryPeriod, queryInterval } = options

this._started = false

this._responder = new Responder()
this._querier = new Querier({
this._responder = new Responder(components)
this._querier = new Querier(components, {
queryInterval,
queryPeriod
})
Expand All @@ -41,11 +41,6 @@ export class GoMulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements
return '@libp2p/go-mdns'
}

init (components: Components): void {
this._responder.init(components)
this._querier.init(components)
}

isStarted () {
return this._started
}
Expand Down
20 changes: 11 additions & 9 deletions src/compat/querier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { SERVICE_TAG_LOCAL, MULTICAST_IP, MULTICAST_PORT } from './constants.js'
import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery'
import type { ResponsePacket } from 'multicast-dns'
import type { RemoteInfo } from 'dgram'
import { Components, Initializable } from '@libp2p/components'
import { findPeerInfoInAnswers } from './utils.js'
import { symbol } from '@libp2p/interface-peer-discovery'
import type { Startable } from '@libp2p/interfaces/dist/src/startable.js'
import type { PeerId } from '@libp2p/interface-peer-id'

const log = logger('libp2p:mdns:compat:querier')

Expand All @@ -16,20 +17,25 @@ export interface QuerierInit {
queryPeriod?: number
}

export interface QuerierComponents {
peerId: PeerId
}

export interface Handle {
stop: () => Promise<void>
}

export class Querier extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Initializable {
export class Querier extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Startable {
private readonly _init: Required<QuerierInit>
private _handle?: Handle
private components: Components = new Components()
private readonly components: QuerierComponents

constructor (init: QuerierInit = {}) {
constructor (components: QuerierComponents, init: QuerierInit = {}) {
super()

const { queryInterval, queryPeriod } = init

this.components = components
this._init = {
// Re-query in leu of network change detection (every 60s by default)
queryInterval: queryInterval ?? 60000,
Expand All @@ -51,10 +57,6 @@ export class Querier extends EventEmitter<PeerDiscoveryEvents> implements PeerDi
return '@libp2p/go-mdns-querier'
}

init (components: Components): void {
this.components = components
}

isStarted () {
return Boolean(this._handle)
}
Expand Down Expand Up @@ -95,7 +97,7 @@ export class Querier extends EventEmitter<PeerDiscoveryEvents> implements PeerDi
log.trace('received mDNS query response')
const answers = event.answers ?? []

const peerInfo = findPeerInfoInAnswers(answers, this.components.getPeerId())
const peerInfo = findPeerInfoInAnswers(answers, this.components.peerId)

if (peerInfo == null) {
log('could not read peer data from query response')
Expand Down
19 changes: 8 additions & 11 deletions src/compat/responder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ import { SERVICE_TAG_LOCAL } from './constants.js'
import { MultiaddrObject, protocols } from '@multiformats/multiaddr'
import type { RemoteInfo } from 'dgram'
import type { Answer } from 'dns-packet'
import { Components, Initializable } from '@libp2p/components'
import type { MulticastDNSComponents } from '../index.js'

const log = logger('libp2p:mdns:compat:responder')

export class Responder implements Initializable {
private components: Components = new Components()
export class Responder {
private readonly components: MulticastDNSComponents
private _mdns?: MDNS.MulticastDNS

constructor () {
this._onQuery = this._onQuery.bind(this)
}

init (components: Components): void {
constructor (components: MulticastDNSComponents) {
this.components = components
this._onQuery = this._onQuery.bind(this)
}

start () {
Expand All @@ -27,7 +24,7 @@ export class Responder implements Initializable {
}

_onQuery (event: QueryPacket, info: RemoteInfo) {
const addresses = this.components.getAddressManager().getAddresses().reduce<MultiaddrObject[]>((acc, addr) => {
const addresses = this.components.addressManager.getAddresses().reduce<MultiaddrObject[]>((acc, addr) => {
addr = addr.decapsulateCode(protocols('p2p').code)

if (addr.isThinWaistAddress()) {
Expand All @@ -51,7 +48,7 @@ export class Responder implements Initializable {
log.trace('got query', event, info)

const answers: Answer[] = []
const peerServiceTagLocal = `${this.components.getPeerId().toString()}.${SERVICE_TAG_LOCAL}`
const peerServiceTagLocal = `${this.components.peerId.toString()}.${SERVICE_TAG_LOCAL}`

answers.push({
name: SERVICE_TAG_LOCAL,
Expand All @@ -66,7 +63,7 @@ export class Responder implements Initializable {
type: 'TXT',
class: 'IN',
ttl: 120,
data: [Buffer.from(this.components.getPeerId().toString())]
data: [Buffer.from(this.components.peerId.toString())]
})

addresses.forEach(ma => {
Expand Down
47 changes: 26 additions & 21 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import * as query from './query.js'
import { GoMulticastDNS } from './compat/index.js'
import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery'
import type { PeerInfo } from '@libp2p/interface-peer-info'
import { Components, Initializable } from '@libp2p/components'
import { symbol } from '@libp2p/interface-peer-discovery'
import type { PeerId } from '@libp2p/interface-peer-id'
import type { AddressManager } from '@libp2p/interface-address-manager'

const log = logger('libp2p:mdns')

export interface MulticastDNSOptions {
export interface MulticastDNSInit {
broadcast?: boolean
interval?: number
serviceTag?: string
Expand All @@ -20,7 +21,12 @@ export interface MulticastDNSOptions {
compatQueryInterval?: number
}

export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Initializable {
export interface MulticastDNSComponents {
peerId: PeerId
addressManager: AddressManager
}

class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
public mdns?: multicastDNS.MulticastDNS

private readonly broadcast: boolean
Expand All @@ -29,24 +35,25 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
private readonly port: number
private _queryInterval: ReturnType<typeof setInterval> | null
private readonly _goMdns?: GoMulticastDNS
private components: Components = new Components()
private readonly components: MulticastDNSComponents

constructor (options: MulticastDNSOptions = {}) {
constructor (components: MulticastDNSComponents, init: MulticastDNSInit = {}) {
super()

this.broadcast = options.broadcast !== false
this.interval = options.interval ?? (1e3 * 10)
this.serviceTag = options.serviceTag ?? 'ipfs.local'
this.port = options.port ?? 5353
this.components = components
this.broadcast = init.broadcast !== false
this.interval = init.interval ?? (1e3 * 10)
this.serviceTag = init.serviceTag ?? 'ipfs.local'
this.port = init.port ?? 5353
this._queryInterval = null
this._onPeer = this._onPeer.bind(this)
this._onMdnsQuery = this._onMdnsQuery.bind(this)
this._onMdnsResponse = this._onMdnsResponse.bind(this)

if (options.compat !== false) {
this._goMdns = new GoMulticastDNS({
queryPeriod: options.compatQueryPeriod,
queryInterval: options.compatQueryInterval
if (init.compat !== false) {
this._goMdns = new GoMulticastDNS(components, {
queryPeriod: init.compatQueryPeriod,
queryInterval: init.compatQueryInterval
})
this._goMdns.addEventListener('peer', this._onPeer)
}
Expand All @@ -60,12 +67,6 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
return '@libp2p/mdns'
}

init (components: Components): void {
this.components = components

this._goMdns?.init(components)
}

isStarted () {
return Boolean(this.mdns)
}
Expand Down Expand Up @@ -97,14 +98,14 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
}

log.trace('received incoming mDNS query')
query.gotQuery(event, this.mdns, this.components.getPeerId(), this.components.getAddressManager().getAddresses(), this.serviceTag, this.broadcast)
query.gotQuery(event, this.mdns, this.components.peerId, this.components.addressManager.getAddresses(), this.serviceTag, this.broadcast)
}

_onMdnsResponse (event: multicastDNS.ResponsePacket) {
log.trace('received mDNS query response')

try {
const foundPeer = query.gotResponse(event, this.components.getPeerId(), this.serviceTag)
const foundPeer = query.gotResponse(event, this.components.peerId, this.serviceTag)

if (foundPeer != null) {
log('discovered peer in mDNS qeury response %p', foundPeer.id)
Expand Down Expand Up @@ -162,6 +163,10 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
}
}

export function mdns (init: MulticastDNSInit = {}): (components: MulticastDNSComponents) => PeerDiscovery {
return (components: MulticastDNSComponents) => new MulticastDNS(components, init)
}

/* for reference
[ { name: 'discovery.ipfs.io.local',
Expand Down
14 changes: 6 additions & 8 deletions test/compat/go-multicast-dns.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { multiaddr } from '@multiformats/multiaddr'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import pDefer from 'p-defer'
import { GoMulticastDNS } from '../../src/compat/index.js'
import { Components } from '@libp2p/components'
import { stubInterface } from 'ts-sinon'
import type { AddressManager } from '@libp2p/interface-address-manager'
import type { PeerInfo } from '@libp2p/interface-peer-info'
Expand All @@ -19,13 +18,12 @@ async function createGoMulticastDNS () {
multiaddr(`/ip4/127.0.0.1/tcp/${port++}/p2p/${peerId.toString()}`)
])

const components = new Components({
const components = {
peerId,
addressManager
})
}

const mdns = new GoMulticastDNS()
mdns.init(components)
const mdns = new GoMulticastDNS(components)

return {
mdns,
Expand Down Expand Up @@ -64,7 +62,7 @@ describe('GoMulticastDNS', () => {
mdnsA.addEventListener('peer', (evt) => {
const { id } = evt.detail

if (!componentsB.getPeerId().equals(id)) {
if (!componentsB.peerId.equals(id)) {
return
}

Expand All @@ -82,7 +80,7 @@ describe('GoMulticastDNS', () => {
mdnsB.stop()
])

expect(peerData.id.equals(componentsB.getPeerId())).to.be.true()
expect(peerData.multiaddrs.map(ma => ma.toString())).includes(componentsB.getAddressManager().getAddresses()[1].toString())
expect(peerData.id.equals(componentsB.peerId)).to.be.true()
expect(peerData.multiaddrs.map(ma => ma.toString())).includes(componentsB.addressManager.getAddresses()[1].toString())
})
})
13 changes: 4 additions & 9 deletions test/compat/querier.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { SERVICE_TAG_LOCAL } from '../../src/compat/constants.js'
import type { PeerId } from '@libp2p/interface-peer-id'
import type { RemoteInfo } from 'dgram'
import type { Answer } from 'dns-packet'
import { Components } from '@libp2p/components'

describe('Querier', () => {
let querier: Querier
Expand All @@ -35,16 +34,14 @@ describe('Querier', () => {
})

it('should start and stop', async () => {
querier = new Querier()
querier.init(new Components({ peerId: peerIds[0] }))
querier = new Querier({ peerId: peerIds[0] })

await querier.start()
await querier.stop()
})

it('should query on interval', async () => {
querier = new Querier({ queryPeriod: 0, queryInterval: 10 })
querier.init(new Components({ peerId: peerIds[0] }))
querier = new Querier({ peerId: peerIds[0] }, { queryPeriod: 0, queryInterval: 10 })

mdns = MDNS()

Expand Down Expand Up @@ -246,8 +243,7 @@ describe('Querier', () => {
* @param {Function} getResponse - Given a query, construct a response to test the querier
*/
async function ensurePeer (getResponse: (event: QueryPacket, info: RemoteInfo) => Answer[]) {
const querier = new Querier()
querier.init(new Components({ peerId: peerIds[0] }))
const querier = new Querier({ peerId: peerIds[0] })
mdns = MDNS()

mdns.on('query', (event, info) => {
Expand Down Expand Up @@ -283,8 +279,7 @@ describe('Querier', () => {
* @param {Function} getResponse - Given a query, construct a response to test the querier
*/
async function ensureNoPeer (getResponse: (event: QueryPacket, info: RemoteInfo) => Answer[]) {
const querier = new Querier()
querier.init(new Components({ peerId: peerIds[0] }))
const querier = new Querier({ peerId: peerIds[0] })
mdns = MDNS()

mdns.on('query', (event, info) => {
Expand Down
Loading

0 comments on commit 36d68fc

Please sign in to comment.