Skip to main content

drasi_lib/wal/
config.rs

1// Copyright 2025 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Configuration types for Write-Ahead Log instances.
16
17use super::error::WalError;
18
19/// Minimum allowed value for [`WriteAheadLogConfig::max_events`].
20///
21/// Values below this would cause excessive eviction churn or make the WAL
22/// effectively unusable for crash recovery.
23pub const MIN_MAX_EVENTS: u64 = 16;
24
25/// Per-source configuration supplied to [`WalProvider::register`](super::WalProvider::register).
26#[derive(Debug, Clone)]
27pub struct WriteAheadLogConfig {
28    /// Maximum number of events retained in the WAL before the capacity policy triggers.
29    pub max_events: u64,
30
31    /// Policy to apply when the WAL reaches `max_events`.
32    pub capacity_policy: CapacityPolicy,
33}
34
35/// Policy for handling new appends when the WAL is at capacity.
36///
37/// **`RejectIncoming`** propagates backpressure. For a transient source (e.g.,
38/// HTTP webhook), this typically means returning 503 to the external producer,
39/// which should retry. This preserves data safety but will cause the source to
40/// appear "stuck" if the producer stops retrying or the consumer is permanently
41/// stalled.
42///
43/// **`OverwriteOldest`** favors availability — keeps accepting new events by
44/// evicting the oldest. Slow consumers may see gaps and trigger their recovery
45/// policy. Choose this when availability matters more than no-loss replay.
46///
47/// Sources should choose based on their backpressure contract with upstream
48/// producers.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum CapacityPolicy {
51    /// Reject the incoming event with [`WalError::CapacityExhausted`].
52    RejectIncoming,
53
54    /// Evict the oldest event(s) to make room for the new one.
55    OverwriteOldest,
56}
57
58impl WriteAheadLogConfig {
59    /// Validate the config. Returns [`WalError::InvalidConfig`] if `max_events`
60    /// is below [`MIN_MAX_EVENTS`].
61    pub fn validate(&self) -> Result<(), WalError> {
62        if self.max_events < MIN_MAX_EVENTS {
63            return Err(WalError::InvalidConfig(format!(
64                "max_events must be at least {MIN_MAX_EVENTS}, got {}",
65                self.max_events
66            )));
67        }
68        Ok(())
69    }
70}
71
72impl Default for WriteAheadLogConfig {
73    fn default() -> Self {
74        Self {
75            max_events: 10_000,
76            capacity_policy: CapacityPolicy::RejectIncoming,
77        }
78    }
79}