diff --git a/libsql-server/src/lib.rs b/libsql-server/src/lib.rs index 8cc1f19372a..af4c397f5fd 100644 --- a/libsql-server/src/lib.rs +++ b/libsql-server/src/lib.rs @@ -100,6 +100,7 @@ pub struct Server, pub disable_namespaces: bool, pub shutdown: Arc, + pub max_active_namespaces: usize, } impl Default for Server { @@ -117,6 +118,7 @@ impl Default for Server { heartbeat_config: Default::default(), disable_namespaces: true, shutdown: Default::default(), + max_active_namespaces: 100, } } } @@ -384,6 +386,7 @@ where db_config: self.db_config.clone(), base_path: self.path.clone(), auth: auth.clone(), + max_active_namespaces: self.max_active_namespaces, }; let (namespaces, proxy_service, replication_service) = replica.configure().await?; self.rpc_client_config = None; @@ -422,6 +425,7 @@ where extensions, base_path: self.path.clone(), disable_namespaces: self.disable_namespaces, + max_active_namespaces: self.max_active_namespaces, join_set: &mut join_set, auth: auth.clone(), }; @@ -487,6 +491,7 @@ struct Primary<'a, A> { extensions: Arc<[PathBuf]>, base_path: Arc, disable_namespaces: bool, + max_active_namespaces: usize, auth: Arc, join_set: &'a mut JoinSet>, } @@ -517,7 +522,12 @@ where disable_namespace: self.disable_namespaces, }; let factory = PrimaryNamespaceMaker::new(conf); - let namespaces = NamespaceStore::new(factory, false, self.db_config.snapshot_at_shutdown); + let namespaces = NamespaceStore::new( + factory, + false, + self.db_config.snapshot_at_shutdown, + self.max_active_namespaces, + ); // eagerly load the default namespace when namespaces are disabled if self.disable_namespaces { @@ -583,6 +593,7 @@ struct Replica { db_config: DbConfig, base_path: Arc, auth: Arc, + max_active_namespaces: usize, } impl Replica { @@ -605,7 +616,7 @@ impl Replica { max_total_response_size: self.db_config.max_total_response_size, }; let factory = ReplicaNamespaceMaker::new(conf); - let namespaces = NamespaceStore::new(factory, true, false); + let namespaces = NamespaceStore::new(factory, true, false, self.max_active_namespaces); let replication_service = ReplicationLogProxyService::new(channel.clone(), uri.clone()); let proxy_service = ReplicaProxyService::new(channel, uri, self.auth.clone()); diff --git a/libsql-server/src/main.rs b/libsql-server/src/main.rs index 57c557324a9..4f850ff6b65 100644 --- a/libsql-server/src/main.rs +++ b/libsql-server/src/main.rs @@ -195,6 +195,10 @@ struct Cli { /// Enable snapshot at shutdown #[clap(long)] snapshot_at_shutdown: bool, + + /// Max active namespaces kept in-memory + #[clap(long, env = "SQLD_MAX_ACTIVE_NAMESPACES", default_value = "100")] + max_active_namespaces: usize, } #[derive(clap::Subcommand, Debug)] @@ -506,6 +510,7 @@ async fn build_server(config: &Cli) -> anyhow::Result { disable_default_namespace: config.disable_default_namespace, disable_namespaces: !config.enable_namespaces, shutdown, + max_active_namespaces: config.max_active_namespaces, }) } diff --git a/libsql-server/src/namespace/mod.rs b/libsql-server/src/namespace/mod.rs index bb4501d9b53..dda6717796a 100644 --- a/libsql-server/src/namespace/mod.rs +++ b/libsql-server/src/namespace/mod.rs @@ -360,7 +360,12 @@ struct NamespaceStoreInner { } impl NamespaceStore { - pub fn new(make_namespace: M, allow_lazy_creation: bool, snapshot_at_shutdown: bool) -> Self { + pub fn new( + make_namespace: M, + allow_lazy_creation: bool, + snapshot_at_shutdown: bool, + max_active_namespaces: usize, + ) -> Self { let store = Cache::>::builder() .async_eviction_listener(|name, ns, _| { Box::pin(async move { @@ -374,7 +379,8 @@ impl NamespaceStore { }) }) // TODO(marin): configurable capacity - .max_capacity(25) + .max_capacity(max_active_namespaces as u64) + .time_to_idle(Duration::from_secs(300)) .build(); Self { inner: Arc::new(NamespaceStoreInner { diff --git a/libsql-server/src/test/bottomless.rs b/libsql-server/src/test/bottomless.rs index 20b04428cbe..b265fb4a1c3 100644 --- a/libsql-server/src/test/bottomless.rs +++ b/libsql-server/src/test/bottomless.rs @@ -64,6 +64,7 @@ async fn configure_server( }, path: path.into().into(), disable_default_namespace: false, + max_active_namespaces: 100, heartbeat_config: None, idle_shutdown_timeout: None, initial_idle_shutdown_timeout: None,