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 (#386)
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 authored Oct 12, 2022
1 parent a5555d1 commit abe5207
Show file tree
Hide file tree
Showing 35 changed files with 442 additions and 440 deletions.
22 changes: 10 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,17 @@ The libp2p-kad-dht module offers 3 APIs: Peer Routing, Content Routing and Peer
### Custom secondary DHT in libp2p

```js
import { create } from '@libp2p/kad-dht'
import { createLibp2pNode } from 'libp2p'
import { kadDht } from '@libp2p/kad-dht'

const node = await createLibp2pNode({
dht: kadDht()
//... other config
})
await node.start()

/**
* @param {Libp2p} libp2p
*/
async function addDHT(libp2p) {
const customDHT = create({
libp2p,
protocolPrefix: '/custom'
})
await customDHT.start()

return customDHT
for await (const event of node.dht.findPeer(node.peerId)) {
console.info(event)
}
```

Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@
"release": "aegir release"
},
"dependencies": {
"@libp2p/components": "^3.0.0",
"@libp2p/crypto": "^1.0.4",
"@libp2p/interface-address-manager": "^2.0.0",
"@libp2p/interface-connection": "^3.0.2",
"@libp2p/interface-connection-manager": "^1.1.1",
"@libp2p/interface-dht": "^1.0.1",
"@libp2p/interface-metrics": "^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 Down Expand Up @@ -173,20 +173,20 @@
"it-stream-types": "^1.0.4",
"it-take": "^1.0.2",
"k-bucket": "^5.1.0",
"multiformats": "^9.6.3",
"multiformats": "^10.0.0",
"p-defer": "^4.0.0",
"p-queue": "^7.2.0",
"private-ip": "^2.3.3",
"protons-runtime": "^3.1.0",
"protons-runtime": "^4.0.1",
"timeout-abort-controller": "^3.0.0",
"uint8arraylist": "^2.0.0",
"uint8arrays": "^3.0.0",
"uint8arrays": "^4.0.2",
"varint": "^6.0.0"
},
"devDependencies": {
"@libp2p/interface-mocks": "^6.0.0",
"@libp2p/interface-mocks": "^7.0.1",
"@libp2p/peer-id-factory": "^1.0.18",
"@libp2p/peer-store": "^4.0.0",
"@libp2p/peer-store": "^5.0.0",
"@types/lodash.random": "^3.2.6",
"@types/lodash.range": "^3.2.6",
"@types/varint": "^6.0.0",
Expand All @@ -202,7 +202,7 @@
"lodash.range": "^3.2.0",
"p-retry": "^5.0.0",
"p-wait-for": "^5.0.0",
"protons": "^5.1.0",
"protons": "^6.0.0",
"sinon": "^14.0.0",
"ts-sinon": "^2.0.2",
"which": "^2.0.2"
Expand Down
26 changes: 12 additions & 14 deletions src/content-fetching/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type { Network } from '../network.js'
import type { Logger } from '@libp2p/logger'
import type { AbortOptions } from '@libp2p/interfaces'
import type { QueryFunc } from '../query/types.js'
import { Components, Initializable } from '@libp2p/components'
import type { KadDHTComponents } from '../index.js'

export interface ContentFetchingInit {
validators: Validators
Expand All @@ -36,18 +36,20 @@ export interface ContentFetchingInit {
lan: boolean
}

export class ContentFetching implements Initializable {
export class ContentFetching {
private readonly log: Logger
private components: Components = new Components()
private readonly components: KadDHTComponents
private readonly validators: Validators
private readonly selectors: Selectors
private readonly peerRouting: PeerRouting
private readonly queryManager: QueryManager
private readonly routingTable: RoutingTable
private readonly network: Network

constructor (init: ContentFetchingInit) {
constructor (components: KadDHTComponents, init: ContentFetchingInit) {
const { validators, selectors, peerRouting, queryManager, routingTable, network, lan } = init

this.components = components
this.log = logger(`libp2p:kad-dht:${lan ? 'lan' : 'wan'}:content-fetching`)
this.validators = validators
this.selectors = selectors
Expand All @@ -57,13 +59,9 @@ export class ContentFetching implements Initializable {
this.network = network
}

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

async putLocal (key: Uint8Array, rec: Uint8Array) { // eslint-disable-line require-await
const dsKey = bufferToRecordKey(key)
await this.components.getDatastore().put(dsKey, rec)
await this.components.datastore.put(dsKey, rec)
}

/**
Expand All @@ -77,7 +75,7 @@ export class ContentFetching implements Initializable {

this.log('fetching record for key %k', dsKey)

const raw = await this.components.getDatastore().get(dsKey)
const raw = await this.components.datastore.get(dsKey)
this.log('found %k in local datastore', dsKey)

const rec = Libp2pRecord.deserialize(raw)
Expand All @@ -102,11 +100,11 @@ export class ContentFetching implements Initializable {
}

// correct ourself
if (this.components.getPeerId().equals(from)) {
if (this.components.peerId.equals(from)) {
try {
const dsKey = bufferToRecordKey(key)
this.log(`Storing corrected record for key ${dsKey.toString()}`)
await this.components.getDatastore().put(dsKey, fixupRec.subarray())
await this.components.datastore.put(dsKey, fixupRec.subarray())
} catch (err: any) {
this.log.error('Failed error correcting self', err)
}
Expand Down Expand Up @@ -147,7 +145,7 @@ export class ContentFetching implements Initializable {
// store the record locally
const dsKey = bufferToRecordKey(key)
this.log(`storing record for key ${dsKey.toString()}`)
await this.components.getDatastore().put(dsKey, record.subarray())
await this.components.datastore.put(dsKey, record.subarray())

// put record to the closest peers
yield * pipe(
Expand Down Expand Up @@ -246,7 +244,7 @@ export class ContentFetching implements Initializable {

yield valueEvent({
value: localRec.value,
from: this.components.getPeerId()
from: this.components.peerId
})
} catch (err: any) {
this.log('error getting local value for %b', key, err)
Expand Down
23 changes: 10 additions & 13 deletions src/content-routing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type { CID } from 'multiformats/cid'
import type { AbortOptions } from '@libp2p/interfaces'
import type { Multiaddr } from '@multiformats/multiaddr'
import type { PeerInfo } from '@libp2p/interface-peer-info'
import { Components, Initializable } from '@libp2p/components'
import type { KadDHTComponents } from '../index.js'

export interface ContentRoutingInit {
network: Network
Expand All @@ -33,18 +33,19 @@ export interface ContentRoutingInit {
lan: boolean
}

export class ContentRouting implements Initializable {
export class ContentRouting {
private readonly log: Logger
private components: Components = new Components()
private readonly components: KadDHTComponents
private readonly network: Network
private readonly peerRouting: PeerRouting
private readonly queryManager: QueryManager
private readonly routingTable: RoutingTable
private readonly providers: Providers

constructor (init: ContentRoutingInit) {
constructor (components: KadDHTComponents, init: ContentRoutingInit) {
const { network, peerRouting, queryManager, routingTable, providers, lan } = init

this.components = components
this.log = logger(`libp2p:kad-dht:${lan ? 'lan' : 'wan'}:content-routing`)
this.network = network
this.peerRouting = peerRouting
Expand All @@ -53,10 +54,6 @@ export class ContentRouting implements Initializable {
this.providers = providers
}

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

/**
* Announce to the network that we can provide the value for a given key and
* are contactable on the given multiaddrs
Expand All @@ -65,11 +62,11 @@ export class ContentRouting implements Initializable {
this.log('provide %s', key)

// Add peer as provider
await this.providers.addProvider(key, this.components.getPeerId())
await this.providers.addProvider(key, this.components.peerId)

const msg = new Message(MESSAGE_TYPE.ADD_PROVIDER, key.bytes, 0)
msg.providerPeers = [{
id: this.components.getPeerId(),
id: this.components.peerId,
multiaddrs,
protocols: []
}]
Expand Down Expand Up @@ -144,13 +141,13 @@ export class ContentRouting implements Initializable {
for (const peerId of provs.slice(0, toFind)) {
providers.push({
id: peerId,
multiaddrs: ((await this.components.getPeerStore().addressBook.get(peerId)) ?? []).map(address => address.multiaddr),
multiaddrs: ((await this.components.peerStore.addressBook.get(peerId)) ?? []).map(address => address.multiaddr),
protocols: []
})
}

yield peerResponseEvent({ from: this.components.getPeerId(), messageType: MESSAGE_TYPE.GET_PROVIDERS, providers })
yield providerEvent({ from: this.components.getPeerId(), providers: providers })
yield peerResponseEvent({ from: this.components.peerId, messageType: MESSAGE_TYPE.GET_PROVIDERS, providers })
yield providerEvent({ from: this.components.peerId, providers: providers })
}

// All done
Expand Down
21 changes: 8 additions & 13 deletions src/dual-kad-dht.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@ import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events'
import type { CID } from 'multiformats'
import type { PeerId } from '@libp2p/interface-peer-id'
import type { PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery'
import { Components, Initializable } from '@libp2p/components'
import { symbol } from '@libp2p/interface-peer-discovery'
import type { KadDHTComponents } from './index.js'

const log = logger('libp2p:kad-dht')

/**
* A DHT implementation modelled after Kademlia with S/Kademlia modifications.
* Original implementation in go: https://github.com/libp2p/go-libp2p-kad-dht.
*/
export class DualKadDHT extends EventEmitter<PeerDiscoveryEvents> implements DualDHT, Initializable {
public wan: KadDHT
public lan: KadDHT
public components: Components = new Components()
export class DualKadDHT extends EventEmitter<PeerDiscoveryEvents> implements DualDHT {
public readonly wan: KadDHT
public readonly lan: KadDHT
public readonly components: KadDHTComponents

constructor (wan: KadDHT, lan: KadDHT) {
constructor (components: KadDHTComponents, wan: KadDHT, lan: KadDHT) {
super()

this.components = components
this.wan = wan
this.lan = lan

Expand All @@ -50,12 +51,6 @@ export class DualKadDHT extends EventEmitter<PeerDiscoveryEvents> implements Dua
return '@libp2p/dual-kad-dht'
}

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

/**
* Is this DHT running.
*/
Expand Down Expand Up @@ -146,7 +141,7 @@ export class DualKadDHT extends EventEmitter<PeerDiscoveryEvents> implements Dua

if (!foundValue) {
yield queryErrorEvent({
from: this.components.getPeerId(),
from: this.components.peerId,
error: errCode(new Error('Not found'), 'ERR_NOT_FOUND')
})
}
Expand Down
29 changes: 25 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { KadDHT as SingleKadDHT } from './kad-dht.js'
import { DualKadDHT } from './dual-kad-dht.js'
import type { Selectors, Validators } from '@libp2p/interface-dht'
import type { Registrar } from '@libp2p/interface-registrar'
import type { AddressManager } from '@libp2p/interface-address-manager'
import type { PeerStore } from '@libp2p/interface-peer-store'
import type { ConnectionManager } from '@libp2p/interface-connection-manager'
import type { Metrics } from '@libp2p/interface-metrics'
import type { PeerId } from '@libp2p/interface-peer-id'
import type { Datastore } from 'interface-datastore'

export interface KadDHTInit {
/**
Expand Down Expand Up @@ -57,18 +64,32 @@ export interface KadDHTInit {
maxOutboundStreams?: number
}

export class KadDHT extends DualKadDHT {
constructor (init?: KadDHTInit) {
super(new SingleKadDHT({
export interface KadDHTComponents {
peerId: PeerId
registrar: Registrar
addressManager: AddressManager
peerStore: PeerStore
metrics?: Metrics
connectionManager: ConnectionManager
datastore: Datastore
}

class KadDHT extends DualKadDHT {
constructor (components: KadDHTComponents, init?: KadDHTInit) {
super(components, new SingleKadDHT(components, {
protocolPrefix: '/ipfs',
...init,
lan: false
}),
new SingleKadDHT({
new SingleKadDHT(components, {
protocolPrefix: '/ipfs',
...init,
clientMode: false,
lan: true
}))
}
}

export function kadDht (init?: KadDHTInit): (components: KadDHTComponents) => DualKadDHT {
return (components: KadDHTComponents) => new KadDHT(components, init)
}
Loading

0 comments on commit abe5207

Please sign in to comment.