(toggl-portal): Poll
This commit is contained in:
parent
d47174efee
commit
7e2848a0c1
38
src/main.rs
38
src/main.rs
@ -1,4 +1,5 @@
|
||||
use crate::client::TogglClient;
|
||||
use crate::entity::time_entry::{self, ActiveModel, Entity as TimeEntry};
|
||||
use crate::types::{Current, ReportEntry, TogglQuery};
|
||||
use anyhow::anyhow;
|
||||
use axum::http::StatusCode;
|
||||
@ -9,19 +10,19 @@ use base64::engine::general_purpose::STANDARD;
|
||||
use base64::Engine;
|
||||
use beachhead::{shutdown_signal, Result};
|
||||
use clap::Parser;
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
use sea_orm::sea_query::OnConflict;
|
||||
use sea_orm::{DatabaseConnection, EntityTrait};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
use sea_orm::{DatabaseConnection, EntityTrait};
|
||||
use sea_orm::sea_query::OnConflict;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use migration::{Migrator, MigratorTrait};
|
||||
use crate::entity::time_entry::{self, Entity as TimeEntry};
|
||||
|
||||
mod client;
|
||||
mod types;
|
||||
mod db;
|
||||
mod entity;
|
||||
mod poll;
|
||||
mod types;
|
||||
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
struct Config {
|
||||
@ -44,7 +45,16 @@ pub async fn report(
|
||||
Json(query): Json<TogglQuery>,
|
||||
) -> Result<Json<Vec<ReportEntry>>> {
|
||||
let report = toggl_client.full_report(&query).await?;
|
||||
let models = report.iter().flat_map(|entry| entry.as_models());
|
||||
cache_report(&db, &report).await?;
|
||||
|
||||
Ok(Json(report))
|
||||
}
|
||||
|
||||
async fn cache_report(
|
||||
db: &DatabaseConnection,
|
||||
models: &Vec<ReportEntry>,
|
||||
) -> Result<()> {
|
||||
let models = models.iter().flat_map(|entry| entry.as_models());
|
||||
|
||||
TimeEntry::insert_many(models)
|
||||
.on_conflict(
|
||||
@ -55,10 +65,12 @@ pub async fn report(
|
||||
time_entry::Column::Start,
|
||||
time_entry::Column::Stop,
|
||||
time_entry::Column::RawJson,
|
||||
]).to_owned()
|
||||
).exec(&db).await?;
|
||||
|
||||
Ok(Json(report))
|
||||
])
|
||||
.to_owned(),
|
||||
)
|
||||
.exec(db)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn current(
|
||||
@ -99,9 +111,9 @@ async fn main() -> Result<()> {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Migrator::up(&db, None)
|
||||
.await
|
||||
.expect("Failed to migrate");
|
||||
Migrator::up(&db, None).await.expect("Failed to migrate");
|
||||
|
||||
tokio::spawn(poll::poll_job(toggl_client.clone(), db.clone()));
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
|
||||
52
src/poll.rs
Normal file
52
src/poll.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use crate::client::TogglClient;
|
||||
use crate::types::TogglQuery;
|
||||
use sea_orm::DatabaseConnection;
|
||||
use tracing::instrument;
|
||||
|
||||
#[tracing::instrument(skip(client, db))]
|
||||
pub async fn poll_job(client: TogglClient, db: DatabaseConnection) {
|
||||
// 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(60 * 60 * 2);
|
||||
|
||||
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))]
|
||||
async fn perform_poll(client: &TogglClient, db: &DatabaseConnection) -> beachhead::Result<usize> {
|
||||
let report = client
|
||||
.full_report(&TogglQuery {
|
||||
start_date: Some(
|
||||
chrono::Utc::now()
|
||||
.date_naive()
|
||||
.format("%Y-%m-%d")
|
||||
.to_string(),
|
||||
),
|
||||
end_date: Some(
|
||||
chrono::Utc::now()
|
||||
.date_naive()
|
||||
.format("%Y-%m-%d")
|
||||
.to_string(),
|
||||
),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
|
||||
crate::cache_report(&db, &report).await?;
|
||||
Ok(report.len())
|
||||
}
|
||||
@ -58,7 +58,7 @@ pub struct Project {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct TogglQuery {
|
||||
pub billable: Option<bool>,
|
||||
pub client_ids: Option<Vec<u64>>,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user