diff options
| author | Conrad Ludgate <conradludgate@gmail.com> | 2023-09-11 09:26:05 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-11 09:26:05 +0100 |
| commit | f90c01f702f6a98b041f766b6a1d857bc1b9afef (patch) | |
| tree | 04a4755bd632abdcf398d0ce903163ed60a5a212 /atuin-server | |
| parent | Use `case` for Linux distro choice in `install.sh` (#1200) (diff) | |
| download | atuin-f90c01f702f6a98b041f766b6a1d857bc1b9afef.zip | |
replace chrono with time (#806)
* replace chrono with time
* Fix test chrono usage
---------
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
Diffstat (limited to '')
| -rw-r--r-- | atuin-server-database/Cargo.toml | 3 | ||||
| -rw-r--r-- | atuin-server-database/src/lib.rs | 98 | ||||
| -rw-r--r-- | atuin-server-database/src/models.rs | 8 | ||||
| -rw-r--r-- | atuin-server-postgres/Cargo.toml | 2 | ||||
| -rw-r--r-- | atuin-server-postgres/src/lib.rs | 11 | ||||
| -rw-r--r-- | atuin-server/Cargo.toml | 4 | ||||
| -rw-r--r-- | atuin-server/src/handlers/history.rs | 27 |
7 files changed, 73 insertions, 80 deletions
diff --git a/atuin-server-database/Cargo.toml b/atuin-server-database/Cargo.toml index 8f1f775e..1b416f9b 100644 --- a/atuin-server-database/Cargo.toml +++ b/atuin-server-database/Cargo.toml @@ -13,9 +13,8 @@ repository = { workspace = true } atuin-common = { path = "../atuin-common", version = "16.0.0" } tracing = "0.1" -chrono = { workspace = true } +time = { workspace = true } eyre = { workspace = true } uuid = { workspace = true } serde = { workspace = true } async-trait = { workspace = true } -chronoutil = "0.2.3" diff --git a/atuin-server-database/src/lib.rs b/atuin-server-database/src/lib.rs index 06ecf910..4ebd517c 100644 --- a/atuin-server-database/src/lib.rs +++ b/atuin-server-database/src/lib.rs @@ -13,13 +13,9 @@ use self::{ models::{History, NewHistory, NewSession, NewUser, Session, User}, }; use async_trait::async_trait; -use atuin_common::{ - record::{EncryptedData, HostId, Record, RecordId, RecordIndex}, - utils::get_days_from_month, -}; -use chrono::{Datelike, TimeZone}; -use chronoutil::RelativeDuration; +use atuin_common::record::{EncryptedData, HostId, Record, RecordId, RecordIndex}; use serde::{de::DeserializeOwned, Serialize}; +use time::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time}; use tracing::instrument; #[derive(Debug)] @@ -34,6 +30,12 @@ impl Display for DbError { } } +impl<T: std::error::Error + Into<time::error::Error>> From<T> for DbError { + fn from(value: T) -> Self { + DbError::Other(value.into().into()) + } +} + impl std::error::Error for DbError {} pub type DbResult<T> = Result<T, DbError>; @@ -75,15 +77,15 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { async fn count_history_range( &self, user: &User, - start: chrono::NaiveDateTime, - end: chrono::NaiveDateTime, + start: PrimitiveDateTime, + end: PrimitiveDateTime, ) -> DbResult<i64>; async fn list_history( &self, user: &User, - created_after: chrono::NaiveDateTime, - since: chrono::NaiveDateTime, + created_after: OffsetDateTime, + since: OffsetDateTime, host: &str, page_size: i64, ) -> DbResult<Vec<History>>; @@ -95,53 +97,51 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { /// Count the history for a given year #[instrument(skip_all)] async fn count_history_year(&self, user: &User, year: i32) -> DbResult<i64> { - let start = chrono::Utc.ymd(year, 1, 1).and_hms_nano(0, 0, 0, 0); - let end = start + RelativeDuration::years(1); + let start = Date::from_calendar_date(year, time::Month::January, 1)?; + let end = Date::from_calendar_date(year + 1, time::Month::January, 1)?; let res = self - .count_history_range(user, start.naive_utc(), end.naive_utc()) + .count_history_range( + user, + start.with_time(Time::MIDNIGHT), + end.with_time(Time::MIDNIGHT), + ) .await?; Ok(res) } /// Count the history for a given month #[instrument(skip_all)] - async fn count_history_month(&self, user: &User, month: chrono::NaiveDate) -> DbResult<i64> { - let start = chrono::Utc - .ymd(month.year(), month.month(), 1) - .and_hms_nano(0, 0, 0, 0); - - // ofc... - let end = if month.month() < 12 { - chrono::Utc - .ymd(month.year(), month.month() + 1, 1) - .and_hms_nano(0, 0, 0, 0) - } else { - chrono::Utc - .ymd(month.year() + 1, 1, 1) - .and_hms_nano(0, 0, 0, 0) - }; + async fn count_history_month(&self, user: &User, year: i32, month: Month) -> DbResult<i64> { + let start = Date::from_calendar_date(year, month, 1)?; + let days = time::util::days_in_year_month(year, month); + let end = start + Duration::days(days as i64); tracing::debug!("start: {}, end: {}", start, end); let res = self - .count_history_range(user, start.naive_utc(), end.naive_utc()) + .count_history_range( + user, + start.with_time(Time::MIDNIGHT), + end.with_time(Time::MIDNIGHT), + ) .await?; Ok(res) } /// Count the history for a given day #[instrument(skip_all)] - async fn count_history_day(&self, user: &User, day: chrono::NaiveDate) -> DbResult<i64> { - let start = chrono::Utc - .ymd(day.year(), day.month(), day.day()) - .and_hms_nano(0, 0, 0, 0); - let end = chrono::Utc - .ymd(day.year(), day.month(), day.day() + 1) - .and_hms_nano(0, 0, 0, 0); + async fn count_history_day(&self, user: &User, day: Date) -> DbResult<i64> { + let end = day + .next_day() + .ok_or_else(|| DbError::Other(eyre::eyre!("no next day?")))?; let res = self - .count_history_range(user, start.naive_utc(), end.naive_utc()) + .count_history_range( + user, + day.with_time(Time::MIDNIGHT), + end.with_time(Time::MIDNIGHT), + ) .await?; Ok(res) } @@ -152,7 +152,7 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { user: &User, period: TimePeriod, year: u64, - month: u64, + month: Month, ) -> DbResult<HashMap<u64, TimePeriodInfo>> { // TODO: Support different timezones. Right now we assume UTC and // everything is stored as such. But it _should_ be possible to @@ -164,7 +164,7 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { // First we need to work out how far back to calculate. Get the // oldest history item let oldest = self.oldest_history(user).await?.timestamp.year(); - let current_year = chrono::Utc::now().year(); + let current_year = OffsetDateTime::now_utc().year(); // All the years we need to get data for // The upper bound is exclusive, so include current +1 @@ -188,13 +188,10 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { TimePeriod::MONTH => { let mut ret = HashMap::new(); - for month in 1..13 { - let count = self - .count_history_month( - user, - chrono::Utc.ymd(year as i32, month, 1).naive_utc(), - ) - .await?; + let months = + std::iter::successors(Some(Month::January), |m| Some(m.next())).take(12); + for month in months { + let count = self.count_history_month(user, year as i32, month).await?; ret.insert( month as u64, @@ -211,14 +208,9 @@ pub trait Database: Sized + Clone + Send + Sync + 'static { TimePeriod::DAY => { let mut ret = HashMap::new(); - for day in 1..get_days_from_month(year as i32, month as u32) { + for day in 1..time::util::days_in_year_month(year as i32, month) { let count = self - .count_history_day( - user, - chrono::Utc - .ymd(year as i32, month as u32, day as u32) - .naive_utc(), - ) + .count_history_day(user, Date::from_calendar_date(year as i32, month, day)?) .await?; ret.insert( diff --git a/atuin-server-database/src/models.rs b/atuin-server-database/src/models.rs index 7183b1ec..b71a9bc9 100644 --- a/atuin-server-database/src/models.rs +++ b/atuin-server-database/src/models.rs @@ -1,25 +1,25 @@ -use chrono::prelude::*; +use time::OffsetDateTime; pub struct History { pub id: i64, pub client_id: String, // a client generated ID pub user_id: i64, pub hostname: String, - pub timestamp: NaiveDateTime, + pub timestamp: OffsetDateTime, /// All the data we have about this command, encrypted. /// /// Currently this is an encrypted msgpack object, but this may change in the future. pub data: String, - pub created_at: NaiveDateTime, + pub created_at: OffsetDateTime, } pub struct NewHistory { pub client_id: String, pub user_id: i64, pub hostname: String, - pub timestamp: chrono::NaiveDateTime, + pub timestamp: OffsetDateTime, /// All the data we have about this command, encrypted. /// diff --git a/atuin-server-postgres/Cargo.toml b/atuin-server-postgres/Cargo.toml index f490a976..703e1210 100644 --- a/atuin-server-postgres/Cargo.toml +++ b/atuin-server-postgres/Cargo.toml @@ -14,7 +14,7 @@ atuin-common = { path = "../atuin-common", version = "16.0.0" } atuin-server-database = { path = "../atuin-server-database", version = "16.0.0" } tracing = "0.1" -chrono = { workspace = true } +time = { workspace = true } serde = { workspace = true } sqlx = { workspace = true } async-trait = { workspace = true } diff --git a/atuin-server-postgres/src/lib.rs b/atuin-server-postgres/src/lib.rs index aa523222..8f473d52 100644 --- a/atuin-server-postgres/src/lib.rs +++ b/atuin-server-postgres/src/lib.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; use sqlx::postgres::PgPoolOptions; use sqlx::Row; +use time::{OffsetDateTime, PrimitiveDateTime}; use tracing::instrument; use wrappers::{DbHistory, DbRecord, DbSession, DbUser}; @@ -139,7 +140,7 @@ impl Database for Postgres { ) .bind(user.id) .bind(id) - .bind(chrono::Utc::now().naive_utc()) + .bind(OffsetDateTime::now_utc()) .fetch_all(&self.pool) .await .map_err(fix_error)?; @@ -175,8 +176,8 @@ impl Database for Postgres { async fn count_history_range( &self, user: &User, - start: chrono::NaiveDateTime, - end: chrono::NaiveDateTime, + start: PrimitiveDateTime, + end: PrimitiveDateTime, ) -> DbResult<i64> { let res: (i64,) = sqlx::query_as( "select count(1) from history @@ -198,8 +199,8 @@ impl Database for Postgres { async fn list_history( &self, user: &User, - created_after: chrono::NaiveDateTime, - since: chrono::NaiveDateTime, + created_after: OffsetDateTime, + since: OffsetDateTime, host: &str, page_size: i64, ) -> DbResult<Vec<History>> { diff --git a/atuin-server/Cargo.toml b/atuin-server/Cargo.toml index f1c44b4c..1b9ad859 100644 --- a/atuin-server/Cargo.toml +++ b/atuin-server/Cargo.toml @@ -3,6 +3,7 @@ name = "atuin-server" edition = "2018" description = "server library for atuin" +rust-version = { workspace = true } version = { workspace = true } authors = { workspace = true } license = { workspace = true } @@ -14,7 +15,7 @@ atuin-common = { path = "../atuin-common", version = "16.0.0" } atuin-server-database = { path = "../atuin-server-database", version = "16.0.0" } tracing = "0.1" -chrono = { workspace = true } +time = { workspace = true } eyre = { workspace = true } uuid = { workspace = true } config = { workspace = true } @@ -27,7 +28,6 @@ async-trait = { workspace = true } axum = "0.6.4" http = "0.2" fs-err = { workspace = true } -chronoutil = "0.2.3" tower = "0.4" tower-http = { version = "0.3", features = ["trace"] } reqwest = { workspace = true } diff --git a/atuin-server/src/handlers/history.rs b/atuin-server/src/handlers/history.rs index bb0aa321..263d6cba 100644 --- a/atuin-server/src/handlers/history.rs +++ b/atuin-server/src/handlers/history.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, convert::TryFrom}; use axum::{ extract::{Path, Query, State}, @@ -6,6 +6,7 @@ use axum::{ Json, }; use http::StatusCode; +use time::Month; use tracing::{debug, error, instrument}; use super::{ErrorResponse, ErrorResponseStatus, RespExt}; @@ -63,16 +64,10 @@ pub async fn list<DB: Database>( }; let history = db - .list_history( - &user, - req.sync_ts.naive_utc(), - req.history_ts.naive_utc(), - &req.host, - page_size, - ) + .list_history(&user, req.sync_ts, req.history_ts, &req.host, page_size) .await; - if req.sync_ts.timestamp_nanos() < 0 || req.history_ts.timestamp_nanos() < 0 { + if req.sync_ts.unix_timestamp_nanos() < 0 || req.history_ts.unix_timestamp_nanos() < 0 { error!("client asked for history from < epoch 0"); return Err( ErrorResponse::reply("asked for history from before epoch 0") @@ -139,7 +134,7 @@ pub async fn add<DB: Database>( client_id: h.id, user_id: user.id, hostname: h.hostname, - timestamp: h.timestamp.naive_utc(), + timestamp: h.timestamp, data: h.data, }) .collect(); @@ -182,11 +177,17 @@ pub async fn calendar<DB: Database>( let year = params.get("year").unwrap_or(&0); let month = params.get("month").unwrap_or(&1); + let month = Month::try_from(*month as u8).map_err(|e| ErrorResponseStatus { + error: ErrorResponse { + reason: e.to_string().into(), + }, + status: http::StatusCode::BAD_REQUEST, + })?; let db = &state.0.database; let focus = match focus { "year" => db - .calendar(&user, TimePeriod::YEAR, *year, *month) + .calendar(&user, TimePeriod::YEAR, *year, month) .await .map_err(|_| { ErrorResponse::reply("failed to query calendar") @@ -194,7 +195,7 @@ pub async fn calendar<DB: Database>( }), "month" => db - .calendar(&user, TimePeriod::MONTH, *year, *month) + .calendar(&user, TimePeriod::MONTH, *year, month) .await .map_err(|_| { ErrorResponse::reply("failed to query calendar") @@ -202,7 +203,7 @@ pub async fn calendar<DB: Database>( }), "day" => db - .calendar(&user, TimePeriod::DAY, *year, *month) + .calendar(&user, TimePeriod::DAY, *year, month) .await .map_err(|_| { ErrorResponse::reply("failed to query calendar") |
