use surrealdb_cnf::ConfigMap;
use surrealdb_syn::ParserConfig;
use crate::exec::config::ExecConfig;
#[cfg(feature = "scripting")]
use crate::fnc::script::config::ScriptConfig;
#[cfg(any(feature = "http", feature = "jwks"))]
use crate::http::config::HttpConfig;
use crate::iam::config::IamConfig;
use crate::idx::config::IdxConfig;
use crate::kvs::ds::config::DatastoreConfig;
use crate::legacy::config::LegacyConfig;
#[cfg(feature = "surrealism")]
use crate::surrealism::config::SurrealismConfig;
#[derive(Clone, Debug, Default)]
pub(crate) struct RuntimeConfig {
pub parser: ParserConfig,
pub exec: ExecConfig,
pub idx: IdxConfig,
pub legacy: LegacyConfig,
pub iam: IamConfig,
pub datastore: DatastoreConfig,
#[cfg(feature = "surrealism")]
pub surrealism: SurrealismConfig,
#[cfg(feature = "scripting")]
pub script: ScriptConfig,
#[cfg(any(feature = "http", feature = "jwks"))]
pub http: HttpConfig,
}
impl RuntimeConfig {
pub(crate) fn load(map: &ConfigMap) -> Self {
Self {
parser: map.load(),
exec: map.load(),
idx: map.load(),
legacy: map.load(),
iam: map.load(),
datastore: map.load(),
#[cfg(feature = "surrealism")]
surrealism: map.load(),
#[cfg(feature = "scripting")]
script: map.load(),
#[cfg(any(feature = "http", feature = "jwks"))]
http: map.load(),
}
}
}
#[cfg(test)]
mod tests {
use surrealdb_cnf::ConfigMap;
use super::*;
fn map_with(key: &str, value: &str) -> ConfigMap {
ConfigMap::empty().with_key_value(key, value)
}
#[test]
fn parser_keys_reach_their_fields() {
use surrealdb_syn::ParserConfig;
let c: ParserConfig = map_with("max_object_parsing_depth", "7").load();
assert_eq!(c.max_object_parsing_depth, 7);
let c: ParserConfig = map_with("max_query_parsing_depth", "7").load();
assert_eq!(c.max_query_parsing_depth, 7);
let c: ParserConfig = map_with("max_expression_parsing_depth", "7").load();
assert_eq!(c.max_expression_parsing_depth, 7);
}
#[test]
fn exec_keys_reach_their_fields() {
let c: ExecConfig = map_with("max_computation_depth", "7").load();
assert_eq!(c.max_computation_depth, 7);
let c: ExecConfig = map_with("operator_buffer_size", "7").load();
assert_eq!(c.operator_buffer_size, 7);
let c: ExecConfig = map_with("scan_batch_size", "7").load();
assert_eq!(c.scan_batch_size, 7);
let c: ExecConfig = map_with("max_order_limit_priority_queue_size", "7").load();
assert_eq!(c.max_order_limit_priority_queue_size, 7);
let c: ExecConfig = map_with("topk_threshold_pushdown_enabled", "false").load();
assert!(!c.topk_threshold_pushdown_enabled);
let c: ExecConfig = map_with("gql_max_join_build_rows", "7").load();
assert_eq!(c.gql_max_join_build_rows, 7);
let c: ExecConfig = map_with("gql_max_path_rows", "7").load();
assert_eq!(c.gql_max_path_rows, 7);
let c: ExecConfig = map_with("gql_max_output_rows", "7").load();
assert_eq!(c.gql_max_output_rows, 7);
let c: ExecConfig = map_with("external_sorting_buffer_limit", "7").load();
assert_eq!(c.external_sorting_buffer_limit, 7);
let c: ExecConfig = map_with("generation_allocation_limit", "3").load();
assert_eq!(c.generation_allocation_limit, 2 << 3);
}
#[test]
fn legacy_and_iam_keys_reach_their_fields() {
let c: LegacyConfig = map_with("max_concurrent_tasks", "7").load();
assert_eq!(c.max_concurrent_tasks, 7);
let c: IamConfig = map_with("insecure_forward_access_errors", "true").load();
assert!(c.insecure_forward_access_errors);
}
#[test]
fn idx_keys_reach_their_fields() {
let c: IdxConfig = map_with("table_doc_ids_batch_size", "7").load();
assert_eq!(c.table_doc_ids_batch_size, 7);
let c: IdxConfig = map_with("hnsw_cache_size", "7").load();
assert_eq!(c.hnsw_cache_size, 7);
{
use crate::idx::config::BuildParallelism;
let c: IdxConfig = map_with("hnsw_build_parallelism", "7").load();
assert_eq!(
c.hnsw_build_parallelism,
BuildParallelism::Fixed(std::num::NonZeroUsize::new(7).expect("non-zero"))
);
let c: IdxConfig = map_with("hnsw_build_parallelism", "serial").load();
assert_eq!(c.hnsw_build_parallelism, BuildParallelism::Serial);
assert_eq!(IdxConfig::default().hnsw_build_parallelism, BuildParallelism::Auto);
}
let c: IdxConfig = map_with("diskann_cache_size", "7").load();
assert_eq!(c.diskann_cache_size, 7);
let c: IdxConfig = map_with("graph_fold_threshold", "7").load();
assert_eq!(c.graph_fold_threshold, IdxConfig::default().graph_fold_threshold);
let c: IdxConfig = map_with("graph_fold_batch", "7").load();
assert_eq!(c.graph_fold_batch, 7);
let c: IdxConfig = map_with("graph_numeric_ids", "true").load();
assert!(c.graph_numeric_ids);
let c: IdxConfig = map_with("graph_resolve_cache_size", "7").load();
assert_eq!(c.graph_resolve_cache_size, 7);
let c: IdxConfig = map_with("graph_inline_props_cap", "7").load();
assert_eq!(c.graph_inline_props_cap, 7);
let c: IdxConfig = map_with("segment_dictionary_path", "/dictionaries").load();
assert_eq!(
c.segment_dictionary_path.as_deref(),
Some(std::path::Path::new("/dictionaries"))
);
assert_eq!(IdxConfig::default().segment_dictionary_path, None);
let dir = std::env::temp_dir();
let c: IdxConfig = map_with("file_allowlist", &dir.to_string_lossy()).load();
assert!(!c.file_allowlist.is_empty());
}
#[test]
fn datastore_keys_reach_their_fields() {
use crate::kvs::TransactionConfig;
use crate::kvs::ds::config::{DatastoreConfig, LiveQueryEngine};
let c: TransactionConfig = map_with("transaction_cache_size", "7").load();
assert_eq!(c.transaction_cache_size, 7);
let c: TransactionConfig = map_with("transaction_max_write_keys", "7").load();
assert_eq!(c.transaction_max_write_keys, 7);
let c: DatastoreConfig = map_with("datastore_cache_size", "7").load();
assert_eq!(c.datastore_cache_size, 7);
let c: DatastoreConfig = map_with("export_batch_size", "7").load();
assert_eq!(c.export_batch_size, 7);
let c: DatastoreConfig = map_with("live_query_engine", "router").load();
assert_eq!(c.live_query_engine, LiveQueryEngine::Router);
let c: DatastoreConfig = map_with("live_query_retention", "5m").load();
assert_eq!(c.live_query_retention, std::time::Duration::from_secs(300));
}
#[cfg(any(feature = "http", feature = "jwks"))]
#[test]
fn http_keys_reach_their_fields() {
use crate::http::config::HttpConfig;
let c: HttpConfig = map_with("max_http_redirects", "7").load();
assert_eq!(c.max_http_redirects, 7);
let c: HttpConfig = map_with("max_http_idle_connections_per_host", "7").load();
assert_eq!(c.max_http_idle_connections_per_host, 7);
let c: HttpConfig = map_with("http_idle_timeout_secs", "7").load();
assert_eq!(c.http_idle_timeout_secs, 7);
let c: HttpConfig = map_with("http_connect_timeout_secs", "7").load();
assert_eq!(c.http_connect_timeout_secs, 7);
let c: HttpConfig = map_with("surrealdb_user_agent", "probe").load();
assert_eq!(c.surrealdb_user_agent, "probe");
}
#[cfg(feature = "scripting")]
#[test]
fn scripting_keys_reach_their_fields() {
use crate::fnc::script::config::ScriptConfig;
let c: ScriptConfig = map_with("scripting_max_stack_size", "7").load();
assert_eq!(c.scripting_max_stack_size, 7);
let c: ScriptConfig = map_with("scripting_max_memory_limit", "7").load();
assert_eq!(c.scripting_max_memory_limit, 7);
let c: ScriptConfig = map_with("scripting_max_time_limit", "7").load();
assert_eq!(c.scripting_max_time_limit, std::time::Duration::from_millis(7));
}
#[cfg(feature = "surrealism")]
#[test]
fn surrealism_keys_reach_their_fields() {
let c: SurrealismConfig = map_with("surrealism_cache_size", "7").load();
assert_eq!(c.surrealism_cache_size, 7);
let c: SurrealismConfig = map_with("surrealism_max_memory", "7").load();
assert_eq!(c.surrealism_max_memory, Some(7));
let c: SurrealismConfig = map_with("surrealism_max_execution_time", "7").load();
assert_eq!(c.surrealism_max_execution_time, Some(7));
let c: SurrealismConfig = map_with("surrealism_max_kv_entries", "7").load();
assert_eq!(c.surrealism_max_kv_entries, Some(7));
let c: SurrealismConfig = map_with("surrealism_max_kv_value_bytes", "7").load();
assert_eq!(c.surrealism_max_kv_value_bytes, Some(7));
let c: SurrealismConfig = map_with("surrealism_max_fs_bytes", "7").load();
assert_eq!(c.surrealism_max_fs_bytes, 7);
let c: SurrealismConfig = map_with("surrealism_log_level", "trace").load();
assert_eq!(c.surrealism_log_level, "trace");
}
#[test]
fn every_layer_is_loaded_into_the_aggregate() {
let map = ConfigMap::empty()
.with_key_value("max_object_parsing_depth", "7")
.with_key_value("operator_buffer_size", "7")
.with_key_value("table_doc_ids_batch_size", "7")
.with_key_value("max_concurrent_tasks", "7")
.with_key_value("insecure_forward_access_errors", "true")
.with_key_value("datastore_cache_size", "7");
let c = RuntimeConfig::load(&map);
assert_eq!(c.parser.max_object_parsing_depth, 7, "parser not loaded");
assert_eq!(c.exec.operator_buffer_size, 7, "exec not loaded");
assert_eq!(c.idx.table_doc_ids_batch_size, 7, "idx not loaded");
assert_eq!(c.legacy.max_concurrent_tasks, 7, "legacy not loaded");
assert!(c.iam.insecure_forward_access_errors, "iam not loaded");
assert_eq!(c.datastore.datastore_cache_size, 7, "datastore not loaded");
#[cfg(feature = "surrealism")]
{
let map = ConfigMap::empty().with_key_value("surrealism_cache_size", "7");
assert_eq!(
RuntimeConfig::load(&map).surrealism.surrealism_cache_size,
7,
"surrealism not loaded"
);
}
#[cfg(feature = "scripting")]
{
let map = ConfigMap::empty().with_key_value("scripting_max_stack_size", "7");
assert_eq!(
RuntimeConfig::load(&map).script.scripting_max_stack_size,
7,
"script not loaded"
);
}
#[cfg(any(feature = "http", feature = "jwks"))]
{
let map = ConfigMap::empty().with_key_value("max_http_redirects", "7");
assert_eq!(RuntimeConfig::load(&map).http.max_http_redirects, 7, "http not loaded");
}
}
#[test]
fn unparsed_knobs_keep_their_defaults() {
let c: ExecConfig = map_with("idiom_recursion_limit", "7").load();
assert_eq!(c.idiom_recursion_limit, ExecConfig::default().idiom_recursion_limit);
#[cfg(feature = "surrealism")]
{
let c: SurrealismConfig = map_with("surrealism_max_pool_size", "7").load();
assert_eq!(
c.surrealism_max_pool_size,
SurrealismConfig::default().surrealism_max_pool_size
);
}
}
}