Skip to content

Commit

Permalink
twiq: Add firestore_rest::begin_transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
bouzuya committed Aug 22, 2022
1 parent 83e5c47 commit dc660d2
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
3 changes: 1 addition & 2 deletions twiq/crates/db/src/event_store.rs
@@ -1,12 +1,11 @@
use std::{collections::HashMap, env, str::FromStr};

use reqwest::Response;
use serde::__private::doc;

use crate::{
event::Event,
event_stream_id::EventStreamId,
event_stream_seq::{self, EventStreamSeq},
event_stream_seq::EventStreamSeq,
firestore_rest::{self, Document, Timestamp, Value},
};

Expand Down
73 changes: 73 additions & 0 deletions twiq/crates/db/src/firestore_rest.rs
Expand Up @@ -147,6 +147,50 @@ pub struct Document {
pub update_time: Timestamp,
}

#[derive(Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub enum TransactionOptions {
ReadOnly {
read_time: String,
},
ReadWrite {
#[serde(skip_serializing_if = "Option::is_none")]
retry_transaction: Option<String>,
},
}

#[derive(Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct BeginTransactionRequestBody {
pub options: TransactionOptions,
}

#[derive(Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct BeginTransactionResponse {
pub transaction: String,
}

pub async fn begin_transaction(
(token, project_id): (&str, &str),
database: &str,
body: BeginTransactionRequestBody,
) -> anyhow::Result<Response> {
// <https://cloud.google.com/firestore/docs/reference/rest/v1/projects.databases.documents/beginTransaction>
let method = Method::POST;
let url = format!(
"https://firestore.googleapis.com/v1/{}/documents:beginTransaction",
database
);

Ok(Client::new()
.request(method, url)
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.header("X-Goog-User-Project", project_id)
.body(serde_json::to_string(&body)?)
.send()
.await?)
}

pub async fn create_document(
(token, project_id): (&str, &str),
parent: &str,
Expand Down Expand Up @@ -397,4 +441,33 @@ mod tests {
assert!(serde_json::to_string(&document).is_ok());
Ok(())
}

#[test]
fn begin_transaction_request_body_test() -> anyhow::Result<()> {
assert_eq!(
serde_json::to_string(&BeginTransactionRequestBody {
options: TransactionOptions::ReadWrite {
retry_transaction: None,
},
})?,
r#"{"options":{"readWrite":{}}}"#
);
assert_eq!(
serde_json::to_string(&BeginTransactionRequestBody {
options: TransactionOptions::ReadWrite {
retry_transaction: Some("abc".to_owned()),
},
})?,
r#"{"options":{"readWrite":{"retry_transaction":"abc"}}}"#
);
assert_eq!(
serde_json::to_string(&BeginTransactionRequestBody {
options: TransactionOptions::ReadOnly {
read_time: "2000-01-02T03:04:05Z".to_owned()
}
})?,
r#"{"options":{"readOnly":{"read_time":"2000-01-02T03:04:05Z"}}}"#
);
Ok(())
}
}
31 changes: 28 additions & 3 deletions twiq/crates/db/src/lib.rs
Expand Up @@ -11,7 +11,29 @@ use std::{collections::HashMap, env};
use anyhow::ensure;
use reqwest::Response;

use crate::firestore_rest::{Document, Value};
use crate::firestore_rest::{
BeginTransactionRequestBody, BeginTransactionResponse, Document, TransactionOptions, Value,
};

async fn begin_transaction_example() -> anyhow::Result<BeginTransactionResponse> {
let bearer_token = env::var("GOOGLE_BEARER_TOKEN")?;
let project_id = env::var("PROJECT_ID")?;
let database_id = "(default)";
let database = format!("projects/{}/databases/{}", project_id, database_id);
let response = firestore_rest::begin_transaction(
(&bearer_token, &project_id),
&database,
BeginTransactionRequestBody {
options: TransactionOptions::ReadWrite {
retry_transaction: None,
},
},
)
.await?;
ensure!(response.status() == 200);
let response: BeginTransactionResponse = response.json().await?;
Ok(response)
}

// select (one)
async fn get_example() -> anyhow::Result<Document> {
Expand Down Expand Up @@ -106,14 +128,17 @@ mod tests {
use super::*;

#[tokio::test]
#[ignore]
async fn test() -> anyhow::Result<()> {
let response = begin_transaction_example().await?;
assert_eq!(serde_json::to_string(&response)?, "");
// let response = create_document_example().await?;
// let status = response.status();
// assert_eq!(status, 200);

// let response = patch_example().await?;
let document = get_example().await?;
assert_eq!(serde_json::to_string(&document)?, "");
// let document = get_example().await?;
// assert_eq!(serde_json::to_string(&document)?, "");
Ok(())
}
}

0 comments on commit dc660d2

Please sign in to comment.