diff --git a/CHANGELOG.md b/CHANGELOG.md index 557a5e1e..a6a27cbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.6] - 2020-02-07 + ### Changed -- Rewrite to `async` / `await`. Rust 1.39 is now the minimum required Rust version. +- Rewrite to `async` / `await`. Rust 1.39 is now the minimum required Rust version. ## [0.0.5] - 2019-08-16 @@ -58,7 +60,8 @@ This release removes the prefix `InfluxDb` of most types in this library and ree - Improved Test Coverage: There's now even more tests verifying correctness of the crate (#5) - It's no longer necessary to supply a wildcard generic when working with serde*integration: `client.json_query::(query)` instead of `client.json_query::(query)` -[unreleased]: https://github.com/Empty2k12/influxdb-rust/compare/v0.0.5...HEAD +[unreleased]: https://github.com/Empty2k12/influxdb-rust/compare/v0.0.6...HEAD +[0.0.5]: https://github.com/Empty2k12/influxdb-rust/compare/v0.0.5...v0.0.6 [0.0.5]: https://github.com/Empty2k12/influxdb-rust/compare/v0.0.5...v0.0.5 [0.0.4]: https://github.com/Empty2k12/influxdb-rust/compare/v0.0.3...v0.0.4 [0.0.3]: https://github.com/Empty2k12/influxdb-rust/compare/v0.0.2...v0.0.3 diff --git a/Cargo.toml b/Cargo.toml index ce24b1b9..cebc081f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "influxdb" -version = "0.0.5" +version = "0.0.6" authors = ["Gero Gerke <11deutron11@gmail.com>"] edition = "2018" description = "InfluxDB Driver for Rust" @@ -14,12 +14,12 @@ repository = "https://github.com/Empty2k12/influxdb-rust" travis-ci = { repository = "Empty2k12/influxdb-rust", branch = "master" } [dependencies] -chrono = { version = "0.4.9", optional = true } -failure = "0.1.5" -futures = "0.3.1" -reqwest = { version = "0.10", features = ["json"] } -serde = { version = "1.0.92", features = ["derive"], optional = true } -serde_json = { version = "1.0", optional = true } +chrono = { version = "0.4.10", optional = true } +failure = "0.1.6" +futures = "0.3.4" +reqwest = { version = "0.10.1", features = ["json"] } +serde = { version = "1.0.104", features = ["derive"], optional = true } +serde_json = { version = "1.0.46", optional = true } [features] use-serde = ["serde", "serde_json"] @@ -27,4 +27,4 @@ chrono_timestamps = ["chrono"] default = ["use-serde"] [dev-dependencies] -tokio = { version = "0.2", features = ["macros"] } +tokio = { version = "0.2.11", features = ["macros"] } diff --git a/README.md b/README.md index b196c836..bbd5412d 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ Pull requests are always welcome. See [Contributing](https://github.com/Empty2k1 - Running multiple queries in one request (e.g. `SELECT * FROM weather_berlin; SELECT * FROM weather_london`) - Authenticated and Unauthenticated Connections - Optional conversion between `Timestamp` and `Chrono::DateTime` via `chrono_timestamps` compilation feature +- `async`/`await` support + ### Planned Features - Read Query Builder instead of supplying raw queries @@ -50,7 +52,7 @@ Pull requests are always welcome. See [Contributing](https://github.com/Empty2k1 Add the following to your `Cargo.toml` ```toml -influxdb = "0.0.5" +influxdb = "0.0.6" ``` For an example with using Serde deserialization, please refer to [serde_integration](crate::integrations::serde_integration) diff --git a/src/lib.rs b/src/lib.rs index 5e531e41..6e45f2ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,8 @@ //! - Running multiple queries in one request (e.g. `SELECT * FROM weather_berlin; SELECT * FROM weather_london`) //! - Authenticated and Unauthenticated Connections //! - Optional conversion between `Timestamp` and `Chrono::DateTime` via `chrono_timestamps` compilation feature +//! - `async`/`await` support +//! //! ## Planned Features //! //! - Read Query Builder instead of supplying raw queries @@ -21,7 +23,7 @@ //! Add the following to your `Cargo.toml` //! //! ```toml -//! influxdb = "0.0.5" +//! influxdb = "0.0.6" //! ``` //! //! For an example with using Serde deserialization, please refer to [serde_integration](crate::integrations::serde_integration) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 97ee96b3..6a0e386b 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -101,43 +101,39 @@ async fn test_authed_write_and_read() { const TEST_NAME: &str = "test_authed_write_and_read"; run_test( - || { - async move { - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let query = format!("CREATE DATABASE {}", TEST_NAME); - client - .query(&Query::raw_read_query(query)) - .await - .expect("could not setup db"); - - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let write_query = Query::write_query(Timestamp::Hours(11), "weather") - .add_field("temperature", 82); - let write_result = client.query(&write_query).await; - assert_result_ok(&write_result); - - let read_query = Query::raw_read_query("SELECT * FROM weather"); - let read_result = client.query(&read_query).await; - assert_result_ok(&read_result); - assert!( - !read_result.unwrap().contains("error"), - "Data contained a database error" - ); - } + || async move { + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let query = format!("CREATE DATABASE {}", TEST_NAME); + client + .query(&Query::raw_read_query(query)) + .await + .expect("could not setup db"); + + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let write_query = + Query::write_query(Timestamp::Hours(11), "weather").add_field("temperature", 82); + let write_result = client.query(&write_query).await; + assert_result_ok(&write_result); + + let read_query = Query::raw_read_query("SELECT * FROM weather"); + let read_result = client.query(&read_query).await; + assert_result_ok(&read_result); + assert!( + !read_result.unwrap().contains("error"), + "Data contained a database error" + ); }, - || { - async move { - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let query = format!("DROP DATABASE {}", TEST_NAME); - - client - .query(&Query::raw_read_query(query)) - .await - .expect("could not clean up db"); - } + || async move { + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let query = format!("DROP DATABASE {}", TEST_NAME); + + client + .query(&Query::raw_read_query(query)) + .await + .expect("could not clean up db"); }, ) .await; @@ -151,65 +147,61 @@ async fn test_wrong_authed_write_and_read() { const TEST_NAME: &str = "test_wrong_authed_write_and_read"; run_test( - || { - async move { - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let query = format!("CREATE DATABASE {}", TEST_NAME); - client - .query(&Query::raw_read_query(query)) - .await - .expect("could not setup db"); - - let client = Client::new("http://localhost:9086", TEST_NAME) - .with_auth("wrong_user", "password"); - let write_query = Query::write_query(Timestamp::Hours(11), "weather") - .add_field("temperature", 82); - let write_result = client.query(&write_query).await; - assert_result_err(&write_result); - match write_result { - Err(Error::AuthorizationError) => {} - _ => panic!(format!( - "Should be an AuthorizationError: {}", - write_result.unwrap_err() - )), - } + || async move { + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let query = format!("CREATE DATABASE {}", TEST_NAME); + client + .query(&Query::raw_read_query(query)) + .await + .expect("could not setup db"); + + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("wrong_user", "password"); + let write_query = + Query::write_query(Timestamp::Hours(11), "weather").add_field("temperature", 82); + let write_result = client.query(&write_query).await; + assert_result_err(&write_result); + match write_result { + Err(Error::AuthorizationError) => {} + _ => panic!(format!( + "Should be an AuthorizationError: {}", + write_result.unwrap_err() + )), + } - let read_query = Query::raw_read_query("SELECT * FROM weather"); - let read_result = client.query(&read_query).await; - assert_result_err(&read_result); - match read_result { - Err(Error::AuthorizationError) => {} - _ => panic!(format!( - "Should be an AuthorizationError: {}", - read_result.unwrap_err() - )), - } + let read_query = Query::raw_read_query("SELECT * FROM weather"); + let read_result = client.query(&read_query).await; + assert_result_err(&read_result); + match read_result { + Err(Error::AuthorizationError) => {} + _ => panic!(format!( + "Should be an AuthorizationError: {}", + read_result.unwrap_err() + )), + } - let client = Client::new("http://localhost:9086", TEST_NAME) - .with_auth("nopriv_user", "password"); - let read_query = Query::raw_read_query("SELECT * FROM weather"); - let read_result = client.query(&read_query).await; - assert_result_err(&read_result); - match read_result { - Err(Error::AuthenticationError) => {} - _ => panic!(format!( - "Should be an AuthenticationError: {}", - read_result.unwrap_err() - )), - } + let client = Client::new("http://localhost:9086", TEST_NAME) + .with_auth("nopriv_user", "password"); + let read_query = Query::raw_read_query("SELECT * FROM weather"); + let read_result = client.query(&read_query).await; + assert_result_err(&read_result); + match read_result { + Err(Error::AuthenticationError) => {} + _ => panic!(format!( + "Should be an AuthenticationError: {}", + read_result.unwrap_err() + )), } }, - || { - async move { - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let query = format!("DROP DATABASE {}", TEST_NAME); - client - .query(&Query::raw_read_query(query)) - .await - .expect("could not clean up db"); - } + || async move { + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let query = format!("DROP DATABASE {}", TEST_NAME); + client + .query(&Query::raw_read_query(query)) + .await + .expect("could not clean up db"); }, ) .await; @@ -223,50 +215,46 @@ async fn test_non_authed_write_and_read() { const TEST_NAME: &str = "test_non_authed_write_and_read"; run_test( - || { - async move { - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let query = format!("CREATE DATABASE {}", TEST_NAME); - client - .query(&Query::raw_read_query(query)) - .await - .expect("could not setup db"); - let non_authed_client = Client::new("http://localhost:9086", TEST_NAME); - let write_query = Query::write_query(Timestamp::Hours(11), "weather") - .add_field("temperature", 82); - let write_result = non_authed_client.query(&write_query).await; - assert_result_err(&write_result); - match write_result { - Err(Error::AuthorizationError) => {} - _ => panic!(format!( - "Should be an AuthorizationError: {}", - write_result.unwrap_err() - )), - } + || async move { + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let query = format!("CREATE DATABASE {}", TEST_NAME); + client + .query(&Query::raw_read_query(query)) + .await + .expect("could not setup db"); + let non_authed_client = Client::new("http://localhost:9086", TEST_NAME); + let write_query = + Query::write_query(Timestamp::Hours(11), "weather").add_field("temperature", 82); + let write_result = non_authed_client.query(&write_query).await; + assert_result_err(&write_result); + match write_result { + Err(Error::AuthorizationError) => {} + _ => panic!(format!( + "Should be an AuthorizationError: {}", + write_result.unwrap_err() + )), + } - let read_query = Query::raw_read_query("SELECT * FROM weather"); - let read_result = non_authed_client.query(&read_query).await; - assert_result_err(&read_result); - match read_result { - Err(Error::AuthorizationError) => {} - _ => panic!(format!( - "Should be an AuthorizationError: {}", - read_result.unwrap_err() - )), - } + let read_query = Query::raw_read_query("SELECT * FROM weather"); + let read_result = non_authed_client.query(&read_query).await; + assert_result_err(&read_result); + match read_result { + Err(Error::AuthorizationError) => {} + _ => panic!(format!( + "Should be an AuthorizationError: {}", + read_result.unwrap_err() + )), } }, - || { - async move { - let client = - Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); - let query = format!("DROP DATABASE {}", TEST_NAME); - client - .query(&Query::raw_read_query(query)) - .await - .expect("could not clean up db"); - } + || async move { + let client = + Client::new("http://localhost:9086", TEST_NAME).with_auth("admin", "password"); + let query = format!("DROP DATABASE {}", TEST_NAME); + client + .query(&Query::raw_read_query(query)) + .await + .expect("could not clean up db"); }, ) .await; @@ -280,28 +268,24 @@ async fn test_write_and_read_field() { const TEST_NAME: &str = "test_write_field"; run_test( - || { - async move { - create_db(TEST_NAME).await.expect("could not setup db"); - let client = create_client(TEST_NAME); - let write_query = Query::write_query(Timestamp::Hours(11), "weather") - .add_field("temperature", 82); - let write_result = client.query(&write_query).await; - assert_result_ok(&write_result); - - let read_query = Query::raw_read_query("SELECT * FROM weather"); - let read_result = client.query(&read_query).await; - assert_result_ok(&read_result); - assert!( - !read_result.unwrap().contains("error"), - "Data contained a database error" - ); - } + || async move { + create_db(TEST_NAME).await.expect("could not setup db"); + let client = create_client(TEST_NAME); + let write_query = + Query::write_query(Timestamp::Hours(11), "weather").add_field("temperature", 82); + let write_result = client.query(&write_query).await; + assert_result_ok(&write_result); + + let read_query = Query::raw_read_query("SELECT * FROM weather"); + let read_result = client.query(&read_query).await; + assert_result_ok(&read_result); + assert!( + !read_result.unwrap().contains("error"), + "Data contained a database error" + ); }, - || { - async move { - delete_db(TEST_NAME).await.expect("could not clean up db"); - } + || async move { + delete_db(TEST_NAME).await.expect("could not clean up db"); }, ) .await; @@ -355,12 +339,10 @@ async fn test_write_and_read_option() { ); } }, - || { - async move { - delete_db("test_write_and_read_option") - .await - .expect("could not clean up db"); - } + || async move { + delete_db("test_write_and_read_option") + .await + .expect("could not clean up db"); }, ) .await; @@ -412,10 +394,8 @@ async fn test_json_query() { ); } }, - || { - async move { - delete_db(TEST_NAME).await.expect("could not clean up db"); - } + || async move { + delete_db(TEST_NAME).await.expect("could not clean up db"); }, ) .await; @@ -433,41 +413,37 @@ async fn test_json_query_vec() { const TEST_NAME: &str = "test_json_query_vec"; run_test( - || { - async move { - create_db(TEST_NAME).await.expect("could not setup db"); - - let client = create_client(TEST_NAME); - let write_query1 = Query::write_query(Timestamp::Hours(11), "temperature_vec") - .add_field("temperature", 16); - let write_query2 = Query::write_query(Timestamp::Hours(12), "temperature_vec") - .add_field("temperature", 17); - let write_query3 = Query::write_query(Timestamp::Hours(13), "temperature_vec") - .add_field("temperature", 18); - - let _write_result = client.query(&write_query1).await; - let _write_result2 = client.query(&write_query2).await; - let _write_result2 = client.query(&write_query3).await; - - #[derive(Deserialize, Debug, PartialEq)] - struct Weather { - time: String, - temperature: i32, - } - - let query = Query::raw_read_query("SELECT * FROM temperature_vec"); - let result = client - .json_query(query) - .await - .and_then(|mut db_result| db_result.deserialize_next::()); - assert_result_ok(&result); - assert_eq!(result.unwrap().series[0].values.len(), 3); + || async move { + create_db(TEST_NAME).await.expect("could not setup db"); + + let client = create_client(TEST_NAME); + let write_query1 = Query::write_query(Timestamp::Hours(11), "temperature_vec") + .add_field("temperature", 16); + let write_query2 = Query::write_query(Timestamp::Hours(12), "temperature_vec") + .add_field("temperature", 17); + let write_query3 = Query::write_query(Timestamp::Hours(13), "temperature_vec") + .add_field("temperature", 18); + + let _write_result = client.query(&write_query1).await; + let _write_result2 = client.query(&write_query2).await; + let _write_result2 = client.query(&write_query3).await; + + #[derive(Deserialize, Debug, PartialEq)] + struct Weather { + time: String, + temperature: i32, } + + let query = Query::raw_read_query("SELECT * FROM temperature_vec"); + let result = client + .json_query(query) + .await + .and_then(|mut db_result| db_result.deserialize_next::()); + assert_result_ok(&result); + assert_eq!(result.unwrap().series[0].values.len(), 3); }, - || { - async move { - delete_db(TEST_NAME).await.expect("could not clean up db"); - } + || async move { + delete_db(TEST_NAME).await.expect("could not clean up db"); }, ) .await; @@ -484,68 +460,64 @@ async fn test_serde_multi_query() { const TEST_NAME: &str = "test_serde_multi_query"; run_test( - || { - async move { - create_db(TEST_NAME).await.expect("could not setup db"); - - #[derive(Deserialize, Debug, PartialEq)] - struct Temperature { - time: String, - temperature: i32, - } - - #[derive(Deserialize, Debug, PartialEq)] - struct Humidity { - time: String, - humidity: i32, - } - - let client = create_client(TEST_NAME); - let write_query = Query::write_query(Timestamp::Hours(11), "temperature") - .add_field("temperature", 16); - let write_query2 = - Query::write_query(Timestamp::Hours(11), "humidity").add_field("humidity", 69); - - let write_result = client.query(&write_query).await; - let write_result2 = client.query(&write_query2).await; - assert_result_ok(&write_result); - assert_result_ok(&write_result2); - - let result = client - .json_query( - Query::raw_read_query("SELECT * FROM temperature") - .add_query("SELECT * FROM humidity"), - ) - .await - .and_then(|mut db_result| { - let temp = db_result.deserialize_next::()?; - let humidity = db_result.deserialize_next::()?; + || async move { + create_db(TEST_NAME).await.expect("could not setup db"); - Ok((temp, humidity)) - }); - assert_result_ok(&result); + #[derive(Deserialize, Debug, PartialEq)] + struct Temperature { + time: String, + temperature: i32, + } - let (temp, humidity) = result.unwrap(); - assert_eq!( - temp.series[0].values[0], - Temperature { - time: "1970-01-01T11:00:00Z".to_string(), - temperature: 16 - }, - ); - assert_eq!( - humidity.series[0].values[0], - Humidity { - time: "1970-01-01T11:00:00Z".to_string(), - humidity: 69 - } - ); + #[derive(Deserialize, Debug, PartialEq)] + struct Humidity { + time: String, + humidity: i32, } + + let client = create_client(TEST_NAME); + let write_query = Query::write_query(Timestamp::Hours(11), "temperature") + .add_field("temperature", 16); + let write_query2 = + Query::write_query(Timestamp::Hours(11), "humidity").add_field("humidity", 69); + + let write_result = client.query(&write_query).await; + let write_result2 = client.query(&write_query2).await; + assert_result_ok(&write_result); + assert_result_ok(&write_result2); + + let result = client + .json_query( + Query::raw_read_query("SELECT * FROM temperature") + .add_query("SELECT * FROM humidity"), + ) + .await + .and_then(|mut db_result| { + let temp = db_result.deserialize_next::()?; + let humidity = db_result.deserialize_next::()?; + + Ok((temp, humidity)) + }); + assert_result_ok(&result); + + let (temp, humidity) = result.unwrap(); + assert_eq!( + temp.series[0].values[0], + Temperature { + time: "1970-01-01T11:00:00Z".to_string(), + temperature: 16 + }, + ); + assert_eq!( + humidity.series[0].values[0], + Humidity { + time: "1970-01-01T11:00:00Z".to_string(), + humidity: 69 + } + ); }, - || { - async move { - delete_db(TEST_NAME).await.expect("could not clean up db"); - } + || async move { + delete_db(TEST_NAME).await.expect("could not clean up db"); }, ) .await;