diff --git a/control_plane/src/local_env.rs b/control_plane/src/local_env.rs index 3ac3ce21df..a677cef125 100644 --- a/control_plane/src/local_env.rs +++ b/control_plane/src/local_env.rs @@ -155,6 +155,9 @@ pub struct NeonStorageControllerConf { /// Threshold for auto-splitting a tenant into shards pub split_threshold: Option, + + /// Whether to enable background reconciliation + pub background_reconcile: Option, } impl NeonStorageControllerConf { @@ -168,6 +171,7 @@ impl Default for NeonStorageControllerConf { Self { max_unavailable: Self::DEFAULT_MAX_UNAVAILABLE_INTERVAL, split_threshold: None, + background_reconcile: None, } } } diff --git a/storage_controller/src/main.rs b/storage_controller/src/main.rs index f1eb0b30fc..a222834051 100644 --- a/storage_controller/src/main.rs +++ b/storage_controller/src/main.rs @@ -75,6 +75,10 @@ struct Cli { #[arg(long)] reconciler_concurrency: Option, + /// Whether to spawn a background reconciliation task (enabled by default) + #[arg(long)] + background_reconcile: Option, + /// How long to wait for the initial database connection to be available. #[arg(long, default_value = "5s")] db_connect_timeout: humantime::Duration, @@ -266,6 +270,7 @@ async fn async_main() -> anyhow::Result<()> { reconciler_concurrency: args .reconciler_concurrency .unwrap_or(RECONCILER_CONCURRENCY_DEFAULT), + background_reconcile: args.background_reconcile.unwrap_or(true), split_threshold: args.split_threshold, neon_local_repo_dir: args.neon_local_repo_dir, }; diff --git a/storage_controller/src/service.rs b/storage_controller/src/service.rs index deaac83ea5..87e4b418bf 100644 --- a/storage_controller/src/service.rs +++ b/storage_controller/src/service.rs @@ -240,6 +240,8 @@ pub struct Config { /// How many Reconcilers may be spawned concurrently pub reconciler_concurrency: usize, + pub background_reconcile: bool, + /// How large must a shard grow in bytes before we split it? /// None disables auto-splitting. pub split_threshold: Option, @@ -1229,14 +1231,16 @@ impl Service { } }); - tokio::task::spawn({ - let this = this.clone(); - let startup_complete = startup_complete.clone(); - async move { - startup_complete.wait().await; - this.background_reconcile().await; - } - }); + if config.background_reconcile { + tokio::task::spawn({ + let this = this.clone(); + let startup_complete = startup_complete.clone(); + async move { + startup_complete.wait().await; + this.background_reconcile().await; + } + }); + } tokio::task::spawn({ let this = this.clone(); diff --git a/test_runner/regress/test_tenants.py b/test_runner/regress/test_tenants.py index 04b3fdd80f..2880d7ea5e 100644 --- a/test_runner/regress/test_tenants.py +++ b/test_runner/regress/test_tenants.py @@ -17,7 +17,6 @@ from fixtures.metrics import ( parse_metrics, ) from fixtures.neon_fixtures import ( - NeonEnv, NeonEnvBuilder, wait_for_last_flush_lsn, ) @@ -29,7 +28,14 @@ from fixtures.utils import wait_until from prometheus_client.samples import Sample -def test_tenant_creation_fails(neon_simple_env: NeonEnv): +def test_tenant_creation_fails(neon_env_builder: NeonEnvBuilder): + + neon_env_builder.storage_controller_config = { + "background_reconcile": False + } + + neon_simple_env = neon_env_builder.init_start() + tenants_dir = neon_simple_env.pageserver.tenant_dir() initial_tenants = sorted( map(lambda t: t.split()[0], neon_simple_env.neon_cli.list_tenants().stdout.splitlines())