Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); perf(test): keep one deterministic WAL race in the default suite by jackwener · Pull Request #2459 · apache/maka · GitHub
Skip to content

perf(test): keep one deterministic WAL race in the default suite - #2459

Merged
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress
Aug 7, 2026
Merged

perf(test): keep one deterministic WAL race in the default suite#2459
jackwener merged 1 commit into
mainfrom
perf/storage-wal-race-stress

Conversation

@jackwener

Copy link
Copy Markdown
Member

Refs #2388(第三条:Twelve repeated fresh-WAL race rounds in the default suite)。按 issue 要求,stress 策略单独成 PR,fixture 缩减不在本 PR。

改了什么

allows concurrent operational owners to initialize the same fresh WAL database 原本把两进程竞争跑 12 轮,每轮起一对 worker + 建删临时目录。

一轮就已经把契约断言完了:两个 owner 竞争初始化同一个全新库,都成功,且结果是当前 schema 版本的 WAL 库。重复不会让这个断言更强——它是在重摇调度器、指望撞上更罕见的交错,那是压力覆盖,有价值,但不该由每一次普通运行来买单。

多出来的 11 轮移到 MAKA_STORAGE_STRESS=1 后面——这是仓库里既有的 stress 闸门root-authority.test.tsgit-workspace-service.test.ts 已在用),所以是一条统一的 stress 路线,不是每个文件一个新开关。

耗时(本机,node --test dist/__tests__/sqlite-recovery-concurrency.test.js

该用例整个文件
默认(改后)139ms1.67s
默认(改前)1686ms3.22s
MAKA_STORAGE_STRESS=11665ms(12 轮照跑)3.18s

两条路线都实跑验证过:默认 12 passed / 0 failed,stress 路线同样 12 passed / 0 failed。

顺带一条调查结论(不在本 PR 改,供 issue 参考)

issue 第一条 Repeated writes to reach a capacity limit 我核过了——指的应该是 rejects an expansion atomically before the complete boundary exceeds capacity(全套最慢的单个用例,4201ms)。它的放大是契约强制的,不是多余的

  • 单请求条目上限 MAX_SANDBOX_BOUNDARY_FILESYSTEM_ENTRIES = 32
  • 单条路径上限 MAX_SANDBOX_BOUNDARY_PATH_CHARS = 4096
  • 单请求序列化上限 MAX_SANDBOX_BOUNDARY_SERIALIZED_BYTES = 64 KiB
  • 累计边界上限 MAX_EXECUTION_BOUNDARY_SERIALIZED_BYTES = 1 MiB

1 MiB ÷ 64 KiB = 至少 16 轮才能触到共享上限,而现有 fixture(32 条 × 1800 字符 ≈ 60 KiB/请求)已经贴着单请求上限了。我试过「两个大请求」的写法,分别被 32 条上限和 64 KiB 上限挡回来。要真正缩短它,只能给 store 加一个测试专用的可注入上限——那是往生产代码里开测试后门,我认为不值得,除非你们判断相反。

验证

  • storage:747 passed / 1 failed,唯一失败是既有的 top-level package import does not initialize node:sqlite(Node v25 的 node:sqlite ExperimentalWarning,与本改动无关)。
  • typecheck / lint / format 全绿。

`allows concurrent operational owners to initialize the same fresh WAL
database` ran its two-process race twelve times, each round spawning a pair of
workers and creating and removing a temp directory. That is 1686ms of a 3.22s
file for an assertion one round already makes: two owners racing to initialize
the same fresh database both succeed, and the result is a WAL database at the
current schema version.
Repetition does not strengthen that claim. It re-rolls the scheduler hoping to
catch a rarer interleaving, which is stress coverage — valuable, but not
something every ordinary run should pay for. The extra rounds move behind
`MAKA_STORAGE_STRESS=1`, the same gate the other multi-process storage probes
already use, so there is one stress route rather than a flag per file.
Timing on this machine, `node --test dist/__tests__/sqlite-recovery-concurrency.test.js`:
default 1686ms -> 139ms for the test, 3.22s -> 1.67s for the file
stress=1 unchanged at 1665ms / 3.18s, still twelve rounds
Refs #2388.
@jackwener

Copy link
Copy Markdown
MemberAuthor

Review by maka-审美专家 — 通过:WAL 竞态重摇 12 轮按 stress/contract 覆盖之分收进既有 MAKA_STORAGE_STRESS 闸门(一条 stress 路线而非每文件一面旗),常规运行 1686ms→139ms,stress 路线原样保留。GitHub #2388 另一半(容量上限重复写入)经核实为契约强制(64KiB 单请求 vs 1MiB 累计=至少 16 轮),拒绝以生产代码测试后门迎合 issue 的错误前提——判断正确并已留证。CI 全绿。合入。

@jackwener
jackwener merged commit 96a879f into mainAug 7, 2026
11 checks passed
Astro-Han pushed a commit that referenced this pull request Aug 9, 2026
…nges (#2474)
* ci(test): auto-enable storage stress rounds for WAL recovery race changes
Refs #2388.
#2459 gated the 12-round fresh-WAL race amplification behind
MAKA_STORAGE_STRESS, but sqlite-recovery-concurrency.test.ts was not in
STORAGE_STRESS_FILES, so CI never re-enabled the amplified rounds even when
the recovery race surface itself changed. Add the test, its spawned worker
fixture, and sqlite-runtime-store.ts (the store the race exercises) to the
stress set, matching how the other multi-process storage probes are wired.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): cover the WAL race's production owners and pin the stress routing
Review follow-up: the amplified race path runs through
acquireOperationalStateDatabase(), so operational-state-store.ts and
sqlite-runtime-schema.ts own the fresh-WAL initialization, locking, and
migration it exercises. Add both to STORAGE_STRESS_FILES, and extend the
planner test's stress table with all five WAL-race paths so the routing
contract stays executable.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
* ci(test): trigger storage stress on every migration the WAL race executes
Review follow-up: acquireOperationalStateDatabase() runs the migrations
owned by the six sqlite-*-schema modules inside the amplified fresh-WAL
race, so all six join STORAGE_STRESS_FILES and the planner's stress table.
sqlite-runtime-store.ts leaves the set - the amplified operational_open_only
branch never constructs it - and a negative planner case pins that boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ac5rv6WUKWtMZgQb5QPN16
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jackwener