token bucket rate limiting with burst + synthetic notice on delay

This commit is contained in:
Damocles 2026-05-01 13:29:52 +02:00
parent d4b8aa731b
commit 496bb5484a
5 changed files with 108 additions and 30 deletions

View file

@ -32,6 +32,13 @@ pub enum WireEvent {
target_event_id_short: String,
key: String,
},
/// Synthetic event from the daemon (not a Matrix event). Currently used
/// to tell the shard "you were rate-limited; events held for X seconds."
Notice {
text: String,
ts: i64,
ts_human: String,
},
}
#[derive(Debug, Serialize)]
@ -56,6 +63,7 @@ pub struct FetchEventResult {
pub const DEFAULT_MODEL: &str = "claude-sonnet-4-6";
pub const DEFAULT_MAX_HISTORY: usize = 20;
pub const DEFAULT_RATE_LIMIT_PER_MIN: u32 = 1;
pub const DEFAULT_RATE_BURST_CAPACITY: u32 = 3;
pub const DEFAULT_SESSION_IDLE_MINUTES: u64 = 10;
pub const DEFAULT_SESSION_MAX_EVENTS: u32 = 100;
@ -65,6 +73,7 @@ pub struct Config {
pub username: String,
pub password: String,
pub rate_limit_per_min: Option<u32>,
pub rate_burst_capacity: Option<u32>,
pub model: Option<String>,
pub max_history: Option<usize>,
pub session_idle_minutes: Option<u64>,
@ -132,10 +141,14 @@ pub struct DaemonState {
/// Per-room: the latest event_id that's been "shown" to Claude. Events
/// after this are "new" on the next invocation. Cleared on daemon restart.
pub last_shown: HashMap<OwnedRoomId, OwnedEventId>,
pub pending_rooms: Vec<OwnedRoomId>,
pub rate_budget: u32,
/// Rooms with unprocessed events. The Instant is when the room first
/// entered the queue (or last became empty, then refilled). Used to
/// surface rate-limit delays to the shard via a synthetic notice event.
pub pending_rooms: Vec<(OwnedRoomId, std::time::Instant)>,
pub rate_budget: f64,
pub rate_limit_per_min: u32,
pub last_rate_reset: std::time::Instant,
pub rate_burst_capacity: u32,
pub last_rate_check: std::time::Instant,
pub model: String,
pub max_history: usize,
pub session_idle_minutes: u64,