Skip to main content

mz_timestamp_oracle/
config.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//! Unified configuration for timestamp oracles.
11//!
12//! This module provides a [`TimestampOracleConfig`] enum that holds the
13//! configuration for a timestamp oracle backend, allowing the choice of
14//! backend to be made at startup time.
15
16use std::sync::Arc;
17
18use mz_ore::metrics::MetricsRegistry;
19use mz_ore::now::NowFn;
20use mz_ore::url::SensitiveUrl;
21use mz_repr::Timestamp;
22
23use crate::TimestampOracle;
24use crate::metrics::Metrics;
25use crate::postgres_oracle::{
26    PostgresTimestampOracle, PostgresTimestampOracleConfig, TimestampOracleParameters,
27};
28
29/// Unified configuration for timestamp oracles.
30///
31/// This enum allows selecting between different timestamp oracle backends
32/// at startup time.
33#[derive(Clone, Debug)]
34pub enum TimestampOracleConfig {
35    /// Use a Postgres/CockroachDB-backed timestamp oracle.
36    Postgres(PostgresTimestampOracleConfig),
37}
38
39impl TimestampOracleConfig {
40    /// Create a timestamp oracle configuration from a URL.
41    ///
42    /// The backend is determined by the URL scheme:
43    /// - `postgres://` or `postgresql://` -> Postgres-backed oracle
44    ///
45    /// Returns an error if the URL scheme is not recognized.
46    pub fn from_url(
47        url: &SensitiveUrl,
48        metrics_registry: &MetricsRegistry,
49    ) -> Result<Self, anyhow::Error> {
50        let scheme = url.scheme();
51        match scheme {
52            "postgres" | "postgresql" => Ok(Self::new_postgres(url, metrics_registry)),
53            _ => {
54                anyhow::bail!(
55                    "unsupported timestamp oracle URL scheme: '{}'. \
56                     Supported schemes: postgres, postgresql",
57                    scheme
58                )
59            }
60        }
61    }
62
63    /// Create a new Postgres-backed timestamp oracle configuration.
64    pub fn new_postgres(url: &SensitiveUrl, metrics_registry: &MetricsRegistry) -> Self {
65        TimestampOracleConfig::Postgres(PostgresTimestampOracleConfig::new(url, metrics_registry))
66    }
67
68    /// Returns the metrics for this configuration.
69    pub fn metrics(&self) -> Arc<Metrics> {
70        match self {
71            TimestampOracleConfig::Postgres(config) => Arc::clone(config.metrics()),
72        }
73    }
74
75    /// Opens a timestamp oracle for the given timeline.
76    pub async fn open(
77        &self,
78        timeline: String,
79        initially: Timestamp,
80        now_fn: NowFn,
81        read_only: bool,
82    ) -> Arc<dyn TimestampOracle<Timestamp> + Send + Sync> {
83        match self {
84            TimestampOracleConfig::Postgres(config) => Arc::new(
85                PostgresTimestampOracle::open(
86                    config.clone(),
87                    timeline,
88                    initially,
89                    now_fn,
90                    read_only,
91                )
92                .await,
93            ),
94        }
95    }
96
97    /// Returns all known timelines and their current timestamps.
98    ///
99    /// This is used during initialization to restore timestamp state from the backend.
100    pub async fn get_all_timelines(&self) -> Result<Vec<(String, Timestamp)>, anyhow::Error> {
101        match self {
102            TimestampOracleConfig::Postgres(config) => {
103                PostgresTimestampOracle::<NowFn>::get_all_timelines(config.clone()).await
104            }
105        }
106    }
107
108    /// Applies configuration parameters.
109    ///
110    /// This is a no-op for non-Postgres backends.
111    pub fn apply_parameters(&self, params: TimestampOracleParameters) {
112        // Only the Postgres oracle supports parameters for now.
113        #[allow(irrefutable_let_patterns)]
114        if let TimestampOracleConfig::Postgres(pg_config) = self {
115            params.apply(pg_config)
116        }
117    }
118}