Refactor API and add 'fetch_within' method
Changed `workspace_id` type to `u64` for broader compatibility. Introduced `fetch_within` to allow fetching time entries within a given date range and abstracted database update logic into `update_database`.
This commit is contained in:
parent
7fb0ab06e1
commit
ead22776c3
46
src/main.rs
46
src/main.rs
@ -1,6 +1,7 @@
|
|||||||
use chrono::{DateTime, TimeDelta, Utc};
|
use chrono::{DateTime, DurationRound, NaiveDate, TimeDelta, Utc};
|
||||||
use sqlx::{Connection, PgConnection};
|
use sqlx::{Connection, PgConnection};
|
||||||
use toggl::TogglApi;
|
use toggl::TogglApi;
|
||||||
|
use crate::toggl::types::{TimeEntry, TogglReportFilters};
|
||||||
|
|
||||||
mod toggl;
|
mod toggl;
|
||||||
mod sensitive;
|
mod sensitive;
|
||||||
@ -55,7 +56,21 @@ impl Worker {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_changed_since(&mut self, look_back: TimeDelta) -> Result<(), AppError> {
|
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()
|
||||||
|
.map(|entry| entry.into_time_entry(self.toggl_api.workspace_id))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
self.update_database(time_entries).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn fetch_changed_since(&mut self, look_back: TimeDelta) -> Result<(), AppError> {
|
||||||
if look_back > TimeDelta::days(90) {
|
if look_back > TimeDelta::days(90) {
|
||||||
return Err(AppError::LookBackTooLarge)
|
return Err(AppError::LookBackTooLarge)
|
||||||
}
|
}
|
||||||
@ -63,7 +78,7 @@ impl Worker {
|
|||||||
self.update_time_entries(Utc::now() - look_back).await
|
self.update_time_entries(Utc::now() - look_back).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(&mut self, default_look_back: TimeDelta) -> Result<(), AppError> {
|
pub async fn update(&mut self, default_look_back: TimeDelta) -> Result<(), AppError> {
|
||||||
let result = sqlx::query!("select max(updated_at) as last_updated_at from time_entries")
|
let result = sqlx::query!("select max(updated_at) as last_updated_at from time_entries")
|
||||||
.fetch_optional(&mut self.db)
|
.fetch_optional(&mut self.db)
|
||||||
.await
|
.await
|
||||||
@ -77,11 +92,15 @@ impl Worker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn update_time_entries(&mut self, fetch_since: DateTime<Utc>) -> Result<(), AppError> {
|
async fn update_time_entries(&mut self, fetch_since: DateTime<Utc>) -> Result<(), AppError> {
|
||||||
let existing_ids = self.get_ids().await?;
|
|
||||||
|
|
||||||
let time_entries = self.toggl_api
|
let time_entries = self.toggl_api
|
||||||
.get_time_entries_for_user_modified_since(fetch_since).await?;
|
.get_time_entries_for_user_modified_since(fetch_since).await?;
|
||||||
|
|
||||||
|
self.update_database(time_entries).await
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
.map(|entry| entry.workspace_id)
|
||||||
.filter(|workspace_id| !existing_ids.workspace_ids.contains(&workspace_id))
|
.filter(|workspace_id| !existing_ids.workspace_ids.contains(&workspace_id))
|
||||||
@ -324,7 +343,18 @@ async fn main() {
|
|||||||
toggl_api: api,
|
toggl_api: api,
|
||||||
};
|
};
|
||||||
|
|
||||||
worker.fetch_changed_since(TimeDelta::days(90))
|
let start = NaiveDate::from_ymd_opt(2024, 2, 1)
|
||||||
.await
|
.expect("Invalid date")
|
||||||
.unwrap();
|
.and_hms_opt(0, 0, 0)
|
||||||
|
.expect("Invalid time")
|
||||||
|
.and_utc();
|
||||||
|
|
||||||
|
let end = NaiveDate::from_ymd_opt(2024, 5, 1)
|
||||||
|
.expect("Invalid date")
|
||||||
|
.and_hms_opt(0, 0, 0)
|
||||||
|
.expect("Invalid time")
|
||||||
|
.and_utc();
|
||||||
|
|
||||||
|
worker.fetch_within(start, end).await
|
||||||
|
.expect("Failed to fetch time entries");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl reqwest_ratelimit::RateLimiter for ReqwestRateLimiter {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TogglApi {
|
pub struct TogglApi {
|
||||||
client: ClientWithMiddleware,
|
client: ClientWithMiddleware,
|
||||||
workspace_id: u32,
|
pub workspace_id: u64,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,11 +212,11 @@ impl TogglApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub async fn search(&self, filters: types::TogglReportFilters) -> Result<Vec<types::ReportEntry>, TogglError> {
|
pub async fn search(&self, workspace_id: u64, filters: types::TogglReportFilters) -> Result<Vec<types::ReportEntry>, TogglError> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{base_url}/workspace/{workspace_id}/search/time_entries",
|
"{base_url}/workspace/{workspace_id}/search/time_entries",
|
||||||
base_url = &REPORTS_BASE_URL,
|
base_url = &REPORTS_BASE_URL,
|
||||||
workspace_id = self.workspace_id,
|
workspace_id = workspace_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut last_row_number = Some(0);
|
let mut last_row_number = Some(0);
|
||||||
@ -432,7 +432,7 @@ pub mod types {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ReportEntry {
|
impl ReportEntry {
|
||||||
fn into_time_entry(self, workspace_id: u64) -> TimeEntry {
|
pub fn into_time_entry(self, workspace_id: u64) -> TimeEntry {
|
||||||
TimeEntry {
|
TimeEntry {
|
||||||
id: self.time_entries[0].id,
|
id: self.time_entries[0].id,
|
||||||
workspace_id,
|
workspace_id,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user