Skip to content

Commit

Permalink
Use serde-firestore-value for parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
bouzuya committed Nov 2, 2023
1 parent 14022fe commit 03c9d6a
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 42 deletions.
23 changes: 19 additions & 4 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions rust/crates/web/Cargo.toml
Expand Up @@ -14,10 +14,12 @@ features = "0.10.0"
google-api-proto = { version = "1.415.0", features = ["google-firestore-v1"] }
google-authz = { version = "1.0.0-alpha.5", features = ["tonic"] }
hyper = { version = "0.14.27", features = ["full"] }
prost-types = "0.12.1"
prost-types = "0.12"
serde = { version = "1.0.190", features = ["derive"] }
serde-firestore-value = "0.2.0"
thiserror = "1.0.50"
tokio = { version = "1.32.0", features = ["full"] }
tonic = { version = "0.10.2", features = ["tls-webpki-roots"] }
tonic = { version = "0.10", features = ["tls-webpki-roots"] }
tower = "0.4.13"

[dev-dependencies]
Expand Down
93 changes: 57 additions & 36 deletions rust/crates/web/src/infra/firestore.rs
@@ -1,18 +1,20 @@
use std::collections::BTreeMap;

use google_api_proto::google::firestore::v1::{
firestore_client::FirestoreClient, precondition::ConditionType, CreateDocumentRequest,
DeleteDocumentRequest, Document, GetDocumentRequest, ListDocumentsRequest,
ListDocumentsResponse, Precondition, UpdateDocumentRequest, Value,
firestore_client::FirestoreClient, precondition::ConditionType, value::ValueType,
CreateDocumentRequest, DeleteDocumentRequest, Document, GetDocumentRequest,
ListDocumentsRequest, ListDocumentsResponse, MapValue, Precondition, UpdateDocumentRequest,
};
use google_authz::{Credentials, GoogleAuthz};
use prost_types::Timestamp;
use serde::Serialize;
use serde_firestore_value::to_value;
use tonic::{transport::Channel, Request};

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("credentials {0}")]
Credentials(#[from] google_authz::CredentialsError),
#[error("serialize {0}")]
Serialize(#[from] serde_firestore_value::Error),
#[error("status {0}")]
Status(#[from] tonic::Status),
#[error("transport {0}")]
Expand Down Expand Up @@ -49,11 +51,10 @@ impl Client {
})
}

pub async fn create(
&mut self,
collection_id: String,
fields: BTreeMap<String, Value>,
) -> Result<Document, Error> {
pub async fn create<V>(&mut self, collection_id: String, fields: V) -> Result<Document, Error>
where
V: Serialize,
{
let response = self
.client
.create_document(Request::new(CreateDocumentRequest {
Expand All @@ -65,7 +66,14 @@ impl Client {
document_id: "".to_string(),
document: Some(Document {
name: "".to_string(),
fields,
fields: {
let ser = to_value(&fields)?;
if let Some(ValueType::MapValue(MapValue { fields })) = ser.value_type {
fields
} else {
panic!("unexpected value_type: {:?}", ser.value_type);
}
},
create_time: None,
update_time: None,
}),
Expand Down Expand Up @@ -128,15 +136,31 @@ impl Client {
Ok(response.into_inner())
}

pub async fn update(
pub async fn update<V>(
&mut self,
document: Document,
name: String,
fields: V,
current_update_time: Timestamp,
) -> Result<Document, Error> {
) -> Result<Document, Error>
where
V: Serialize,
{
let response = self
.client
.update_document(Request::new(UpdateDocumentRequest {
document: Some(document),
document: Some(Document {
name,
fields: {
let ser = to_value(&fields)?;
if let Some(ValueType::MapValue(MapValue { fields })) = ser.value_type {
fields
} else {
panic!("unexpected value_type: {:?}", ser.value_type);
}
},
create_time: None,
update_time: None,
}),
update_mask: None,
mask: None,
current_document: Some(Precondition {
Expand All @@ -150,8 +174,10 @@ impl Client {

#[cfg(test)]
mod tests {
use std::collections::BTreeMap;

use anyhow::Context;
use google_api_proto::google::firestore::v1::value::ValueType;
use google_api_proto::google::firestore::v1::{value::ValueType, Value};

use super::*;

Expand All @@ -174,14 +200,18 @@ mod tests {
}

// CREATE
let mut fields = BTreeMap::new();
fields.insert(
"k1".to_owned(),
Value {
value_type: Some(ValueType::StringValue("v1".to_owned())),
},
);
let created = client.create(collection_name.to_string(), fields).await?;
#[derive(serde::Serialize)]
struct V {
k1: String,
}
let created = client
.create(
collection_name.to_string(),
V {
k1: "v1".to_owned(),
},
)
.await?;
assert!(created
.name
.starts_with("projects/demo-project1/databases/(default)/documents/repositories/"),);
Expand Down Expand Up @@ -210,18 +240,9 @@ mod tests {
// UPDATE
let updated = client
.update(
Document {
fields: {
let mut fields = BTreeMap::new();
fields.insert(
"k1".to_owned(),
Value {
value_type: Some(ValueType::StringValue("v2".to_owned())),
},
);
fields
},
..got.clone()
got.name.clone(),
V {
k1: "v2".to_owned(), // "v1" -> "v2
},
got.update_time.context("update_time")?,
)
Expand Down

0 comments on commit 03c9d6a

Please sign in to comment.