Skip to content

Commit fe3b4e5

Browse files
committed
refactor: cleanup watcher and child process when something goes wrong
1 parent b8e6dfc commit fe3b4e5

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

src/dev_server.ts

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { EnvLoader, EnvParser } from '@adonisjs/env'
1717
import { run } from './run.js'
1818
import { watch } from './watch.js'
1919
import type { DevServerOptions } from './types.js'
20+
import type { Watcher } from '@poppinss/chokidar-ts'
2021

2122
/**
2223
* Instance of CLIUI
@@ -43,6 +44,9 @@ export class DevServer {
4344
#httpServerProcess?: ExecaChildProcess<string>
4445
#isMetaFileWithReloadsEnabled: picomatch.Matcher
4546
#isMetaFileWithReloadsDisabled: picomatch.Matcher
47+
#watcher?: ReturnType<Watcher['watch']>
48+
#onError?: (error: any) => any
49+
#onClose?: (exitCode: number) => any
4650

4751
/**
4852
* Getting reference to colors library from logger
@@ -136,7 +140,7 @@ export class DevServer {
136140
/**
137141
* Starts the HTTP server
138142
*/
139-
#startHTTPServer(port: string) {
143+
#startHTTPServer(port: string, mode: 'blocking' | 'nonblocking') {
140144
this.#httpServerProcess = run(this.#cwd, {
141145
script: this.#scriptFile,
142146
env: { PORT: port, ...this.#options.env },
@@ -159,15 +163,20 @@ export class DevServer {
159163
}
160164
})
161165

162-
this.#httpServerProcess.on('error', (error) => {
163-
this.#logger.warning('unable to connect to underlying HTTP server process')
164-
this.#logger.fatal(error)
165-
})
166-
167-
this.#httpServerProcess.on('close', (exitCode) => {
168-
this.#logger.warning(`underlying HTTP server closed with status code "${exitCode}"`)
169-
this.#logger.info('watching file system and waiting for application to recover')
170-
})
166+
this.#httpServerProcess
167+
.then((result) => {
168+
this.#logger.warning(`underlying HTTP server closed with status code "${result.exitCode}"`)
169+
if (mode === 'nonblocking') {
170+
this.#onClose?.(result.exitCode)
171+
this.#watcher?.close()
172+
}
173+
})
174+
.catch((error) => {
175+
this.#logger.warning('unable to connect to underlying HTTP server process')
176+
this.#logger.fatal(error)
177+
this.#onError?.(error)
178+
this.#watcher?.close()
179+
})
171180
}
172181

173182
/**
@@ -179,7 +188,7 @@ export class DevServer {
179188
this.#httpServerProcess.kill('SIGKILL')
180189
}
181190

182-
this.#startHTTPServer(port)
191+
this.#startHTTPServer(port, 'blocking')
183192
}
184193

185194
/**
@@ -190,39 +199,67 @@ export class DevServer {
190199
return this
191200
}
192201

202+
/**
203+
* Add listener to get notified when dev server is
204+
* closed
205+
*/
206+
onClose(callback: (exitCode: number) => any): this {
207+
this.#onClose = callback
208+
return this
209+
}
210+
211+
/**
212+
* Add listener to get notified when dev server exists
213+
* with an error
214+
*/
215+
onError(callback: (error: any) => any): this {
216+
this.#onError = callback
217+
return this
218+
}
219+
193220
/**
194221
* Start the development server
195222
*/
196223
async start() {
197224
this.#clearScreen()
198225
this.#logger.info('starting HTTP server...')
199-
this.#startHTTPServer(String(await this.#getPort()))
226+
this.#startHTTPServer(String(await this.#getPort()), 'nonblocking')
200227
}
201228

202229
/**
203230
* Start the development server in watch mode
204231
*/
205232
async startAndWatch(ts: typeof tsStatic, options?: { poll: boolean }) {
206-
const port = String(await this.#getPort())
207-
208233
this.#isWatching = true
209234
this.#clearScreen()
210235

236+
const port = String(await this.#getPort())
237+
211238
this.#logger.info('starting HTTP server...')
212-
this.#startHTTPServer(port)
239+
this.#startHTTPServer(port, 'blocking')
213240

214241
const output = watch(this.#cwd, ts, options || {})
215242
if (!output) {
243+
this.#onClose?.(1)
216244
return
217245
}
218246

247+
this.#watcher = output.chokidar
248+
219249
/**
220250
* Notify the watcher is ready
221251
*/
222252
output.watcher.on('watcher:ready', () => {
223253
this.#logger.info('watching file system for changes...')
224254
})
225255

256+
output.chokidar.on('error', (error) => {
257+
this.#logger.warning('file system watcher failure')
258+
this.#logger.fatal(error)
259+
this.#onError?.(error)
260+
output.chokidar.close()
261+
})
262+
226263
/**
227264
* Changes in TypeScript source file
228265
*/

0 commit comments

Comments
 (0)