Run rustfmt and fix some clippy lints

This commit is contained in:
Joshua Coles 2024-03-03 20:53:41 +00:00
parent 479389dde6
commit b7102e12a6
5 changed files with 56 additions and 70 deletions

View File

@ -5,7 +5,8 @@ use sea_orm::{NotSet, Set};
impl ReportRow { impl ReportRow {
pub fn to_time_entries(&self, workspace_id: i64) -> Vec<TimeEntry> { pub fn to_time_entries(&self, workspace_id: i64) -> Vec<TimeEntry> {
self.time_entries.iter() self.time_entries
.iter()
.map(|inner| TimeEntry { .map(|inner| TimeEntry {
id: inner.id as i64, id: inner.id as i64,
description: self.description.clone(), description: self.description.clone(),
@ -21,7 +22,8 @@ impl ReportRow {
duration: inner.seconds as i64, duration: inner.seconds as i64,
tag_ids: self.tag_ids.iter().map(|ids| *ids as i64).collect(), tag_ids: self.tag_ids.iter().map(|ids| *ids as i64).collect(),
user_id: self.user_id as i64, user_id: self.user_id as i64,
}).collect() })
.collect()
} }
} }
@ -62,10 +64,10 @@ impl Client {
client::ActiveModel { client::ActiveModel {
id: Set(self.id), id: Set(self.id),
name: Set(self.name.clone()), name: Set(self.name.clone()),
archived: Set(self.archived.clone()), archived: Set(self.archived),
workspace_id: Set(self.wid), workspace_id: Set(self.wid),
at: Set(self.at.clone().fixed_offset()), at: Set(self.at.clone().fixed_offset()),
server_deleted_at: Set(self.server_deleted_at.clone().map(|dt| dt.fixed_offset())), server_deleted_at: Set(self.server_deleted_at.map(|dt| dt.fixed_offset())),
} }
} }

View File

