Report update statistics
This commit is contained in:
parent
7759632848
commit
479389dde6
14
src/poll.rs
14
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<usize> {
|
||||
) -> utils::Result<UpdateStats> {
|
||||
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
|
||||
}
|
||||
|
||||
@ -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<TogglApiClient>,
|
||||
Extension(db): Extension<DatabaseConnection>,
|
||||
Query(RefreshQuery { start_date, end_date }): Query<RefreshQuery>,
|
||||
) -> utils::Result<&'static str> {
|
||||
) -> utils::Result<Json<UpdateStats>> {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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<Condition>,
|
||||
) -> utils::Result<()> {
|
||||
) -> utils::Result<UpdateStats> {
|
||||
let (deleted_entries, time_entries) = time_entries
|
||||
.iter()
|
||||
.partition::<Vec<_>, _>(|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::<Vec<_>>();
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user