dsh-unlag 1.7.9 → 1.7.10

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.
Files changed (2) hide show
  1. package/index.js +21 -1
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -26,6 +26,9 @@ export const name = 'dsh-unlag'
26
26
  */
27
27
  export const inject = ['webServer']
28
28
 
29
+ /** A transaction that has not finished in this long is stuck; the press reports it instead of hanging. */
30
+ const RELOAD_TIMEOUT_MS = 20_000
31
+
29
32
  const LOG_PATH = join(homedir(), '.dsh', 'unlag-reload.log')
30
33
  /** Tests point this at a scratch file, so a test run leaves the live log readable. */
31
34
  const logTarget = () => process.env.DSH_UNLAG_LOG ?? LOG_PATH
@@ -182,10 +185,27 @@ function pluginReloader(ctx, config) {
182
185
  * @returns what the service reported, so the caller can tell done from partly done.
183
186
  */
184
187
  const reload = async (hmr) => {
188
+ /**
189
+ * Queue the recomposition through the service's own queue. A watcher callback created while a
190
+ * reload was restarting this plugin inherits that reload's context, and the service reads any
191
+ * request made from that context as a nested one even though the transaction is over. Leaving
192
+ * that context first is what the service's own watcher does, and it keeps the request queued
193
+ * instead of running a second recomposition beside the first.
194
+ */
195
+ const ask = (service) =>
196
+ typeof service.executing?.exit === 'function'
197
+ ? service.executing.exit(() => service.runExclusive(() => service.reconcileProfile([])))
198
+ : service.runExclusive(() => service.reconcileProfile([]))
199
+ const abandoned = () =>
200
+ new Promise((_resolve, reject) => {
201
+ const limit = Number(process.env.DSH_UNLAG_TIMEOUT_MS ?? '') || RELOAD_TIMEOUT_MS
202
+ const timer = setTimeout(() => reject(new Error('the plugin update did not finish in time')), limit)
203
+ timer.unref?.()
204
+ })
185
205
  let result = null
186
206
  for (let attempt = 0; ; attempt += 1) {
187
207
  try {
188
- result = await hmr.runExclusive(() => hmr.reconcileProfile([]))
208
+ result = await Promise.race([ask(hmr), abandoned()])
189
209
  break
190
210
  } catch (error) {
191
211
  const message = String(error?.message ?? error)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-unlag",
3
- "version": "1.7.9",
3
+ "version": "1.7.10",
4
4
  "type": "module",
5
5
  "description": "One press applies plugin edits right away and brings a laggy interface back; running turns, queued messages and unsent input are untouched, and nothing restarts.",
6
6
  "license": "MIT",