dsh-unlag 1.9.112 → 1.9.114
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/client.js +2 -2
- package/index.js +19 -0
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -15,8 +15,8 @@ window.__ModuleLoader__.load({
|
|
|
15
15
|
* repeating one generic sentence.
|
|
16
16
|
*/
|
|
17
17
|
const REASONS = zh
|
|
18
|
-
? { list: '读不到启动信息', slow: '启动信息读得太慢', row: '启动信息不完整', src: '启动脚本没有地址', graph: '已装插件清单读不到', plugin: '有插件已不在运行', script: '启动脚本读不到', empty: '启动脚本是空的', covers: '启动脚本缺插件', parse: '启动脚本内容不完整', size: '启动脚本太大', verify: '插件后端没有应答', screen: '页面状态读不到' }
|
|
19
|
-
: { list: 'startup info is unavailable', slow: 'the startup list answered too slowly', row: 'startup info is incomplete', src: 'a startup script has no address', graph: 'the plugin list cannot be read', plugin: 'a plugin is no longer running', script: 'a startup script cannot be read', empty: 'a startup script is empty', covers: 'a startup script misses a plugin', parse: 'a startup script is incomplete', size: 'a startup script is too large', verify: 'the plugin is not answering', screen: 'the page state cannot be read' };
|
|
18
|
+
? { list: '读不到启动信息', slow: '启动信息读得太慢', row: '启动信息不完整', src: '启动脚本没有地址', graph: '已装插件清单读不到', plugin: '有插件已不在运行', script: '启动脚本读不到', empty: '启动脚本是空的', covers: '启动脚本缺插件', parse: '启动脚本内容不完整', size: '启动脚本太大', verify: '插件后端没有应答', screen: '页面状态读不到', busy: '另一次刷新还在进行', dependencies: '插件依赖还没有运行', missing: '启动清单里有插件已经不见了', network: '读取插件时出错', register: '插件没有登记自己' }
|
|
19
|
+
: { list: 'startup info is unavailable', slow: 'the startup list answered too slowly', row: 'startup info is incomplete', src: 'a startup script has no address', graph: 'the plugin list cannot be read', plugin: 'a plugin is no longer running', script: 'a startup script cannot be read', empty: 'a startup script is empty', covers: 'a startup script misses a plugin', parse: 'a startup script is incomplete', size: 'a startup script is too large', verify: 'the plugin is not answering', screen: 'the page state cannot be read', busy: 'another rebuild is already running', dependencies: 'a plugin dependency is not running', missing: 'a plugin in the startup list is gone', network: 'the plugins could not be read', register: 'a plugin did not register itself' };
|
|
20
20
|
|
|
21
21
|
/** The last reason a readiness check refused for, or null after a check that passed. */
|
|
22
22
|
let holdReason = null;
|
package/index.js
CHANGED
|
@@ -116,6 +116,8 @@ const MAX_TOTAL_SCRIPT_BYTES = 128 * 1024 * 1024
|
|
|
116
116
|
* app could boot from, and it is answered as such instead of being read.
|
|
117
117
|
*/
|
|
118
118
|
const MAX_LIST_BODY_BYTES = 1024 * 1024
|
|
119
|
+
/** Checks that may read the plugin table at the same time. Each one holds a script at a time. */
|
|
120
|
+
const MAX_CONCURRENT_CHECKS = 3
|
|
119
121
|
/** The body reader's answer for a request past its bound: not JSON, and not an empty list either. */
|
|
120
122
|
const TOO_LARGE = Symbol('too-large')
|
|
121
123
|
|
|
@@ -1872,6 +1874,8 @@ function serveButton(ctx, controller, config) {
|
|
|
1872
1874
|
return null
|
|
1873
1875
|
}
|
|
1874
1876
|
const settings = settingsOf(config)
|
|
1877
|
+
/** One counter for the whole route set: the check is the only body that reads scripts. */
|
|
1878
|
+
let checking = 0
|
|
1875
1879
|
const handlers = [
|
|
1876
1880
|
[
|
|
1877
1881
|
`${BASE_PATH}/state`,
|
|
@@ -1916,6 +1920,18 @@ function serveButton(ctx, controller, config) {
|
|
|
1916
1920
|
const method = String(req?.method ?? 'GET').toUpperCase()
|
|
1917
1921
|
if (method !== 'POST') return sendJson(res, 405, { status: 'method' })
|
|
1918
1922
|
if (buttonAllowed(req) === false) return sendJson(res, 403, { status: 'forbidden' })
|
|
1923
|
+
/**
|
|
1924
|
+
* Each check holds the bytes of one script while it reads them, so a page that asks in a
|
|
1925
|
+
* loop, or several windows asking at once, must not stack those reads without a ceiling: the
|
|
1926
|
+
* app is the process that would run out of memory. Past three the check is refused in its
|
|
1927
|
+
* own words rather than served slowly or not at all.
|
|
1928
|
+
*/
|
|
1929
|
+
if (checking >= MAX_CONCURRENT_CHECKS) {
|
|
1930
|
+
log(`a startup check was refused: ${String(checking)} checks are already reading the plugin table`)
|
|
1931
|
+
return sendJson(res, 200, { status: 'blocked', reason: 'busy', detail: 'another startup check is still running' })
|
|
1932
|
+
}
|
|
1933
|
+
checking += 1
|
|
1934
|
+
try {
|
|
1919
1935
|
const clientModules = ctx.get('clientModules')
|
|
1920
1936
|
if (typeof clientModules?.fetchBundle !== 'function' || typeof clientModules?.graph !== 'function') {
|
|
1921
1937
|
return sendJson(res, 200, { status: 'blocked', reason: 'list', detail: 'the plugin table is not running' })
|
|
@@ -1943,6 +1959,9 @@ function serveButton(ctx, controller, config) {
|
|
|
1943
1959
|
log(`a startup row names a plugin this app no longer serves: ${verdict.leftOut.join(', ')}; the page comes up without it`)
|
|
1944
1960
|
}
|
|
1945
1961
|
sendJson(res, 200, verdict)
|
|
1962
|
+
} finally {
|
|
1963
|
+
checking -= 1
|
|
1964
|
+
}
|
|
1946
1965
|
} catch (error) {
|
|
1947
1966
|
log(`cannot answer ${BASE_PATH}/verify: ${error?.message ?? error}`)
|
|
1948
1967
|
sendJson(res, 500, { status: 'error' })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-unlag",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.114",
|
|
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",
|