Line data Source code
1 : use camino::Utf8PathBuf;
2 :
3 : #[cfg(test)]
4 : mod tests;
5 :
6 : use const_format::formatcp;
7 : use posthog_client_lite::PostHogClientConfig;
8 : use utils::serde_percent::Percent;
9 : pub const DEFAULT_PG_LISTEN_PORT: u16 = 64000;
10 : pub const DEFAULT_PG_LISTEN_ADDR: &str = formatcp!("127.0.0.1:{DEFAULT_PG_LISTEN_PORT}");
11 : pub const DEFAULT_HTTP_LISTEN_PORT: u16 = 9898;
12 : pub const DEFAULT_HTTP_LISTEN_ADDR: &str = formatcp!("127.0.0.1:{DEFAULT_HTTP_LISTEN_PORT}");
13 : // TODO: gRPC is disabled by default for now, but the port is used in neon_local.
14 : pub const DEFAULT_GRPC_LISTEN_PORT: u16 = 51051; // storage-broker already uses 50051
15 :
16 : use std::collections::HashMap;
17 : use std::fmt::Display;
18 : use std::num::{NonZeroU64, NonZeroUsize};
19 : use std::str::FromStr;
20 : use std::time::Duration;
21 :
22 : use postgres_backend::AuthType;
23 : use remote_storage::RemoteStorageConfig;
24 : use serde_with::serde_as;
25 : use utils::logging::LogFormat;
26 :
27 : use crate::models::{ImageCompressionAlgorithm, LsnLease};
28 :
29 : // Certain metadata (e.g. externally-addressable name, AZ) is delivered
30 : // as a separate structure. This information is not needed by the pageserver
31 : // itself, it is only used for registering the pageserver with the control
32 : // plane and/or storage controller.
33 0 : #[derive(PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
34 : pub struct NodeMetadata {
35 : #[serde(rename = "host")]
36 : pub postgres_host: String,
37 : #[serde(rename = "port")]
38 : pub postgres_port: u16,
39 : pub grpc_host: Option<String>,
40 : pub grpc_port: Option<u16>,
41 : pub http_host: String,
42 : pub http_port: u16,
43 : pub https_port: Option<u16>,
44 :
45 : // Deployment tools may write fields to the metadata file beyond what we
46 : // use in this type: this type intentionally only names fields that require.
47 : #[serde(flatten)]
48 : pub other: HashMap<String, serde_json::Value>,
49 : }
50 :
51 : impl Display for NodeMetadata {
52 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 0 : write!(
54 0 : f,
55 0 : "postgresql://{}:{} ",
56 : self.postgres_host, self.postgres_port
57 0 : )?;
58 0 : if let Some(grpc_host) = &self.grpc_host {
59 0 : let grpc_port = self.grpc_port.unwrap_or_default();
60 0 : write!(f, "grpc://{grpc_host}:{grpc_port} ")?;
61 0 : }
62 0 : write!(f, "http://{}:{} ", self.http_host, self.http_port)?;
63 0 : write!(f, "other:{:?}", self.other)?;
64 0 : Ok(())
65 0 : }
66 : }
67 :
68 : /// PostHog integration config. This is used in pageserver, storcon, and neon_local.
69 : /// Ensure backward compatibility when adding new fields.
70 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
71 : pub struct PostHogConfig {
72 : /// PostHog project ID
73 : #[serde(default)]
74 : #[serde(skip_serializing_if = "Option::is_none")]
75 : pub project_id: Option<String>,
76 : /// Server-side (private) API key
77 : #[serde(default)]
78 : #[serde(skip_serializing_if = "Option::is_none")]
79 : pub server_api_key: Option<String>,
80 : /// Client-side (public) API key
81 : #[serde(default)]
82 : #[serde(skip_serializing_if = "Option::is_none")]
83 : pub client_api_key: Option<String>,
84 : /// Private API URL
85 : #[serde(default)]
86 : #[serde(skip_serializing_if = "Option::is_none")]
87 : pub private_api_url: Option<String>,
88 : /// Public API URL
89 : #[serde(default)]
90 : #[serde(skip_serializing_if = "Option::is_none")]
91 : pub public_api_url: Option<String>,
92 : /// Refresh interval for the feature flag spec.
93 : /// The storcon will push the feature flag spec to the pageserver. If the pageserver does not receive
94 : /// the spec for `refresh_interval`, it will fetch the spec from the PostHog API.
95 : #[serde(default)]
96 : #[serde(skip_serializing_if = "Option::is_none")]
97 : #[serde(with = "humantime_serde")]
98 : pub refresh_interval: Option<Duration>,
99 : }
100 :
101 : impl PostHogConfig {
102 0 : pub fn try_into_posthog_config(self) -> Result<PostHogClientConfig, &'static str> {
103 0 : let Some(project_id) = self.project_id else {
104 0 : return Err("project_id is required");
105 : };
106 0 : let Some(server_api_key) = self.server_api_key else {
107 0 : return Err("server_api_key is required");
108 : };
109 0 : let Some(client_api_key) = self.client_api_key else {
110 0 : return Err("client_api_key is required");
111 : };
112 0 : let Some(private_api_url) = self.private_api_url else {
113 0 : return Err("private_api_url is required");
114 : };
115 0 : let Some(public_api_url) = self.public_api_url else {
116 0 : return Err("public_api_url is required");
117 : };
118 0 : Ok(PostHogClientConfig {
119 0 : project_id,
120 0 : server_api_key,
121 0 : client_api_key,
122 0 : private_api_url,
123 0 : public_api_url,
124 0 : })
125 0 : }
126 : }
127 :
128 : /// `pageserver.toml`
129 : ///
130 : /// We use serde derive with `#[serde(default)]` to generate a deserializer
131 : /// that fills in the default values for each config field.
132 : ///
133 : /// If there cannot be a static default value because we need to make runtime
134 : /// checks to determine the default, make it an `Option` (which defaults to None).
135 : /// The runtime check should be done in the consuming crate, i.e., `pageserver`.
136 : ///
137 : /// Unknown fields are silently ignored during deserialization.
138 : /// The alternative, which we used in the past, was to set `deny_unknown_fields`,
139 : /// which fails deserialization, and hence pageserver startup, if there is an unknown field.
140 : /// The reason we don't do that anymore is that it complicates
141 : /// usage of config fields for feature flagging, which we commonly do for
142 : /// region-by-region rollouts.
143 : /// The complications mainly arise because the `pageserver.toml` contents on a
144 : /// prod server have a separate lifecycle from the pageserver binary.
145 : /// For instance, `pageserver.toml` contents today are defined in the internal
146 : /// infra repo, and thus introducing a new config field to pageserver and
147 : /// rolling it out to prod servers are separate commits in separate repos
148 : /// that can't be made or rolled back atomically.
149 : /// Rollbacks in particular pose a risk with deny_unknown_fields because
150 : /// the old pageserver binary may reject a new config field, resulting in
151 : /// an outage unless the person doing the pageserver rollback remembers
152 : /// to also revert the commit that added the config field in to the
153 : /// `pageserver.toml` templates in the internal infra repo.
154 : /// (A pre-deploy config check would eliminate this risk during rollbacks,
155 : /// cf [here](https://github.com/neondatabase/cloud/issues/24349).)
156 : /// In addition to this compatibility problem during emergency rollbacks,
157 : /// deny_unknown_fields adds further complications when decomissioning a feature
158 : /// flag: with deny_unknown_fields, we can't remove a flag from the [`ConfigToml`]
159 : /// until all prod servers' `pageserver.toml` files have been updated to a version
160 : /// that doesn't specify the flag. Otherwise new software would fail to start up.
161 : /// This adds the requirement for an intermediate step where the new config field
162 : /// is accepted but ignored, prolonging the decomissioning process by an entire
163 : /// release cycle.
164 : /// By contrast with unknown fields silently ignored, decomissioning a feature
165 : /// flag is a one-step process: we can skip the intermediate step and straight
166 : /// remove the field from the [`ConfigToml`]. We leave the field in the
167 : /// `pageserver.toml` files on prod servers until we reach certainty that we
168 : /// will not roll back to old software whose behavior was dependent on config.
169 : /// Then we can remove the field from the templates in the internal infra repo.
170 : /// This process is [documented internally](
171 : /// https://docs.neon.build/storage/pageserver_configuration.html).
172 : ///
173 : /// Note that above relaxed compatbility for the config format does NOT APPLY
174 : /// TO THE STORAGE FORMAT. As general guidance, when introducing storage format
175 : /// changes, ensure that the potential rollback target version will be compatible
176 : /// with the new format. This must hold regardless of what flags are set in in the `pageserver.toml`:
177 : /// any format version that exists in an environment must be compatible with the software that runs there.
178 : /// Use a pageserver.toml flag only to gate whether software _writes_ the new format.
179 : /// For more compatibility considerations, refer to [internal docs](
180 : /// https://docs.neon.build/storage/compat.html?highlight=compat#format-versions--compatibility)
181 : #[serde_as]
182 : #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
183 : #[serde(default)]
184 : pub struct ConfigToml {
185 : // types mapped 1:1 into the runtime PageServerConfig type
186 : pub listen_pg_addr: String,
187 : pub listen_http_addr: String,
188 : pub listen_https_addr: Option<String>,
189 : pub listen_grpc_addr: Option<String>,
190 : pub ssl_key_file: Utf8PathBuf,
191 : pub ssl_cert_file: Utf8PathBuf,
192 : #[serde(with = "humantime_serde")]
193 : pub ssl_cert_reload_period: Duration,
194 : pub ssl_ca_file: Option<Utf8PathBuf>,
195 : pub availability_zone: Option<String>,
196 : #[serde(with = "humantime_serde")]
197 : pub wait_lsn_timeout: Duration,
198 : #[serde(with = "humantime_serde")]
199 : pub wal_redo_timeout: Duration,
200 : pub superuser: String,
201 : pub locale: String,
202 : pub page_cache_size: usize,
203 : pub max_file_descriptors: usize,
204 : pub pg_distrib_dir: Option<Utf8PathBuf>,
205 : #[serde_as(as = "serde_with::DisplayFromStr")]
206 : pub http_auth_type: AuthType,
207 : #[serde_as(as = "serde_with::DisplayFromStr")]
208 : pub pg_auth_type: AuthType,
209 : pub grpc_auth_type: AuthType,
210 : pub auth_validation_public_key_path: Option<Utf8PathBuf>,
211 : pub remote_storage: Option<RemoteStorageConfig>,
212 : pub tenant_config: TenantConfigToml,
213 : #[serde_as(as = "serde_with::DisplayFromStr")]
214 : pub broker_endpoint: storage_broker::Uri,
215 : #[serde(with = "humantime_serde")]
216 : pub broker_keepalive_interval: Duration,
217 : #[serde_as(as = "serde_with::DisplayFromStr")]
218 : pub log_format: LogFormat,
219 : pub concurrent_tenant_warmup: NonZeroUsize,
220 : pub concurrent_tenant_size_logical_size_queries: NonZeroUsize,
221 : #[serde(with = "humantime_serde")]
222 : pub metric_collection_interval: Duration,
223 : pub metric_collection_endpoint: Option<reqwest::Url>,
224 : pub metric_collection_bucket: Option<RemoteStorageConfig>,
225 : #[serde(with = "humantime_serde")]
226 : pub synthetic_size_calculation_interval: Duration,
227 : pub disk_usage_based_eviction: DiskUsageEvictionTaskConfig,
228 : pub test_remote_failures: u64,
229 : pub test_remote_failures_probability: u64,
230 : pub ondemand_download_behavior_treat_error_as_warn: bool,
231 : #[serde(with = "humantime_serde")]
232 : pub background_task_maximum_delay: Duration,
233 : pub control_plane_api: Option<reqwest::Url>,
234 : pub control_plane_api_token: Option<String>,
235 : pub control_plane_emergency_mode: bool,
236 : /// Unstable feature: subject to change or removal without notice.
237 : /// See <https://github.com/neondatabase/neon/pull/9218>.
238 : pub import_pgdata_upcall_api: Option<reqwest::Url>,
239 : /// Unstable feature: subject to change or removal without notice.
240 : /// See <https://github.com/neondatabase/neon/pull/9218>.
241 : pub import_pgdata_upcall_api_token: Option<String>,
242 : /// Unstable feature: subject to change or removal without notice.
243 : /// See <https://github.com/neondatabase/neon/pull/9218>.
244 : pub import_pgdata_aws_endpoint_url: Option<reqwest::Url>,
245 : pub heatmap_upload_concurrency: usize,
246 : pub secondary_download_concurrency: usize,
247 : pub virtual_file_io_engine: Option<crate::models::virtual_file::IoEngineKind>,
248 : pub ingest_batch_size: u64,
249 : pub max_vectored_read_bytes: MaxVectoredReadBytes,
250 : pub max_get_vectored_keys: MaxGetVectoredKeys,
251 : pub image_compression: ImageCompressionAlgorithm,
252 : pub timeline_offloading: bool,
253 : pub ephemeral_bytes_per_memory_kb: usize,
254 : pub l0_flush: Option<crate::models::L0FlushConfig>,
255 : pub virtual_file_io_mode: Option<crate::models::virtual_file::IoMode>,
256 : #[serde(skip_serializing_if = "Option::is_none")]
257 : pub no_sync: Option<bool>,
258 : pub page_service_pipelining: PageServicePipeliningConfig,
259 : pub get_vectored_concurrent_io: GetVectoredConcurrentIo,
260 : pub enable_read_path_debugging: Option<bool>,
261 : #[serde(skip_serializing_if = "Option::is_none")]
262 : pub validate_wal_contiguity: Option<bool>,
263 : #[serde(skip_serializing_if = "Option::is_none")]
264 : pub load_previous_heatmap: Option<bool>,
265 : #[serde(skip_serializing_if = "Option::is_none")]
266 : pub generate_unarchival_heatmap: Option<bool>,
267 : pub tracing: Option<Tracing>,
268 : pub enable_tls_page_service_api: bool,
269 : pub dev_mode: bool,
270 : #[serde(skip_serializing_if = "Option::is_none")]
271 : pub posthog_config: Option<PostHogConfig>,
272 : pub timeline_import_config: TimelineImportConfig,
273 : #[serde(skip_serializing_if = "Option::is_none")]
274 : pub basebackup_cache_config: Option<BasebackupCacheConfig>,
275 : #[serde(skip_serializing_if = "Option::is_none")]
276 : pub image_layer_generation_large_timeline_threshold: Option<u64>,
277 : pub force_metric_collection_on_scrape: bool,
278 : }
279 :
280 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
281 : #[serde(default)]
282 : pub struct DiskUsageEvictionTaskConfig {
283 : pub max_usage_pct: utils::serde_percent::Percent,
284 : pub min_avail_bytes: u64,
285 : #[serde(with = "humantime_serde")]
286 : pub period: Duration,
287 : #[cfg(feature = "testing")]
288 : pub mock_statvfs: Option<statvfs::mock::Behavior>,
289 : /// Select sorting for evicted layers
290 : #[serde(default)]
291 : pub eviction_order: EvictionOrder,
292 : pub enabled: bool,
293 : }
294 :
295 : impl Default for DiskUsageEvictionTaskConfig {
296 140 : fn default() -> Self {
297 140 : Self {
298 140 : max_usage_pct: Percent::new(80).unwrap(),
299 140 : min_avail_bytes: 2_000_000_000,
300 140 : period: Duration::from_secs(60),
301 140 : #[cfg(feature = "testing")]
302 140 : mock_statvfs: None,
303 140 : eviction_order: EvictionOrder::default(),
304 140 : enabled: true,
305 140 : }
306 140 : }
307 : }
308 :
309 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
310 : #[serde(tag = "mode", rename_all = "kebab-case")]
311 : pub enum PageServicePipeliningConfig {
312 : Serial,
313 : Pipelined(PageServicePipeliningConfigPipelined),
314 : }
315 0 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
316 : pub struct PageServicePipeliningConfigPipelined {
317 : /// Failed config parsing and validation if larger than `max_get_vectored_keys`.
318 : pub max_batch_size: NonZeroUsize,
319 : pub execution: PageServiceProtocolPipelinedExecutionStrategy,
320 : // The default below is such that new versions of the software can start
321 : // with the old configuration.
322 : #[serde(default)]
323 : pub batching: PageServiceProtocolPipelinedBatchingStrategy,
324 : }
325 :
326 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
327 : #[serde(rename_all = "kebab-case")]
328 : pub enum PageServiceProtocolPipelinedExecutionStrategy {
329 : ConcurrentFutures,
330 : Tasks,
331 : }
332 :
333 0 : #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
334 : #[serde(rename_all = "kebab-case")]
335 : pub enum PageServiceProtocolPipelinedBatchingStrategy {
336 : /// All get page requests in a batch will be at the same LSN
337 : #[default]
338 : UniformLsn,
339 : /// Get page requests in a batch may be at different LSN
340 : ///
341 : /// One key cannot be present more than once at different LSNs in
342 : /// the same batch.
343 : ScatteredLsn,
344 : }
345 :
346 : #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
347 : #[serde(tag = "mode", rename_all = "kebab-case")]
348 : pub enum GetVectoredConcurrentIo {
349 : /// The read path is fully sequential: layers are visited
350 : /// one after the other and IOs are issued and waited upon
351 : /// from the same task that traverses the layers.
352 : Sequential,
353 : /// The read path still traverses layers sequentially, and
354 : /// index blocks will be read into the PS PageCache from
355 : /// that task, with waiting.
356 : /// But data IOs are dispatched and waited upon from a sidecar
357 : /// task so that the traversing task can continue to traverse
358 : /// layers while the IOs are in flight.
359 : /// If the PS PageCache miss rate is low, this improves
360 : /// throughput dramatically.
361 : SidecarTask,
362 : }
363 :
364 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
365 : pub struct Ratio {
366 : pub numerator: usize,
367 : pub denominator: usize,
368 : }
369 :
370 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
371 : pub struct OtelExporterConfig {
372 : pub endpoint: String,
373 : pub protocol: OtelExporterProtocol,
374 : #[serde(with = "humantime_serde")]
375 : pub timeout: Duration,
376 : }
377 :
378 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
379 : #[serde(rename_all = "kebab-case")]
380 : pub enum OtelExporterProtocol {
381 : Grpc,
382 : HttpBinary,
383 : HttpJson,
384 : }
385 :
386 0 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
387 : pub struct Tracing {
388 : pub sampling_ratio: Ratio,
389 : pub export_config: OtelExporterConfig,
390 : }
391 :
392 : impl From<&OtelExporterConfig> for tracing_utils::ExportConfig {
393 0 : fn from(val: &OtelExporterConfig) -> Self {
394 0 : tracing_utils::ExportConfig {
395 0 : endpoint: Some(val.endpoint.clone()),
396 0 : protocol: val.protocol.into(),
397 0 : timeout: val.timeout,
398 0 : }
399 0 : }
400 : }
401 :
402 : impl From<OtelExporterProtocol> for tracing_utils::Protocol {
403 0 : fn from(val: OtelExporterProtocol) -> Self {
404 0 : match val {
405 0 : OtelExporterProtocol::Grpc => tracing_utils::Protocol::Grpc,
406 0 : OtelExporterProtocol::HttpJson => tracing_utils::Protocol::HttpJson,
407 0 : OtelExporterProtocol::HttpBinary => tracing_utils::Protocol::HttpBinary,
408 : }
409 0 : }
410 : }
411 :
412 0 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
413 : pub struct TimelineImportConfig {
414 : pub import_job_concurrency: NonZeroUsize,
415 : pub import_job_soft_size_limit: NonZeroUsize,
416 : pub import_job_checkpoint_threshold: NonZeroUsize,
417 : /// Max size of the remote storage partial read done by any job
418 : pub import_job_max_byte_range_size: NonZeroUsize,
419 : }
420 :
421 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
422 : #[serde(default)]
423 : pub struct BasebackupCacheConfig {
424 : #[serde(with = "humantime_serde")]
425 : pub cleanup_period: Duration,
426 : /// Maximum total size of basebackup cache entries on disk in bytes.
427 : /// The cache may slightly exceed this limit because we do not know
428 : /// the exact size of the cache entry untill it's written to disk.
429 : pub max_total_size_bytes: u64,
430 : // TODO(diko): support max_entry_size_bytes.
431 : // pub max_entry_size_bytes: u64,
432 : pub max_size_entries: usize,
433 : /// Size of the channel used to send prepare requests to the basebackup cache worker.
434 : /// If exceeded, new prepare requests will be dropped.
435 : pub prepare_channel_size: usize,
436 : }
437 :
438 : impl Default for BasebackupCacheConfig {
439 0 : fn default() -> Self {
440 0 : Self {
441 0 : cleanup_period: Duration::from_secs(60),
442 0 : max_total_size_bytes: 1024 * 1024 * 1024, // 1 GiB
443 0 : // max_entry_size_bytes: 16 * 1024 * 1024, // 16 MiB
444 0 : max_size_entries: 10000,
445 0 : prepare_channel_size: 100,
446 0 : }
447 0 : }
448 : }
449 :
450 : pub mod statvfs {
451 : pub mod mock {
452 0 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
453 : #[serde(tag = "type")]
454 : pub enum Behavior {
455 : Success {
456 : blocksize: u64,
457 : total_blocks: u64,
458 : name_filter: Option<utils::serde_regex::Regex>,
459 : },
460 : #[cfg(feature = "testing")]
461 : Failure { mocked_error: MockedError },
462 : }
463 :
464 : #[cfg(feature = "testing")]
465 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
466 : #[allow(clippy::upper_case_acronyms)]
467 : pub enum MockedError {
468 : EIO,
469 : }
470 :
471 : #[cfg(feature = "testing")]
472 : impl From<MockedError> for nix::Error {
473 0 : fn from(e: MockedError) -> Self {
474 0 : match e {
475 0 : MockedError::EIO => nix::Error::EIO,
476 : }
477 0 : }
478 : }
479 : }
480 : }
481 :
482 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
483 : #[serde(tag = "type", content = "args")]
484 : pub enum EvictionOrder {
485 : RelativeAccessed {
486 : highest_layer_count_loses_first: bool,
487 : },
488 : }
489 :
490 : impl Default for EvictionOrder {
491 144 : fn default() -> Self {
492 144 : Self::RelativeAccessed {
493 144 : highest_layer_count_loses_first: true,
494 144 : }
495 144 : }
496 : }
497 :
498 : #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
499 : #[serde(transparent)]
500 : pub struct MaxVectoredReadBytes(pub NonZeroUsize);
501 :
502 : #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
503 : #[serde(transparent)]
504 : pub struct MaxGetVectoredKeys(NonZeroUsize);
505 :
506 : impl MaxGetVectoredKeys {
507 72004 : pub fn get(&self) -> usize {
508 72004 : self.0.get()
509 72004 : }
510 : }
511 :
512 : /// Tenant-level configuration values, used for various purposes.
513 : #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
514 : #[serde(default)]
515 : pub struct TenantConfigToml {
516 : // Flush out an inmemory layer, if it's holding WAL older than this
517 : // This puts a backstop on how much WAL needs to be re-digested if the
518 : // page server crashes.
519 : // This parameter actually determines L0 layer file size.
520 : pub checkpoint_distance: u64,
521 : // Inmemory layer is also flushed at least once in checkpoint_timeout to
522 : // eventually upload WAL after activity is stopped.
523 : #[serde(with = "humantime_serde")]
524 : pub checkpoint_timeout: Duration,
525 : // Target file size, when creating image and delta layers.
526 : // This parameter determines L1 layer file size.
527 : pub compaction_target_size: u64,
528 : // How often to check if there's compaction work to be done.
529 : // Duration::ZERO means automatic compaction is disabled.
530 : #[serde(with = "humantime_serde")]
531 : pub compaction_period: Duration,
532 : /// Level0 delta layer threshold for compaction.
533 : pub compaction_threshold: usize,
534 : /// Controls the amount of L0 included in a single compaction iteration.
535 : /// The unit is `checkpoint_distance`, i.e., a size.
536 : /// We add L0s to the set of layers to compact until their cumulative
537 : /// size exceeds `compaction_upper_limit * checkpoint_distance`.
538 : pub compaction_upper_limit: usize,
539 : pub compaction_algorithm: crate::models::CompactionAlgorithmSettings,
540 : /// If true, enable shard ancestor compaction (enabled by default).
541 : pub compaction_shard_ancestor: bool,
542 : /// If true, compact down L0 across all tenant timelines before doing regular compaction. L0
543 : /// compaction must be responsive to avoid read amp during heavy ingestion. Defaults to true.
544 : pub compaction_l0_first: bool,
545 : /// If true, use a separate semaphore (i.e. concurrency limit) for the L0 compaction pass. Only
546 : /// has an effect if `compaction_l0_first` is true. Defaults to true.
547 : pub compaction_l0_semaphore: bool,
548 : /// Level0 delta layer threshold at which to delay layer flushes such that they take 2x as long,
549 : /// and block on layer flushes during ephemeral layer rolls, for compaction backpressure. This
550 : /// helps compaction keep up with WAL ingestion, and avoids read amplification blowing up.
551 : /// Should be >compaction_threshold. 0 to disable. Defaults to 3x compaction_threshold.
552 : pub l0_flush_delay_threshold: Option<usize>,
553 : /// Level0 delta layer threshold at which to stall layer flushes. Must be >compaction_threshold
554 : /// to avoid deadlock. 0 to disable. Disabled by default.
555 : pub l0_flush_stall_threshold: Option<usize>,
556 : // Determines how much history is retained, to allow
557 : // branching and read replicas at an older point in time.
558 : // The unit is #of bytes of WAL.
559 : // Page versions older than this are garbage collected away.
560 : pub gc_horizon: u64,
561 : // Interval at which garbage collection is triggered.
562 : // Duration::ZERO means automatic GC is disabled
563 : #[serde(with = "humantime_serde")]
564 : pub gc_period: Duration,
565 : // Delta layer churn threshold to create L1 image layers.
566 : pub image_creation_threshold: usize,
567 : // HADRON
568 : // When the timeout is reached, PageServer will (1) force compact any remaining L0 deltas and
569 : // (2) create image layers if there are any L1 deltas.
570 : #[serde(with = "humantime_serde")]
571 : pub image_layer_force_creation_period: Option<Duration>,
572 : // Determines how much history is retained, to allow
573 : // branching and read replicas at an older point in time.
574 : // The unit is time.
575 : // Page versions older than this are garbage collected away.
576 : #[serde(with = "humantime_serde")]
577 : pub pitr_interval: Duration,
578 : /// Maximum amount of time to wait while opening a connection to receive wal, before erroring.
579 : #[serde(with = "humantime_serde")]
580 : pub walreceiver_connect_timeout: Duration,
581 : /// Considers safekeepers stalled after no WAL updates were received longer than this threshold.
582 : /// A stalled safekeeper will be changed to a newer one when it appears.
583 : #[serde(with = "humantime_serde")]
584 : pub lagging_wal_timeout: Duration,
585 : /// Considers safekeepers lagging when their WAL is behind another safekeeper for more than this threshold.
586 : /// A lagging safekeeper will be changed after `lagging_wal_timeout` time elapses since the last WAL update,
587 : /// to avoid eager reconnects.
588 : pub max_lsn_wal_lag: NonZeroU64,
589 : pub eviction_policy: crate::models::EvictionPolicy,
590 : pub min_resident_size_override: Option<u64>,
591 : // See the corresponding metric's help string.
592 : #[serde(with = "humantime_serde")]
593 : pub evictions_low_residence_duration_metric_threshold: Duration,
594 :
595 : /// If non-zero, the period between uploads of a heatmap from attached tenants. This
596 : /// may be disabled if a Tenant will not have secondary locations: only secondary
597 : /// locations will use the heatmap uploaded by attached locations.
598 : #[serde(with = "humantime_serde")]
599 : pub heatmap_period: Duration,
600 :
601 : /// If true then SLRU segments are dowloaded on demand, if false SLRU segments are included in basebackup
602 : pub lazy_slru_download: bool,
603 :
604 : pub timeline_get_throttle: crate::models::ThrottleConfig,
605 :
606 : // How much WAL must be ingested before checking again whether a new image layer is required.
607 : // Expresed in multiples of checkpoint distance.
608 : pub image_layer_creation_check_threshold: u8,
609 :
610 : // How many multiples of L0 `compaction_threshold` will preempt image layer creation and do L0 compaction.
611 : // Set to 0 to disable preemption.
612 : pub image_creation_preempt_threshold: usize,
613 :
614 : /// The length for an explicit LSN lease request.
615 : /// Layers needed to reconstruct pages at LSN will not be GC-ed during this interval.
616 : #[serde(with = "humantime_serde")]
617 : pub lsn_lease_length: Duration,
618 :
619 : /// The length for an implicit LSN lease granted as part of `get_lsn_by_timestamp` request.
620 : /// Layers needed to reconstruct pages at LSN will not be GC-ed during this interval.
621 : #[serde(with = "humantime_serde")]
622 : pub lsn_lease_length_for_ts: Duration,
623 :
624 : /// Enable auto-offloading of timelines.
625 : /// (either this flag or the pageserver-global one need to be set)
626 : pub timeline_offloading: bool,
627 :
628 : /// Enable rel_size_v2 for this tenant. Once enabled, the tenant will persist this information into
629 : /// `index_part.json`, and it cannot be reversed.
630 : pub rel_size_v2_enabled: bool,
631 :
632 : // gc-compaction related configs
633 : /// Enable automatic gc-compaction trigger on this tenant.
634 : pub gc_compaction_enabled: bool,
635 : /// Enable verification of gc-compaction results.
636 : pub gc_compaction_verification: bool,
637 : /// The initial threshold for gc-compaction in KB. Once the total size of layers below the gc-horizon is above this threshold,
638 : /// gc-compaction will be triggered.
639 : pub gc_compaction_initial_threshold_kb: u64,
640 : /// The ratio that triggers the auto gc-compaction. If (the total size of layers between L2 LSN and gc-horizon) / (size below the L2 LSN)
641 : /// is above this ratio, gc-compaction will be triggered.
642 : pub gc_compaction_ratio_percent: u64,
643 : /// Tenant level performance sampling ratio override. Controls the ratio of get page requests
644 : /// that will get perf sampling for the tenant.
645 : pub sampling_ratio: Option<Ratio>,
646 :
647 : /// Capacity of relsize snapshot cache (used by replicas).
648 : pub relsize_snapshot_cache_capacity: usize,
649 :
650 : /// Enable preparing basebackup on XLOG_CHECKPOINT_SHUTDOWN and using it in basebackup requests.
651 : // FIXME: Remove skip_serializing_if when the feature is stable.
652 : #[serde(skip_serializing_if = "std::ops::Not::not")]
653 : pub basebackup_cache_enabled: bool,
654 : }
655 :
656 : pub mod defaults {
657 : pub use storage_broker::DEFAULT_ENDPOINT as BROKER_DEFAULT_ENDPOINT;
658 :
659 : use crate::models::ImageCompressionAlgorithm;
660 :
661 : pub const DEFAULT_WAIT_LSN_TIMEOUT: &str = "300 s";
662 : pub const DEFAULT_WAL_REDO_TIMEOUT: &str = "60 s";
663 :
664 : pub const DEFAULT_SUPERUSER: &str = "cloud_admin";
665 : pub const DEFAULT_LOCALE: &str = if cfg!(target_os = "macos") {
666 : "C"
667 : } else {
668 : "C.UTF-8"
669 : };
670 :
671 : pub const DEFAULT_PAGE_CACHE_SIZE: usize = 8192;
672 : pub const DEFAULT_MAX_FILE_DESCRIPTORS: usize = 100;
673 :
674 : pub const DEFAULT_LOG_FORMAT: &str = "plain";
675 :
676 : pub const DEFAULT_CONCURRENT_TENANT_WARMUP: usize = 8;
677 :
678 : pub const DEFAULT_CONCURRENT_TENANT_SIZE_LOGICAL_SIZE_QUERIES: usize = 1;
679 :
680 : pub const DEFAULT_METRIC_COLLECTION_INTERVAL: &str = "10 min";
681 : pub const DEFAULT_METRIC_COLLECTION_ENDPOINT: Option<reqwest::Url> = None;
682 : pub const DEFAULT_SYNTHETIC_SIZE_CALCULATION_INTERVAL: &str = "10 min";
683 : pub const DEFAULT_BACKGROUND_TASK_MAXIMUM_DELAY: &str = "10s";
684 :
685 : pub const DEFAULT_HEATMAP_UPLOAD_CONCURRENCY: usize = 8;
686 : pub const DEFAULT_SECONDARY_DOWNLOAD_CONCURRENCY: usize = 1;
687 :
688 : pub const DEFAULT_INGEST_BATCH_SIZE: u64 = 100;
689 :
690 : /// Soft limit for the maximum size of a vectored read.
691 : ///
692 : /// This is determined by the largest NeonWalRecord that can exist (minus dbdir and reldir keys
693 : /// which are bounded by the blob io limits only). As of this writing, that is a `NeonWalRecord::ClogSetCommitted` record,
694 : /// with 32k xids. That's the max number of XIDS on a single CLOG page. The size of such a record
695 : /// is `sizeof(Transactionid) * 32768 + (some fixed overhead from 'timestamp`, the Vec length and whatever extra serde serialization adds)`.
696 : /// That is, slightly above 128 kB.
697 : pub const DEFAULT_MAX_VECTORED_READ_BYTES: usize = 130 * 1024; // 130 KiB
698 :
699 : pub const DEFAULT_MAX_GET_VECTORED_KEYS: usize = 32;
700 :
701 : pub const DEFAULT_IMAGE_COMPRESSION: ImageCompressionAlgorithm =
702 : ImageCompressionAlgorithm::Zstd { level: Some(1) };
703 :
704 : pub const DEFAULT_EPHEMERAL_BYTES_PER_MEMORY_KB: usize = 0;
705 :
706 : pub const DEFAULT_IO_BUFFER_ALIGNMENT: usize = 512;
707 :
708 : pub const DEFAULT_SSL_KEY_FILE: &str = "server.key";
709 : pub const DEFAULT_SSL_CERT_FILE: &str = "server.crt";
710 : }
711 :
712 : impl Default for ConfigToml {
713 138 : fn default() -> Self {
714 : use defaults::*;
715 :
716 : Self {
717 138 : listen_pg_addr: (DEFAULT_PG_LISTEN_ADDR.to_string()),
718 138 : listen_http_addr: (DEFAULT_HTTP_LISTEN_ADDR.to_string()),
719 138 : listen_https_addr: (None),
720 138 : listen_grpc_addr: None, // TODO: default to 127.0.0.1:51051
721 138 : ssl_key_file: Utf8PathBuf::from(DEFAULT_SSL_KEY_FILE),
722 138 : ssl_cert_file: Utf8PathBuf::from(DEFAULT_SSL_CERT_FILE),
723 138 : ssl_cert_reload_period: Duration::from_secs(60),
724 138 : ssl_ca_file: None,
725 138 : availability_zone: (None),
726 138 : wait_lsn_timeout: (humantime::parse_duration(DEFAULT_WAIT_LSN_TIMEOUT)
727 138 : .expect("cannot parse default wait lsn timeout")),
728 138 : wal_redo_timeout: (humantime::parse_duration(DEFAULT_WAL_REDO_TIMEOUT)
729 138 : .expect("cannot parse default wal redo timeout")),
730 138 : superuser: (DEFAULT_SUPERUSER.to_string()),
731 138 : locale: DEFAULT_LOCALE.to_string(),
732 : page_cache_size: (DEFAULT_PAGE_CACHE_SIZE),
733 : max_file_descriptors: (DEFAULT_MAX_FILE_DESCRIPTORS),
734 138 : pg_distrib_dir: None, // Utf8PathBuf::from("./pg_install"), // TODO: formely, this was std::env::current_dir()
735 138 : http_auth_type: (AuthType::Trust),
736 138 : pg_auth_type: (AuthType::Trust),
737 138 : grpc_auth_type: (AuthType::Trust),
738 138 : auth_validation_public_key_path: (None),
739 138 : remote_storage: None,
740 138 : broker_endpoint: (storage_broker::DEFAULT_ENDPOINT
741 138 : .parse()
742 138 : .expect("failed to parse default broker endpoint")),
743 138 : broker_keepalive_interval: (humantime::parse_duration(
744 138 : storage_broker::DEFAULT_KEEPALIVE_INTERVAL,
745 : )
746 138 : .expect("cannot parse default keepalive interval")),
747 138 : log_format: (LogFormat::from_str(DEFAULT_LOG_FORMAT).unwrap()),
748 :
749 138 : concurrent_tenant_warmup: (NonZeroUsize::new(DEFAULT_CONCURRENT_TENANT_WARMUP)
750 138 : .expect("Invalid default constant")),
751 138 : concurrent_tenant_size_logical_size_queries: NonZeroUsize::new(
752 : DEFAULT_CONCURRENT_TENANT_SIZE_LOGICAL_SIZE_QUERIES,
753 : )
754 138 : .unwrap(),
755 138 : metric_collection_interval: (humantime::parse_duration(
756 138 : DEFAULT_METRIC_COLLECTION_INTERVAL,
757 : )
758 138 : .expect("cannot parse default metric collection interval")),
759 138 : synthetic_size_calculation_interval: (humantime::parse_duration(
760 138 : DEFAULT_SYNTHETIC_SIZE_CALCULATION_INTERVAL,
761 : )
762 138 : .expect("cannot parse default synthetic size calculation interval")),
763 138 : metric_collection_endpoint: (DEFAULT_METRIC_COLLECTION_ENDPOINT),
764 :
765 138 : metric_collection_bucket: (None),
766 :
767 138 : disk_usage_based_eviction: DiskUsageEvictionTaskConfig::default(),
768 :
769 : test_remote_failures: (0),
770 : test_remote_failures_probability: (100),
771 :
772 : ondemand_download_behavior_treat_error_as_warn: (false),
773 :
774 138 : background_task_maximum_delay: (humantime::parse_duration(
775 138 : DEFAULT_BACKGROUND_TASK_MAXIMUM_DELAY,
776 : )
777 138 : .unwrap()),
778 :
779 138 : control_plane_api: (None),
780 138 : control_plane_api_token: (None),
781 : control_plane_emergency_mode: (false),
782 :
783 138 : import_pgdata_upcall_api: (None),
784 138 : import_pgdata_upcall_api_token: (None),
785 138 : import_pgdata_aws_endpoint_url: (None),
786 :
787 : heatmap_upload_concurrency: (DEFAULT_HEATMAP_UPLOAD_CONCURRENCY),
788 : secondary_download_concurrency: (DEFAULT_SECONDARY_DOWNLOAD_CONCURRENCY),
789 :
790 : ingest_batch_size: (DEFAULT_INGEST_BATCH_SIZE),
791 :
792 138 : virtual_file_io_engine: None,
793 :
794 138 : max_vectored_read_bytes: (MaxVectoredReadBytes(
795 138 : NonZeroUsize::new(DEFAULT_MAX_VECTORED_READ_BYTES).unwrap(),
796 138 : )),
797 138 : max_get_vectored_keys: (MaxGetVectoredKeys(
798 138 : NonZeroUsize::new(DEFAULT_MAX_GET_VECTORED_KEYS).unwrap(),
799 138 : )),
800 : image_compression: (DEFAULT_IMAGE_COMPRESSION),
801 : timeline_offloading: true,
802 : ephemeral_bytes_per_memory_kb: (DEFAULT_EPHEMERAL_BYTES_PER_MEMORY_KB),
803 138 : l0_flush: None,
804 138 : virtual_file_io_mode: None,
805 138 : tenant_config: TenantConfigToml::default(),
806 138 : no_sync: None,
807 138 : page_service_pipelining: PageServicePipeliningConfig::Pipelined(
808 138 : PageServicePipeliningConfigPipelined {
809 138 : max_batch_size: NonZeroUsize::new(32).unwrap(),
810 138 : execution: PageServiceProtocolPipelinedExecutionStrategy::ConcurrentFutures,
811 138 : batching: PageServiceProtocolPipelinedBatchingStrategy::ScatteredLsn,
812 138 : },
813 138 : ),
814 138 : get_vectored_concurrent_io: GetVectoredConcurrentIo::SidecarTask,
815 138 : enable_read_path_debugging: if cfg!(feature = "testing") {
816 138 : Some(true)
817 : } else {
818 0 : None
819 : },
820 138 : validate_wal_contiguity: None,
821 138 : load_previous_heatmap: None,
822 138 : generate_unarchival_heatmap: None,
823 138 : tracing: None,
824 : enable_tls_page_service_api: false,
825 : dev_mode: false,
826 138 : timeline_import_config: TimelineImportConfig {
827 138 : import_job_concurrency: NonZeroUsize::new(32).unwrap(),
828 138 : import_job_soft_size_limit: NonZeroUsize::new(256 * 1024 * 1024).unwrap(),
829 138 : import_job_checkpoint_threshold: NonZeroUsize::new(32).unwrap(),
830 138 : import_job_max_byte_range_size: NonZeroUsize::new(4 * 1024 * 1024).unwrap(),
831 138 : },
832 138 : basebackup_cache_config: None,
833 138 : posthog_config: None,
834 138 : image_layer_generation_large_timeline_threshold: Some(2 * 1024 * 1024 * 1024),
835 : force_metric_collection_on_scrape: true,
836 : }
837 138 : }
838 : }
839 :
840 : pub mod tenant_conf_defaults {
841 :
842 : // FIXME: This current value is very low. I would imagine something like 1 GB or 10 GB
843 : // would be more appropriate. But a low value forces the code to be exercised more,
844 : // which is good for now to trigger bugs.
845 : // This parameter actually determines L0 layer file size.
846 : pub const DEFAULT_CHECKPOINT_DISTANCE: u64 = 256 * 1024 * 1024;
847 : pub const DEFAULT_CHECKPOINT_TIMEOUT: &str = "10 m";
848 :
849 : // FIXME the below configs are only used by legacy algorithm. The new algorithm
850 : // has different parameters.
851 :
852 : // Target file size, when creating image and delta layers.
853 : // This parameter determines L1 layer file size.
854 : pub const DEFAULT_COMPACTION_TARGET_SIZE: u64 = 128 * 1024 * 1024;
855 :
856 : pub const DEFAULT_COMPACTION_PERIOD: &str = "20 s";
857 : pub const DEFAULT_COMPACTION_THRESHOLD: usize = 10;
858 : pub const DEFAULT_COMPACTION_SHARD_ANCESTOR: bool = true;
859 :
860 : // This value needs to be tuned to avoid OOM. We have 3/4*CPUs threads for L0 compaction, that's
861 : // 3/4*8=6 on most of our pageservers. Compacting 10 layers requires a maximum of
862 : // DEFAULT_CHECKPOINT_DISTANCE*10 memory, that's 2560MB. So with this config, we can get a maximum peak
863 : // compaction usage of 15360MB.
864 : pub const DEFAULT_COMPACTION_UPPER_LIMIT: usize = 10;
865 : // Enable L0 compaction pass and semaphore by default. L0 compaction must be responsive to avoid
866 : // read amp.
867 : pub const DEFAULT_COMPACTION_L0_FIRST: bool = true;
868 : pub const DEFAULT_COMPACTION_L0_SEMAPHORE: bool = true;
869 :
870 : pub const DEFAULT_COMPACTION_ALGORITHM: crate::models::CompactionAlgorithm =
871 : crate::models::CompactionAlgorithm::Legacy;
872 :
873 : pub const DEFAULT_GC_HORIZON: u64 = 64 * 1024 * 1024;
874 :
875 : // Large DEFAULT_GC_PERIOD is fine as long as PITR_INTERVAL is larger.
876 : // If there's a need to decrease this value, first make sure that GC
877 : // doesn't hold a layer map write lock for non-trivial operations.
878 : // Relevant: https://github.com/neondatabase/neon/issues/3394
879 : pub const DEFAULT_GC_PERIOD: &str = "1 hr";
880 : pub const DEFAULT_IMAGE_CREATION_THRESHOLD: usize = 3;
881 : // Currently, any value other than 0 will trigger image layer creation preemption immediately with L0 backpressure
882 : // without looking at the exact number of L0 layers.
883 : // It was expected to have the following behavior:
884 : // > If there are more than threshold * compaction_threshold (that is 3 * 10 in the default config) L0 layers, image
885 : // > layer creation will end immediately. Set to 0 to disable.
886 : pub const DEFAULT_IMAGE_CREATION_PREEMPT_THRESHOLD: usize = 3;
887 : pub const DEFAULT_PITR_INTERVAL: &str = "7 days";
888 : pub const DEFAULT_WALRECEIVER_CONNECT_TIMEOUT: &str = "10 seconds";
889 : pub const DEFAULT_WALRECEIVER_LAGGING_WAL_TIMEOUT: &str = "10 seconds";
890 : // The default limit on WAL lag should be set to avoid causing disconnects under high throughput
891 : // scenarios: since the broker stats are updated ~1/s, a value of 1GiB should be sufficient for
892 : // throughputs up to 1GiB/s per timeline.
893 : pub const DEFAULT_MAX_WALRECEIVER_LSN_WAL_LAG: u64 = 1024 * 1024 * 1024;
894 : pub const DEFAULT_EVICTIONS_LOW_RESIDENCE_DURATION_METRIC_THRESHOLD: &str = "24 hour";
895 : // By default ingest enough WAL for two new L0 layers before checking if new image
896 : // image layers should be created.
897 : pub const DEFAULT_IMAGE_LAYER_CREATION_CHECK_THRESHOLD: u8 = 2;
898 : pub const DEFAULT_GC_COMPACTION_ENABLED: bool = true;
899 : pub const DEFAULT_GC_COMPACTION_VERIFICATION: bool = true;
900 : pub const DEFAULT_GC_COMPACTION_INITIAL_THRESHOLD_KB: u64 = 5 * 1024 * 1024; // 5GB
901 : pub const DEFAULT_GC_COMPACTION_RATIO_PERCENT: u64 = 100;
902 : pub const DEFAULT_RELSIZE_SNAPSHOT_CACHE_CAPACITY: usize = 1000;
903 : }
904 :
905 : impl Default for TenantConfigToml {
906 138 : fn default() -> Self {
907 : use tenant_conf_defaults::*;
908 138 : Self {
909 138 : checkpoint_distance: DEFAULT_CHECKPOINT_DISTANCE,
910 138 : checkpoint_timeout: humantime::parse_duration(DEFAULT_CHECKPOINT_TIMEOUT)
911 138 : .expect("cannot parse default checkpoint timeout"),
912 138 : compaction_target_size: DEFAULT_COMPACTION_TARGET_SIZE,
913 138 : compaction_period: humantime::parse_duration(DEFAULT_COMPACTION_PERIOD)
914 138 : .expect("cannot parse default compaction period"),
915 138 : compaction_threshold: DEFAULT_COMPACTION_THRESHOLD,
916 138 : compaction_upper_limit: DEFAULT_COMPACTION_UPPER_LIMIT,
917 138 : compaction_algorithm: crate::models::CompactionAlgorithmSettings {
918 138 : kind: DEFAULT_COMPACTION_ALGORITHM,
919 138 : },
920 138 : compaction_shard_ancestor: DEFAULT_COMPACTION_SHARD_ANCESTOR,
921 138 : compaction_l0_first: DEFAULT_COMPACTION_L0_FIRST,
922 138 : compaction_l0_semaphore: DEFAULT_COMPACTION_L0_SEMAPHORE,
923 138 : l0_flush_delay_threshold: None,
924 138 : l0_flush_stall_threshold: None,
925 138 : gc_horizon: DEFAULT_GC_HORIZON,
926 138 : gc_period: humantime::parse_duration(DEFAULT_GC_PERIOD)
927 138 : .expect("cannot parse default gc period"),
928 138 : image_creation_threshold: DEFAULT_IMAGE_CREATION_THRESHOLD,
929 138 : image_layer_force_creation_period: None,
930 138 : pitr_interval: humantime::parse_duration(DEFAULT_PITR_INTERVAL)
931 138 : .expect("cannot parse default PITR interval"),
932 138 : walreceiver_connect_timeout: humantime::parse_duration(
933 138 : DEFAULT_WALRECEIVER_CONNECT_TIMEOUT,
934 138 : )
935 138 : .expect("cannot parse default walreceiver connect timeout"),
936 138 : lagging_wal_timeout: humantime::parse_duration(DEFAULT_WALRECEIVER_LAGGING_WAL_TIMEOUT)
937 138 : .expect("cannot parse default walreceiver lagging wal timeout"),
938 138 : max_lsn_wal_lag: NonZeroU64::new(DEFAULT_MAX_WALRECEIVER_LSN_WAL_LAG)
939 138 : .expect("cannot parse default max walreceiver Lsn wal lag"),
940 138 : eviction_policy: crate::models::EvictionPolicy::NoEviction,
941 138 : min_resident_size_override: None,
942 138 : evictions_low_residence_duration_metric_threshold: humantime::parse_duration(
943 138 : DEFAULT_EVICTIONS_LOW_RESIDENCE_DURATION_METRIC_THRESHOLD,
944 138 : )
945 138 : .expect("cannot parse default evictions_low_residence_duration_metric_threshold"),
946 138 : heatmap_period: Duration::ZERO,
947 138 : lazy_slru_download: false,
948 138 : timeline_get_throttle: crate::models::ThrottleConfig::disabled(),
949 138 : image_layer_creation_check_threshold: DEFAULT_IMAGE_LAYER_CREATION_CHECK_THRESHOLD,
950 138 : image_creation_preempt_threshold: DEFAULT_IMAGE_CREATION_PREEMPT_THRESHOLD,
951 138 : lsn_lease_length: LsnLease::DEFAULT_LENGTH,
952 138 : lsn_lease_length_for_ts: LsnLease::DEFAULT_LENGTH_FOR_TS,
953 138 : timeline_offloading: true,
954 138 : rel_size_v2_enabled: false,
955 138 : gc_compaction_enabled: DEFAULT_GC_COMPACTION_ENABLED,
956 138 : gc_compaction_verification: DEFAULT_GC_COMPACTION_VERIFICATION,
957 138 : gc_compaction_initial_threshold_kb: DEFAULT_GC_COMPACTION_INITIAL_THRESHOLD_KB,
958 138 : gc_compaction_ratio_percent: DEFAULT_GC_COMPACTION_RATIO_PERCENT,
959 138 : sampling_ratio: None,
960 138 : relsize_snapshot_cache_capacity: DEFAULT_RELSIZE_SNAPSHOT_CACHE_CAPACITY,
961 138 : basebackup_cache_enabled: false,
962 138 : }
963 138 : }
964 : }
|