This commit is contained in:
2024-07-27 20:51:30 +01:00
parent 71f9ed3312
commit 25a52fa0e5
2 changed files with 193 additions and 117 deletions
+61 -36
View File
@@ -1,13 +1,13 @@
use chrono::{DateTime, DurationRound, NaiveDate, TimeDelta, Utc};
use sqlx::{Connection, PgConnection, Postgres, QueryBuilder};
use toggl::TogglApi;
use crate::toggl::types::{Project, Tag, TimeEntry, TogglReportFilters, TrackingClient};
use chrono::{DateTime, DurationRound, NaiveDate, TimeDelta, Utc};
use itertools::Itertools;
use soa_rs::Soa;
use sqlx::{Connection, PgConnection, Postgres, QueryBuilder};
use toggl::TogglApi;
use tracing_subscriber::fmt::time;
mod toggl;
mod sensitive;
mod toggl;
#[derive(Debug, thiserror::Error)]
enum AppError {
@@ -59,14 +59,25 @@ impl Worker {
})
}
pub async fn fetch_within(&mut self, start: DateTime<Utc>, end: DateTime<Utc>) -> Result<(), AppError> {
let results = self.toggl_api.search(self.toggl_api.workspace_id, TogglReportFilters {
start_date: Some(start.date_naive()),
end_date: Some(end.date_naive()),
..Default::default()
}).await?;
pub async fn fetch_within(
&mut self,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> Result<(), AppError> {
let results = self
.toggl_api
.search(
self.toggl_api.workspace_id,
TogglReportFilters {
start_date: Some(start.date_naive()),
end_date: Some(end.date_naive()),
..Default::default()
},
)
.await?;
let time_entries = results.into_iter()
let time_entries = results
.into_iter()
.map(|entry| entry.into_time_entry(self.toggl_api.workspace_id))
.collect::<Vec<_>>();
@@ -95,8 +106,10 @@ impl Worker {
}
async fn update_time_entries(&mut self, fetch_since: DateTime<Utc>) -> Result<(), AppError> {
let time_entries = self.toggl_api
.get_time_entries_for_user_modified_since(fetch_since).await?;
let time_entries = self
.toggl_api
.get_time_entries_for_user_modified_since(fetch_since)
.await?;
self.update_database(time_entries).await
}
@@ -104,17 +117,20 @@ impl Worker {
async fn update_database(&mut self, time_entries: Vec<TimeEntry>) -> Result<(), AppError> {
let existing_ids = self.get_ids().await?;
let fetch_workspaces = time_entries.iter()
let fetch_workspaces = time_entries
.iter()
.map(|entry| entry.workspace_id)
.filter(|workspace_id| !existing_ids.workspace_ids.contains(&workspace_id))
.collect::<Vec<_>>();
let fetch_projects = time_entries.iter()
let fetch_projects = time_entries
.iter()
.map(|entry| entry.project_id)
.filter_map(|project_id| project_id)
.any(|project_id| !existing_ids.project_ids.contains(&project_id));
let fetch_tags = time_entries.iter()
let fetch_tags = time_entries
.iter()
.flat_map(|entry| entry.tag_ids.iter())
.any(|tag| !existing_ids.tag_ids.contains(&tag));
@@ -137,7 +153,10 @@ impl Worker {
Ok(())
}
async fn update_time_entries_chunk(&mut self, time_entries: &[TimeEntry]) -> Result<(), AppError> {
async fn update_time_entries_chunk(
&mut self,
time_entries: &[TimeEntry],
) -> Result<(), AppError> {
let time_entries = Soa::from(time_entries);
sqlx::query!(
@@ -179,10 +198,12 @@ impl Worker {
}
async fn update_workspaces(&mut self, workspace_ids: &[u64]) -> Result<(), AppError> {
let workspaces = workspace_ids.iter()
let workspaces = workspace_ids
.iter()
.map(|id| self.toggl_api.get_workspace(*id));
let workspaces = futures::future::join_all(workspaces).await
let workspaces = futures::future::join_all(workspaces)
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()?;
@@ -196,12 +217,20 @@ impl Worker {
organization_id = excluded.organization_id,
name = excluded.name
"#,
&workspaces.id().iter().map(|id| *id as i64).collect::<Vec<_>>()[..],
&workspaces.organization_id().iter().map(|id| *id as i64).collect::<Vec<_>>()[..],
&workspaces
.id()
.iter()
.map(|id| *id as i64)
.collect::<Vec<_>>()[..],
&workspaces
.organization_id()
.iter()
.map(|id| *id as i64)
.collect::<Vec<_>>()[..],
workspaces.name(),
)
.execute(&mut self.db)
.await?;
.execute(&mut self.db)
.await?;
Ok(())
}
@@ -209,7 +238,8 @@ impl Worker {
async fn update_projects(&mut self, existing_ids: &TableSummary) -> Result<(), AppError> {
let projects = self.toggl_api.get_projects().await?;
let fetch_clients = projects.iter()
let fetch_clients = projects
.iter()
.map(|project| project.client_id)
.filter_map(|client_id| client_id)
.any(|client_id| !existing_ids.client_ids.contains(&(client_id as u64)));
@@ -335,28 +365,21 @@ impl Worker {
#[tokio::main]
async fn main() {
dotenv::dotenv()
.expect("Failed to load .env file");
dotenv::dotenv().expect("Failed to load .env file");
// Init tracing
tracing_subscriber::fmt::init();
let api = TogglApi::new(
sensitive::API_TOKEN,
sensitive::WORKSPACE_ID,
);
let api = TogglApi::new(sensitive::API_TOKEN, sensitive::WORKSPACE_ID);
let database_url = std::env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let mut worker = Worker {
db: PgConnection::connect(&database_url).await.unwrap(),
toggl_api: api,
};
worker.update_tags()
.await
.unwrap();
worker.update_tags().await.unwrap();
let start = NaiveDate::from_ymd_opt(2024, 2, 1)
.expect("Invalid date")
@@ -370,6 +393,8 @@ async fn main() {
.expect("Invalid time")
.and_utc();
worker.fetch_within(start, end).await
worker
.fetch_within(start, end)
.await
.expect("Failed to fetch time entries");
}