Skip to content

Commit

Permalink
twiq: Move client, credential to firestore_rpc::helper
Browse files Browse the repository at this point in the history
  • Loading branch information
bouzuya committed Nov 1, 2022
1 parent b02238b commit d33b878
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 52 deletions.
56 changes: 54 additions & 2 deletions twiq/crates/db/src/firestore_rpc.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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<Channel, impl Fn(Request<()>) -> Result<Request<()>, 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<Credential, Error> {
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<i64> {
document.fields.get(key).map(value_into_i64_unchecked)
}
Expand Down
61 changes: 11 additions & 50 deletions 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<T, E = Error> = std::result::Result<T, E>;
Expand All @@ -42,8 +34,8 @@ pub struct FirestoreTransaction {

impl FirestoreTransaction {
pub async fn begin(project_id: String, database_id: String) -> Result<Self> {
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 {
Expand All @@ -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,
Expand Down Expand Up @@ -103,37 +95,6 @@ impl FirestoreTransaction {
pub fn project_id(&self) -> String {
self.project_id.clone()
}

async fn client(
credential: &Credential,
) -> Result<
FirestoreClient<
InterceptedService<Channel, impl Fn(Request<()>) -> Result<Request<()>, 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<Credential> {
let config = CredentialConfig::builder()
.scopes(vec!["https://www.googleapis.com/auth/cloud-platform".into()])
.build()?;
Ok(Credential::find_default(config).await?)
}
}

#[cfg(test)]
Expand Down

0 comments on commit d33b878

Please sign in to comment.