Skip to content

Commit

Permalink
fix: add status property (#2269)
Browse files Browse the repository at this point in the history
To tell if the node has been started or not.
  • Loading branch information
achingbrain committed Nov 30, 2023
1 parent 06e6d23 commit a32e70b
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 11 deletions.
10 changes: 10 additions & 0 deletions packages/interface/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ export interface PendingDial {
multiaddrs: Multiaddr[]
}

export type Libp2pStatus = 'starting' | 'started' | 'stopping' | 'stopped'

/**
* Libp2p nodes implement this interface.
*/
Expand Down Expand Up @@ -410,8 +412,16 @@ export interface Libp2p<T extends ServiceMap = ServiceMap> extends Startable, Ty
*/
metrics?: Metrics

/**
* The logger used by this libp2p node
*/
logger: ComponentLogger

/**
* The current status of the libp2p node
*/
status: Libp2pStatus

/**
* Get a deduplicated list of peer advertising multiaddrs by concatenating
* the listen addresses used by transports with any configured
Expand Down
21 changes: 10 additions & 11 deletions packages/libp2p/src/libp2p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { DefaultUpgrader } from './upgrader.js'
import * as pkg from './version.js'
import type { Components } from './components.js'
import type { Libp2p, Libp2pInit, Libp2pOptions } from './index.js'
import type { PeerRouting, ContentRouting, Libp2pEvents, PendingDial, ServiceMap, AbortOptions, ComponentLogger, Logger, Connection, NewStreamOptions, Stream, Metrics, PeerId, PeerInfo, PeerStore, Topology } from '@libp2p/interface'
import type { PeerRouting, ContentRouting, Libp2pEvents, PendingDial, ServiceMap, AbortOptions, ComponentLogger, Logger, Connection, NewStreamOptions, Stream, Metrics, PeerId, PeerInfo, PeerStore, Topology, Libp2pStatus } from '@libp2p/interface'
import type { StreamHandler, StreamHandlerOptions } from '@libp2p/interface-internal'

export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends TypedEventEmitter<Libp2pEvents> implements Libp2p<T> {
Expand All @@ -34,14 +34,16 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
public metrics?: Metrics
public services: T
public logger: ComponentLogger
public status: Libp2pStatus

public components: Components
#started: boolean
private readonly log: Logger

constructor (init: Libp2pInit<T>) {
super()

this.status = 'stopped'

// event bus - components can listen to this emitter to be notified of system events
// and also cause them to be emitted
const events = new TypedEventEmitter<Libp2pEvents>()
Expand All @@ -58,7 +60,6 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
// This emitter gets listened to a lot
setMaxListeners(Infinity, events)

this.#started = false
this.peerId = init.peerId
this.logger = init.logger ?? defaultLogger()
this.log = this.logger.forComponent('libp2p')
Expand Down Expand Up @@ -196,11 +197,11 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
* Starts the libp2p node and all its subsystems
*/
async start (): Promise<void> {
if (this.#started) {
if (this.status !== 'stopped') {
return
}

this.#started = true
this.status = 'starting'

this.log('libp2p is starting')

Expand All @@ -209,6 +210,7 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
await this.components.start()
await this.components.afterStart?.()

this.status = 'started'
this.safeDispatchEvent('start', { detail: this })
this.log('libp2p has started')
} catch (err: any) {
Expand All @@ -222,26 +224,23 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
* Stop the libp2p node by closing its listeners and open connections
*/
async stop (): Promise<void> {
if (!this.#started) {
if (this.status !== 'started') {
return
}

this.log('libp2p is stopping')

this.#started = false
this.status = 'stopping'

await this.components.beforeStop?.()
await this.components.stop()
await this.components.afterStop?.()

this.status = 'stopped'
this.safeDispatchEvent('stop', { detail: this })
this.log('libp2p has stopped')
}

isStarted (): boolean {
return this.#started
}

getConnections (peerId?: PeerId): Connection[] {
return this.components.connectionManager.getConnections(peerId)
}
Expand Down
49 changes: 49 additions & 0 deletions packages/libp2p/test/core/status.node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-env mocha */

import { plaintext } from '@libp2p/plaintext'
import { tcp } from '@libp2p/tcp'
import { expect } from 'aegir/chai'
import { createLibp2pNode, type Libp2pNode } from '../../src/libp2p.js'

const listenAddr = '/ip4/0.0.0.0/tcp/0'

describe('status', () => {
let libp2p: Libp2pNode

after(async () => {
await libp2p.stop()
})

it('should have status', async () => {
libp2p = await createLibp2pNode({
start: false,
addresses: {
listen: [listenAddr]
},
transports: [
tcp()
],
connectionEncryption: [
plaintext()
]
})

expect(libp2p).to.have.property('status', 'stopped')

const startP = libp2p.start()

expect(libp2p).to.have.property('status', 'starting')

await startP

expect(libp2p).to.have.property('status', 'started')

const stopP = libp2p.stop()

expect(libp2p).to.have.property('status', 'stopping')

await stopP

expect(libp2p).to.have.property('status', 'stopped')
})
})

0 comments on commit a32e70b

Please sign in to comment.