89 lines
2.6 KiB
Rust
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())
|
|
}
|