docs/superpowers/plans/2026-08-16-async-ps-resultset-heartbeat.md
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Restore the established 256 MiB worker-progress heartbeat while an asynchronous prepared statement converts a very large buffered resultset.
Architecture: Extend the binary prepared-statement row insertion point, MySQL_ResultSet::add_row(MYSQL_ROWS *), with the same resultset-size boundary check already used by init_with_stmt(). The row loop, packet generation, buffer ownership, resultset throttling, and watchdog configuration remain unchanged; only a boundary crossing performs a clock read and heartbeat store.
Tech Stack: C++17, MariaDB Connector/C prepared-statement result structures, ProxySQL MySQL worker watchdog, GitHub Actions ASAN TAP integration tests.
ci/verify-asan-label, the branch for PR 6083.0xFFFFFFF resultset progress boundary used by init_with_stmt().atomic_curtime for every row or packet; update it only when output crosses another 256 MiB boundary.restart_on_missing_heartbeats, loop bounds, resultset suspension thresholds, or MariaDB coroutine-buffer ownership.CI-unit-tests-asan-coverage unchanged.mysql84-binlog-g1 to the agent already handling that known issue.Files:
lib/MySQL_ResultSet.cpp:324-333test/tap/tests/test_ps_large_result-t.cpp:142-245 (existing regression test; no source modification)Interfaces:
Consumes: MySQL_ResultSet::resultset_size, the packet byte count returned by MySQL_Protocol::generate_pkt_row3(), and the owning myds->sess->thread worker pointer.
Produces: one atomic_curtime refresh whenever successfully converted prepared-statement output crosses a 0xFFFFFFF byte boundary.
Step 1: Confirm the existing regression test is red
Inspect the already-recorded failing ASAN job:
gh run view 31945039923 --job 95159626833 --log | rg 'test_ps_large_result-t|Missed heartbeat|assert'
Expected: test_ps_large_result-t starts, the MySQL worker accumulates missed
heartbeats, and ProxySQL aborts before the TAP can fetch all 10,000,000 rows.
This is the required failing end-to-end test; do not weaken or replace it.
In MySQL_ResultSet::add_row(MYSQL_ROWS *rows), after
generate_pkt_row3() returns pkt_length and before incrementing
resultset_size, add:
const unsigned long long next_resultset_size = resultset_size + pkt_length;
if (
resultset_size / 0xFFFFFFF != next_resultset_size / 0xFFFFFFF
&& myds && myds->sess && myds->sess->thread
) {
myds->sess->thread->atomic_curtime = monotonic_time();
}
Replace resultset_size+=pkt_length; with:
resultset_size = next_resultset_size;
Keep packet sequence and row-count updates in their existing order. Do not
modify either loop in lib/mysql_connection.cpp.
Run:
make -B -C lib obj/MySQL_ResultSet.oo WITHASAN=1 NOJEMALLOC=1
Expected: MySQL_ResultSet.cpp compiles successfully with
-fsanitize=address and no new compiler diagnostics.
Run:
git diff --check
git diff -- lib/MySQL_ResultSet.cpp
git status --short
Expected: no whitespace errors; the production diff is limited to the boundary check and existing counter assignment; only the plan and intended source file are tracked changes. The pre-existing untracked artifacts remain untouched.
git add lib/MySQL_ResultSet.cpp
git commit -m "fix: heartbeat during large PS resultsets"
Expected: the commit contains only lib/MySQL_ResultSet.cpp.
Files:
CI-mysql84-g8, including test_ps_large_result-t.Interfaces:
Consumes: the ci:asan label already attached to PR 6083 and the branch commits from Task 1.
Produces: a new label-selected ASAN CI run in which test_ps_large_result-t completes without a watchdog abort.
Step 1: Publish the branch
git push origin ci/verify-asan-label
Expected: PR 6083 advances to the pushed implementation head. Adding or removing labels is not used to trigger the run.
gh pr view 6083 --json url,headRefName,headRefOid,labels
Expected: the head branch is ci/verify-asan-label and the labels include
ci:asan.
gh pr checks 6083 --watch --interval 30
Expected: a new build and fan-out run is associated with the pushed head. Do not retrigger it by changing labels.
Resolve the latest branch run for CI-mysql84-g8 and search its log:
heartbeat_g8_run_id=$(gh run list --workflow CI-mysql84-g8.yml --branch ci/verify-asan-label --limit 1 --json databaseId --jq '.[0].databaseId')
gh run view "$heartbeat_g8_run_id" --log | rg -C 4 'test_ps_large_result-t|Missed heartbeat|Fetched 10000000 rows|Fetched 4GB'
Expected: test_ps_large_result-t reports both Fetched 10000000 rows and
Fetched 4GB, with no watchdog missed-heartbeat termination and no ASAN
finding. If another test fails, classify it separately before making any
additional code change.
Run:
gh pr checks 6083
Expected: report the heartbeat regression independently from known
mysql84-binlog-g1 work and from the AI workflow handoff fix tracked in PR
6097. Do not claim PR 6083 is entirely green unless every required check has
actually passed.