1use std::path::PathBuf;
4use std::time::Duration;
5
6use byteor_core::config::Environment;
7
8use crate::stages::ReplayDataGuardConfig;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub enum ReplayMode {
13 DryRun,
15 Execute,
17}
18
19#[derive(Clone, Debug)]
21pub struct ReplayOptions {
22 pub bundle_dir: PathBuf,
24 pub lane_graph_shm_dir: Option<PathBuf>,
26 pub single_ring_lane_path: Option<PathBuf>,
28 pub journal_lane: Option<String>,
30 pub last_n: usize,
32 pub mode: ReplayMode,
34 pub dataguard: Option<ReplayDataGuardConfig>,
36 pub env: Environment,
38 pub approval: Option<String>,
40 pub out_audit_path: PathBuf,
42 pub clean: bool,
44 pub drain_timeout: Option<Duration>,
46 pub journal_buffer_limit_bytes: Option<usize>,
48}
49
50pub(crate) fn accumulate_replay_accounting(
51 current: byteor_policy::ReplayAccounting,
52 selected_actions: u64,
53 selected_bytes: u64,
54) -> byteor_policy::ReplayAccounting {
55 byteor_policy::ReplayAccounting {
56 actions_so_far: current.actions_so_far.saturating_add(selected_actions),
57 input_bytes_so_far: current.input_bytes_so_far.saturating_add(selected_bytes),
58 }
59}
60
61const DEFAULT_DRAIN_TIMEOUT: Duration = Duration::from_secs(5);
62
63pub(crate) fn replay_drain_timeout(opts: &ReplayOptions) -> Duration {
64 opts.drain_timeout.unwrap_or(DEFAULT_DRAIN_TIMEOUT)
65}
66
67pub(crate) fn replay_journal_buffer_limit_bytes(opts: &ReplayOptions) -> Result<usize, String> {
68 let limit = opts
69 .journal_buffer_limit_bytes
70 .unwrap_or(crate::journal::DEFAULT_JOURNAL_BUFFER_LIMIT_BYTES);
71 if limit == 0 {
72 return Err("replay: journal buffer limit must be > 0".to_string());
73 }
74 if limit > crate::journal::MAX_JOURNAL_BUFFER_LIMIT_BYTES {
75 return Err(format!(
76 "replay: journal buffer limit exceeds max: requested={} max={}",
77 limit,
78 crate::journal::MAX_JOURNAL_BUFFER_LIMIT_BYTES
79 ));
80 }
81 Ok(limit)
82}