Skip to main content

hermes_server/
config.rs

1use std::net::SocketAddr;
2use std::path::PathBuf;
3
4pub struct ServerConfig {
5    pub listen_addr: SocketAddr,
6    /// Capacity of the broadcast (fanout) and mpsc (queue-group) channels
7    /// inside the broker engine. This is the main buffer between publishers
8    /// and subscribers.
9    pub subscriber_channel_capacity: usize,
10    /// Capacity of the gRPC output mpsc channel per subscriber.
11    /// This is a small decoupling buffer between the forwarding task and the
12    /// gRPC write. Keep it small — back-pressure should be handled by the
13    /// broadcast/mpsc channel above.
14    pub grpc_output_buffer: usize,
15    /// Path to the redb store file. None = fire-and-forget only, no durable mode.
16    pub store_path: Option<PathBuf>,
17    /// How often the redelivery loop runs (seconds).
18    pub redelivery_interval_secs: u64,
19    /// Max delivery attempts before dead-lettering.
20    pub max_delivery_attempts: u32,
21    /// How long to keep acked messages before GC (seconds).
22    pub retention_secs: u64,
23    /// Default ack timeout for durable subscriptions (seconds).
24    pub default_ack_timeout_secs: u32,
25    /// Default max in-flight messages for durable subscriptions.
26    pub default_max_in_flight: u32,
27    /// How often the GC loop runs (seconds).
28    pub gc_interval_secs: u64,
29    /// Max expired messages processed per consumer per redelivery cycle.
30    pub redelivery_batch_size: u32,
31}
32
33impl Default for ServerConfig {
34    fn default() -> Self {
35        Self {
36            listen_addr: "0.0.0.0:4222".parse().unwrap(),
37            subscriber_channel_capacity: 8192,
38            grpc_output_buffer: 1024,
39            store_path: None,
40            redelivery_interval_secs: 5,
41            max_delivery_attempts: 5,
42            retention_secs: 3600,
43            default_ack_timeout_secs: 30,
44            default_max_in_flight: 32,
45            gc_interval_secs: 60,
46            redelivery_batch_size: 100,
47        }
48    }
49}
50
51impl ServerConfig {
52    pub fn from_env() -> Self {
53        let mut config = Self::default();
54
55        if let Ok(addr) = std::env::var("HERMES_LISTEN_ADDR")
56            && let Ok(parsed) = addr.parse()
57        {
58            config.listen_addr = parsed;
59        }
60        if let Ok(cap) = std::env::var("HERMES_CHANNEL_CAPACITY")
61            && let Ok(parsed) = cap.parse()
62        {
63            config.subscriber_channel_capacity = parsed;
64        }
65        if let Ok(v) = std::env::var("HERMES_GRPC_OUTPUT_BUFFER")
66            && let Ok(parsed) = v.parse()
67        {
68            config.grpc_output_buffer = parsed;
69        }
70        if let Ok(path) = std::env::var("HERMES_STORE_PATH") {
71            config.store_path = Some(PathBuf::from(path));
72        }
73        if let Ok(v) = std::env::var("HERMES_REDELIVERY_INTERVAL")
74            && let Ok(parsed) = v.parse()
75        {
76            config.redelivery_interval_secs = parsed;
77        }
78        if let Ok(v) = std::env::var("HERMES_MAX_DELIVERY_ATTEMPTS")
79            && let Ok(parsed) = v.parse()
80        {
81            config.max_delivery_attempts = parsed;
82        }
83        if let Ok(v) = std::env::var("HERMES_RETENTION_SECS")
84            && let Ok(parsed) = v.parse()
85        {
86            config.retention_secs = parsed;
87        }
88        if let Ok(v) = std::env::var("HERMES_ACK_TIMEOUT")
89            && let Ok(parsed) = v.parse()
90        {
91            config.default_ack_timeout_secs = parsed;
92        }
93        if let Ok(v) = std::env::var("HERMES_MAX_IN_FLIGHT")
94            && let Ok(parsed) = v.parse()
95        {
96            config.default_max_in_flight = parsed;
97        }
98        if let Ok(v) = std::env::var("HERMES_GC_INTERVAL")
99            && let Ok(parsed) = v.parse()
100        {
101            config.gc_interval_secs = parsed;
102        }
103        if let Ok(v) = std::env::var("HERMES_REDELIVERY_BATCH_SIZE")
104            && let Ok(parsed) = v.parse()
105        {
106            config.redelivery_batch_size = parsed;
107        }
108
109        config
110    }
111}