Skip to main content

mz_storage_types/
dyncfgs.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Dyncfgs used by the storage layer. Despite their name, these can be used
11//! "statically" during rendering, or dynamically within timely operators.
12
13use mz_dyncfg::{Config, ConfigSet, ParameterScope};
14use std::time::Duration;
15
16/// When dataflows observe an invariant violation it is either due to a bug or due to the cluster
17/// being shut down. This configuration defines the amount of time to wait before panicking the
18/// process, which will register the invariant violation.
19pub const CLUSTER_SHUTDOWN_GRACE_PERIOD: Config<Duration> = Config::new(
20    "storage_cluster_shutdown_grace_period",
21    Duration::from_secs(10 * 60),
22    "When dataflows observe an invariant violation it is either due to a bug or due to \
23        the cluster being shut down. This configuration defines the amount of time to \
24        wait before panicking the process, which will register the invariant violation.",
25    ParameterScope::Replica,
26);
27
28// Flow control
29
30/// Whether rendering should use `mz_join_core` rather than DD's `JoinCore::join_core`.
31/// Configuration for basic hydration backpressure.
32pub const DELAY_SOURCES_PAST_REHYDRATION: Config<bool> = Config::new(
33    "storage_dataflow_delay_sources_past_rehydration",
34    // This was original `false`, but it is not enabled everywhere.
35    true,
36    "Whether or not to delay sources producing values in some scenarios \
37        (namely, upsert) till after rehydration is finished",
38    ParameterScope::Environment,
39);
40
41/// Whether storage dataflows should suspend execution while downstream operators are still
42/// processing data.
43pub const SUSPENDABLE_SOURCES: Config<bool> = Config::new(
44    "storage_dataflow_suspendable_sources",
45    true,
46    "Whether storage dataflows should suspend execution while downstream operators are still \
47        processing data.",
48    ParameterScope::Environment,
49);
50
51// Controller
52
53/// When enabled, force-downgrade the controller's since handle on the shard
54/// during shard finalization.
55pub const STORAGE_DOWNGRADE_SINCE_DURING_FINALIZATION: Config<bool> = Config::new(
56    "storage_downgrade_since_during_finalization",
57    // This was original `false`, but it is not enabled everywhere.
58    true,
59    "When enabled, force-downgrade the controller's since handle on the shard\
60    during shard finalization",
61    ParameterScope::Environment,
62);
63
64/// The interval of time to keep when truncating the replica metrics history.
65pub const REPLICA_METRICS_HISTORY_RETENTION_INTERVAL: Config<Duration> = Config::new(
66    "replica_metrics_history_retention_interval",
67    Duration::from_secs(60 * 60 * 24 * 30), // 30 days
68    "The interval of time to keep when truncating the replica metrics history.",
69    ParameterScope::Environment,
70);
71
72/// The interval of time to keep when truncating the wallclock lag history.
73pub const WALLCLOCK_LAG_HISTORY_RETENTION_INTERVAL: Config<Duration> = Config::new(
74    "wallclock_lag_history_retention_interval",
75    Duration::from_secs(60 * 60 * 24 * 30), // 30 days
76    "The interval of time to keep when truncating the wallclock lag history.",
77    ParameterScope::Environment,
78);
79
80/// The interval of time to keep when truncating the wallclock lag histogram.
81pub const WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RETENTION_INTERVAL: Config<Duration> = Config::new(
82    "wallclock_global_lag_histogram_retention_interval",
83    Duration::from_secs(60 * 60 * 24 * 30), // 30 days
84    "The interval of time to keep when truncating the wallclock lag histogram.",
85    ParameterScope::Environment,
86);
87
88// Kafka
89
90/// Rules for enriching the `client.id` property of Kafka clients with
91/// additional data.
92///
93/// The configuration value must be a JSON array of objects containing keys
94/// named `pattern` and `payload`, both of type string. Rules are checked in the
95/// order they are defined. The rule's pattern must be a regular expression
96/// understood by the Rust `regex` crate. If the rule's pattern matches the
97/// address of any broker in the connection, then the payload is appended to the
98/// client ID. A rule's payload is always prefixed with `-`, to separate it from
99/// the preceding data in the client ID.
100pub const KAFKA_CLIENT_ID_ENRICHMENT_RULES: Config<fn() -> serde_json::Value> = Config::new(
101    "kafka_client_id_enrichment_rules",
102    || serde_json::json!([]),
103    "Rules for enriching the `client.id` property of Kafka clients with additional data.",
104    ParameterScope::Environment,
105);
106
107/// The maximum time we will wait before re-polling rdkafka to see if new partitions/data are
108/// available.
109pub const KAFKA_POLL_MAX_WAIT: Config<Duration> = Config::new(
110    "kafka_poll_max_wait",
111    Duration::from_secs(1),
112    "The maximum time we will wait before re-polling rdkafka to see if new partitions/data are \
113    available.",
114    ParameterScope::Replica,
115);
116
117/// How often Kafka sources recommit offsets that have not changed, so that brokers do not expire
118/// them. Must stay well below the broker's `offsets.retention.minutes`. Zero disables it.
119pub const KAFKA_OFFSET_COMMIT_REFRESH_INTERVAL: Config<Duration> = Config::new(
120    "kafka_offset_commit_refresh_interval",
121    Duration::from_secs(10 * 60),
122    "How often Kafka sources recommit offsets that have not changed, which must stay well below \
123    the broker's offsets.retention.minutes. Zero disables it.",
124    ParameterScope::Replica,
125);
126
127/// Whether to check the low watermark for Kafka sources and error if the start offset/resume
128/// upper has been compacted away.
129/// Environment-scoped because it decides whether a definite error is emitted.
130/// Replicas of one cluster disagreeing would write different collection
131/// contents, so the value has to be coherent across them.
132pub const KAFKA_LOW_WATERMARK_CHECK: Config<bool> = Config::new(
133    "kafka_low_watermark_check",
134    true,
135    "Whether to check the low watermark for Kafka sources and error if the start \
136    offset/resume upper has been compacted away.",
137    ParameterScope::Environment,
138);
139
140pub const KAFKA_DEFAULT_AWS_PRIVATELINK_ENDPOINT_IDENTIFICATION_ALGORITHM: Config<&'static str> =
141    Config::new(
142        "kafka_default_aws_privatelink_endpoint_identification_algorithm",
143        // Default to no hostname verification, which is the default in versions of `librdkafka <1.9.2`.
144        "none",
145        "The value we set for the 'ssl.endpoint.identification.algorithm' option in the Kafka \
146    Connection config. default: 'none'",
147        ParameterScope::Environment,
148    );
149
150pub const KAFKA_BUFFERED_EVENT_RESIZE_THRESHOLD_ELEMENTS: Config<usize> = Config::new(
151    "kafka_buffered_event_resize_threshold_elements",
152    1000,
153    "In the Kafka sink operator we might need to buffer messages before emitting them. As a \
154        performance optimization we reuse the buffer allocations, but shrink it to retain at \
155        most this number of elements.",
156    ParameterScope::Replica,
157);
158
159/// Sets retry.backoff.ms in librdkafka for sources and sinks.
160/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
161pub const KAFKA_RETRY_BACKOFF: Config<Duration> = Config::new(
162    "kafka_retry_backoff",
163    Duration::from_millis(100),
164    "Sets retry.backoff.ms in librdkafka for sources and sinks.",
165    ParameterScope::Replica,
166);
167
168/// Sets retry.backoff.max.ms in librdkafka for sources and sinks.
169/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
170pub const KAFKA_RETRY_BACKOFF_MAX: Config<Duration> = Config::new(
171    "kafka_retry_backoff_max",
172    Duration::from_secs(1),
173    "Sets retry.backoff.max.ms in librdkafka for sources and sinks.",
174    ParameterScope::Replica,
175);
176
177/// Sets reconnect.backoff.ms in librdkafka for sources and sinks.
178/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
179pub const KAFKA_RECONNECT_BACKOFF: Config<Duration> = Config::new(
180    "kafka_reconnect_backoff",
181    Duration::from_millis(100),
182    "Sets reconnect.backoff.ms in librdkafka for sources and sinks.",
183    ParameterScope::Replica,
184);
185
186/// Sets reconnect.backoff.max.ms in librdkafka for sources and sinks.
187/// We default to 30s instead of 10s to avoid constant reconnection attempts in the event of
188/// auth changes or unavailability.
189/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
190pub const KAFKA_RECONNECT_BACKOFF_MAX: Config<Duration> = Config::new(
191    "kafka_reconnect_backoff_max",
192    Duration::from_secs(30),
193    "Sets reconnect.backoff.max.ms in librdkafka for sources and sinks.",
194    ParameterScope::Replica,
195);
196
197/// Sets message.max.bytes in librdkafka for Kafka sink producers.
198/// Maximum Kafka protocol request message size. Producer-side, this controls
199/// the maximum size of a single message (including framing) that the client
200/// will allow. Defaults to the librdkafka default of 1,000,000 bytes.
201/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
202pub const KAFKA_SINK_MESSAGE_MAX_BYTES: Config<usize> = Config::new(
203    "kafka_sink_message_max_bytes",
204    1_000_000,
205    "Sets message.max.bytes in librdkafka for Kafka sink producers.",
206    ParameterScope::Environment,
207);
208
209/// Sets batch.size in librdkafka for Kafka sink producers.
210/// Maximum size (in bytes) of all messages batched in one MessageSet, including
211/// protocol framing overhead. Defaults to the librdkafka default of 1,000,000
212/// bytes.
213/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
214pub const KAFKA_SINK_BATCH_SIZE: Config<usize> = Config::new(
215    "kafka_sink_batch_size",
216    1_000_000,
217    "Sets batch.size in librdkafka for Kafka sink producers.",
218    ParameterScope::Environment,
219);
220
221/// Sets batch.num.messages in librdkafka for Kafka sink producers.
222/// Maximum number of messages batched in one MessageSet. Defaults to the
223/// librdkafka default of 10,000 messages.
224/// See <https://docs.confluent.io/platform/current/clients/librdkafka/html/md_CONFIGURATION.html>
225pub const KAFKA_SINK_BATCH_NUM_MESSAGES: Config<usize> = Config::new(
226    "kafka_sink_batch_num_messages",
227    10_000,
228    "Sets batch.num.messages in librdkafka for Kafka sink producers.",
229    ParameterScope::Environment,
230);
231
232/// Whether Kafka sinks attach a `materialize-sink-id` header, holding the
233/// sink's `GlobalId`, to every message they produce.
234///
235/// Environment-scoped because it changes the messages the sink produces.
236pub const KAFKA_SINK_EMIT_SINK_ID_HEADER: Config<bool> = Config::new(
237    "kafka_sink_emit_sink_id_header",
238    true,
239    "Whether Kafka sinks attach a `materialize-sink-id` header to every message they produce.",
240    ParameterScope::Environment,
241);
242
243// MySQL
244
245/// Replication heartbeat interval requested from the MySQL server.
246pub const MYSQL_REPLICATION_HEARTBEAT_INTERVAL: Config<Duration> = Config::new(
247    "mysql_replication_heartbeat_interval",
248    Duration::from_secs(30),
249    "Replication heartbeat interval requested from the MySQL server.",
250    ParameterScope::Replica,
251);
252
253/// Whether to split snapshot reads of tables with a supported single-column
254/// primary key into per-worker PK ranges. When disabled, each table is read
255/// whole by a single worker.
256pub static MYSQL_SOURCE_SNAPSHOT_PARALLELISM: Config<bool> = Config::new(
257    "mysql_source_snapshot_parallelism",
258    true,
259    "Whether to split MySQL snapshot reads across workers by primary-key ranges.",
260    ParameterScope::Replica,
261);
262
263/// Smallest estimated row count the MySQL snapshot partitioner attempts to subdivide.
264pub static MYSQL_SOURCE_SNAPSHOT_PARTITION_MIN_ROWS: Config<usize> = Config::new(
265    "mysql_source_snapshot_partition_min_rows",
266    50_000,
267    "Minimum estimated rows the MySQL snapshot partitioner attempts to split.",
268    ParameterScope::Replica,
269);
270
271/// Cap on string primary key prefixes visited when attempting to partition a table for
272/// parallel snapshotting in MySQL. This limits runtime on high-cardinality prefixes,
273/// and will return correct but likely more skewed boundaries on budget exhaustion.
274pub static MYSQL_SOURCE_SNAPSHOT_PARTITION_PROBED_PREFIXES_PER_BILLION_ROWS: Config<usize> =
275    Config::new(
276        "mysql_source_snapshot_partition_probed_prefixes_per_billion_rows",
277        1_000,
278        "Cap on MySQL snapshot PK-prefix partitioning probed prefixes per table, per billion \
279     estimated rows; when exhausted, splitting stops early with coarser partition boundaries. \
280     The per-table budget is additionally hard-capped at 5000.",
281        ParameterScope::Replica,
282    );
283
284/// If the optimizer estimates the table has fewer rows than this, compute the exact row count
285/// with `COUNT(*)`. Otherwise, report the `information_schema` estimate directly.
286pub static MYSQL_SOURCE_SNAPSHOT_EXACT_COUNT_MAX_ROWS: Config<usize> = Config::new(
287    "mysql_source_snapshot_exact_count_max_rows",
288    1_000_000,
289    "Maximum estimated table size for which MySQL snapshots compute an exact COUNT(*) \
290     for the size gauge; larger tables report the information_schema estimate.",
291    ParameterScope::Replica,
292);
293
294// Postgres
295
296/// Interval to poll `confirmed_flush_lsn` to get a resumption lsn.
297pub const PG_FETCH_SLOT_RESUME_LSN_INTERVAL: Config<Duration> = Config::new(
298    "postgres_fetch_slot_resume_lsn_interval",
299    Duration::from_millis(500),
300    "Interval to poll `confirmed_flush_lsn` to get a resumption lsn.",
301    ParameterScope::Replica,
302);
303
304/// Timeout for `CREATE_REPLICATION_SLOT` on the upstream server. Applied as the session's
305/// `lock_timeout`, which bounds the wait for in-progress upstream transactions to end. This has
306/// no effect when the upsteam is a physical standby.
307pub const PG_SOURCE_REPLICATION_SLOT_CREATION_TIMEOUT: Config<Duration> = Config::new(
308    "pg_source_replication_slot_creation_timeout",
309    Duration::from_secs(60),
310    "Timeout for creating a replication slot on the upstream PostgreSQL server. Applied as \
311     `lock_timeout`, which bounds the wait for in-progress upstream transactions to end. \
312     Has no effect with physical standbys.",
313    ParameterScope::Replica,
314);
315
316/// Interval to re-validate the schemas of ingested tables.
317pub const PG_SCHEMA_VALIDATION_INTERVAL: Config<Duration> = Config::new(
318    "pg_schema_validation_interval",
319    Duration::from_secs(15),
320    "Interval to re-validate the schemas of ingested tables.",
321    ParameterScope::Environment,
322);
323
324/// Controls behavior of PG Source when the upstream DB timeline changes. The default behavior
325/// is to emit a definite error forcing source recreation. In cases of HA, the upstream DB may
326/// provide guarantees of failover without loss of data (e.g. CloudSQL maintenance). Changing this
327/// flag puts the onus on the customer to recreate the source if the upstream DB changes timeline
328/// in a way that introduces data loss (e.g. manual failover, restore, etc.).
329/// Environment-scoped because it decides whether a definite error is emitted.
330/// Replicas of one cluster disagreeing would write different collection
331/// contents, so the value has to be coherent across them.
332pub static PG_SOURCE_VALIDATE_TIMELINE: Config<bool> = Config::new(
333    "pg_source_validate_timeline",
334    true,
335    "Whether to treat a timeline switch as a definite error",
336    ParameterScope::Environment,
337);
338
339/// Controls behavior of the SQL Server source when the upstream DB restore history changes. The
340/// default behavior is to emit a definite error, forcing source recreation.  In cases of Always
341/// On Availability Group (AOAG), the upstream DB may guarantee continuity without loss of data.
342/// Changing this flag puts the onus on the customer to recreate the source if the upstream DB
343/// changes in a way that introduces data loss.
344/// Environment-scoped because it decides whether a definite error is emitted.
345/// Replicas of one cluster disagreeing would write different collection
346/// contents, so the value has to be coherent across them.
347pub static SQL_SERVER_SOURCE_VALIDATE_RESTORE_HISTORY: Config<bool> = Config::new(
348    "sql_server_source_validate_restore_history",
349    true,
350    "Whether to treat a restore history change as a definite error",
351    ParameterScope::Environment,
352);
353
354// AWS
355
356/// The AWS SDK's connect timeout on the AssumeRole prefetcher's STS calls.
357/// Raise it if credential fetches time out on slow connections.
358///
359/// The default matches the SDK's own 3.1 second default, so behavior only
360/// changes when an operator raises it.
361///
362/// Read once when a connection is set up. Running sinks are unaffected by
363/// changes until their dataflow restarts.
364pub const AWS_PREFETCH_STS_CONNECT_TIMEOUT: Config<Duration> = Config::new(
365    "aws_prefetch_sts_connect_timeout",
366    Duration::from_millis(3100),
367    "Connect timeout for the AWS AssumeRole credentials prefetcher's STS calls.",
368    ParameterScope::Replica,
369);
370
371// Networking
372
373/// Whether or not to enforce that external connection addresses are global
374/// (not private or local) when resolving them.
375///
376/// Read on both `environmentd` (purification, `COPY` planning) and the replica.
377/// Deliberately environment-scoped even so: this is a security control, and a
378/// per-replica override would weaken it for part of the environment only.
379pub const ENFORCE_EXTERNAL_ADDRESSES: Config<bool> = Config::new(
380    "storage_enforce_external_addresses",
381    false,
382    "Whether or not to enforce that external connection addresses are global \
383          (not private or local) when resolving them",
384    ParameterScope::Environment,
385);
386
387// Upsert
388
389/// Whether or not to prevent buffering the entire _upstream_ snapshot in
390/// memory when processing it in memory. This is generally understood to reduce
391/// memory consumption.
392///
393/// When false, in general the memory utilization while processing the snapshot is:
394/// # of snapshot updates + (# of unique keys in snapshot * N), where N is some small
395/// integer number of buffers
396///
397/// When true, in general the memory utilization while processing the snapshot is:
398/// # of snapshot updates + (RocksDB buffers + # of keys in batch produced by upstream) * # of
399/// workers.
400///
401/// Without hydration flow control, which is not yet implemented, there are workloads that may
402/// cause the latter to use more memory, which is why we offer this configuration.
403pub const STORAGE_UPSERT_PREVENT_SNAPSHOT_BUFFERING: Config<bool> = Config::new(
404    "storage_upsert_prevent_snapshot_buffering",
405    true,
406    "Prevent snapshot buffering in upsert.",
407    ParameterScope::Replica,
408);
409
410/// Whether to enable the merge operator in upsert for the RocksDB backend.
411pub const STORAGE_ROCKSDB_USE_MERGE_OPERATOR: Config<bool> = Config::new(
412    "storage_rocksdb_use_merge_operator",
413    true,
414    "Use the native rocksdb merge operator where possible.",
415    ParameterScope::Environment,
416);
417
418/// If `storage_upsert_prevent_snapshot_buffering` is true, this prevents the upsert
419/// operator from buffering too many events from the upstream snapshot. In the absence
420/// of hydration flow control, this could prevent certain workloads from causing egregiously
421/// large writes to RocksDB.
422pub const STORAGE_UPSERT_MAX_SNAPSHOT_BATCH_BUFFERING: Config<Option<usize>> = Config::new(
423    "storage_upsert_max_snapshot_batch_buffering",
424    None,
425    "Limit snapshot buffering in upsert.",
426    ParameterScope::Replica,
427);
428
429/// Allow the upsert-v2 stash to spill out of RSS. Off by default; while off,
430/// the stash keeps everything resident.
431///
432/// The spill mechanism depends on the stash flavor
433/// ([`ENABLE_UPSERT_CHUNKED_STASH`]):
434///
435/// * Chunked: sets the storage chunk spill gate
436///   (`mz_timely_util::columnar::chunk::StorageSpill`), which only upsert's
437///   chunks read, independently of compute's
438///   `enable_column_paged_batcher_spill`. Spilled chunks draw on the one
439///   shared pool budget, and the gate is consulted at every chunk commit, so
440///   flips apply to running dataflows.
441/// * Paged: gates the storage-owned column pager the stash and feedback
442///   arrangement route their chains through, independently of compute's
443///   `enable_column_paged_batcher_spill`. Captured at operator
444///   construction, so flips apply to dataflows created after the change.
445///
446/// Enabling it also installs the process buffer pool (via compute's config
447/// handler, which reads this flag from the aggregate dyncfg set), so
448/// storage-only spilling needs no compute-side gate.
449pub const ENABLE_UPSERT_PAGED_SPILL: Config<bool> = Config::new(
450    "enable_upsert_paged_spill",
451    false,
452    "Allow the upsert-v2 stash to spill out of RSS, through the buffer pool (chunked stash \
453     flavor) or the column pager (paged stash flavor).",
454    ParameterScope::Replica,
455);
456
457/// Use the chunked stash flavor for the upsert-v2 operator: differential's
458/// chunk merge batcher for the source stash and a spine of chunk batches for
459/// the feedback arrangement, with a bulk-probe drain. When `false` (the
460/// default), the paged flavor is used: the paged columnar merge batcher and a
461/// `ValRowSpine`, with a cursor-based drain. See
462/// `mz_storage::upsert_continual_feedback_v2::UpsertStashFlavor` for the
463/// comparison.
464///
465/// Read at operator construction time; flips take effect on dataflows created
466/// after the change. Only meaningful when [`ENABLE_UPSERT_V2`] is `true`.
467/// Spilling in either flavor is gated by [`ENABLE_UPSERT_PAGED_SPILL`].
468pub const ENABLE_UPSERT_CHUNKED_STASH: Config<bool> = Config::new(
469    "enable_upsert_chunked_stash",
470    false,
471    "Use the chunk batcher and chunk spine for the upsert-v2 stash and feedback arrangement, \
472     instead of the paged columnar merge batcher and ValRowSpine. Only meaningful when \
473     enable_upsert_v2 is true.",
474    ParameterScope::Replica,
475);
476
477// RocksDB
478
479/// How many times to try to cleanup old RocksDB DB's on disk before giving up.
480pub const STORAGE_ROCKSDB_CLEANUP_TRIES: Config<usize> = Config::new(
481    "storage_rocksdb_cleanup_tries",
482    5,
483    "How many times to try to cleanup old RocksDB DB's on disk before giving up.",
484    ParameterScope::Replica,
485);
486
487/// Delay interval when reconnecting to a source / sink after halt.
488pub const STORAGE_SUSPEND_AND_RESTART_DELAY: Config<Duration> = Config::new(
489    "storage_suspend_and_restart_delay",
490    Duration::from_secs(5),
491    "Delay interval when reconnecting to a source / sink after halt.",
492    ParameterScope::Replica,
493);
494
495/// Whether to use the new continual feedback upsert operator.
496pub const STORAGE_USE_CONTINUAL_FEEDBACK_UPSERT: Config<bool> = Config::new(
497    "storage_use_continual_feedback_upsert",
498    true,
499    "Whether to use the new continual feedback upsert operator.",
500    ParameterScope::Environment,
501);
502
503/// Whether to use the v2 upsert operator.
504pub const ENABLE_UPSERT_V2: Config<bool> = Config::new(
505    "enable_upsert_v2",
506    false,
507    "Whether to use the v2 upsert operator.",
508    ParameterScope::Environment,
509);
510
511/// The interval at which the storage server performs maintenance tasks.
512pub const STORAGE_SERVER_MAINTENANCE_INTERVAL: Config<Duration> = Config::new(
513    "storage_server_maintenance_interval",
514    Duration::from_millis(10),
515    "The interval at which the storage server performs maintenance tasks. Zero enables maintenance on every iteration.",
516    ParameterScope::Replica,
517);
518
519/// If set, iteratively search the progress topic for a progress record with increasing lookback.
520pub const SINK_PROGRESS_SEARCH: Config<bool> = Config::new(
521    "storage_sink_progress_search",
522    true,
523    "If set, iteratively search the progress topic for a progress record with increasing lookback.",
524    ParameterScope::Environment,
525);
526
527/// Configure how to behave when trying to create an existing topic with specified configs.
528pub const SINK_ENSURE_TOPIC_CONFIG: Config<&'static str> = Config::new(
529    "storage_sink_ensure_topic_config",
530    "skip",
531    "If `skip`, don't check the config of existing topics; if `check`, fetch the config and \
532    warn if it does not match the expected configs; if `alter`, attempt to change the upstream to \
533    match the expected configs.",
534    ParameterScope::Environment,
535);
536
537/// How far ahead of the remap upper the source `persist_sink` commits a ceiling while a
538/// snapshotting export holds its frontier pinned, so that it can group updates into one batch.
539///
540/// The persist sink mints descriptions based on the data frontier. During a snapshot, that frontier
541/// does not progress. Providing a lookahead instructs the minter to commit to a ceiling based
542/// on the remap upper, which is used by the batch writers to group updates into a batch.
543/// The minter honors the ceiling by minting descriptions at or beyond it. The whole snapshot and
544/// the CDC events that were captured concurrently, up to the ceiling, become one description,
545/// appended once.
546///
547/// Because the reclock stamps every update below the remap upper, the ceiling is ahead of the data
548/// by at least the lookahead even if the export has seen no data. It still has to reach the writers
549/// ahead of the rows stamped under the newest binding, since a builder only takes updates at times
550/// it was opened for, so this wants to be at least one `timestamp_interval`. An update that outruns
551/// it writes a batch of its own instead, which costs a batch rather than correctness.
552///
553/// Only applies to an export of a Postgres source (for now) that is snapshotting in this dataflow
554/// incarnation, and only until the frontier moves off the time its snapshot occupies. Zero disables
555/// committing ahead, leaving descriptions derived from the frontier alone and every timestamp
556/// writing its own batch.
557///
558/// A nonzero value also switches the Postgres snapshot operator to emitting its rewind requests
559/// as soon as the snapshot bound is known instead of after the copy completes, so the replication
560/// stream is read while the snapshot runs, and lets each export's frontier advance once it has no
561/// snapshot data left to emit. Replication data received for an export that is still snapshotting
562/// is staged in the dataflow until its snapshot completes, which is the many-timestamp shape the
563/// lookahead groups. The two are one setting because reading the stream concurrently without the
564/// grouping keeps one batch builder per timestamp resident until each reaches the blob target size.
565pub const STORAGE_PERSIST_SINK_DESCRIPTION_LOOKAHEAD: Config<Duration> = Config::new(
566    "storage_persist_sink_description_lookahead",
567    Duration::ZERO,
568    "Determines how far past the remap upper the source persist sink will commit to a ceiling \
569    in order to group data into one batch and one description, and whether the Postgres \
570    replication stream is read while a snapshot runs. Zero disables both, leaving every \
571    timestamp writing its own batch. Other values below the tick interval are clamped to the \
572    tick interval.",
573    ParameterScope::Environment,
574);
575
576/// Configure mz-ore overflowing type behavior.
577pub const ORE_OVERFLOWING_BEHAVIOR: Config<&'static str> = Config::new(
578    "ore_overflowing_behavior",
579    "soft_panic",
580    "Overflow behavior for Overflowing types. One of 'ignore', 'panic', 'soft_panic'.",
581    ParameterScope::Environment,
582);
583
584/// The time after which we delete per-replica statistics (for sources and
585/// sinks) after there have been no updates.
586///
587/// This time is opportunistic, statistics are not guaranteed to be deleted
588/// after the retention time runs out.
589pub const STATISTICS_RETENTION_DURATION: Config<Duration> = Config::new(
590    "storage_statistics_retention_duration",
591    Duration::from_secs(86_400), /* one day */
592    "The time after which we delete per replica statistics (for sources and sinks) after there have been no updates.",
593    ParameterScope::Environment,
594);
595
596/// Adds the full set of all storage `Config`s.
597pub fn all_dyncfgs(configs: ConfigSet) -> ConfigSet {
598    configs
599        .add(&AWS_PREFETCH_STS_CONNECT_TIMEOUT)
600        .add(&CLUSTER_SHUTDOWN_GRACE_PERIOD)
601        .add(&DELAY_SOURCES_PAST_REHYDRATION)
602        .add(&ENFORCE_EXTERNAL_ADDRESSES)
603        .add(&KAFKA_BUFFERED_EVENT_RESIZE_THRESHOLD_ELEMENTS)
604        .add(&KAFKA_CLIENT_ID_ENRICHMENT_RULES)
605        .add(&KAFKA_DEFAULT_AWS_PRIVATELINK_ENDPOINT_IDENTIFICATION_ALGORITHM)
606        .add(&KAFKA_LOW_WATERMARK_CHECK)
607        .add(&KAFKA_OFFSET_COMMIT_REFRESH_INTERVAL)
608        .add(&KAFKA_POLL_MAX_WAIT)
609        .add(&KAFKA_RETRY_BACKOFF)
610        .add(&KAFKA_RETRY_BACKOFF_MAX)
611        .add(&KAFKA_RECONNECT_BACKOFF)
612        .add(&KAFKA_RECONNECT_BACKOFF_MAX)
613        .add(&KAFKA_SINK_MESSAGE_MAX_BYTES)
614        .add(&KAFKA_SINK_BATCH_SIZE)
615        .add(&KAFKA_SINK_BATCH_NUM_MESSAGES)
616        .add(&KAFKA_SINK_EMIT_SINK_ID_HEADER)
617        .add(&MYSQL_REPLICATION_HEARTBEAT_INTERVAL)
618        .add(&MYSQL_SOURCE_SNAPSHOT_EXACT_COUNT_MAX_ROWS)
619        .add(&MYSQL_SOURCE_SNAPSHOT_PARALLELISM)
620        .add(&MYSQL_SOURCE_SNAPSHOT_PARTITION_MIN_ROWS)
621        .add(&MYSQL_SOURCE_SNAPSHOT_PARTITION_PROBED_PREFIXES_PER_BILLION_ROWS)
622        .add(&ORE_OVERFLOWING_BEHAVIOR)
623        .add(&PG_FETCH_SLOT_RESUME_LSN_INTERVAL)
624        .add(&PG_SCHEMA_VALIDATION_INTERVAL)
625        .add(&PG_SOURCE_REPLICATION_SLOT_CREATION_TIMEOUT)
626        .add(&PG_SOURCE_VALIDATE_TIMELINE)
627        .add(&REPLICA_METRICS_HISTORY_RETENTION_INTERVAL)
628        .add(&SINK_ENSURE_TOPIC_CONFIG)
629        .add(&SINK_PROGRESS_SEARCH)
630        .add(&SQL_SERVER_SOURCE_VALIDATE_RESTORE_HISTORY)
631        .add(&STORAGE_DOWNGRADE_SINCE_DURING_FINALIZATION)
632        .add(&STORAGE_ROCKSDB_CLEANUP_TRIES)
633        .add(&STORAGE_ROCKSDB_USE_MERGE_OPERATOR)
634        .add(&STORAGE_PERSIST_SINK_DESCRIPTION_LOOKAHEAD)
635        .add(&STORAGE_SERVER_MAINTENANCE_INTERVAL)
636        .add(&STORAGE_SUSPEND_AND_RESTART_DELAY)
637        .add(&STORAGE_UPSERT_MAX_SNAPSHOT_BATCH_BUFFERING)
638        .add(&STORAGE_UPSERT_PREVENT_SNAPSHOT_BUFFERING)
639        .add(&STORAGE_USE_CONTINUAL_FEEDBACK_UPSERT)
640        .add(&ENABLE_UPSERT_V2)
641        .add(&SUSPENDABLE_SOURCES)
642        .add(&ENABLE_UPSERT_PAGED_SPILL)
643        .add(&ENABLE_UPSERT_CHUNKED_STASH)
644        .add(&WALLCLOCK_GLOBAL_LAG_HISTOGRAM_RETENTION_INTERVAL)
645        .add(&WALLCLOCK_LAG_HISTORY_RETENTION_INTERVAL)
646        .add(&crate::sources::sql_server::CDC_CLEANUP_CHANGE_TABLE)
647        .add(&crate::sources::sql_server::CDC_CLEANUP_CHANGE_TABLE_MAX_DELETES)
648        .add(&crate::sources::sql_server::MAX_LSN_WAIT)
649        .add(&crate::sources::sql_server::SNAPSHOT_PROGRESS_REPORT_INTERVAL)
650        .add(&STATISTICS_RETENTION_DURATION)
651}