Skip to content

Commit 855bec9

Browse files
authored
feat: add server.clean method (#830)
Like `factory.clean`, `server.clean` shuts down any running Kubo nodes created by the server and removes references to them.
1 parent b424960 commit 855bec9

File tree

5 files changed

+95
-23
lines changed

5 files changed

+95
-23
lines changed

src/endpoint/routes.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ const badRequest = (err: Error & { stdout?: string }): void => {
2626
throw boom.badRequest(msg)
2727
}
2828

29-
const nodes: Record<string, Node> = {}
30-
31-
export default (server: Server, createFactory: () => Factory | Promise<Factory>): void => {
29+
export default (server: Server, ipfsd: Factory, nodes: Record<string, Node>): void => {
3230
/**
3331
* Spawn a controller
3432
*/
@@ -38,7 +36,6 @@ export default (server: Server, createFactory: () => Factory | Promise<Factory>)
3836
handler: async (request) => {
3937
const options: any = request.payload ?? {}
4038
try {
41-
const ipfsd = await createFactory()
4239
const id = nanoid()
4340
nodes[id] = await ipfsd.spawn({
4441
...options,

src/endpoint/server.ts

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import Hapi from '@hapi/hapi'
22
import routes from './routes.js'
3-
import type { Factory } from '../index.js'
4-
5-
interface CreateFactory {
6-
(): Factory
7-
}
3+
import type { Node, Factory } from '../index.js'
84

95
export interface ServerInit {
106
port?: number
@@ -19,14 +15,16 @@ class Server {
1915
private server: Hapi.Server | null
2016
public port: number
2117
public host: string
22-
private readonly createFactory: CreateFactory
18+
private readonly ipfsd: Factory
19+
public readonly nodes: Record<string, Node>
2320

24-
constructor (options: ServerInit = { port: 43134, host: 'localhost' }, createFactory: CreateFactory) {
21+
constructor (options: ServerInit = { port: 43134, host: 'localhost' }, factory: Factory) {
2522
this.options = options
2623
this.server = null
2724
this.port = this.options.port ?? 43134
2825
this.host = this.options.host ?? 'localhost'
29-
this.createFactory = createFactory
26+
this.ipfsd = factory
27+
this.nodes = {}
3028
}
3129

3230
/**
@@ -42,7 +40,7 @@ class Server {
4240
}
4341
})
4442

45-
routes(this.server, this.createFactory)
43+
routes(this.server, this.ipfsd, this.nodes)
4644

4745
await this.server.start()
4846

@@ -56,6 +54,21 @@ class Server {
5654
if (this.server != null) {
5755
await this.server.stop(options)
5856
}
57+
58+
await this.clean()
59+
}
60+
61+
/**
62+
* Stop any nodes created by this server
63+
*/
64+
async clean (): Promise<void> {
65+
await this.ipfsd.clean()
66+
67+
// remove references to nodes
68+
for (const key of Object.getOwnPropertyNames(this.nodes)) {
69+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
70+
delete this.nodes[key]
71+
}
5972
}
6073
}
6174

src/index.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,5 @@ export const createServer = (options?: number | { port: number }, factoryOptions
286286
return new Server({
287287
port,
288288
host: '127.0.0.1'
289-
}, () => {
290-
return createFactory(factoryOptions, factoryOverrides)
291-
})
289+
}, createFactory(factoryOptions, factoryOverrides))
292290
}

test/create.spec.ts

+66
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,70 @@ describe('`createServer`', () => {
172172
})
173173
await node.stop()
174174
})
175+
176+
it('should clean server', async () => {
177+
if (!isNode && !isElectronMain) {
178+
return
179+
}
180+
181+
server = createServer(33333, {
182+
type: 'kubo',
183+
test: true,
184+
disposable: false,
185+
rpc: createKuboRPCClient,
186+
bin: isNode ? kubo.path() : undefined
187+
})
188+
await server.start()
189+
190+
const factory = createFactory({
191+
endpoint: `http://127.0.0.1:${server.port}`
192+
})
193+
194+
const node = await factory.spawn({
195+
type: 'kubo',
196+
remote: true,
197+
rpc: createKuboRPCClient
198+
})
199+
200+
await expect(node.api.isOnline()).to.eventually.be.true()
201+
expect(Object.keys(server.nodes)).to.have.lengthOf(1)
202+
203+
await server.clean()
204+
205+
await expect(node.api.isOnline()).to.eventually.be.false()
206+
expect(Object.keys(server.nodes)).to.have.lengthOf(0)
207+
})
208+
209+
it('should clean server on stop', async () => {
210+
if (!isNode && !isElectronMain) {
211+
return
212+
}
213+
214+
server = createServer(44444, {
215+
type: 'kubo',
216+
test: true,
217+
disposable: false,
218+
rpc: createKuboRPCClient,
219+
bin: isNode ? kubo.path() : undefined
220+
})
221+
await server.start()
222+
223+
const factory = createFactory({
224+
endpoint: `http://127.0.0.1:${server.port}`
225+
})
226+
227+
const node = await factory.spawn({
228+
type: 'kubo',
229+
remote: true,
230+
rpc: createKuboRPCClient
231+
})
232+
233+
await expect(node.api.isOnline()).to.eventually.be.true()
234+
expect(Object.keys(server.nodes)).to.have.lengthOf(1)
235+
236+
await server.stop()
237+
238+
await expect(node.api.isOnline()).to.eventually.be.false()
239+
expect(Object.keys(server.nodes)).to.have.lengthOf(0)
240+
})
175241
})

test/endpoint/routes.node.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ describe('routes', function () {
1717

1818
before(async () => {
1919
server = new Hapi.Server({ port: 43134 })
20-
routes(server, async () => {
21-
return createFactory({
22-
type: 'kubo',
23-
rpc: createKuboRPCClient,
24-
bin: isNode ? kubo.path() : undefined
25-
})
26-
})
20+
routes(server, createFactory({
21+
type: 'kubo',
22+
rpc: createKuboRPCClient,
23+
bin: isNode ? kubo.path() : undefined
24+
}), {})
2725
})
2826

2927
after(async () => {

0 commit comments

Comments
 (0)