dsh-unlag 1.9.114 → 1.9.115

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 +28 -4
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1710,11 +1710,14 @@ export async function verifyStartupRows(graph, fetchBody, rows, budgetMs = MAX_V
1710
1710
  for (const id of item.ids) if (served.has(id)) listed.add(id)
1711
1711
  for (const id of item.ids) if (!served.has(id)) leftOut.add(id)
1712
1712
  let response = null
1713
- try {
1714
- response = await fetchBody(item.url)
1715
- } catch (error) {
1716
- return { status: 'blocked', reason: 'network', detail: `${item.url}: ${String(error?.message ?? error)}` }
1713
+ const read = await withDeadline(() => fetchBody(item.url), budgetMs - (Date.now() - began))
1714
+ if (read.timedOut === true) {
1715
+ return { status: 'blocked', reason: 'slow', detail: `${item.url} did not answer within the time this check waits` }
1716
+ }
1717
+ if ('error' in read) {
1718
+ return { status: 'blocked', reason: 'network', detail: `${item.url}: ${String(read.error?.message ?? read.error)}` }
1717
1719
  }
1720
+ response = read.value
1718
1721
  // Reading the answer is the same kind of step as fetching it: a response whose status or body
1719
1722
  // cannot be read is one this check cannot approve, and saying which script failed beats
1720
1723
  // abandoning the whole list without a name in the reason.
@@ -1822,6 +1825,27 @@ export async function verifyStartup(clientModules, rows) {
1822
1825
  return verifyStartupRows(graph, (url) => readStartupScript(clientModules, url), rows)
1823
1826
  }
1824
1827
 
1828
+ /** The sentinel a read that ran past its time resolves to: a value, never an error. */
1829
+ const LATE = Symbol('late')
1830
+
1831
+ /**
1832
+ * One read the check will not wait past. The budget is counted between rows already; a single
1833
+ * address that never answers would otherwise hold the press past the moment the page stops waiting
1834
+ * for it, and the page would be told the check timed out with nothing naming what hung. Racing the
1835
+ * read keeps the reason the check's own, and the read itself is left to finish with its bytes
1836
+ * dropped, so nothing is left half-read.
1837
+ */
1838
+ async function withDeadline(work, ms) {
1839
+ let timer = null
1840
+ const late = new Promise((resolve) => {
1841
+ timer = setTimeout(() => resolve(LATE), Math.max(0, ms))
1842
+ })
1843
+ const settled = Promise.resolve().then(work).then((value) => ({ value }), (error) => ({ error }))
1844
+ const answer = await Promise.race([settled, late])
1845
+ if (timer !== null) clearTimeout(timer)
1846
+ return answer === LATE ? { timedOut: true } : answer
1847
+ }
1848
+
1825
1849
  /** What one press is told when the update it waits for did not answer in time. */
1826
1850
  const STILL_APPLYING = Object.freeze({ status: 'applying', warnings: [], pending: [], restartReason: null, failedEntries: [] });
1827
1851
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-unlag",
3
- "version": "1.9.114",
3
+ "version": "1.9.115",
4
4
  "type": "module",
5
5
  "description": "A press applies plugin edits right away and brings a laggy interface back; automatic reloading stays off unless you turn it on, so the press is the only trigger, and nothing restarts.",
6
6
  "license": "MIT",