@ -1,19 +1,12 @@
use crate::entity::prelude::TimeEntry; use crate::entity::time_entry;
use crate::entity::{client, project, time_entry}; use crate::sync_service::{update_database, UpdateStats};
use crate::toggl_api::types::{Client, Project, TogglReportQuery};
use crate::toggl_api::TogglApiClient; use crate::toggl_api::TogglApiClient;
use crate::utils; use crate::utils;
use crate::utils::day_exclusivity_condition;
use chrono::{DateTime, FixedOffset}; use chrono::{DateTime, FixedOffset};
use sea_orm::DatabaseBackend::Postgres;
use sea_orm::{
ConnectionTrait, DatabaseConnection, EntityOrSelect, EntityTrait, QueryOrder, QuerySelect,
Statement,
};
use std::ops::Sub;
use migration::Order; use migration::Order;
use sea_orm::{DatabaseConnection, EntityTrait, QueryOrder, QuerySelect};
use std::ops::Sub;
use tracing::instrument; use tracing::instrument;
use crate::sync_service::{update_database, UpdateStats};
#[tracing::instrument(skip(client, db))] #[tracing::instrument(skip(client, db))]
pub async fn poll_job(client: TogglApiClient, db: DatabaseConnection, poll_period: u64) { pub async fn poll_job(client: TogglApiClient, db: DatabaseConnection, poll_period: u64) {
@ -24,10 +17,7 @@ pub async fn poll_job(client: TogglApiClient, db: DatabaseConnection, poll_perio
tracing::info!("Polling Toggl API"); tracing::info!("Polling Toggl API");
match perform_poll(&client, &db).await { match perform_poll(&client, &db).await {
Ok(poll_update_data) => { Ok(poll_update_data) => {
tracing::info!( tracing::info!("Successfully polled Toggl API: {:?}", poll_update_data);
"Successfully polled Toggl API: {:?}",
poll_update_data
);
} }
Err(error) => { Err(error) => {
@ -63,10 +53,5 @@ pub async fn perform_poll(
.await?; .await?;
// These are changes only so there is no need to enforce exclusivity // These are changes only so there is no need to enforce exclusivity
update_database( update_database(db, toggl_client, &time_entries, None).await
db,
toggl_client,
&time_entries,
None,
).await
} }

View File

@ -1,3 +1,4 @@
use crate::sync_service::UpdateStats;
use crate::toggl_api::types::{self, Client, Project, ReportRow, TogglReportQuery}; use crate::toggl_api::types::{self, Client, Project, ReportRow, TogglReportQuery};
use crate::toggl_api::TogglApiClient; use crate::toggl_api::TogglApiClient;
use crate::{entity, sync_service, utils}; use crate::{entity, sync_service, utils};
@ -11,8 +12,7 @@ use sea_orm::{DatabaseConnection, EntityTrait};
use serde::Deserialize; use serde::Deserialize;
use serde_json::Value; use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use tracing::{instrument}; use tracing::instrument;
use crate::sync_service::UpdateStats;
#[instrument(skip(db, toggl_client))] #[instrument(skip(db, toggl_client))]
pub async fn report( pub async fn report(
@ -21,13 +21,11 @@ pub async fn report(
Json(query): Json<TogglReportQuery>, Json(query): Json<TogglReportQuery>,
) -> utils::Result<Json<Vec<ReportRow>>> { ) -> utils::Result<Json<Vec<ReportRow>>> {
let report = toggl_client.full_report(&query).await?; let report = toggl_client.full_report(&query).await?;
let time_entries = report.iter().flat_map(|entry| entry.to_time_entries(toggl_client.workspace_id())).collect::<Vec<_>>(); let time_entries = report
sync_service::update_database( .iter()
&db, .flat_map(|entry| entry.to_time_entries(toggl_client.workspace_id()))
&toggl_client, .collect::<Vec<_>>();
&time_entries, sync_service::update_database(&db, &toggl_client, &time_entries, None).await?;
None,
).await?;
Ok(Json(report)) Ok(Json(report))
} }
@ -36,7 +34,7 @@ pub async fn report(
pub async fn current( pub async fn current(
Extension(toggl_client): Extension<TogglApiClient>, Extension(toggl_client): Extension<TogglApiClient>,
) -> utils::Result<Json<Option<types::TimeEntry>>> { ) -> utils::Result<Json<Option<types::TimeEntry>>> {
Ok(toggl_client.fetch_current_time_entry().await.map(Json)?) toggl_client.fetch_current_time_entry().await.map(Json)
} }
#[instrument(skip(toggl_client))] #[instrument(skip(toggl_client))]
@ -81,11 +79,11 @@ pub async fn clients(
pub async fn health( pub async fn health(
Extension(toggl_client): Extension<TogglApiClient>, Extension(toggl_client): Extension<TogglApiClient>,
) -> utils::Result<&'static str> { ) -> utils::Result<&'static str> {
return if toggl_client.check_health().await { if toggl_client.check_health().await {
Ok("Ok") Ok("Ok")
} else { } else {
Err(anyhow!("Panopto health check failed").into()) Err(anyhow!("Toggl health check failed").into())
}; }
} }
pub async fn import_csv( pub async fn import_csv(
@ -119,31 +117,33 @@ pub struct RefreshQuery {
pub async fn refresh( pub async fn refresh(
Extension(toggl_client): Extension<TogglApiClient>, Extension(toggl_client): Extension<TogglApiClient>,
Extension(db): Extension<DatabaseConnection>, Extension(db): Extension<DatabaseConnection>,
Query(RefreshQuery { start_date, end_date }): Query<RefreshQuery>, Query(RefreshQuery {
start_date,
end_date,
}): Query<RefreshQuery>,
) -> utils::Result<Json<UpdateStats>> { ) -> utils::Result<Json<UpdateStats>> {
let time_entries = match (start_date, end_date) { let time_entries = match (start_date, end_date) {
(Some(start_date), Some(end_date)) => { (Some(start_date), Some(end_date)) => {
toggl_client.fetch_time_entries_in_range(start_date, end_date).await? toggl_client
.fetch_time_entries_in_range(start_date, end_date)
.await?
} }
(Some(start_date), None) => { (Some(start_date), None) => {
let end_date = Utc::now(); let end_date = Utc::now();
toggl_client.fetch_time_entries_in_range(start_date, end_date).await? toggl_client
.fetch_time_entries_in_range(start_date, end_date)
.await?
} }
(None, Some(_)) => { (None, Some(_)) => {
return Err(anyhow!("start_date must be provided if end_date is provided").into()); return Err(anyhow!("start_date must be provided if end_date is provided").into());
} }
_ => { _ => toggl_client.fetch_recent_time_entries().await?,
toggl_client.fetch_recent_time_entries().await?
}
}; };
sync_service::update_database( sync_service::update_database(&db, &toggl_client, &time_entries, None)
&db, .await
&toggl_client, .map(Json)
&time_entries,
None,
).await.map(Json)
} }

View File

@ -1,11 +1,11 @@
use crate::entity::{client, project, time_entry};
use crate::entity::time_entry::Entity as TimeEntry; use crate::entity::time_entry::Entity as TimeEntry;
use crate::toggl_api::types::{Client, Project, ReportRow, TimeEntry as ToggleApiTimeEntry}; use crate::entity::{client, project, time_entry};
use crate::toggl_api::types::{Client, Project, TimeEntry as ToggleApiTimeEntry};
use crate::toggl_api::TogglApiClient;
use crate::utils; use crate::utils;
use migration::Condition; use migration::Condition;
use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QuerySelect}; use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, QuerySelect};
use serde::Serialize; use serde::Serialize;
use crate::toggl_api::TogglApiClient;
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct UpdateStats { pub struct UpdateStats {
@ -39,7 +39,8 @@ pub async fn update_database(
deleted: 0, deleted: 0,
}; };
let deleted_ids = deleted_entries.iter() let deleted_ids = deleted_entries
.iter()
.map(|entry| entry.id) .map(|entry| entry.id)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -62,7 +63,7 @@ pub async fn update_database(
let new_projects = time_entries let new_projects = time_entries
.iter() .iter()
.filter_map(|entry| entry.project_id) .filter_map(|entry| entry.project_id)
.any(|project_id| !existing_project_ids.contains(&(project_id as i64))); .any(|project_id| !existing_project_ids.contains(&project_id));
if new_projects { if new_projects {
let clients = toggl_client.fetch_clients().await?; let clients = toggl_client.fetch_clients().await?;
@ -80,20 +81,19 @@ pub async fn update_database(
.await?; .await?;
} }
let ids = time_entries.iter() let ids = time_entries
.iter()
.map(|entry| entry.id) .map(|entry| entry.id)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let models = time_entries.into_iter() let models = time_entries
.into_iter()
.map(|entry| entry.as_model()) .map(|entry| entry.as_model())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// TODO: Why is this needed? // TODO: Why is this needed?
if models.is_empty() { if models.is_empty() {
return Ok(UpdateStats { return Ok(UpdateStats { retrieved, written });
retrieved,
written,
});
} }
let insert_result = TimeEntry::insert_many(models) let insert_result = TimeEntry::insert_many(models)
@ -114,8 +114,5 @@ pub async fn update_database(
.await?; .await?;
} }
Ok(UpdateStats { Ok(UpdateStats { retrieved, written })
retrieved, }
written,
})
}

View File

@ -49,7 +49,7 @@ impl TogglApiClient {
} }
pub fn new(workspace_id: &str, api_token: &str) -> Self { pub fn new(workspace_id: &str, api_token: &str) -> Self {
let toggl_auth = &STANDARD.encode(&format!("{}:api_token", api_token)); let toggl_auth = &STANDARD.encode(format!("{}:api_token", api_token));
let client = Client::builder() let client = Client::builder()
.default_headers(Self::default_headers(toggl_auth)) .default_headers(Self::default_headers(toggl_auth))
@ -107,7 +107,8 @@ impl TogglApiClient {
pub async fn fetch_recent_time_entries(&self) -> crate::Result<Vec<TimeEntry>> { pub async fn fetch_recent_time_entries(&self) -> crate::Result<Vec<TimeEntry>> {
let url = format!("{base_url}/me/time_entries", base_url = self.base_url); let url = format!("{base_url}/me/time_entries", base_url = self.base_url);
Ok(self.make_request(self.client.get(url)) Ok(self
.make_request(self.client.get(url))
.await? .await?
.json::<Vec<TimeEntry>>() .json::<Vec<TimeEntry>>()
.await?) .await?)
@ -132,7 +133,8 @@ impl TogglApiClient {
pub async fn fetch_time_entries_in_range( pub async fn fetch_time_entries_in_range(
&self, &self,
start: DateTime<Utc>, end: DateTime<Utc>, start: DateTime<Utc>,
end: DateTime<Utc>,
) -> crate::Result<Vec<TimeEntry>> { ) -> crate::Result<Vec<TimeEntry>> {
let url = format!("{base_url}/me/time_entries", base_url = self.base_url); let url = format!("{base_url}/me/time_entries", base_url = self.base_url);
@ -211,7 +213,7 @@ impl TogglApiClient {
.make_request( .make_request(
self.client self.client
.post(&url) .post(&url)
.json(&Self::paginate_filters(&filters, last_row_number_n)), .json(&Self::paginate_filters(filters, last_row_number_n)),
) )
.await?; .await?;