From 479389dde647362e27dc45c2f2e2d2d572e7c4c9 Mon Sep 17 00:00:00 2001 From: Joshua Coles Date: Sun, 3 Mar 2024 20:49:27 +0000 Subject: [PATCH] Report update statistics --- src/poll.rs | 14 ++++++-------- src/routes.rs | 7 +++---- src/sync_service.rs | 47 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/poll.rs b/src/poll.rs index dabab8f..145a5d5 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -13,7 +13,7 @@ use sea_orm::{ use std::ops::Sub; use migration::Order; use tracing::instrument; -use crate::sync_service::update_database; +use crate::sync_service::{update_database, UpdateStats}; #[tracing::instrument(skip(client, db))] pub async fn poll_job(client: TogglApiClient, db: DatabaseConnection, poll_period: u64) { @@ -23,10 +23,10 @@ pub async fn poll_job(client: TogglApiClient, db: DatabaseConnection, poll_perio loop { tracing::info!("Polling Toggl API"); match perform_poll(&client, &db).await { - Ok(report_entries_count) => { + Ok(poll_update_data) => { tracing::info!( - "Successfully polled Toggl API: {:?} entries retrieved", - report_entries_count + "Successfully polled Toggl API: {:?}", + poll_update_data ); } @@ -43,7 +43,7 @@ pub async fn poll_job(client: TogglApiClient, db: DatabaseConnection, poll_perio pub async fn perform_poll( toggl_client: &TogglApiClient, db: &DatabaseConnection, -) -> utils::Result { +) -> utils::Result { let since = time_entry::Entity::find() .select_only() .column(time_entry::Column::ServerUpdatedAt) @@ -68,7 +68,5 @@ pub async fn perform_poll( toggl_client, &time_entries, None, - ).await?; - - Ok(time_entries.len()) + ).await } diff --git a/src/routes.rs b/src/routes.rs index 5a61a4b..e609157 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -12,6 +12,7 @@ use serde::Deserialize; use serde_json::Value; use std::collections::HashMap; use tracing::{instrument}; +use crate::sync_service::UpdateStats; #[instrument(skip(db, toggl_client))] pub async fn report( @@ -119,7 +120,7 @@ pub async fn refresh( Extension(toggl_client): Extension, Extension(db): Extension, Query(RefreshQuery { start_date, end_date }): Query, -) -> utils::Result<&'static str> { +) -> utils::Result> { let time_entries = match (start_date, end_date) { (Some(start_date), Some(end_date)) => { toggl_client.fetch_time_entries_in_range(start_date, end_date).await? @@ -144,7 +145,5 @@ pub async fn refresh( &toggl_client, &time_entries, None, - ).await?; - - Ok("Ok") + ).await.map(Json) } diff --git a/src/sync_service.rs b/src/sync_service.rs index 83a5e0e..fb6657f 100644 --- a/src/sync_service.rs +++ b/src/sync_service.rs @@ -4,29 +4,52 @@ use crate::toggl_api::types::{Client, Project, ReportRow, TimeEntry as ToggleApi use crate::utils; use migration::Condition; use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QuerySelect}; -use tracing::{debug, instrument}; +use serde::Serialize; use crate::toggl_api::TogglApiClient; +#[derive(Debug, Serialize)] +pub struct UpdateStats { + retrieved: UpdateStatsInner, + written: UpdateStatsInner, +} + +#[derive(Debug, Serialize)] +pub struct UpdateStatsInner { + updated: usize, + deleted: usize, +} + pub async fn update_database( db: &DatabaseConnection, toggl_client: &TogglApiClient, time_entries: &[ToggleApiTimeEntry], exclusive_on: Option, -) -> utils::Result<()> { +) -> utils::Result { let (deleted_entries, time_entries) = time_entries .iter() .partition::, _>(|entry| entry.server_deleted_at.is_some()); + let retrieved = UpdateStatsInner { + updated: time_entries.len(), + deleted: deleted_entries.len(), + }; + + let mut written = UpdateStatsInner { + updated: 0, + deleted: 0, + }; + let deleted_ids = deleted_entries.iter() .map(|entry| entry.id) .collect::>(); if !deleted_ids.is_empty() { - debug!("Deleting time entries: {:?}", deleted_ids); - TimeEntry::delete_many() + let delete_result = TimeEntry::delete_many() .filter(time_entry::Column::TogglId.is_in(deleted_ids)) .exec(db) .await?; + + written.deleted = delete_result.rows_affected as usize; } let existing_project_ids = project::Entity::find() @@ -67,14 +90,19 @@ pub async fn update_database( // TODO: Why is this needed? if models.is_empty() { - return Ok(()); + return Ok(UpdateStats { + retrieved, + written, + }); } - TimeEntry::insert_many(models) + let insert_result = TimeEntry::insert_many(models) .on_conflict(ToggleApiTimeEntry::grafting_conflict_statement()) - .exec(db) + .exec_without_returning(db) .await?; + written.updated = insert_result as usize; + if let Some(exclusive_on) = exclusive_on { TimeEntry::delete_many() .filter( @@ -86,5 +114,8 @@ pub async fn update_database( .await?; } - Ok(()) + Ok(UpdateStats { + retrieved, + written, + }) } \ No newline at end of file