From d33b878e82d8362646ec7f4426a500fbd01a0112 Mon Sep 17 00:00:00 2001 From: bouzuya Date: Tue, 1 Nov 2022 21:15:00 +0900 Subject: [PATCH] twiq: Move client, credential to firestore_rpc::helper --- twiq/crates/db/src/firestore_rpc.rs | 56 ++++++++++++++++++- twiq/crates/db/src/firestore_transaction.rs | 61 ++++----------------- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/twiq/crates/db/src/firestore_rpc.rs b/twiq/crates/db/src/firestore_rpc.rs index 495b7093..45d1d311 100644 --- a/twiq/crates/db/src/firestore_rpc.rs +++ b/twiq/crates/db/src/firestore_rpc.rs @@ -19,9 +19,17 @@ pub mod google { } pub mod helper { + use super::google::firestore::v1::{ + firestore_client::FirestoreClient, value::ValueType, Document, Value, + }; + use google_cloud_auth::{Credential, CredentialConfig}; use prost_types::Timestamp; - - use super::google::firestore::v1::{value::ValueType, Document, Value}; + use tonic::{ + codegen::InterceptedService, + metadata::AsciiMetadataValue, + transport::{Channel, ClientTlsConfig, Endpoint}, + Request, Status, + }; pub mod path { /// ```rust @@ -71,6 +79,50 @@ pub mod helper { } } + #[derive(Debug, thiserror::Error)] + pub enum Error { + #[error("google_cloud_auth {0}")] + GoogleCloudAuth(#[from] google_cloud_auth::Error), + #[error("status {0}")] + Status(#[from] Status), + #[error("tonic invalid metadata value {0}")] + TonicInvalidMetadataValue(#[from] tonic::metadata::errors::InvalidMetadataValue), + #[error("transport {0}")] + TonicTransport(#[from] tonic::transport::Error), + } + + pub async fn client( + credential: &Credential, + ) -> Result< + FirestoreClient< + InterceptedService) -> Result, Status>>, + >, + Error, + > { + let access_token = credential.access_token().await?; + let channel = Endpoint::from_static("https://firestore.googleapis.com") + .tls_config(ClientTlsConfig::new().domain_name("firestore.googleapis.com"))? + .connect() + .await?; + let mut metadata_value = + AsciiMetadataValue::try_from(format!("Bearer {}", access_token.value))?; + metadata_value.set_sensitive(true); + let client = FirestoreClient::with_interceptor(channel, move |mut request: Request<()>| { + request + .metadata_mut() + .insert("authorization", metadata_value.clone()); + Ok(request) + }); + Ok(client) + } + + pub async fn credential() -> Result { + let config = CredentialConfig::builder() + .scopes(vec!["https://www.googleapis.com/auth/cloud-platform".into()]) + .build()?; + Ok(Credential::find_default(config).await?) + } + pub fn get_field_as_i64(document: &Document, key: &str) -> Option { document.fields.get(key).map(value_into_i64_unchecked) } diff --git a/twiq/crates/db/src/firestore_transaction.rs b/twiq/crates/db/src/firestore_transaction.rs index dc003ef0..19a02b84 100644 --- a/twiq/crates/db/src/firestore_transaction.rs +++ b/twiq/crates/db/src/firestore_transaction.rs @@ -1,33 +1,25 @@ use std::sync::Arc; -use google_cloud_auth::{Credential, CredentialConfig}; +use google_cloud_auth::Credential; use tokio::sync::Mutex; -use tonic::{ - codegen::InterceptedService, - metadata::AsciiMetadataValue, - transport::{Channel, ClientTlsConfig, Endpoint}, - Request, Status, -}; use crate::firestore_rpc::{ google::firestore::v1::{ - firestore_client::FirestoreClient, transaction_options::{Mode, ReadWrite}, BeginTransactionRequest, CommitRequest, TransactionOptions, Write, }, - helper::path::{collection_path, database_path, document_path}, + helper::{ + client, credential, + path::{collection_path, database_path, document_path}, + }, }; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("google_cloud_auth {0}")] - GoogleCloudAuth(#[from] google_cloud_auth::Error), + #[error("{0}")] + Error(#[from] crate::firestore_rpc::helper::Error), #[error("status {0}")] - Status(#[from] Status), - #[error("tonic invalid metadata value {0}")] - TonicInvalidMetadataValue(#[from] tonic::metadata::errors::InvalidMetadataValue), - #[error("tonic transport {0}")] - TonicTransport(#[from] tonic::transport::Error), + Status(#[from] tonic::Status), } pub type Result = std::result::Result; @@ -42,8 +34,8 @@ pub struct FirestoreTransaction { impl FirestoreTransaction { pub async fn begin(project_id: String, database_id: String) -> Result { - let credential = Self::credential().await?; - let mut client = Self::client(&credential).await?; + let credential = credential().await?; + let mut client = client(&credential).await?; let database = database_path(&project_id, &database_id); let response = client .begin_transaction(BeginTransactionRequest { @@ -68,7 +60,7 @@ impl FirestoreTransaction { pub async fn commit(self) -> Result<()> { let writes = self.writes.lock().await.clone(); let database = self.database_path(); - let mut client = Self::client(&self.credential).await?; + let mut client = client(&self.credential).await?; let _ = client .commit(CommitRequest { database, @@ -103,37 +95,6 @@ impl FirestoreTransaction { pub fn project_id(&self) -> String { self.project_id.clone() } - - async fn client( - credential: &Credential, - ) -> Result< - FirestoreClient< - InterceptedService) -> Result, Status>>, - >, - > { - let access_token = credential.access_token().await?; - let channel = Endpoint::from_static("https://firestore.googleapis.com") - .tls_config(ClientTlsConfig::new().domain_name("firestore.googleapis.com"))? - .connect() - .await?; - let mut metadata_value = - AsciiMetadataValue::try_from(format!("Bearer {}", access_token.value))?; - metadata_value.set_sensitive(true); - let client = FirestoreClient::with_interceptor(channel, move |mut request: Request<()>| { - request - .metadata_mut() - .insert("authorization", metadata_value.clone()); - Ok(request) - }); - Ok(client) - } - - async fn credential() -> Result { - let config = CredentialConfig::builder() - .scopes(vec!["https://www.googleapis.com/auth/cloud-platform".into()]) - .build()?; - Ok(Credential::find_default(config).await?) - } } #[cfg(test)]