toggl-portal/src/poll.rs

89 lines
2.6 KiB
Rust

use crate::client::TogglClient;
use crate::entity::{client, project, time_entry};
use crate::types::{Project, ProjectClient, TogglQuery};
use sea_orm::{DatabaseConnection, EntityTrait, QuerySelect};
use tracing::instrument;
use crate::day_exclusivity_condition;
#[tracing::instrument(skip(client, db))]
pub async fn poll_job(client: TogglClient, db: DatabaseConnection, poll_period: u64) {
// Every 2h, poll the Toggl API for new time entries for today to cache them in the database
let period = tokio::time::Duration::from_secs(poll_period);
loop {
tracing::info!("Polling Toggl API");
match perform_poll(&client, &db).await {
Ok(report_entries_count) => {
tracing::info!(
"Successfully polled Toggl API: {:?} entries retrieved",
report_entries_count
);
}
Err(error) => {
tracing::error!("Failed to poll Toggl API: {:?}", error);
}
}
tokio::time::sleep(period).await;
}
}
#[instrument(skip(client, db))]
pub async fn perform_poll(
client: &TogglClient,
db: &DatabaseConnection,
) -> beachhead::Result<usize> {
let now = chrono::Utc::now();
let today_string = now
.date_naive()
.format("%Y-%m-%d")
.to_string();
let report = client
.full_report(&TogglQuery {
start_date: Some(today_string.clone()),
end_date: Some(today_string.clone()),
..Default::default()
})
.await?;
let existing_project_ids = project::Entity::find()
.select_only()
.column(project::Column::TogglId)
.into_tuple::<i64>()
.all(db)
.await?;
let new_projects = report
.iter()
.filter_map(|entry| entry.project_id)
.any(|project_id| !existing_project_ids.contains(&(project_id as i64)));
if new_projects {
let clients = client.fetch_clients().await?;
client::Entity::insert_many(clients.iter().map(ProjectClient::as_model))
.on_conflict(ProjectClient::grafting_conflict_statement())
.exec(db)
.await?;
let projects = client.fetch_projects().await?;
project::Entity::insert_many(projects.iter().map(Project::as_model))
.on_conflict(Project::grafting_conflict_statement())
.exec(db)
.await?;
}
crate::cache_report(
&db,
&report,
Some(
day_exclusivity_condition(now.date_naive(), now.date_naive()),
),
)
.await?;
Ok(report.len())
}