@typed-assistant/builder 0.0.82 → 0.0.84

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,17 @@
1
1
  # @typed-assistant/builder
2
2
 
3
+ ## 0.0.84
4
+
5
+ ### Patch Changes
6
+
7
+ - Improve logging for random crashes.
8
+
9
+ ## 0.0.83
10
+
11
+ ### Patch Changes
12
+
13
+ - Undo last fix.
14
+
3
15
  ## 0.0.82
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typed-assistant/builder",
3
- "version": "0.0.82",
3
+ "version": "0.0.84",
4
4
  "exports": {
5
5
  "./appProcess": "./src/appProcess.tsx",
6
6
  "./bunInstall": "./src/bunInstall.tsx",
@@ -28,10 +28,10 @@
28
28
  "eslint-plugin-html": "^7.1.0",
29
29
  "ts-toolbelt": "^9.6.0",
30
30
  "typescript": "^5.4.0",
31
+ "@typed-assistant/eslint-config": "0.0.10",
31
32
  "@typed-assistant/logger": "0.0.22",
32
- "@typed-assistant/typescript-config": "0.0.10",
33
- "@typed-assistant/utils": "0.0.19",
34
- "@typed-assistant/eslint-config": "0.0.10"
33
+ "@typed-assistant/typescript-config": "0.0.11",
34
+ "@typed-assistant/utils": "0.0.19"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public",
@@ -45,13 +45,7 @@ const getReader = (
45
45
  ) => {
46
46
  const cachedReader = readers[type].get(stream)
47
47
  if (!cachedReader) {
48
- readers[type].forEach((reader, cachedStream) => {
49
- // Properly release the lock before deleting
50
- try {
51
- reader.releaseLock()
52
- } catch (e) {
53
- // Ignore if already released
54
- }
48
+ readers[type].forEach((_reader, cachedStream) => {
55
49
  readers[type].delete(cachedStream)
56
50
  })
57
51
  }
@@ -71,8 +65,6 @@ let stats = {
71
65
  memory_percent: null as number | null,
72
66
  max_memory_usage: 0,
73
67
  }
74
- let statsInterval: ReturnType<typeof setInterval> | null = null
75
-
76
68
  const getStats = async () => {
77
69
  const { data, error } = await withErrorHandling(
78
70
  getSupervisorAPI<{
@@ -101,6 +93,8 @@ const getStats = async () => {
101
93
  : stats.max_memory_usage,
102
94
  }
103
95
  }
96
+
97
+ setTimeout(getStats, 10 * ONE_SECOND)
104
98
  }
105
99
 
106
100
  export const startWebappServer = async ({
@@ -239,7 +233,14 @@ export const startWebappServer = async ({
239
233
  }),
240
234
 
241
235
  async open(ws) {
242
- // Set the log subscriber first to avoid race conditions
236
+ ws.send(
237
+ await getLogsFromFile({
238
+ filter: ws.data.query.filter,
239
+ level: ws.data.query.level,
240
+ limit: ws.data.query.limit,
241
+ offset: ws.data.query.offset,
242
+ }),
243
+ )
243
244
  logSubscribers.set(ws.id, async () => {
244
245
  ws.send(
245
246
  await getLogsFromFile({
@@ -250,15 +251,6 @@ export const startWebappServer = async ({
250
251
  }),
251
252
  )
252
253
  })
253
- // Then send the initial logs
254
- ws.send(
255
- await getLogsFromFile({
256
- filter: ws.data.query.filter,
257
- level: ws.data.query.level,
258
- limit: ws.data.query.limit,
259
- offset: ws.data.query.offset,
260
- }),
261
- )
262
254
  },
263
255
  close(ws) {
264
256
  logSubscribers.delete(ws.id)
@@ -345,49 +337,44 @@ export const startWebappServer = async ({
345
337
 
346
338
  watchLogFileSize()
347
339
 
348
- // Start stats polling interval
349
- statsInterval = setInterval(getStats, 10 * 1000)
340
+ getStats()
350
341
 
351
342
  addKillListener(async () => {
352
343
  watcher.close()
353
344
  await server.stop()
354
- // Clean up all websocket subscribers
355
- subscribers.clear()
356
- logSubscribers.clear()
357
- // Release and clear all readers
358
- for (const reader of readers.stdout.values()) {
359
- try {
360
- reader.releaseLock()
361
- } catch (e) {
362
- /* ignore */
363
- }
364
- }
365
- for (const reader of readers.stderr.values()) {
366
- try {
367
- reader.releaseLock()
368
- } catch (e) {
369
- /* ignore */
370
- }
371
- }
372
- readers.stdout.clear()
373
- readers.stderr.clear()
374
- // Clear stats polling interval
375
- if (statsInterval) clearInterval(statsInterval)
376
345
  })
377
346
 
378
347
  // eslint-disable-next-line no-constant-condition
379
348
  while (true) {
380
- getSubprocesses().app.exitCode
381
- const stdoutReader = getReader("stdout", getSubprocesses().app.stdout)
382
- const stderrReader = getReader("stderr", getSubprocesses().app.stderr)
383
- const { value } = await stdoutReader.read()
384
- const { value: stderrValue } = value
385
- ? { value: undefined }
386
- : await stderrReader.read()
387
-
388
- const decodedString = stderrValue
389
- ? decoder.decode(stderrValue)
390
- : decoder.decode(value)
349
+ const app = getSubprocesses().app
350
+ const stdoutReader = getReader("stdout", app.stdout)
351
+ const stderrReader = getReader("stderr", app.stderr)
352
+ const stdoutResult = await stdoutReader.read()
353
+ const stderrResult =
354
+ stdoutResult.value === undefined
355
+ ? await stderrReader.read()
356
+ : ({
357
+ value: undefined,
358
+ done: true,
359
+ } satisfies ReadableStreamDefaultReadDoneResult)
360
+
361
+ const streamEnded =
362
+ stdoutResult.done &&
363
+ (stderrResult.done || stderrResult.value === undefined)
364
+ if (streamEnded) {
365
+ logger.warn(
366
+ {
367
+ emoji: "😴",
368
+ additionalDetails: JSON.stringify({ exitCode: app.exitCode }),
369
+ },
370
+ "Subprocess output streams ended; waiting for restart or new output",
371
+ )
372
+ await new Promise((resolve) => setTimeout(resolve, 1000))
373
+ continue
374
+ }
375
+
376
+ const chunk = stdoutResult.value ?? stderrResult.value
377
+ const decodedString = chunk ? decoder.decode(chunk) : ""
391
378
  const convertedMessage = convert.toHtml(decodedString)
392
379
  if (convertedMessage !== "") {
393
380
  lastMessage = convertedMessage
@@ -404,14 +391,12 @@ export const startWebappServer = async ({
404
391
  emoji: "💀",
405
392
  additionalDetails: JSON.stringify({
406
393
  exitCode: getSubprocesses().app.exitCode,
407
- stderrValue,
408
- stderrValueDecoded: decodedString,
409
394
  }),
410
395
  },
411
- "Process is returning an empty string. Restarting app...",
396
+ "Process is returning an empty string",
412
397
  )
413
- onRestartAppRequest()
414
- break
398
+ await new Promise((resolve) => setTimeout(resolve, 1000))
399
+ continue
415
400
  }
416
401
  subscribers.forEach((send) => send(convertedMessage))
417
402
  }