@typed-assistant/builder 0.0.88 → 0.0.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @typed-assistant/builder
2
2
 
3
+ ## 0.0.89
4
+
5
+ ### Patch Changes
6
+
7
+ - More robust restarting of app when process error occurs.
8
+
3
9
  ## 0.0.88
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typed-assistant/builder",
3
- "version": "0.0.88",
3
+ "version": "0.0.89",
4
4
  "exports": {
5
5
  "./appProcess": "./src/appProcess.tsx",
6
6
  "./bunInstall": "./src/bunInstall.tsx",
@@ -30,8 +30,8 @@
30
30
  "typescript": "^5.4.0",
31
31
  "@typed-assistant/eslint-config": "0.0.10",
32
32
  "@typed-assistant/logger": "0.0.22",
33
- "@typed-assistant/utils": "0.0.19",
34
- "@typed-assistant/typescript-config": "0.0.11"
33
+ "@typed-assistant/typescript-config": "0.0.11",
34
+ "@typed-assistant/utils": "0.0.19"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public",
@@ -47,16 +47,20 @@ export async function setup({
47
47
  },
48
48
  onProcessError: async (message) => {
49
49
  const messageAll = `${message}. Restarting app...`
50
- logger.fatal({ emoji: "🚨" }, messageAll)
50
+ logger.fatal({ emoji: "🚨" }, messageAll)
51
51
  onProcessError?.(messageAll, addonUrl)
52
- subprocesses = await killAndRestartApp(
52
+ if (subprocesses.app) await killSubprocess(subprocesses.app)
53
+ if (watcher) watcher.close()
54
+ if (processChecker) processChecker.stop()
55
+ if ("stop" in gitPoller) gitPoller.stop()
56
+ setup({
53
57
  entryFile,
54
- { mdiPaths },
55
- subprocesses,
56
- )
58
+ mdiPaths,
59
+ onProcessError,
60
+ })
57
61
  },
58
62
  })
