bench(soak): add mysql_cdc to the nightly soak rotation (CON-179 R6) - #4750
bench(soak): add mysql_cdc to the nightly soak rotation (CON-179 R6)#4750prakhargarg105 wants to merge 2 commits into
Conversation
Second connector in the soak rotation, following SOAK.md's recipe: - scenarios/mysql/orders-soak.yaml: the same sustained-moderate profile as the postgres soak (10K writes/sec x 1.2 KB ~= 12 MB/s, ~10-15% of mysql_cdc's ~100-115 MB/s measured read ceiling) for 90 minutes at one vCPU point, plus the 30m orders-soak-pr.yaml binary-arm variant for /soak mysql/orders-soak-pr. checkpoint_limit is raised above batching.count (the 1024 default admits an oversized batch only when nothing is pending, serializing the pipeline to one batch in flight), and the reset sets RDS 'binlog retention hours' every run — backup_retention_period only ENABLES binlog; RDS purges backed-up binlogs within minutes without the rds_set_configuration call, and a mid-soak reconnect would die with ERROR 1236. - terraform stacks/mysql + modules/rds-mysql: recovered from the benchmarking branch and brought up to this tree's conventions (bench-session-id tag for the reaper, cloud-nuke-excluded exemption, required_version 1.10 for lockfile locking, nullable storage_throughput with the same >=400 GB gp3 tiering as postgres). binlog_format=ROW / binlog_row_image=FULL are what mysql_cdc requires. - runner: the mysql_cdc engineSpec entry and the discrete-flags reset form return from git history, with the current rpk-based topic cleanup kept. The reset renders `mariadb` (guaranteed by mariadb1011 on the runner host) rather than betting on the deprecated `mysql` compat symlink, refuses at render time to emit a command with any empty connection part (bash collapses -p"" to a bare -p an hour into a paid session), and rejects multiline reset SQL, which %q quoting would silently alter. - seeders/cdc-rows-mysql: a port of the current postgres seeder — the old benchmarking-branch mysql seeder predates the worker/tick remainder fairness fixes and the one-placeholder-per-row change, so this ports forward instead of copying back. InterpolateParams is enabled because, unlike pgx, go-sql-driver otherwise wraps every parameterized Exec in a hidden server-side Prepare+Execute+Close. - soak_nightly.yml: the rotation becomes a matrix resolved by a plan job (the dispatch input is allowlisted BEFORE strategy evaluation, so a crafted value can't fan one dispatch into N paid soak jobs), serialized with max-parallel: 1 — one bench at a time, ever; manual dispatch still runs exactly the scenario named in the input. - terraform/persistent soak_scenarios gains the mysql entry (dashboard + stall/rss-slope/backlog alarms per entry). Password auth deliberately: the IAM credential-rotation lever this soak is destined for (RDS IAM tokens ride normal-protocol MySQL connections, unlike postgres replication) lands as its own increment — it needs the AWSAuthenticationPlugin DB user in reset, an rds-db:connect policy in the stack, and a live validation pass. SOAK.md/README updated accordingly. Operator steps BEFORE this merges (the cron arms itself on the default branch): `task aws:persistent` re-apply (new dashboard + alarms), then a manual nightly dispatch with scenario=mysql/orders-soak; the baseline comparator stays advisory until three soak-index entries exist. Known follow-ups (shared with the postgres seeder, deferred to keep the two in lockstep): extract the duplicated worker/tick/payload math into a shared package, and cancel sibling workload workers on first error instead of degrading to 15/16 rate for the rest of the window. Verified: go test -race -shuffle=on, golangci-lint, gofumpt clean on the benchmarking module; terraform validate + fmt clean on the new stack; both scenarios pass `task aws:validate`. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e29bce0 to
1b89dc9
Compare
|
Live validation: PASSED — run 33441795019 (manual dispatch of
Byte-for-byte the same profile the postgres soak validated at (also 12.19 MB/s median), which is what you'd want from an identical 10K×1.2KB workload. Operational state: the persistent stack already carries the mysql dashboard ( 🤖 Generated with Claude Code |
grep -Eq evaluates per line, so a multi-line dispatch input (reachable via the REST dispatch API) passed the allowlist on its first conforming line and was then written verbatim into the line-oriented $GITHUB_OUTPUT — where an embedded `scenarios=` assignment or heredoc could re-assign the matrix and fan one dispatch into N paid soak jobs. Bash's =~ anchors $ to end-of-string and no class in the pattern admits a newline, so multi-line values now fail both the plan job's gate and the per-job re-check. Verified: the review comment's newline and heredoc payloads pass the old grep and are rejected by =~; valid paths still pass. soak_pr.yml's sibling check is not affected: its `| xargs` flattens newlines to spaces before the regex, and a space fails the allowlist. Found by claude-review on #4750. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| the input's aws block, and reset steps change. | ||
|
|
||
| connector: mysql_cdc | ||
| stack: mysql |
There was a problem hiding this comment.
Soak results will land in a new docs/benchmark-results/mysql.md, not the existing mysql-cdc.md
The runner derives the results page from s.Stack, not the connector:
connect/benchmarking/aws/runner/main.go
Lines 567 to 571 in c00b992
AppendMarkdown opens that path with os.O_APPEND|os.O_CREATE, so a missing file is silently created rather than erroring:
connect/benchmarking/aws/runner/render.go
Lines 223 to 228 in c00b992
With stack: mysql the target is docs/benchmark-results/mysql.md, which does not exist — mysql_cdc's results page is docs/benchmark-results/mysql-cdc.md. The first nightly mysql soak will therefore create a second, parallel results file for the same connector, and the ~100-115 MB/s ceiling this scenario's description calibrates against (recorded in mysql-cdc.md) will sit in a different file from the soak trend line.
This diverges from the documented convention in docs/benchmarking.md — "Each connector gets its own file (e.g. mssqlserver-cdc.md)" — which CONTRIBUTING §1.3.4 points at for the reporting requirements. Postgres does not hit this because stack: postgres happens to match the existing postgres.md.
Suggested fix: rename docs/benchmark-results/mysql-cdc.md to mysql.md so the AWS soak appends to the established page (and update the link in docs/benchmarking.md's connector table), or make the results filename come from the connector rather than the stack. stack can't simply be renamed here since it also selects terraform/stacks/<stack> and the S3 state key.
What
Adds mysql_cdc as the second connector in the CDC soak rotation, following SOAK.md's "Adding a connector to the rotation" recipe end to end:
scenarios/mysql/orders-soak.yaml: the same sustained-moderate profile as the postgres soak (10K writes/sec × 1.2 KB ≈ 12 MB/s, ~10–15% of mysql_cdc's ~100–115 MB/s measured read ceiling) for 90 minutes at one vCPU point; plus the 30morders-soak-pr.yamlbinary-arm variant for/soak mysql/orders-soak-pr.stacks/mysql+modules/rds-mysql, recovered from the benchmarking branch and brought up to this tree's conventions:bench-session-idtag (reaper age signal),cloud-nuke-excludedexemption,required_version >= 1.10(lockfile locking), nullablestorage_throughputwith the same ≥400 GB gp3 tiering as postgres.binlog_format=ROW/binlog_row_image=FULLare what mysql_cdc requires.mysql_cdcengineSpec entry and the discrete-flags reset form return from git history, keeping the current rpk-based topic cleanup.seeders/cdc-rows-mysqlis a forward-port of the current postgres seeder (the old benchmarking-branch copy predates the worker/tick remainder fairness fixes and the one-placeholder-per-row change), withInterpolateParamsenabled since go-sql-driver, unlike pgx, otherwise wraps every parameterized Exec in a hidden server-side Prepare+Execute+Close.soak_nightly.ymlbecomes a matrix resolved by a plan job (the dispatch input is allowlisted BEFORE strategy evaluation, so a crafted value can't fan one dispatch into N paid soak jobs), serialized withmax-parallel: 1— one bench at a time, ever.terraform/persistentsoak_scenariosgains the mysql entry (dashboard + stall/rss-slope/backlog alarms).Landmines defused (found in review)
backup_retention_period=1only enables binlog — RDS purges backed-up binlogs within minutes unlessCALL mysql.rds_set_configuration('binlog retention hours', 24)is issued, which the reset now does every run. Without it, any mid-soak reconnect dies with ERROR 1236, a red night indistinguishable from a connector regression.checkpoint_limit: the 1024 default admits an oversized batch only when nothing is pending, serializing the pipeline to one 5000-row batch in flight; both scenarios set 10000.mariadb(guaranteed by mariadb1011 on the runner host) rather than betting on the deprecatedmysqlcompat symlink, refuses at render time to emit a command with any empty terraform-output connection part (bash collapses-p""to a bare-pan hour into a paid session), and rejects multiline reset SQL, which%qquoting would silently alter.Deliberately deferred
rds-db:connectpolicy in the stack, and a live validation pass. Password auth first, exactly how the postgres soak entered rotation.Operator steps (BEFORE merge — the cron arms itself on the default branch)
TF_VAR_soak_alert_email=<team-alias> task aws:persistentre-apply (creates the mysql dashboard + alarms; until then nothing watches mysql metrics). Note bench: deliver soak alarms and reaper notices to Slack via AWS Chatbot #4733's Slack Chatbot subscription rides the same SNS topic — merge ordering with that branch just needs one persistent apply from main afterwards.scenario=mysql/orders-soakfor live validation; the baseline comparator stays advisory until three soak-index entries exist.Verification
go test -race -shuffle=on ./..., golangci-lint, gofumpt: clean on the benchmarking moduleterraform validate+terraform fmt -check: clean on the new stack/moduletask aws:validate scenario=mysql/orders-soakand=mysql/orders-soak-pr: pass🤖 Generated with Claude Code