From 02763d3f361799934429c887ee5fad44c72ff2cc Mon Sep 17 00:00:00 2001 From: Kiran Muddukrishna Date: Mon, 22 Jun 2026 09:39:05 +1000 Subject: [PATCH] refactor(config): remove deprecated operator_workers/scheduler_workers aliases drivers is now the only accepted key for operator concurrency; the compat aliases were retained only for one release after the rename soaked. --- docs/architecture.md | 2 +- docs/configuration.md | 2 -- pkg/api/config.go | 54 +--------------------------------------- pkg/api/operator_test.go | 19 -------------- 4 files changed, 2 insertions(+), 75 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index f9d970d3..90fe4355 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -622,7 +622,7 @@ The operator is part of Tern orchestration. The API service starts it on server Each operator driver runs immediately on startup, then polls every 10 seconds. The driver claims at most one apply per tick and resumes it through the Tern client for that apply's deployment and environment. Fresh applies also send a best-effort wake signal after their apply and task rows are committed, so a driver can claim them immediately instead of waiting for the next poll tick. -`drivers` controls operator concurrency (the deprecated `operator_workers` and `scheduler_workers` aliases are still accepted for one release). The default is four drivers, so an untuned server can still make progress across independent databases and environments concurrently. More drivers help larger installations with many independent schema changes because each driver can claim and resume a different target during the same operator tick. +`drivers` controls operator concurrency. The default is four drivers, so an untuned server can still make progress across independent databases and environments concurrently. More drivers help larger installations with many independent schema changes because each driver can claim and resume a different target during the same operator tick. In a multi-pod deployment, every SchemaBot pod runs its own operator. Each operator has its own configurable driver pool, and every driver coordinates through shared storage before resuming an apply. When a recovered apply came from a PR comment, the driver attaches a reconstructed `ProgressObserver` before calling `ResumeApply()` so the resumed progress poller can keep updating PR comments. diff --git a/docs/configuration.md b/docs/configuration.md index c7e60d83..bdd104bb 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -270,8 +270,6 @@ Increase `drivers` when one SchemaBot server should make operator progress acros A driver claim means selecting one stale apply and refreshing its heartbeat in the same storage transaction. That heartbeat refresh is the driver's lease while it reloads state and drives the apply to a terminal state. -> **Deprecated:** the previous `operator_workers` and `scheduler_workers` keys still work as aliases for `drivers` and are honored with a deprecation warning. Set only one of the three. The aliases will be removed one release after the driver rename has soaked. - ## Pending Drops For MySQL databases executed by the Spirit engine, `DROP TABLE` statements are diff --git a/pkg/api/config.go b/pkg/api/config.go index c575a5c2..10a03618 100644 --- a/pkg/api/config.go +++ b/pkg/api/config.go @@ -101,23 +101,7 @@ type ServerConfig struct { // SKIP LOCKED to prevent races. Defaults to DefaultDrivers. Drivers int `yaml:"drivers"` - // OperatorWorkers is the deprecated alias for Drivers. It is kept so existing - // config files that still set operator_workers continue to load (the YAML - // decoder runs with KnownFields(true) and would otherwise reject the unknown - // key). Validate() folds it into Drivers when the new key is unset and logs a - // deprecation warning. Remove one release after the driver rename has soaked. - // - // Deprecated: use drivers. - OperatorWorkers int `yaml:"operator_workers,omitempty"` - - // SchedulerWorkers is the original deprecated alias for Drivers, predating - // operator_workers. It is kept for the same KnownFields(true) reason and is - // folded into Drivers by Validate() with a deprecation warning. - // - // Deprecated: use drivers. - SchedulerWorkers int `yaml:"scheduler_workers,omitempty"` - - // OperatorClaimOperations switches operator drivers to claim work at the + // OperatorClaimOperations switches drivers to claim work at the // apply_operations (per-deployment) level via FindNextApplyOperation instead // of the apply level via FindNextApply. While every apply still owns exactly // one operation, the operation-scoped drive resolves to the same work as the @@ -720,44 +704,8 @@ func LoadServerConfigFromFile(path string) (*ServerConfig, error) { return &config, nil } -// resolveDeprecatedDrivers folds the deprecated operator_workers and -// scheduler_workers keys into drivers. When only a deprecated key is set it is -// honored and a deprecation warning is logged; setting more than one of the -// three keys is rejected so the effective value is never ambiguous. -func (c *ServerConfig) resolveDeprecatedDrivers() error { - set := 0 - if c.Drivers != 0 { - set++ - } - if c.OperatorWorkers != 0 { - set++ - } - if c.SchedulerWorkers != 0 { - set++ - } - if set > 1 { - return fmt.Errorf("set only one of drivers, operator_workers, or scheduler_workers (operator_workers and scheduler_workers are deprecated)") - } - - if c.OperatorWorkers != 0 { - slog.Warn("operator_workers is deprecated; use drivers", "operator_workers", c.OperatorWorkers) - c.Drivers = c.OperatorWorkers - c.OperatorWorkers = 0 - } - if c.SchedulerWorkers != 0 { - slog.Warn("scheduler_workers is deprecated; use drivers", "scheduler_workers", c.SchedulerWorkers) - c.Drivers = c.SchedulerWorkers - c.SchedulerWorkers = 0 - } - return nil -} - // Validate checks the configuration for required fields and consistency. func (c *ServerConfig) Validate() error { - if err := c.resolveDeprecatedDrivers(); err != nil { - return err - } - // The database registry is required for the control plane and for a // single-database data plane. A data plane configured with a target_resolver // resolves opaque targets dynamically and has no database registry, so it is diff --git a/pkg/api/operator_test.go b/pkg/api/operator_test.go index c55b4adc..3973dea5 100644 --- a/pkg/api/operator_test.go +++ b/pkg/api/operator_test.go @@ -27,25 +27,6 @@ func TestDriversConfig(t *testing.T) { config := &ServerConfig{Drivers: 3} assert.Equal(t, 3, config.Drivers) }) - - t.Run("deprecated operator_workers folds into drivers", func(t *testing.T) { - config := &ServerConfig{OperatorWorkers: 2} - require.NoError(t, config.resolveDeprecatedDrivers()) - assert.Equal(t, 2, config.Drivers) - assert.Equal(t, 0, config.OperatorWorkers) - }) - - t.Run("deprecated scheduler_workers folds into drivers", func(t *testing.T) { - config := &ServerConfig{SchedulerWorkers: 2} - require.NoError(t, config.resolveDeprecatedDrivers()) - assert.Equal(t, 2, config.Drivers) - assert.Equal(t, 0, config.SchedulerWorkers) - }) - - t.Run("setting multiple keys is rejected", func(t *testing.T) { - config := &ServerConfig{Drivers: 4, OperatorWorkers: 2} - assert.Error(t, config.resolveDeprecatedDrivers()) - }) } // recordingApplyOperationStore records the state-mutating call made by