Allow for removing now deleted entries on refresh
This commit is contained in:
parent
bc95081399
commit
2b7cc00fb6
60
src/main.rs
60
src/main.rs
@ -1,7 +1,9 @@
|
|||||||
use crate::client::TogglClient;
|
use crate::client::TogglClient;
|
||||||
use crate::entity::prelude::TimeEntry;
|
use crate::entity::prelude::TimeEntry;
|
||||||
|
use crate::entity::time_entry;
|
||||||
use crate::types::{Current, Project, ProjectClient, ReportEntry, TogglQuery};
|
use crate::types::{Current, Project, ProjectClient, ReportEntry, TogglQuery};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
use axum::extract::Query;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::routing::{get, post};
|
use axum::routing::{get, post};
|
||||||
@ -9,14 +11,15 @@ use axum::{Extension, Json, Router};
|
|||||||
use base64::engine::general_purpose::STANDARD;
|
use base64::engine::general_purpose::STANDARD;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use beachhead::{shutdown_signal, Result};
|
use beachhead::{shutdown_signal, Result};
|
||||||
|
use chrono::{NaiveDate, NaiveTime};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use migration::{Migrator, MigratorTrait};
|
use migration::{Migrator, MigratorTrait};
|
||||||
use sea_orm::{DatabaseConnection, EntityTrait};
|
use sea_orm::sea_query::IntoCondition;
|
||||||
|
use sea_orm::{ColumnTrait, Condition, DatabaseConnection, EntityTrait, QueryFilter};
|
||||||
|
use serde::Deserialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use axum::extract::Query;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
@ -54,15 +57,24 @@ pub async fn report(
|
|||||||
let report = toggl_client.full_report(&query).await?;
|
let report = toggl_client.full_report(&query).await?;
|
||||||
debug!("Returned results: {:?}", report);
|
debug!("Returned results: {:?}", report);
|
||||||
|
|
||||||
cache_report(&db, &report).await?;
|
// We don't perform any deletes on report-fetched entries
|
||||||
|
cache_report(&db, &report, None).await?;
|
||||||
|
|
||||||
Ok(Json(report))
|
Ok(Json(report))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
async fn cache_report(db: &DatabaseConnection, models: &Vec<ReportEntry>) -> Result<()> {
|
async fn cache_report(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
models: &Vec<ReportEntry>,
|
||||||
|
exclusive_on: Option<Condition>,
|
||||||
|
) -> Result<()> {
|
||||||
let models = models.iter().flat_map(|entry| entry.as_models());
|
let models = models.iter().flat_map(|entry| entry.as_models());
|
||||||
let models = models.collect::<Vec<_>>();
|
let models = models.collect::<Vec<_>>();
|
||||||
|
let ids = models
|
||||||
|
.iter()
|
||||||
|
.map(|entry| entry.toggl_id.clone().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
debug!("Caching report entries: {:?}", models);
|
debug!("Caching report entries: {:?}", models);
|
||||||
|
|
||||||
// TODO: Why is this needed?
|
// TODO: Why is this needed?
|
||||||
@ -75,6 +87,17 @@ async fn cache_report(db: &DatabaseConnection, models: &Vec<ReportEntry>) -> Res
|
|||||||
.exec(db)
|
.exec(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
if let Some(exclusive_on) = exclusive_on {
|
||||||
|
TimeEntry::delete_many()
|
||||||
|
.filter(
|
||||||
|
Condition::all()
|
||||||
|
.add(exclusive_on)
|
||||||
|
.add(time_entry::Column::TogglId.is_in(ids).not()),
|
||||||
|
)
|
||||||
|
.exec(db)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,26 +166,33 @@ async fn refresh(
|
|||||||
Extension(db): Extension<DatabaseConnection>,
|
Extension(db): Extension<DatabaseConnection>,
|
||||||
Query(RefreshQuery { start_date }): Query<RefreshQuery>,
|
Query(RefreshQuery { start_date }): Query<RefreshQuery>,
|
||||||
) -> Result<&'static str> {
|
) -> Result<&'static str> {
|
||||||
let date = chrono::Utc::now()
|
let end_date = chrono::Utc::now();
|
||||||
.naive_utc()
|
let end_date_query_string = end_date.date_naive().format("%Y-%m-%d").to_string();
|
||||||
.date()
|
let start_date_query_string = start_date.unwrap_or(end_date_query_string.clone());
|
||||||
.format("%Y-%m-%d")
|
let start_date = NaiveDate::parse_from_str(&start_date_query_string, "%Y-%m-%d")?;
|
||||||
.to_string();
|
|
||||||
|
|
||||||
let start_date = start_date.unwrap_or(date.clone());
|
|
||||||
|
|
||||||
let query = TogglQuery {
|
let query = TogglQuery {
|
||||||
start_date: Some(start_date),
|
start_date: Some(start_date_query_string),
|
||||||
end_date: Some(date),
|
end_date: Some(end_date_query_string),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = toggl_client.full_report(&query).await?;
|
let report = toggl_client.full_report(&query).await?;
|
||||||
cache_report(&db, &report).await?;
|
let exclusivity_condition = day_exclusivity_condition(start_date, end_date.date_naive());
|
||||||
|
cache_report(&db, &report, Some(exclusivity_condition)).await?;
|
||||||
|
|
||||||
Ok("Ok")
|
Ok("Ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn day_exclusivity_condition(start: NaiveDate, end: NaiveDate) -> Condition {
|
||||||
|
time_entry::Column::Start
|
||||||
|
.between(
|
||||||
|
start.and_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()),
|
||||||
|
end.and_time(NaiveTime::from_hms_opt(23, 59, 59).unwrap()),
|
||||||
|
)
|
||||||
|
.into_condition()
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// install global collector configured based on RUST_LOG env var.
|
// install global collector configured based on RUST_LOG env var.
|
||||||
|
|||||||
35
src/poll.rs
35
src/poll.rs
@ -1,8 +1,9 @@
|
|||||||
use crate::client::TogglClient;
|
use crate::client::TogglClient;
|
||||||
|
use crate::entity::{client, project, time_entry};
|
||||||
use crate::types::{Project, ProjectClient, TogglQuery};
|
use crate::types::{Project, ProjectClient, TogglQuery};
|
||||||
use sea_orm::{DatabaseConnection, EntityTrait, QuerySelect};
|
use sea_orm::{DatabaseConnection, EntityTrait, QuerySelect};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
use crate::entity::{project, client};
|
use crate::day_exclusivity_condition;
|
||||||
|
|
||||||
#[tracing::instrument(skip(client, db))]
|
#[tracing::instrument(skip(client, db))]
|
||||||
pub async fn poll_job(client: TogglClient, db: DatabaseConnection, poll_period: u64) {
|
pub async fn poll_job(client: TogglClient, db: DatabaseConnection, poll_period: u64) {
|
||||||
@ -33,20 +34,16 @@ pub async fn perform_poll(
|
|||||||
client: &TogglClient,
|
client: &TogglClient,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> beachhead::Result<usize> {
|
) -> beachhead::Result<usize> {
|
||||||
|
let now = chrono::Utc::now();
|
||||||
|
let today_string = now
|
||||||
|
.date_naive()
|
||||||
|
.format("%Y-%m-%d")
|
||||||
|
.to_string();
|
||||||
|
|
||||||
let report = client
|
let report = client
|
||||||
.full_report(&TogglQuery {
|
.full_report(&TogglQuery {
|
||||||
start_date: Some(
|
start_date: Some(today_string.clone()),
|
||||||
chrono::Utc::now()
|
end_date: Some(today_string.clone()),
|
||||||
.date_naive()
|
|
||||||
.format("%Y-%m-%d")
|
|
||||||
.to_string(),
|
|
||||||
),
|
|
||||||
end_date: Some(
|
|
||||||
chrono::Utc::now()
|
|
||||||
.date_naive()
|
|
||||||
.format("%Y-%m-%d")
|
|
||||||
.to_string(),
|
|
||||||
),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
@ -58,7 +55,8 @@ pub async fn perform_poll(
|
|||||||
.all(db)
|
.all(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let new_projects = report.iter()
|
let new_projects = report
|
||||||
|
.iter()
|
||||||
.filter_map(|entry| entry.project_id)
|
.filter_map(|entry| entry.project_id)
|
||||||
.any(|project_id| !existing_project_ids.contains(&(project_id as i64)));
|
.any(|project_id| !existing_project_ids.contains(&(project_id as i64)));
|
||||||
|
|
||||||
@ -78,6 +76,13 @@ pub async fn perform_poll(
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::cache_report(&db, &report).await?;
|
crate::cache_report(
|
||||||
|
&db,
|
||||||
|
&report,
|
||||||
|
Some(
|
||||||
|
day_exclusivity_condition(now.date_naive(), now.date_naive()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
Ok(report.len())
|
Ok(report.len())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user