133 lines
3.5 KiB
Rust
133 lines
3.5 KiB
Rust
use anyhow::{anyhow, Result};
|
|
use async_trait::async_trait;
|
|
use futures_util::future::try_join_all;
|
|
use google_walletobjects1::api::{
|
|
FlightClass, FlightObject, FlightclasMethods, FlightobjectMethods,
|
|
};
|
|
use std::sync::Arc;
|
|
|
|
#[async_trait]
|
|
pub trait InsertOrUpdate<T: Clone> {
|
|
async fn insert_now(&self, value: &T) -> Result<bool>;
|
|
async fn update_now(&self, value: &T) -> Result<()>;
|
|
}
|
|
|
|
fn is_already_exists(err: &google_walletobjects1::Error) -> bool {
|
|
match err {
|
|
google_walletobjects1::Error::BadRequest(v) => match v.pointer("/error/code") {
|
|
Some(num) => num == 409,
|
|
None => false,
|
|
},
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl<S> InsertOrUpdate<FlightClass> for FlightclasMethods<'_, S>
|
|
where
|
|
S: tower_service::Service<http::Uri> + Clone + Send + Sync + 'static,
|
|
S::Response: hyper::client::connect::Connection
|
|
+ tokio::io::AsyncRead
|
|
+ tokio::io::AsyncWrite
|
|
+ Send
|
|
+ Unpin
|
|
+ 'static,
|
|
S::Future: Send + Unpin + 'static,
|
|
S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
|
|
{
|
|
async fn insert_now(&self, value: &FlightClass) -> Result<bool> {
|
|
self.insert(value.clone())
|
|
.doit()
|
|
.await
|
|
.and(Ok(true))
|
|
.or_else(|e| {
|
|
if is_already_exists(&e) {
|
|
Ok(false)
|
|
} else {
|
|
Err(anyhow!(e))
|
|
}
|
|
})
|
|
}
|
|
async fn update_now(&self, value: &FlightClass) -> Result<()> {
|
|
self.update(
|
|
value.clone(),
|
|
&value
|
|
.id
|
|
.clone()
|
|
.ok_or_else(|| anyhow!("no id on FlightClass"))?,
|
|
)
|
|
.doit()
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl<S> InsertOrUpdate<FlightObject> for FlightobjectMethods<'_, S>
|
|
where
|
|
S: tower_service::Service<http::Uri> + Clone + Send + Sync + 'static,
|
|
S::Response: hyper::client::connect::Connection
|
|
+ tokio::io::AsyncRead
|
|
+ tokio::io::AsyncWrite
|
|
+ Send
|
|
+ Unpin
|
|
+ 'static,
|
|
S::Future: Send + Unpin + 'static,
|
|
S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
|
|
{
|
|
async fn insert_now(&self, value: &FlightObject) -> Result<bool> {
|
|
self.insert(value.clone())
|
|
.doit()
|
|
.await
|
|
.and(Ok(true))
|
|
.or_else(|e| {
|
|
if is_already_exists(&e) {
|
|
Ok(false)
|
|
} else {
|
|
Err(anyhow!(e))
|
|
}
|
|
})
|
|
}
|
|
async fn update_now(&self, value: &FlightObject) -> Result<()> {
|
|
self.update(
|
|
value.clone(),
|
|
&value
|
|
.id
|
|
.clone()
|
|
.ok_or_else(|| anyhow!("no id on FlightObject"))?,
|
|
)
|
|
.doit()
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub async fn insert_or_update_now<T: Clone>(into: &dyn InsertOrUpdate<T>, value: &T) -> Result<()> {
|
|
let created: bool = into.insert_now(value).await?;
|
|
if !created {
|
|
into.update_now(value).await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn insert_or_update_now_arc<T: Clone>(
|
|
into: Arc<&dyn InsertOrUpdate<T>>,
|
|
value: &T,
|
|
) -> Result<()> {
|
|
insert_or_update_now(*into.as_ref(), value).await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn insert_or_update_many<T: Clone>(
|
|
into: &dyn InsertOrUpdate<T>,
|
|
values: &Vec<T>,
|
|
) -> Result<()> {
|
|
let i = Arc::new(into);
|
|
try_join_all(
|
|
values
|
|
.iter()
|
|
.map(|c| insert_or_update_now_arc(i.clone(), c)),
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|