Repository navigation
Add composite MySQL safety checks and stable recovery - #196
pradeepkintali wants to merge 8 commits into
Conversation
Allow replica-lag checks to require cached primary and ProxySQL safety metrics, fail closed for configured probes, and hold recovery until a cooling period completes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0fbc396f-32f9-449a-8537-6264e8665c31
Require a full healthy window after process or leader startup, expose the blocking metric in check responses, and publish recovery latch state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0fbc396f-32f9-449a-8537-6264e8665c31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0fbc396f-32f9-449a-8537-6264e8665c31
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Recovery semantics and direct-memcache behavior can bypass or inconsistently apply the new safety gates.
Review effort: Balanced
Findings: 1
Open (4)
What changed in this PR
Adds composite MySQL safety checks, recovery hysteresis, and configurable Vitess tablet discovery.
Changes:
- Composes replica checks with required primary and ProxySQL metrics.
- Adds fail-closed behavior, recovery thresholds, cooling periods, and metrics.
- Supports validated
REPLICA,MASTER, andPRIMARYVitess tablet configuration.
| File | Description |
|---|---|
pkg/base/throttle_metric.go |
Adds recovery-state metric errors. |
pkg/config/config_test.go |
Tests new configuration validation. |
pkg/config/mysql_config.go |
Adds composite and recovery settings. |
pkg/config/vitess_config.go |
Validates tablet types. |
pkg/throttle/check.go |
Evaluates required clusters. |
pkg/throttle/check_result.go |
Reports the blocking metric. |
pkg/throttle/throttler.go |
Implements recovery latching. |
pkg/throttle/throttler_test.go |
Tests composition and recovery. |
pkg/vitess/api_client.go |
Filters configured tablet types. |
pkg/vitess/api_client_test.go |
Tests primary discovery. |
doc/mysql.md |
Documents configuration and rollout scope. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Preserve the replica validation API, apply read overrides consistently, reset recovery state on leadership regain, and enforce required clusters for direct memcache consumers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0fbc396f-32f9-449a-8537-6264e8665c31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0fbc396f-32f9-449a-8537-6264e8665c31
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: dea961fa-5766-415f-a0f5-2562c55a0385
| dependencies, fail-on-no-hosts, or a recovery duration, legacy cluster | ||
| decisions retain their existing behavior. | ||
| 2. Add separately named primary metrics in shadow mode, without adding them to | ||
| the application's normal cluster `RequiredClusters`. Validate writer |
There was a problem hiding this comment.
This feels like an easy to miss self inflicted problem that could happen if you added clusters at the same time as adding to RequiredClusters. Maybe adding a ShadowRequiredClusters could have a built in way of adding requirements but in a safer way? It could still emit would reject counters but not actually reject writes?
There was a problem hiding this comment.
Thanks for flagging this rollout hazard. I checked the companion Puppet configuration and rendered the full production configuration: EnforcedClusters: [] and EnforceAll: false generate the 61 standalone primary probes without changing any normal cluster configuration or adding required dependencies. Probe self-check failures, aggregated metrics, and recovery telemetry can be observed before activation.
For this collection-only rollout, I have kept the existing controls rather than adding ShadowRequiredClusters to the server API. I tightened the server and Puppet rollout docs to explicitly require probe deployment/validation first and enforcement in a separate reviewed configuration change, so adding probes and enforcing them together is not the rollout path.
To be clear, the current shadow mode is not a composite dry run and does not emit composite would-reject counters. Your proposed setting would add that capability; I am deferring that feature rather than claiming the existing telemetry is equivalent. No enforcement was enabled. Full production renders on both Puppet branches confirm normal clusters remain unchanged with the empty allowlist, and selective enforcement changes only the chosen canary.
There was a problem hiding this comment.
The safeguards you're relying on (EnforcedClusters, EnforceAll, full-render checks, a separate reviewed activation change) all live in our internal configuration management, not in freno. Anyone running freno outside GitHub gets none of them. In freno itself, enforcement is just a RequiredClusters edit with no dry run, and the caveats sit at the bottom of a long section mixed in with GitHub-specific rollout steps.
If ShadowRequiredClusters stays out of this PR, the public repo needs to carry the safety information itself:
- Move GitHub-internal rollout content out of
doc/mysql.md.EnforcedClusters/EnforceAll, the Datadog baselines, the fleet 30-second window, and the Add composite MySQL safety checks and stable recovery #196/Harden primary protection recovery and Vitess discovery #197 branch history aren't freno concepts. Someone outside GitHub will look forEnforcedClustersin the freno config and won't find it. That material belongs in the internal deployment docs alongside that config. - Start the section with a short "Behavior changes" callout that applies to any deployment:
- Any cluster with
RecoveryDurationMillis > 0returns429for at least that window after every process start and leader change, even with noRequiredClusters. freno can't reload config without a restart (Configuration.Reload()has no callers), so every config change, including a rollback, triggers this. RequiredClustersfails closed. If a dependency can't be collected (wrong discovery, missing grants, or an empty host list withFailOnNoHosts), checks for the cluster that requires it return500.- While any dependency is unhealthy, that cluster's memcache key is deleted.
- There is no dry run. A config change that adds a probe and references it from
RequiredClustersat the same time can block writes immediately. - Clients with a wait budget shorter than
RecoveryDurationMilliswill time out during recovery.
- Any cluster with
- Log the composite config at startup. Write one line for each cluster that sets
RequiredClusters,RecoveryDurationMillis, orFailOnNoHosts, so operators see it in the logs and not only in the docs. - Make it visible from
README.md. freno ships from master without release notes, so anyone pulling master gets this with no announcement. Link the callout from the MySQL section ofREADME.md(next to "Read more about freno and MySQL throttling"), so people see it without reading to the end ofdoc/mysql.md.
ShadowRequiredClusters is still the real fix. A would-reject counter is the only way any deployment can validate a dependency before it starts blocking writes. If it's deferred, please open an issue for it and link it from the doc.
Preserve MASTER as a deprecated input alias and the existing numeric tablet mapping. Clarify that shadow collection precedes enforcement and is not composite dry-run counting. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: fbc83df2-d1af-406f-b97b-51cf0aaa570d