59
- setupWatcher({
63
+ const watcher = setupWatcher({
60
64
  directoryToWatch,
61
65
  entryFile,
62
66
  mdiPaths,
@@ -66,7 +70,7 @@ export async function setup({
66
70
  getSubprocesses: () => subprocesses,
67
71
  })
68
72
 
69
- checkProcesses(entryFile, {
73
+ const processChecker = checkProcesses(entryFile, {
70
74
  onMultiProcessError: (ps) => {
71
75
  const message = `Multiple processes detected. Restarting addon...`
72
76
  logger.fatal({ additionalDetails: ps, emoji: "🚨" }, message)
@@ -84,7 +88,8 @@ export async function setup({
84
88
  )
85
89
  },
86
90
  })
87
- await setupGitSync({
91
+
92
+ const gitPoller = await setupGitSync({
88
93
  onChangesPulled: async () => {
89
94
  subprocesses = await killAndRestartApp(
90
95
  entryFile,
@@ -133,7 +138,7 @@ async function killAndRestartApp(
133
138
 
134
139
  let multipleProcessesErrorCount = 0
135
140
  let noProcessesErrorCount = 0
136
- const checkProcesses = async (
141
+ const checkProcesses = (
137
142
  entryFile: string,
138
143
  {
139
144
  onMultiProcessError,
@@ -143,33 +148,33 @@ const checkProcesses = async (
143
148
  onNoProcessError?: (psOutput: string) => void | Promise<void>
144
149
  },
145
150
  ) => {
146
- const ps = await $`ps -f`.text()
147
- const matches = ps.match(new RegExp(`bun .+${entryFile}`, "gmi")) ?? []
151
+ const interval = setInterval(async () => {
152
+ const ps = await $`ps -f`.text()
153
+ logger.debug({ emoji: "🔍" }, `Checking processes...\n${ps}`)
154
+ const matches = ps.match(new RegExp(`bun .+${entryFile}`, "gmi")) ?? []
148
155
 
149
- if (matches.length > 1) {
150
- multipleProcessesErrorCount++
151
- if (multipleProcessesErrorCount > 5) {
152
- await onMultiProcessError?.(ps)
153
- return
156
+ if (matches.length > 1) {
157
+ multipleProcessesErrorCount++
158
+ if (multipleProcessesErrorCount > 5) {
159
+ await onMultiProcessError?.(ps)
160
+ return
161
+ }
162
+ } else {
163
+ multipleProcessesErrorCount = 0
154
164
  }
155
- } else {
156
- multipleProcessesErrorCount = 0
157
- }
158
165
 
159
- if (matches.length === 0) {
160
- noProcessesErrorCount++
161
- if (noProcessesErrorCount > 5) {
162
- await onNoProcessError?.(ps)
163
- return
166
+ if (matches.length === 0) {
167
+ noProcessesErrorCount++
168
+ if (noProcessesErrorCount > 5) {
169
+ await onNoProcessError?.(ps)
170
+ return
171
+ }
172
+ } else {
173
+ noProcessesErrorCount = 0
164
174
  }
165
- } else {
166
- noProcessesErrorCount = 0
167
- }
175
+ }, 10000)
168
176
 
169
- setTimeout(
170
- () => checkProcesses(entryFile, { onMultiProcessError, onNoProcessError }),
171
- 5000,
172
- )
177
+ return { stop: () => clearInterval(interval) }
173
178
  }
174
179
 
175
180
  const getAddonInfo = async () => {
@@ -200,7 +205,7 @@ const setupGitSync = async ({
200
205
  }
201
206
 
202
207
  logger.warn({ emoji: "⬇️" }, "Setting up git poller...")
203
- await setupGitPoller({ onChangesPulled })
208
+ return setupGitPoller({ onChangesPulled })
204
209
  }
205
210
 
206
211
  const ig = ignore().add(
@@ -11,13 +11,14 @@ export const setupGitPoller = async ({
11
11
  onChangesPulled: () => void
12
12
  }) => {
13
13
  const duration = gitPullPollDuration ?? 30
14
- await pullChanges({ onChangesPulled })
15
- logger.debug(
16
- { emoji: "⬇️⏳" },
17
- `Pulling changes again in ${duration} seconds...`,
18
- )
19
14
 
20
- setTimeout(() => {
21
- setupGitPoller({ gitPullPollDuration, onChangesPulled })
15
+ const interval = setInterval(async () => {
16
+ await pullChanges({ onChangesPulled })
17
+ logger.debug(
18
+ { emoji: "⬇️⏳" },
19
+ `Pulling changes again in ${duration} seconds...`,
20
+ )
22
21
  }, duration * ONE_SECOND)
22
+
23
+ return { stop: () => clearInterval(interval) }
23
24
  }
@@ -346,8 +346,7 @@ export const startWebappServer = async ({
346
346
  await server.stop()
347
347
  })
348
348
 
349
- let emptyStringCount = 0
350
- let outputStreamsEmptyCount = 0
349
+ let fatalErrorMessage = ""
351
350
 
352
351
  // eslint-disable-next-line no-constant-condition
353
352
  while (true) {
@@ -367,21 +366,8 @@ export const startWebappServer = async ({
367
366
  stdoutResult.done &&
368
367
  (stderrResult.done || stderrResult.value === undefined)
369
368
  if (streamEnded) {
370
- logger.warn(
371
- {
372
- emoji: "😴",
373
- additionalDetails: JSON.stringify({ exitCode: app.exitCode }),
374
- },
375
- "Subprocess output streams ended; waiting for restart or new output",
376
- )
377
- await new Promise((resolve) => setTimeout(resolve, 1000))
378
- outputStreamsEmptyCount += 1
379
- const outputStreamsEmptyMessage = "Process output streams have ended"
380
- if (outputStreamsEmptyCount === 10) {
381
- onProcessError(outputStreamsEmptyMessage)
382
- break
383
- }
384
- continue
369
+ fatalErrorMessage = "Subprocess output streams ended"
370
+ break
385
371
  }
386
372
 
387
373
  const chunk = stdoutResult.value ?? stderrResult.value
@@ -389,37 +375,22 @@ export const startWebappServer = async ({
389
375
  const convertedMessage = convert.toHtml(decodedString)
390
376
  if (convertedMessage !== "") {
391
377
  lastMessage = convertedMessage
378
+ subscribers.forEach((send) => send(convertedMessage))
379
+ } else {
380
+ fatalErrorMessage = "Process is returning an empty string"
381
+ break
392
382
  }
393
- if (convertedMessage === "") {
394
- emptyStringCount += 1
395
- const emptyStringMessage = "Process is returning an empty string"
396
- if (emptyStringCount === 10) {
397
- onProcessError(emptyStringMessage)
398
- break
399
- }
400
- subscribers.forEach((send) =>
401
- send(
402
- "Process is returning an empty string. This was the last non-empty message:\n\n" +
403
- lastMessage,
404
- ),
405
- )
406
- logger.fatal(
407
- {
408
- emoji: "💀",
409
- additionalDetails: JSON.stringify({
410
- exitCode: getSubprocesses().app.exitCode,
411
- }),
412
- },
413
- emptyStringMessage,
414
- )
415
- await new Promise((resolve) => setTimeout(resolve, 1000))
416
- continue
417
- }
418
- emptyStringCount = 0
419
- subscribers.forEach((send) => send(convertedMessage))
420
383
  }
421
384
 
422
- return server
385
+ subscribers.forEach((send) =>
386
+ send(
387
+ "Fatal error occured. This was the last non-empty message:\n\n" +
388
+ lastMessage,
389
+ ),
390
+ )
391
+
392
+ logger.warn({ emoji: "💀" }, fatalErrorMessage)
393
+ onProcessError(fatalErrorMessage)
423
394
  }
424
395
 
425
396
  export type WebServer = Awaited<ReturnType<typeof startWebappServer>>