reminder: atomic delivery transaction + per-tick batch cap
This commit is contained in:
parent
e45d161cb8
commit
b86c0a2217
2 changed files with 67 additions and 33 deletions
|
|
@ -86,6 +86,12 @@ enum Cmd {
|
|||
Deny { id: i64 },
|
||||
}
|
||||
|
||||
/// Per-tick cap on reminders the scheduler delivers. Anything over this
|
||||
/// stays due in the table and gets picked up on the next 5s tick — keeps
|
||||
/// a 10k-deep backlog from flooding the broker (or hogging its mutex) in
|
||||
/// one shot.
|
||||
const REMINDER_BATCH_LIMIT: u64 = 100;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
|
|
@ -166,36 +172,30 @@ async fn main() -> Result<()> {
|
|||
// operator-initiated transient state.
|
||||
crash_watch::spawn(coord.clone());
|
||||
// Reminder scheduler: checks for due reminders every 5 seconds,
|
||||
// delivers them as inbox messages from "reminder".
|
||||
// delivers them atomically (insert inbox + mark sent in one
|
||||
// sqlite transaction so a transient failure on the second step
|
||||
// can never produce a duplicate next tick). Per-cycle batch
|
||||
// limit caps the burst — leftover reminders stay due and get
|
||||
// picked up on the next tick instead of monopolising the broker
|
||||
// mutex.
|
||||
let reminder_coord = coord.clone();
|
||||
tokio::spawn(async move {
|
||||
use hive_sh4re::Message;
|
||||
loop {
|
||||
// Query all due reminders in a single DB call
|
||||
match reminder_coord.broker.get_all_due_reminders() {
|
||||
match reminder_coord
|
||||
.broker
|
||||
.get_due_reminders(REMINDER_BATCH_LIMIT)
|
||||
{
|
||||
Ok(reminders) => {
|
||||
for (agent, id, message, _file_path) in reminders {
|
||||
// Deliver as inbox message from "reminder"
|
||||
if let Err(e) = reminder_coord.broker.send(&Message {
|
||||
from: "reminder".to_owned(),
|
||||
to: agent.clone(),
|
||||
body: message.clone(),
|
||||
}) {
|
||||
if let Err(e) =
|
||||
reminder_coord.broker.deliver_reminder(id, &agent, &message)
|
||||
{
|
||||
tracing::warn!(
|
||||
reminder_id = id,
|
||||
%agent,
|
||||
error = ?e,
|
||||
"failed to deliver reminder"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Mark as sent
|
||||
if let Err(e) = reminder_coord.broker.mark_reminder_sent(id) {
|
||||
tracing::warn!(
|
||||
reminder_id = id,
|
||||
error = ?e,
|
||||
"failed to mark reminder sent"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue