db: share one now_f64() instead of four private copies

handlers, queue, send and link_cache each carried the same SystemTime
helper; a single crate::db::now_f64() removes the drift risk.
This commit is contained in:
2026-08-08 20:23:58 +08:00
parent 72130b9023
commit 99009aae9a
4 changed files with 13 additions and 22 deletions
+9
View File
@@ -19,6 +19,15 @@ pub fn open_db(path: &str) -> rusqlite::Result<Connection> {
Ok(conn) Ok(conn)
} }
/// Unix timestamp in fractional seconds. Shared by the queue, chat store and
/// link cache (previously four private copies).
pub fn now_f64() -> f64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs_f64())
.unwrap_or(0.0)
}
/// Runs `f` against a fresh connection on a blocking thread, returning the /// Runs `f` against a fresh connection on a blocking thread, returning the
/// closure's result. Owns the `spawn_blocking` + `expect` ceremony shared by /// closure's result. Owns the `spawn_blocking` + `expect` ceremony shared by
/// every table access; the caller maps errors to its own log line. /// every table access; the caller maps errors to its own log line.
+1 -7
View File
@@ -1,4 +1,5 @@
use crate::config::Config; use crate::config::Config;
use crate::db::now_f64;
use crate::link_cache::{CachedMediaKind, CachedPost, LinkCache}; use crate::link_cache::{CachedMediaKind, CachedPost, LinkCache};
use crate::queue::PersistentTaskQueue; use crate::queue::PersistentTaskQueue;
use crate::send::{self, MediaItemPayload, Task}; use crate::send::{self, MediaItemPayload, Task};
@@ -111,13 +112,6 @@ where
.await .await
} }
fn now_f64() -> f64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs_f64())
.unwrap_or(0.0)
}
/// Extracts URL and text-link entities (text + caption), deduped in order. /// Extracts URL and text-link entities (text + caption), deduped in order.
pub fn extract_urls(message: &Message) -> Vec<String> { pub fn extract_urls(message: &Message) -> Vec<String> {
let mut urls = Vec::new(); let mut urls = Vec::new();
+1 -7
View File
@@ -8,6 +8,7 @@
//! [`Config::link_cache_ttl`]; a stale entry is dropped lazily on read and //! [`Config::link_cache_ttl`]; a stale entry is dropped lazily on read and
//! by the periodic prune in `main`. //! by the periodic prune in `main`.
use crate::db::now_f64;
use rusqlite::{Connection, params}; use rusqlite::{Connection, params};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
@@ -163,13 +164,6 @@ impl LinkCache {
} }
} }
fn now_f64() -> f64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs_f64())
.unwrap_or(0.0)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
+2 -8
View File
@@ -5,13 +5,14 @@
//! flow. The Python dict-mutation hack (attempts inside the payload) is //! flow. The Python dict-mutation hack (attempts inside the payload) is
//! replaced by dedicated columns. //! replaced by dedicated columns.
use crate::db::now_f64;
use parking_lot::Mutex; use parking_lot::Mutex;
use rusqlite::{Connection, TransactionBehavior, params}; use rusqlite::{Connection, TransactionBehavior, params};
use serde_json::Value; use serde_json::Value;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::time::{Duration, SystemTime, UNIX_EPOCH}; use std::time::Duration;
use tokio::sync::Notify; use tokio::sync::Notify;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
@@ -62,13 +63,6 @@ struct QueueWorker {
dead_letter: Arc<DeadLetter>, dead_letter: Arc<DeadLetter>,
} }
fn now_f64() -> f64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs_f64())
.unwrap_or(0.0)
}
/// Resets rows left `in_progress` with an expired lock TTL back to `pending` /// Resets rows left `in_progress` with an expired lock TTL back to `pending`
/// so they can be leased again (crash/panic recovery). /// so they can be leased again (crash/panic recovery).
fn recover_update(conn: &rusqlite::Connection) -> rusqlite::Result<()> { fn recover_update(conn: &rusqlite::Connection) -> rusqlite::Result<()> {