Summary
PRIMARYdiscovery (with deprecatedMASTERinput alias) while preserving the default replica behavior.Configuration and rollout controls
RequiredClusters,FailOnNoHosts, andRecoveryDurationMillisare opt-in.Existing clusters retain legacy behavior when these settings are absent.
There is no new global runtime feature switch in this PR.
The companion Puppet PR github/puppet#44086 initially generates shadow primary
probes with
EnforcedClusters: []andEnforceAll: false. Its October 8-15threshold refresh is based on observed data, including incidents, not a verified
healthy baseline; no enforcement is enabled. This is collection-only shadowing, not a composite dry run: there are no composite would-reject counters. Probe validation and enforcement must be separate reviewed configuration changes.
Rollout plan
errors, and recovery gauges before adding required dependencies.
five-minute Datadog baselines with the instantaneous SQL probe.
30-second server recovery window; the Ruby client's default maximum wait is
only 10 seconds. Do not silently enlarge every caller's wait budget.
HTTP/memcache paths, then expand against owner-approved success criteria.
The #197 changes were merged into this feature branch, not directly into
master; a merged stacked PR does not establish a deployed server version.
The client switch in github/freno-client#37 is independent of server enforcement.
Rollback plan
Remove the primary dependency while preserving replica-lag checks. For the
companion Puppet configuration, remove the cluster from
EnforcedClusters,keep
EnforceAllfalse, and deploy. Account for service notifications, restarts,and startup recovery; this is not an instantaneous runtime toggle.
Validation
Original implementation validation:
go test -count=1 ./...go vet ./pkg/base ./pkg/config ./pkg/throttle ./pkg/http ./pkg/mysql ./pkg/proxysql ./pkg/vitessgo vet ./...has pre-existingtesting.T.Fatalfcalls from non-test goroutines ininternal/rafttests.October 15 review follow-up makes PRIMARY canonical, retains MASTER as a deprecated input alias, updates discovery and companion Puppet generation together, and clarifies collection-only shadow rollout. The pinned Vitess dependency is unchanged.
Validation passed on both parent and stacked branches: vendored Go configuration/Vitess tests and vet, Go formatting, five parent and eleven stacked Puppet ERB specs, and full production rendering with 61 shadow primary probes, all 15 Vitess probes using PRIMARY, unchanged normal clusters with enforcement off, and selective canary enforcement verified in memory.
git diff --checkpassed. These checks are not a full Puppet catalog/integration run.Scope boundaries
This PR provides admission checks and recovery behavior, not universal database
load shedding. Each deployment owns metrics, thresholds, discovery, monitoring,
application concurrency, and safe fallback behavior. Fleet ProxySQL-capacity
enforcement is not included in the companion Puppet rollout.