hive-c0re: finish chrono-clock migration
This commit is contained in:
parent
f4a35786b1
commit
9293c5d580
14 changed files with 82 additions and 78 deletions
|
|
@ -16,7 +16,7 @@ use std::path::Path;
|
|||
use std::sync::Mutex;
|
||||
|
||||
use anyhow::{Context, Result, bail};
|
||||
use hive_sh4re::wire_time::now_unix;
|
||||
use chrono::{DateTime, Utc};
|
||||
use rusqlite::{Connection, OptionalExtension, params};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
@ -78,25 +78,25 @@ pub struct Schedule {
|
|||
/// `None` = one-shot, deleted after first fire.
|
||||
/// `Some(n)` = recurring every `n` seconds.
|
||||
pub interval_seconds: Option<u64>,
|
||||
pub next_fire_at_unix: i64,
|
||||
pub created_at_unix: i64,
|
||||
pub next_fire_at_unix: DateTime<Utc>,
|
||||
pub created_at_unix: DateTime<Utc>,
|
||||
pub source: ScheduleSource,
|
||||
/// Set when the *entire* schedule was cancelled (all targets
|
||||
/// flipped, or operator cancel-all). Worker reaps these on the
|
||||
/// next pass.
|
||||
pub cancelled_at_unix: Option<i64>,
|
||||
pub cancelled_at_unix: Option<DateTime<Utc>>,
|
||||
pub description: Option<String>,
|
||||
/// Set while the schedule is paused. Worker skips rows where
|
||||
/// `paused_at_unix IS NOT NULL`. Cleared by `resume()`.
|
||||
pub paused_at_unix: Option<i64>,
|
||||
pub paused_at_unix: Option<DateTime<Utc>>,
|
||||
pub targets: Vec<ScheduleTarget>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ScheduleTarget {
|
||||
pub target: String,
|
||||
pub cancelled_at_unix: Option<i64>,
|
||||
pub last_fired_at_unix: Option<i64>,
|
||||
pub cancelled_at_unix: Option<DateTime<Utc>>,
|
||||
pub last_fired_at_unix: Option<DateTime<Utc>>,
|
||||
pub last_result: Option<String>,
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ impl ScheduledPrompts {
|
|||
&new.body,
|
||||
new.interval_seconds.map(i64::try_from).and_then(Result::ok),
|
||||
new.first_fire_at_unix,
|
||||
now_unix(),
|
||||
Utc::now().timestamp(),
|
||||
new.source.to_db_string(),
|
||||
&new.description,
|
||||
],
|
||||
|
|
@ -472,7 +472,7 @@ impl ScheduledPrompts {
|
|||
// orphaned tombstone. Plus removing-then-adding is the
|
||||
// natural way to "restart history" on one target without
|
||||
// a separate flow.
|
||||
let now = now_unix();
|
||||
let now = Utc::now().timestamp();
|
||||
if let Some(remove) = patch.targets_remove.as_deref() {
|
||||
for target in remove {
|
||||
tx.execute(
|
||||
|
|
@ -536,7 +536,7 @@ impl ScheduledPrompts {
|
|||
/// already-cancelled row.
|
||||
pub fn cancel_all(&self, id: i64) -> Result<()> {
|
||||
let mut conn = self.conn.lock().unwrap();
|
||||
let now = now_unix();
|
||||
let now = Utc::now().timestamp();
|
||||
let tx = conn.transaction()?;
|
||||
tx.execute(
|
||||
"UPDATE scheduled_prompts
|
||||
|
|
@ -560,7 +560,7 @@ impl ScheduledPrompts {
|
|||
/// are silently skipped.
|
||||
pub fn cancel_targets(&self, id: i64, targets: &[String]) -> Result<()> {
|
||||
let mut conn = self.conn.lock().unwrap();
|
||||
let now = now_unix();
|
||||
let now = Utc::now().timestamp();
|
||||
let tx = conn.transaction()?;
|
||||
for target in targets {
|
||||
tx.execute(
|
||||
|
|
@ -599,7 +599,7 @@ impl ScheduledPrompts {
|
|||
/// cancelled or does not exist (handlers downcast to emit 404).
|
||||
pub fn pause(&self, id: i64) -> Result<()> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
let now = now_unix();
|
||||
let now = Utc::now().timestamp();
|
||||
let n = conn.execute(
|
||||
"UPDATE scheduled_prompts
|
||||
SET paused_at_unix = COALESCE(paused_at_unix, ?1)
|
||||
|
|
@ -653,12 +653,16 @@ fn row_to_schedule_header(row: &rusqlite::Row) -> rusqlite::Result<Schedule> {
|
|||
owner: row.get(1)?,
|
||||
body: row.get(2)?,
|
||||
interval_seconds: interval.and_then(|i| u64::try_from(i).ok()),
|
||||
next_fire_at_unix: row.get(4)?,
|
||||
created_at_unix: row.get(5)?,
|
||||
next_fire_at_unix: hive_sh4re::wire_time::from_secs(row.get(4)?),
|
||||
created_at_unix: hive_sh4re::wire_time::from_secs(row.get(5)?),
|
||||
source: ScheduleSource::from_db_string(&source_str),
|
||||
cancelled_at_unix: row.get(7)?,
|
||||
cancelled_at_unix: row
|
||||
.get::<_, Option<i64>>(7)?
|
||||
.map(hive_sh4re::wire_time::from_secs),
|
||||
description: row.get(8)?,
|
||||
paused_at_unix: row.get(9)?,
|
||||
paused_at_unix: row
|
||||
.get::<_, Option<i64>>(9)?
|
||||
.map(hive_sh4re::wire_time::from_secs),
|
||||
targets: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
|
@ -673,8 +677,12 @@ fn load_targets(conn: &Connection, schedule_id: i64) -> Result<Vec<ScheduleTarge
|
|||
let rows = stmt.query_map(params![schedule_id], |row| {
|
||||
Ok(ScheduleTarget {
|
||||
target: row.get(0)?,
|
||||
cancelled_at_unix: row.get(1)?,
|
||||
last_fired_at_unix: row.get(2)?,
|
||||
cancelled_at_unix: row
|
||||
.get::<_, Option<i64>>(1)?
|
||||
.map(hive_sh4re::wire_time::from_secs),
|
||||
last_fired_at_unix: row
|
||||
.get::<_, Option<i64>>(2)?
|
||||
.map(hive_sh4re::wire_time::from_secs),
|
||||
last_result: row.get(3)?,
|
||||
})
|
||||
})?;
|
||||
|
|
@ -771,7 +779,7 @@ mod tests {
|
|||
let skipped = db.rearm(id, 400).expect("rearm");
|
||||
assert_eq!(skipped, 5);
|
||||
let s = db.get(id).expect("get").expect("present");
|
||||
assert_eq!(s.next_fire_at_unix, 460);
|
||||
assert_eq!(s.next_fire_at_unix.timestamp(), 460);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -793,7 +801,7 @@ mod tests {
|
|||
// the manual fire-now "reset timer" path uses now + interval.
|
||||
db.set_next_fire(id, 1_234).expect("set_next_fire");
|
||||
let s = db.get(id).expect("get").expect("present");
|
||||
assert_eq!(s.next_fire_at_unix, 1_234);
|
||||
assert_eq!(s.next_fire_at_unix.timestamp(), 1_234);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -814,7 +822,7 @@ mod tests {
|
|||
let skipped = db.rearm(id, 100).expect("rearm");
|
||||
assert_eq!(skipped, 0);
|
||||
let s = db.get(id).expect("get").expect("present");
|
||||
assert_eq!(s.next_fire_at_unix, 160);
|
||||
assert_eq!(s.next_fire_at_unix.timestamp(), 160);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -825,7 +833,7 @@ mod tests {
|
|||
assert_eq!(skipped, 0);
|
||||
// next_fire_at unchanged — one-shots are reaped via delete().
|
||||
let s = db.get(id).expect("get").expect("present");
|
||||
assert_eq!(s.next_fire_at_unix, 100);
|
||||
assert_eq!(s.next_fire_at_unix.timestamp(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -878,7 +886,7 @@ mod tests {
|
|||
// Cancelled targets do NOT get last-result writes.
|
||||
assert!(alice.last_fired_at_unix.is_none());
|
||||
assert!(alice.last_result.is_none());
|
||||
assert_eq!(bob.last_fired_at_unix, Some(200));
|
||||
assert_eq!(bob.last_fired_at_unix.map(|dt| dt.timestamp()), Some(200));
|
||||
assert_eq!(bob.last_result.as_deref(), Some("ok"));
|
||||
}
|
||||
|
||||
|
|
@ -909,7 +917,7 @@ mod tests {
|
|||
assert_eq!(s.body, "new body");
|
||||
assert_eq!(s.description.as_deref(), Some("old desc"));
|
||||
assert_eq!(s.interval_seconds, Some(60));
|
||||
assert_eq!(s.next_fire_at_unix, 100);
|
||||
assert_eq!(s.next_fire_at_unix.timestamp(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue