-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move to async #31
Move to async #31
Changes from all commits
6c62fb2
20713b6
9b0a701
c3f40d2
b732468
be09f2f
96366b6
1f87723
cc78ab5
4f78f64
1d39dda
e8d4a5e
fd25261
fbe1a08
5bb7938
477695a
7d1e776
56729cf
aa6b93f
203363e
6a21910
4c5b64e
d6df985
fa549cc
319b40a
c70e508
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ use firestore_db_and_auth::{documents, dto, errors, sessions, Credentials, Fireb | |
use firestore_db_and_auth::documents::WriteResult; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
use futures::stream::StreamExt; | ||
|
||
mod utils; | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
|
@@ -21,7 +23,7 @@ struct DemoDTOPartial { | |
an_int: u32, | ||
} | ||
|
||
fn write_document(session: &mut ServiceSession, doc_id: &str) -> errors::Result<WriteResult> { | ||
async fn write_document(session: &mut ServiceSession, doc_id: &str) -> errors::Result<WriteResult> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally the question to ask here in the examples is if we want to convert all of the examples to async code. I don't think the lib should imply that you must use async (though I think most people would indeed chose to do so). Personally I would choose to move forward with the |
||
println!("Write document"); | ||
|
||
let obj = DemoDTO { | ||
|
@@ -30,10 +32,16 @@ fn write_document(session: &mut ServiceSession, doc_id: &str) -> errors::Result< | |
a_timestamp: chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Nanos, true), | ||
}; | ||
|
||
documents::write(session, "tests", Some(doc_id), &obj, documents::WriteOptions::default()) | ||
documents::write( | ||
session, | ||
"tests", | ||
Some(doc_id), | ||
&obj, | ||
documents::WriteOptions::default() | ||
).await | ||
} | ||
|
||
fn write_partial_document(session: &mut ServiceSession, doc_id: &str) -> errors::Result<WriteResult> { | ||
async fn write_partial_document(session: &mut ServiceSession, doc_id: &str) -> errors::Result<WriteResult> { | ||
println!("Partial write document"); | ||
|
||
let obj = DemoDTOPartial { | ||
|
@@ -47,7 +55,7 @@ fn write_partial_document(session: &mut ServiceSession, doc_id: &str) -> errors: | |
Some(doc_id), | ||
&obj, | ||
documents::WriteOptions { merge: true }, | ||
) | ||
).await | ||
} | ||
|
||
fn check_write(result: WriteResult, doc_id: &str) { | ||
|
@@ -62,25 +70,25 @@ fn check_write(result: WriteResult, doc_id: &str) { | |
); | ||
} | ||
|
||
fn service_account_session(cred: Credentials) -> errors::Result<()> { | ||
let mut session = ServiceSession::new(cred).unwrap(); | ||
let b = session.access_token().to_owned(); | ||
async fn service_account_session(cred: Credentials) -> errors::Result<()> { | ||
let mut session = ServiceSession::new(cred).await.unwrap(); | ||
let b = session.access_token().await.to_owned(); | ||
|
||
let doc_id = "service_test"; | ||
check_write(write_document(&mut session, doc_id)?, doc_id); | ||
check_write(write_document(&mut session, doc_id).await?, doc_id); | ||
|
||
// Check if cached value is used | ||
assert_eq!(session.access_token(), b); | ||
assert_eq!(session.access_token().await, b); | ||
|
||
println!("Read and compare document"); | ||
let read: DemoDTO = documents::read(&mut session, "tests", doc_id)?; | ||
let read: DemoDTO = documents::read(&mut session, "tests", doc_id).await?; | ||
|
||
assert_eq!(read.a_string, "abcd"); | ||
assert_eq!(read.an_int, 14); | ||
|
||
check_write(write_partial_document(&mut session, doc_id)?, doc_id); | ||
check_write(write_partial_document(&mut session, doc_id).await?, doc_id); | ||
println!("Read and compare document"); | ||
let read: DemoDTOPartial = documents::read(&mut session, "tests", doc_id)?; | ||
let read: DemoDTOPartial = documents::read(&mut session, "tests", doc_id).await?; | ||
|
||
// Should be updated | ||
assert_eq!(read.an_int, 16); | ||
|
@@ -90,14 +98,17 @@ fn service_account_session(cred: Credentials) -> errors::Result<()> { | |
Ok(()) | ||
} | ||
|
||
fn user_account_session(cred: Credentials) -> errors::Result<()> { | ||
let user_session = utils::user_session_with_cached_refresh_token(&cred)?; | ||
async fn user_account_session(cred: Credentials) -> errors::Result<()> { | ||
let user_session = utils::user_session_with_cached_refresh_token(&cred).await?; | ||
|
||
assert_eq!(user_session.user_id, utils::TEST_USER_ID); | ||
assert_eq!(user_session.project_id(), cred.project_id); | ||
|
||
println!("user::Session::by_access_token"); | ||
let user_session = sessions::user::Session::by_access_token(&cred, &user_session.access_token_unchecked())?; | ||
let user_session = sessions::user::Session::by_access_token( | ||
&cred, | ||
&user_session.access_token_unchecked().await | ||
).await?; | ||
|
||
assert_eq!(user_session.user_id, utils::TEST_USER_ID); | ||
|
||
|
@@ -117,13 +128,13 @@ fn user_account_session(cred: Credentials) -> errors::Result<()> { | |
Some(doc_id), | ||
&obj, | ||
documents::WriteOptions::default(), | ||
)?, | ||
).await?, | ||
doc_id, | ||
); | ||
|
||
// Test reading | ||
println!("user::Session documents::read"); | ||
let read: DemoDTO = documents::read(&user_session, "tests", doc_id)?; | ||
let read: DemoDTO = documents::read(&user_session, "tests", doc_id).await?; | ||
|
||
assert_eq!(read.a_string, "abc"); | ||
assert_eq!(read.an_int, 12); | ||
|
@@ -135,22 +146,24 @@ fn user_account_session(cred: Credentials) -> errors::Result<()> { | |
"abc".into(), | ||
dto::FieldOperator::EQUAL, | ||
"a_string", | ||
)? | ||
).await? | ||
.collect(); | ||
assert_eq!(results.len(), 1); | ||
let doc: DemoDTO = documents::read_by_name(&user_session, &results.get(0).unwrap().name)?; | ||
let doc: DemoDTO = documents::read_by_name(&user_session, &results.get(0).unwrap().name).await?; | ||
assert_eq!(doc.a_string, "abc"); | ||
|
||
let mut count = 0; | ||
let list_it: documents::List<DemoDTO, _> = documents::list(&user_session, "tests".to_owned()); | ||
let list_it = documents::list(&user_session, "tests".to_owned()) | ||
.collect::<Vec<errors::Result<(DemoDTO, _)>>>() | ||
.await; | ||
for _doc in list_it { | ||
count += 1; | ||
} | ||
assert_eq!(count, 2); | ||
|
||
// test if the call fails for a non existing document | ||
println!("user::Session documents::delete"); | ||
let r = documents::delete(&user_session, "tests/non_existing", true); | ||
let r = documents::delete(&user_session, "tests/non_existing", true).await; | ||
assert!(r.is_err()); | ||
match r.err().unwrap() { | ||
errors::FirebaseError::APIError(code, message, context) => { | ||
|
@@ -161,7 +174,7 @@ fn user_account_session(cred: Credentials) -> errors::Result<()> { | |
_ => panic!("Expected an APIError"), | ||
}; | ||
|
||
documents::delete(&user_session, &("tests/".to_owned() + doc_id), false)?; | ||
documents::delete(&user_session, &("tests/".to_owned() + doc_id), false).await?; | ||
|
||
// Check if document is indeed removed | ||
println!("user::Session documents::query"); | ||
|
@@ -171,71 +184,81 @@ fn user_account_session(cred: Credentials) -> errors::Result<()> { | |
"abc".into(), | ||
dto::FieldOperator::EQUAL, | ||
"a_string", | ||
)? | ||
) | ||
.await? | ||
.count(); | ||
assert_eq!(count, 0); | ||
|
||
println!("user::Session documents::query for f64"); | ||
let f: f64 = 13.37; | ||
let count = documents::query(&user_session, "tests", f.into(), dto::FieldOperator::EQUAL, "a_float")?.count(); | ||
|
||
let count = documents::query(&user_session, "tests", f.into(), dto::FieldOperator::EQUAL, "a_float") | ||
.await?; | ||
|
||
let count = count | ||
.count(); | ||
assert_eq!(count, 0); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn main() -> errors::Result<()> { | ||
#[tokio::main] | ||
async fn main() -> errors::Result<()> { | ||
// Search for a credentials file in the root directory | ||
use std::path::PathBuf; | ||
let mut credential_file = PathBuf::from(env!("CARGO_MANIFEST_DIR")); | ||
credential_file.push("firebase-service-account.json"); | ||
let mut cred = Credentials::from_file(credential_file.to_str().unwrap())?; | ||
let cred = Credentials::from_file(credential_file.to_str().unwrap()).await?; | ||
|
||
// Only download the public keys once, and cache them. | ||
let jwkset = utils::from_cache_file(credential_file.with_file_name("cached_jwks.jwks").as_path(), &cred)?; | ||
let jwkset = utils::from_cache_file( | ||
credential_file.with_file_name("cached_jwks.jwks").as_path(), | ||
&cred | ||
).await?; | ||
cred.add_jwks_public_keys(&jwkset); | ||
cred.verify()?; | ||
cred.verify().await?; | ||
|
||
// Perform some db operations via a service account session | ||
service_account_session(cred.clone())?; | ||
service_account_session(cred.clone()).await?; | ||
|
||
// Perform some db operations via a firebase user session | ||
user_account_session(cred)?; | ||
user_account_session(cred).await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// For integration tests and doc code snippets: Create a Credentials instance. | ||
/// Necessary public jwk sets are downloaded or re-used if already present. | ||
#[cfg(test)] | ||
fn valid_test_credentials() -> errors::Result<Credentials> { | ||
async fn valid_test_credentials() -> errors::Result<Credentials> { | ||
use std::path::PathBuf; | ||
let mut jwks_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); | ||
jwks_path.push("firebase-service-account.jwks"); | ||
|
||
let mut cred: Credentials = Credentials::new(include_str!("../firebase-service-account.json"))?; | ||
let mut cred: Credentials = Credentials::new(include_str!("../tests/service-account-test.json"))?; | ||
|
||
// Only download the public keys once, and cache them. | ||
let jwkset = utils::from_cache_file(jwks_path.as_path(), &cred)?; | ||
let jwkset = utils::from_cache_file(jwks_path.as_path(), &cred).await?; | ||
cred.add_jwks_public_keys(&jwkset); | ||
cred.verify()?; | ||
|
||
Ok(cred) | ||
} | ||
|
||
#[test] | ||
fn valid_test_credentials_test() -> errors::Result<()> { | ||
valid_test_credentials()?; | ||
#[tokio::test] | ||
async fn valid_test_credentials_test() -> errors::Result<()> { | ||
valid_test_credentials().await?; | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn service_account_session_test() -> errors::Result<()> { | ||
service_account_session(valid_test_credentials()?)?; | ||
#[tokio::test] | ||
async fn service_account_session_test() -> errors::Result<()> { | ||
service_account_session(valid_test_credentials().await?).await?; | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn user_account_session_test() -> errors::Result<()> { | ||
user_account_session(valid_test_credentials()?)?; | ||
#[tokio::test] | ||
async fn user_account_session_test() -> errors::Result<()> { | ||
user_account_session(valid_test_credentials().await?).await?; | ||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue this should probably be a major version breaking change. With the changes proposed here all
sync
code disappears - meaning this library becomes exclusivelyasync
. Changes here would no longer be compatible with those using the sync only version of this library