use std::time::Duration;
use thiserror::Error;
pub const DEFAULT_SEQUENCER_BATCH_SIZE: u32 = 1000;
pub const DEFAULT_POLL_INTERVAL: Duration = Duration::from_secs(600);
pub const DEFAULT_PARTITION_BATCH_LIMIT: u32 = 128;
pub const DEFAULT_MAX_INNER_ITERATIONS: u32 = 8;
pub const DEFAULT_POKER_INTERVAL: Duration = Duration::from_secs(60);
pub const DEFAULT_MSG_BATCH_SIZE: u32 = 1;
pub const DEFAULT_BACKOFF_BASE: Duration = Duration::from_secs(1);
pub const DEFAULT_BACKOFF_MAX: Duration = Duration::from_secs(60);
pub const DEFAULT_LEASE_DURATION: Duration = Duration::from_secs(30);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Partitions(u16);
impl Partitions {
#[must_use]
pub const fn of(n: u16) -> Self {
assert!(
n >= 1 && n <= 64 && n.is_power_of_two(),
"partition count must be a power of 2 between 1 and 64"
);
Self(n)
}
#[must_use]
pub const fn count(self) -> u16 {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OutboxMessageId(pub i64);
#[derive(Debug)]
pub struct EnqueueMessage<'a> {
pub partition: u32,
pub payload: Vec<u8>,
pub payload_type: &'a str,
}
#[derive(Debug, Error)]
pub enum OutboxError {
#[error("queue '{0}' is not registered")]
QueueNotRegistered(String),
#[error("partition {partition} is out of range for queue '{queue}' (max {max})")]
PartitionOutOfRange {
queue: String,
partition: u32,
max: u32,
},
#[error("payload size {size} exceeds maximum {max}")]
PayloadTooLarge { size: usize, max: usize },
#[error("partition count mismatch for queue '{queue}': expected {expected}, found {found}")]
PartitionCountMismatch {
queue: String,
expected: u16,
found: usize,
},
#[error("invalid queue name: '{0}'")]
InvalidQueueName(String),
#[error("invalid payload type: '{0}'")]
InvalidPayloadType(String),
#[error(transparent)]
Database(#[from] sea_orm::DbErr),
}
#[derive(Debug, Clone, Default)]
pub struct OutboxConfig {
pub sequencer: SequencerConfig,
}
#[derive(Debug, Clone)]
pub struct SequencerConfig {
pub batch_size: u32,
pub poll_interval: Duration,
pub partition_batch_limit: u32,
pub max_inner_iterations: u32,
}
impl Default for SequencerConfig {
fn default() -> Self {
Self {
batch_size: DEFAULT_SEQUENCER_BATCH_SIZE,
poll_interval: DEFAULT_POLL_INTERVAL,
partition_batch_limit: DEFAULT_PARTITION_BATCH_LIMIT,
max_inner_iterations: DEFAULT_MAX_INNER_ITERATIONS,
}
}
}
#[derive(Debug, Clone)]
pub struct QueueConfig {
pub lease_duration: Duration,
pub msg_batch_size: u32,
pub(crate) poll_interval: Duration,
pub backoff_base: Duration,
pub backoff_max: Duration,
}
#[derive(Debug, Clone, Copy)]
pub struct DecoupledConfig {
pub lease_duration: Duration,
}
impl Default for DecoupledConfig {
fn default() -> Self {
Self {
lease_duration: DEFAULT_LEASE_DURATION,
}
}
}
pub const DEFAULT_VACUUM_COOLDOWN: Duration = Duration::from_secs(3600);
impl Default for QueueConfig {
fn default() -> Self {
Self {
lease_duration: DEFAULT_LEASE_DURATION,
msg_batch_size: DEFAULT_MSG_BATCH_SIZE,
poll_interval: DEFAULT_POLL_INTERVAL,
backoff_base: DEFAULT_BACKOFF_BASE,
backoff_max: DEFAULT_BACKOFF_MAX,
}
}
}