diff --git a/docs/source/connecting/compression.md b/docs/source/connecting/compression.md index 018c4cffc2..85b8a2c646 100644 --- a/docs/source/connecting/compression.md +++ b/docs/source/connecting/compression.md @@ -13,7 +13,7 @@ An example enabling `Snappy` compression algorithm: # extern crate scylla; # extern crate tokio; use scylla::{Session, SessionBuilder}; -use scylla::transport::Compression; +use scylla::connection::Compression; use std::error::Error; #[tokio::main] diff --git a/docs/source/execution-profiles/create-and-use.md b/docs/source/execution-profiles/create-and-use.md index 01bfa52d99..01dcd6c3c8 100644 --- a/docs/source/execution-profiles/create-and-use.md +++ b/docs/source/execution-profiles/create-and-use.md @@ -8,7 +8,7 @@ To create an `ExecutionProfile` and attach it as default for `Session`: # async fn check_only_compiles() -> Result<(), Box> { use scylla::{Session, SessionBuilder}; use scylla::statement::Consistency; -use scylla::transport::ExecutionProfile; +use scylla::execution::ExecutionProfile; let profile = ExecutionProfile::builder() .consistency(Consistency::LocalOne) @@ -34,7 +34,7 @@ To create an `ExecutionProfile` and attach it to a `Query`: # async fn check_only_compiles() -> Result<(), Box> { use scylla::query::Query; use scylla::statement::Consistency; -use scylla::transport::ExecutionProfile; +use scylla::execution::ExecutionProfile; use std::time::Duration; let profile = ExecutionProfile::builder() @@ -60,7 +60,7 @@ To create an `ExecutionProfile` based on another profile: # use std::error::Error; # async fn check_only_compiles() -> Result<(), Box> { use scylla::statement::Consistency; -use scylla::transport::ExecutionProfile; +use scylla::execution::ExecutionProfile; use std::time::Duration; let base_profile = ExecutionProfile::builder() diff --git a/docs/source/execution-profiles/maximal-example.md b/docs/source/execution-profiles/maximal-example.md index 2e328970d6..36166341df 100644 --- a/docs/source/execution-profiles/maximal-example.md +++ b/docs/source/execution-profiles/maximal-example.md @@ -9,9 +9,9 @@ use scylla::query::Query; use scylla::speculative_execution::SimpleSpeculativeExecutionPolicy; use scylla::statement::{Consistency, SerialConsistency}; -use scylla::transport::ExecutionProfile; -use scylla::transport::load_balancing::DefaultPolicy; -use scylla::transport::retry_policy::FallthroughRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::load_balancing::DefaultPolicy; +use scylla::execution::retries::FallthroughRetryPolicy; use std::{sync::Arc, time::Duration}; let profile = ExecutionProfile::builder() diff --git a/docs/source/execution-profiles/priority.md b/docs/source/execution-profiles/priority.md index ccc57b73b0..e99b9eeab3 100644 --- a/docs/source/execution-profiles/priority.md +++ b/docs/source/execution-profiles/priority.md @@ -16,7 +16,7 @@ Priorities of execution profiles and directly set options: use scylla::{Session, SessionBuilder}; use scylla::query::Query; use scylla::statement::Consistency; -use scylla::transport::ExecutionProfile; +use scylla::execution::ExecutionProfile; let session_profile = ExecutionProfile::builder() .consistency(Consistency::One) diff --git a/docs/source/execution-profiles/remap.md b/docs/source/execution-profiles/remap.md index a64aee3916..308cb2b483 100644 --- a/docs/source/execution-profiles/remap.md +++ b/docs/source/execution-profiles/remap.md @@ -26,7 +26,7 @@ Below, the remaps described above are followed in code. use scylla::{Session, SessionBuilder}; use scylla::query::Query; use scylla::statement::Consistency; -use scylla::transport::ExecutionProfile; +use scylla::execution::ExecutionProfile; let profile1 = ExecutionProfile::builder() .consistency(Consistency::One) diff --git a/docs/source/load-balancing/load-balancing.md b/docs/source/load-balancing/load-balancing.md index 3ec27dd7e1..231d460086 100644 --- a/docs/source/load-balancing/load-balancing.md +++ b/docs/source/load-balancing/load-balancing.md @@ -9,7 +9,7 @@ balancing plan based on the query information and the state of the cluster. Load balancing policies do not influence to which nodes connections are being opened. For a node connection blacklist configuration refer to -`scylla::transport::host_filter::HostFilter`, which can be set session-wide +`scylla::cluster::host_filter::HostFilter`, which can be set session-wide using `SessionBuilder::host_filter` method. In this chapter, "target" will refer to a pair ``. @@ -51,8 +51,8 @@ The newly created execution profile is then converted to a handle using # async fn check_only_compiles(uri: &str) -> Result<(), Box> { use scylla::SessionBuilder; use scylla::load_balancing::DefaultPolicy; -use scylla::transport::ExecutionProfile; -use scylla::transport::session::Session; +use scylla::execution::ExecutionProfile; +use scylla::session::Session; use std::sync::Arc; let policy = Arc::new(DefaultPolicy::default()); diff --git a/docs/source/migration-guides/0.15-deserialization.md b/docs/source/migration-guides/0.15-deserialization.md index 3c9d11478d..8fe2ddd1c6 100644 --- a/docs/source/migration-guides/0.15-deserialization.md +++ b/docs/source/migration-guides/0.15-deserialization.md @@ -285,7 +285,7 @@ let legacy_result: LegacyQueryResult = result.into_legacy_result()?; ```rust # extern crate scylla; -# use scylla::transport::iterator::{QueryPager, LegacyRowIterator}; +# use scylla::execution::pager::{QueryPager, LegacyRowIterator}; # use std::error::Error; # async fn check_only_compiles(pager: QueryPager) -> Result<(), Box> { let pager: QueryPager = pager; diff --git a/docs/source/queries/result.md b/docs/source/queries/result.md index db63637e7b..636541bdd9 100644 --- a/docs/source/queries/result.md +++ b/docs/source/queries/result.md @@ -21,8 +21,8 @@ return a `QueryResult` with rows represented as `Option>`. ## Parsing using convenience methods -By calling [`QueryResult::into_rows_result`](https://docs.rs/scylla/latest/scylla/transport/query_result/struct.QueryResult.html#method.into_rows_result), -one can obtain [`QueryRowsResult`](https://docs.rs/scylla/latest/scylla/transport/query_result/struct.QueryRowsResult.html). +By calling [`QueryResult::into_rows_result`](https://docs.rs/scylla/latest/scylla/response/query_result/struct.QueryResult.html#method.into_rows_result), +one can obtain [`QueryRowsResult`](https://docs.rs/scylla/latest/scylla/response/query_result/struct.QueryRowsResult.html). `QueryRowsResult` provides convenience methods for parsing rows. Here are a few of them: * `rows::()` - returns the rows parsed as the given type @@ -30,7 +30,7 @@ Here are a few of them: * `first_row::()` - returns the first received row; fails if there are no rows * `single_row::()` - same as `first_row`, but fails when there is more than one row -Additionally, [`QueryResult`](https://docs.rs/scylla/latest/scylla/transport/query_result/struct.QueryResult.html) has a method `result_not_rows()`, which ensures that query response was not `rows` and thus helps avoid bugs. +Additionally, [`QueryResult`](https://docs.rs/scylla/latest/scylla/response/query_result/struct.QueryResult.html) has a method `result_not_rows()`, which ensures that query response was not `rows` and thus helps avoid bugs. ```rust # extern crate scylla; @@ -59,8 +59,8 @@ session.query_unpaged("INSERT INTO ks.tab (a) VALUES (0)", &[]).await?.result_no # Ok(()) # } ``` -For more see [`QueryResult`](https://docs.rs/scylla/latest/scylla/transport/query_result/struct.QueryResult.html) -and [`QueryRowsResult`](https://docs.rs/scylla/latest/scylla/transport/query_result/struct.QueryRowsResult.html) +For more see [`QueryResult`](https://docs.rs/scylla/latest/scylla/response/query_result/struct.QueryResult.html) +and [`QueryRowsResult`](https://docs.rs/scylla/latest/scylla/response/query_result/struct.QueryRowsResult.html) ### `NULL` values `NULL` values will return an error when parsed as a Rust type. diff --git a/docs/source/queries/timeouts.md b/docs/source/queries/timeouts.md index f99b186cab..6e4f36072b 100644 --- a/docs/source/queries/timeouts.md +++ b/docs/source/queries/timeouts.md @@ -18,7 +18,7 @@ However, setting per-statement timeout to `None` results in falling back to per- # use std::error::Error; # async fn timeouts() -> Result<(), Box> { use scylla::{Session, SessionBuilder, query::Query}; -use scylla::transport::ExecutionProfile; +use scylla::execution::ExecutionProfile; use std::time::Duration; let uri = std::env::var("SCYLLA_URI") diff --git a/docs/source/retry-policy/default.md b/docs/source/retry-policy/default.md index 3b57562c29..50157330df 100644 --- a/docs/source/retry-policy/default.md +++ b/docs/source/retry-policy/default.md @@ -12,8 +12,8 @@ To use in `Session`: # use std::sync::Arc; # async fn check_only_compiles() -> Result<(), Box> { use scylla::{Session, SessionBuilder}; -use scylla::transport::ExecutionProfile; -use scylla::transport::retry_policy::DefaultRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::DefaultRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(DefaultRetryPolicy::new())) @@ -37,8 +37,8 @@ To use in a [simple query](../queries/simple.md): # use std::sync::Arc; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; -use scylla::transport::ExecutionProfile; -use scylla::transport::retry_policy::DefaultRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::DefaultRetryPolicy; // Create a Query manually and set the retry policy let mut my_query: Query = Query::new("INSERT INTO ks.tab (a) VALUES(?)"); @@ -66,8 +66,8 @@ To use in a [prepared query](../queries/prepared.md): # use std::sync::Arc; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::prepared_statement::PreparedStatement; -use scylla::transport::ExecutionProfile; -use scylla::transport::retry_policy::DefaultRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::DefaultRetryPolicy; // Create PreparedStatement manually and set the retry policy let mut prepared: PreparedStatement = session diff --git a/docs/source/retry-policy/downgrading-consistency.md b/docs/source/retry-policy/downgrading-consistency.md index 2e335f6e4e..1047659f8f 100644 --- a/docs/source/retry-policy/downgrading-consistency.md +++ b/docs/source/retry-policy/downgrading-consistency.md @@ -53,8 +53,8 @@ To use in `Session`: # use std::sync::Arc; # async fn check_only_compiles() -> Result<(), Box> { use scylla::{Session, SessionBuilder}; -use scylla::transport::ExecutionProfile; -use scylla::transport::downgrading_consistency_retry_policy::DowngradingConsistencyRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::DowngradingConsistencyRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(DowngradingConsistencyRetryPolicy::new())) @@ -78,8 +78,8 @@ To use in a [simple query](../queries/simple.md): # use std::sync::Arc; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; -use scylla::transport::ExecutionProfile; -use scylla::transport::downgrading_consistency_retry_policy::DowngradingConsistencyRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::DowngradingConsistencyRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(DowngradingConsistencyRetryPolicy::new())) @@ -105,8 +105,8 @@ To use in a [prepared query](../queries/prepared.md): # use std::sync::Arc; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::prepared_statement::PreparedStatement; -use scylla::transport::ExecutionProfile; -use scylla::transport::downgrading_consistency_retry_policy::DowngradingConsistencyRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::DowngradingConsistencyRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(DowngradingConsistencyRetryPolicy::new())) diff --git a/docs/source/retry-policy/fallthrough.md b/docs/source/retry-policy/fallthrough.md index a2056c52ef..f23e77c891 100644 --- a/docs/source/retry-policy/fallthrough.md +++ b/docs/source/retry-policy/fallthrough.md @@ -11,8 +11,8 @@ To use in `Session`: # use std::sync::Arc; # async fn check_only_compiles() -> Result<(), Box> { use scylla::{Session, SessionBuilder}; -use scylla::transport::ExecutionProfile; -use scylla::transport::retry_policy::FallthroughRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::FallthroughRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(FallthroughRetryPolicy::new())) @@ -36,8 +36,8 @@ To use in a [simple query](../queries/simple.md): # use std::sync::Arc; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; -use scylla::transport::ExecutionProfile; -use scylla::transport::retry_policy::FallthroughRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::FallthroughRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(FallthroughRetryPolicy::new())) @@ -63,8 +63,8 @@ To use in a [prepared query](../queries/prepared.md): # use std::sync::Arc; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::prepared_statement::PreparedStatement; -use scylla::transport::ExecutionProfile; -use scylla::transport::retry_policy::FallthroughRetryPolicy; +use scylla::execution::ExecutionProfile; +use scylla::execution::retries::FallthroughRetryPolicy; let handle = ExecutionProfile::builder() .retry_policy(Arc::new(FallthroughRetryPolicy::new())) diff --git a/docs/source/speculative-execution/percentile.md b/docs/source/speculative-execution/percentile.md index 243429d97f..f6584bee4d 100644 --- a/docs/source/speculative-execution/percentile.md +++ b/docs/source/speculative-execution/percentile.md @@ -17,7 +17,7 @@ use scylla::{ Session, SessionBuilder, speculative_execution::PercentileSpeculativeExecutionPolicy, - transport::execution_profile::ExecutionProfile, + execution::execution_profile::ExecutionProfile, }; let policy = PercentileSpeculativeExecutionPolicy { diff --git a/docs/source/speculative-execution/simple.md b/docs/source/speculative-execution/simple.md index ad7720e664..4982fa195a 100644 --- a/docs/source/speculative-execution/simple.md +++ b/docs/source/speculative-execution/simple.md @@ -17,7 +17,7 @@ use scylla::{ Session, SessionBuilder, speculative_execution::SimpleSpeculativeExecutionPolicy, - transport::execution_profile::ExecutionProfile, + execution::execution_profile::ExecutionProfile, }; let policy = SimpleSpeculativeExecutionPolicy { diff --git a/docs/source/tracing/basic.md b/docs/source/tracing/basic.md index 08417a1e09..301d397af0 100644 --- a/docs/source/tracing/basic.md +++ b/docs/source/tracing/basic.md @@ -12,7 +12,7 @@ return a `QueryResult` which contains a `tracing_id` if tracing was enabled. # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; use scylla::QueryResult; -use scylla::tracing::TracingInfo; +use scylla::execution::tracing::TracingInfo; use uuid::Uuid; // Create a Query manually and enable tracing @@ -40,7 +40,7 @@ if let Some(id) = tracing_id { # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::prepared_statement::PreparedStatement; use scylla::QueryResult; -use scylla::tracing::TracingInfo; +use scylla::execution::tracing::TracingInfo; use uuid::Uuid; // Prepare the query @@ -72,7 +72,7 @@ if let Some(id) = tracing_id { # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::batch::Batch; use scylla::QueryResult; -use scylla::tracing::TracingInfo; +use scylla::execution::tracing::TracingInfo; use uuid::Uuid; // Create a batch statement diff --git a/docs/source/tracing/paged.md b/docs/source/tracing/paged.md index 20975dfc3a..206d556d98 100644 --- a/docs/source/tracing/paged.md +++ b/docs/source/tracing/paged.md @@ -13,7 +13,7 @@ If tracing is enabled the row iterator will contain a list of tracing ids for al # use std::error::Error; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; -use scylla::tracing::TracingInfo; +use scylla::execution::tracing::TracingInfo; use futures::StreamExt; use uuid::Uuid; @@ -51,7 +51,7 @@ for id in tracing_ids { # use std::error::Error; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::prepared_statement::PreparedStatement; -use scylla::tracing::TracingInfo; +use scylla::execution::tracing::TracingInfo; use futures::StreamExt; use uuid::Uuid; diff --git a/docs/source/tracing/prepare.md b/docs/source/tracing/prepare.md index 2f3850cbde..cef6a48d1c 100644 --- a/docs/source/tracing/prepare.md +++ b/docs/source/tracing/prepare.md @@ -10,7 +10,7 @@ # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; use scylla::prepared_statement::PreparedStatement; -use scylla::tracing::TracingInfo; +use scylla::execution::tracing::TracingInfo; use uuid::Uuid; // Prepare the query with tracing enabled diff --git a/docs/source/tracing/query-history.md b/docs/source/tracing/query-history.md index c7c0e0b3b6..e8f7f53948 100644 --- a/docs/source/tracing/query-history.md +++ b/docs/source/tracing/query-history.md @@ -12,7 +12,7 @@ This history includes all requests sent, decisions to retry and speculative exec # use std::error::Error; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; -use scylla::history::{HistoryCollector, StructuredHistory}; +use scylla::execution::history::{HistoryCollector, StructuredHistory}; use std::sync::Arc; // Create a query for which we would like to trace the history of its execution diff --git a/examples/allocations.rs b/examples/allocations.rs index d10ad9771b..6f7c141f0b 100644 --- a/examples/allocations.rs +++ b/examples/allocations.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::{statement::prepared_statement::PreparedStatement, SessionBuilder}; use std::io::Write; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/examples/basic.rs b/examples/basic.rs index c4fe10b8b3..c5d6a19c7b 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -2,7 +2,7 @@ use anyhow::Result; use futures::StreamExt as _; use futures::TryStreamExt as _; use scylla::frame::response::result::Row; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::DeserializeRow; use scylla::SessionBuilder; use std::env; diff --git a/examples/compare-tokens.rs b/examples/compare-tokens.rs index ab4bbb6b16..ca5e8d922d 100644 --- a/examples/compare-tokens.rs +++ b/examples/compare-tokens.rs @@ -1,6 +1,6 @@ use anyhow::Result; +use scylla::cluster::NodeAddr; use scylla::routing::Token; -use scylla::transport::NodeAddr; use scylla::{Session, SessionBuilder}; use std::env; diff --git a/examples/cql-time-types.rs b/examples/cql-time-types.rs index 29a66349e2..068c0e90f7 100644 --- a/examples/cql-time-types.rs +++ b/examples/cql-time-types.rs @@ -6,7 +6,7 @@ use chrono::{DateTime, NaiveDate, NaiveTime, Utc}; use futures::{StreamExt as _, TryStreamExt as _}; use scylla::frame::response::result::CqlValue; use scylla::frame::value::{CqlDate, CqlTime, CqlTimestamp}; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; diff --git a/examples/cqlsh-rs.rs b/examples/cqlsh-rs.rs index 1a2941c900..d8216b7dd9 100644 --- a/examples/cqlsh-rs.rs +++ b/examples/cqlsh-rs.rs @@ -3,10 +3,10 @@ use rustyline::completion::{Completer, Pair}; use rustyline::error::ReadlineError; use rustyline::{CompletionType, Config, Context, Editor}; use rustyline_derive::{Helper, Highlighter, Hinter, Validator}; +use scylla::connection::Compression; use scylla::frame::response::result::Row; -use scylla::transport::query_result::IntoRowsResultError; -use scylla::transport::session::Session; -use scylla::transport::Compression; +use scylla::response::query_result::IntoRowsResultError; +use scylla::session::Session; use scylla::QueryResult; use scylla::SessionBuilder; use std::env; diff --git a/examples/custom_deserialization.rs b/examples/custom_deserialization.rs index 5a5991edfe..cded1c7c8a 100644 --- a/examples/custom_deserialization.rs +++ b/examples/custom_deserialization.rs @@ -1,7 +1,7 @@ use anyhow::Result; use scylla::deserialize::DeserializeValue; use scylla::frame::response::result::ColumnType; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; diff --git a/examples/custom_load_balancing_policy.rs b/examples/custom_load_balancing_policy.rs index 5c279f2331..ba6033a5b2 100644 --- a/examples/custom_load_balancing_policy.rs +++ b/examples/custom_load_balancing_policy.rs @@ -1,11 +1,12 @@ use anyhow::Result; use rand::thread_rng; use rand::Rng; -use scylla::transport::NodeRef; +use scylla::cluster::NodeRef; use scylla::{ + cluster::ClusterData, + execution::ExecutionProfile, load_balancing::{LoadBalancingPolicy, RoutingInfo}, routing::Shard, - transport::{ClusterData, ExecutionProfile}, Session, SessionBuilder, }; use std::{env, sync::Arc}; diff --git a/examples/execution_profile.rs b/examples/execution_profile.rs index 3562966ac5..93ec6df0d3 100644 --- a/examples/execution_profile.rs +++ b/examples/execution_profile.rs @@ -1,11 +1,11 @@ use anyhow::Result; +use scylla::execution::retries::{DefaultRetryPolicy, FallthroughRetryPolicy}; +use scylla::execution::ExecutionProfile; use scylla::load_balancing; use scylla::query::Query; -use scylla::retry_policy::{DefaultRetryPolicy, FallthroughRetryPolicy}; +use scylla::session::Session; use scylla::speculative_execution::PercentileSpeculativeExecutionPolicy; use scylla::statement::{Consistency, SerialConsistency}; -use scylla::transport::session::Session; -use scylla::transport::ExecutionProfile; use scylla::{SessionBuilder, SessionConfig}; use std::env; use std::sync::Arc; diff --git a/examples/get_by_name.rs b/examples/get_by_name.rs index 4aca66f665..7960dd9c51 100644 --- a/examples/get_by_name.rs +++ b/examples/get_by_name.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Result}; use scylla::frame::response::result::Row; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; diff --git a/examples/logging.rs b/examples/logging.rs index 6b090acbcb..a73eec3ece 100644 --- a/examples/logging.rs +++ b/examples/logging.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; use tracing::info; diff --git a/examples/query_history.rs b/examples/query_history.rs index 04d9586481..4fa7ee2deb 100644 --- a/examples/query_history.rs +++ b/examples/query_history.rs @@ -2,10 +2,10 @@ use anyhow::Result; use futures::StreamExt as _; +use scylla::execution::history::{HistoryCollector, StructuredHistory}; use scylla::frame::response::result::Row; -use scylla::history::{HistoryCollector, StructuredHistory}; use scylla::query::Query; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; use std::sync::Arc; diff --git a/examples/schema_agreement.rs b/examples/schema_agreement.rs index d37cc32b72..4263bf40ff 100644 --- a/examples/schema_agreement.rs +++ b/examples/schema_agreement.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; use futures::TryStreamExt as _; -use scylla::transport::errors::QueryError; -use scylla::transport::session::Session; +use scylla::execution::errors::QueryError; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; use std::time::Duration; diff --git a/examples/speculative-execution.rs b/examples/speculative-execution.rs index e6c64e3ad7..0328789e2a 100644 --- a/examples/speculative-execution.rs +++ b/examples/speculative-execution.rs @@ -1,6 +1,6 @@ use scylla::{ - speculative_execution::PercentileSpeculativeExecutionPolicy, - transport::execution_profile::ExecutionProfile, Session, SessionBuilder, + execution::execution_profile::ExecutionProfile, + speculative_execution::PercentileSpeculativeExecutionPolicy, Session, SessionBuilder, }; use anyhow::Result; diff --git a/examples/tls.rs b/examples/tls.rs index d95f14bea2..9c7bff1595 100644 --- a/examples/tls.rs +++ b/examples/tls.rs @@ -1,6 +1,6 @@ use anyhow::Result; use futures::TryStreamExt as _; -use scylla::transport::session::Session; +use scylla::session::Session; use scylla::SessionBuilder; use std::env; use std::fs; diff --git a/examples/tower.rs b/examples/tower.rs index f521b1b614..988781fadc 100644 --- a/examples/tower.rs +++ b/examples/tower.rs @@ -1,5 +1,5 @@ use scylla::frame::response::result::Row; -use scylla::transport::session::Session; +use scylla::session::Session; use std::env; use std::future::Future; use std::pin::Pin; @@ -15,7 +15,7 @@ struct SessionService { // A trivial service implementation for sending parameterless simple string requests to Scylla. impl Service for SessionService { type Response = scylla::QueryResult; - type Error = scylla::transport::errors::QueryError; + type Error = scylla::execution::errors::QueryError; type Future = Pin>>>; fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { diff --git a/examples/tracing.rs b/examples/tracing.rs index dd035c095d..bda674afc1 100644 --- a/examples/tracing.rs +++ b/examples/tracing.rs @@ -4,10 +4,10 @@ use anyhow::{anyhow, Result}; use futures::StreamExt as _; use scylla::batch::Batch; +use scylla::execution::tracing::TracingInfo; use scylla::statement::{ prepared_statement::PreparedStatement, query::Query, Consistency, SerialConsistency, }; -use scylla::tracing::TracingInfo; use scylla::QueryResult; use scylla::{Session, SessionBuilder}; use std::env; diff --git a/scylla/benches/benchmark.rs b/scylla/benches/benchmark.rs index 61d35d8f97..39075fde76 100644 --- a/scylla/benches/benchmark.rs +++ b/scylla/benches/benchmark.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use bytes::BytesMut; -use scylla::transport::partitioner::{calculate_token_for_partition_key, Murmur3Partitioner}; +use scylla::routing::partitioner::{calculate_token_for_partition_key, Murmur3Partitioner}; use scylla_cql::{ frame::{response::result::ColumnType, types}, types::serialize::row::SerializedValues, diff --git a/scylla/src/authentication/mod.rs b/scylla/src/authentication/mod.rs index 2e43b2dee6..a39a74a103 100644 --- a/scylla/src/authentication/mod.rs +++ b/scylla/src/authentication/mod.rs @@ -1,6 +1,8 @@ use async_trait::async_trait; use bytes::{BufMut, BytesMut}; +pub use crate::frame::Authenticator; + /// Type to represent an authentication error message. pub type AuthError = String; diff --git a/scylla/src/cloud/mod.rs b/scylla/src/cloud/mod.rs index fd991a8d45..7ff9cb405e 100644 --- a/scylla/src/cloud/mod.rs +++ b/scylla/src/cloud/mod.rs @@ -11,7 +11,7 @@ use openssl::{ use tracing::warn; use uuid::Uuid; -use crate::transport::connection::{ConnectionConfig, SslConfig}; +use crate::connection::{ConnectionConfig, SslConfig}; pub(crate) fn set_ssl_config_for_scylla_cloud_host( host_id: Option, diff --git a/scylla/src/transport/cluster.rs b/scylla/src/cluster/cluster.rs similarity index 97% rename from scylla/src/transport/cluster.rs rename to scylla/src/cluster/cluster.rs index 309fe58157..dcac500881 100644 --- a/scylla/src/transport/cluster.rs +++ b/scylla/src/cluster/cluster.rs @@ -1,17 +1,14 @@ +use crate::cluster::host_filter::HostFilter; +use crate::cluster::node::Node; +use crate::connection::{Connection, PoolConfig, VerifiedKeyspaceName}; +use crate::execution::errors::{BadQuery, NewSessionError, QueryError}; /// Cluster manages up to date information and connections to database nodes use crate::frame::response::event::{Event, StatusChangeEvent}; use crate::prepared_statement::TokenCalculationError; +use crate::routing::locator::ReplicaLocator; +use crate::routing::partitioner::PartitionerName; use crate::routing::{Shard, Token}; -use crate::transport::errors::{BadQuery, NewSessionError, QueryError}; -use crate::transport::host_filter::HostFilter; -use crate::transport::session::TABLET_CHANNEL_SIZE; -use crate::transport::{ - connection::{Connection, VerifiedKeyspaceName}, - connection_pool::PoolConfig, - node::Node, - partitioner::PartitionerName, - topology::{Keyspace, Metadata, MetadataReader}, -}; +use crate::session::TABLET_CHANNEL_SIZE; use arc_swap::ArcSwap; use futures::future::join_all; @@ -26,13 +23,10 @@ use std::time::Duration; use tracing::{debug, warn}; use uuid::Uuid; -use super::locator::tablets::{RawTablet, Tablet, TabletsInfo}; -use super::node::{InternalKnownNode, NodeAddr}; -use super::NodeRef; - -use super::locator::ReplicaLocator; -use super::partitioner::calculate_token_for_partition_key; -use super::topology::Strategy; +use crate::cluster::metadata::{Keyspace, Metadata, MetadataReader, Strategy}; +use crate::cluster::node::{InternalKnownNode, NodeAddr, NodeRef}; +use crate::routing::locator::tablets::{RawTablet, Tablet, TabletsInfo}; +use crate::routing::partitioner::calculate_token_for_partition_key; /// Cluster manages up to date information and connections to database nodes. /// All data can be accessed by cloning Arc in the `data` field diff --git a/scylla/src/transport/host_filter.rs b/scylla/src/cluster/host_filter.rs similarity index 87% rename from scylla/src/transport/host_filter.rs rename to scylla/src/cluster/host_filter.rs index 2838f1733c..5a3d133bc3 100644 --- a/scylla/src/transport/host_filter.rs +++ b/scylla/src/cluster/host_filter.rs @@ -1,15 +1,15 @@ //! Host filters. //! //! Host filters are essentially just a predicate over -//! [`Peer`]s. Currently, they are used -//! by the [`Session`](crate::transport::session::Session) to determine whether +//! [`Peer`]s. Currently, they are used by the +//! [`Session`](crate::session::Session) to determine whether //! connections should be opened to a given node or not. use std::collections::HashSet; use std::io::Error; use std::net::{SocketAddr, ToSocketAddrs}; -use crate::transport::topology::Peer; +use crate::cluster::metadata::Peer; /// The `HostFilter` trait. pub trait HostFilter: Send + Sync { @@ -55,11 +55,11 @@ impl AllowListHostFilter { impl HostFilter for AllowListHostFilter { fn accept(&self, peer: &Peer) -> bool { match peer.address { - super::NodeAddr::Translatable(addr) => self.allowed.contains(&addr), + crate::cluster::NodeAddr::Translatable(addr) => self.allowed.contains(&addr), // If the address is Untranslatable, then the node either was originally // an ContactPoint, or a Translatable node for which the host filter // returned true. - super::NodeAddr::Untranslatable(_) => true, + crate::cluster::NodeAddr::Untranslatable(_) => true, } } } diff --git a/scylla/src/transport/topology.rs b/scylla/src/cluster/metadata.rs similarity index 99% rename from scylla/src/transport/topology.rs rename to scylla/src/cluster/metadata.rs index 7bbfc6b2a1..7a1ea925dd 100644 --- a/scylla/src/transport/topology.rs +++ b/scylla/src/cluster/metadata.rs @@ -1,13 +1,12 @@ +use crate::cluster::host_filter::HostFilter; +use crate::cluster::node::resolve_contact_points; +use crate::connection::{Connection, ConnectionConfig, NodeConnectionPool, PoolConfig, PoolSize}; use crate::deserialize::DeserializeOwnedRow; +use crate::execution::errors::{DbError, NewSessionError, QueryError}; +use crate::execution::pager::QueryPager; use crate::frame::response::event::Event; use crate::routing::Token; use crate::statement::query::Query; -use crate::transport::connection::{Connection, ConnectionConfig}; -use crate::transport::connection_pool::{NodeConnectionPool, PoolConfig, PoolSize}; -use crate::transport::errors::{DbError, NewSessionError, QueryError}; -use crate::transport::host_filter::HostFilter; -use crate::transport::iterator::QueryPager; -use crate::transport::node::resolve_contact_points; use crate::utils::parse::{ParseErrorCause, ParseResult, ParserState}; use futures::future::{self, FutureExt}; @@ -31,11 +30,11 @@ use tokio::sync::{broadcast, mpsc}; use tracing::{debug, error, trace, warn}; use uuid::Uuid; -use super::errors::{ +use crate::cluster::node::{InternalKnownNode, NodeAddr, ResolvedContactPoint}; +use crate::execution::errors::{ KeyspaceStrategyError, KeyspacesMetadataError, MetadataError, PeersMetadataError, ProtocolError, TablesMetadataError, UdtMetadataError, ViewsMetadataError, }; -use super::node::{InternalKnownNode, NodeAddr, ResolvedContactPoint}; /// Allows to read current metadata from the cluster pub(crate) struct MetadataReader { @@ -977,7 +976,7 @@ where let fut = async move { let pager = make_keyspace_filtered_query_pager(conn, query_str, keyspaces_to_fetch).await?; - let stream: super::iterator::TypedRowStream = + let stream: crate::execution::pager::TypedRowStream = pager.rows_stream::().map_err(convert_typecheck_error)?; Ok::<_, QueryError>(stream) }; diff --git a/scylla/src/cluster/mod.rs b/scylla/src/cluster/mod.rs new file mode 100644 index 0000000000..2500efd303 --- /dev/null +++ b/scylla/src/cluster/mod.rs @@ -0,0 +1,27 @@ +//! This module holds entities that represent the cluster as a whole, +//! nodes in the cluster (together with a pool of connections), +//! the cluster's state, and logic for ruling out specific nodes. +//! +//! This includes: +//! - node's representation (Node), +//! - metadata representation, fetching and management, including: +//! - topology metadata, +//! - schema metadata, +//! - tablet metadata, +//! - ClusterData, which is a snapshot of the cluster's state. +//! - ClusterData is replaced atomically upon a metadata refresh, +//! preventing any issues arising from mutability, including races. +//! - HostFilter, which is a way to filter out some nodes and thus +//! not contact them at all on any condition. +//! + +#[allow(clippy::module_inception)] +mod cluster; +pub mod host_filter; +pub mod metadata; +pub(crate) mod node; + +pub use cluster::ClusterData; +pub(crate) use cluster::{use_keyspace_result, Cluster, ClusterNeatDebug}; + +pub use node::{KnownNode, Node, NodeAddr, NodeRef}; diff --git a/scylla/src/transport/node.rs b/scylla/src/cluster/node.rs similarity index 96% rename from scylla/src/transport/node.rs rename to scylla/src/cluster/node.rs index ba2b3d9f4c..2f3df0b7c8 100644 --- a/scylla/src/transport/node.rs +++ b/scylla/src/cluster/node.rs @@ -3,12 +3,12 @@ use tokio::net::lookup_host; use tracing::warn; use uuid::Uuid; +use crate::connection::Connection; +use crate::connection::VerifiedKeyspaceName; +use crate::connection::{NodeConnectionPool, PoolConfig}; +use crate::execution::errors::{ConnectionPoolError, QueryError}; /// Node represents a cluster node along with it's data and connections use crate::routing::{Shard, Sharder}; -use crate::transport::connection::Connection; -use crate::transport::connection::VerifiedKeyspaceName; -use crate::transport::connection_pool::{NodeConnectionPool, PoolConfig}; -use crate::transport::errors::{ConnectionPoolError, QueryError}; use std::fmt::Display; use std::io; @@ -22,7 +22,7 @@ use std::{ }, }; -use super::topology::{PeerEndpoint, UntranslatedEndpoint}; +use crate::cluster::metadata::{PeerEndpoint, UntranslatedEndpoint}; /// This enum is introduced to support address translation only upon opening a connection, /// as well as to cope with a bug present in older Cassandra and Scylla releases. @@ -65,7 +65,7 @@ impl Display for NodeAddr { } } -/// Node represents a cluster node along with it's data and connections +/// Node represents a cluster node along with its data and connections /// /// Note: if a Node changes its broadcast address, then it is not longer /// represented by the same instance of Node struct, but instead diff --git a/scylla/src/transport/connection.rs b/scylla/src/connection/connection.rs similarity index 94% rename from scylla/src/transport/connection.rs rename to scylla/src/connection/connection.rs index 3a550ae6ae..8589dfaf3d 100644 --- a/scylla/src/transport/connection.rs +++ b/scylla/src/connection/connection.rs @@ -1,3 +1,4 @@ +use async_trait::async_trait; use bytes::Bytes; use futures::{future::RemoteHandle, FutureExt}; use scylla_cql::frame::frame_errors::CqlResponseParseError; @@ -21,6 +22,7 @@ use uuid::Uuid; use std::borrow::Cow; #[cfg(feature = "ssl")] use std::pin::Pin; +use std::str::FromStr; use std::sync::atomic::AtomicU64; use std::time::Duration; #[cfg(feature = "ssl")] @@ -30,11 +32,12 @@ use tokio_openssl::SslStream; pub(crate) use ssl_config::SslConfig; use crate::authentication::AuthenticatorProvider; -use crate::transport::errors::{ +use crate::execution::errors::{ BadKeyspaceName, BrokenConnectionError, BrokenConnectionErrorKind, ConnectionError, ConnectionSetupRequestError, ConnectionSetupRequestErrorKind, CqlEventHandlingError, DbError, QueryError, RequestError, ResponseParseError, TranslationError, UserRequestError, }; +use crate::response::{NonErrorAuthResponse, NonErrorStartupResponse, QueryResponse}; use scylla_cql::frame::response::authenticate::Authenticate; use std::collections::{BTreeSet, HashMap, HashSet}; use std::convert::TryFrom; @@ -46,30 +49,29 @@ use std::{ net::{Ipv4Addr, Ipv6Addr}, }; -use super::errors::{ProtocolError, SchemaVersionFetchError, UseKeyspaceProtocolError}; -use super::iterator::QueryPager; -use super::locator::tablets::{RawTablet, TabletParsingError}; -use super::query_result::QueryResult; -use super::session::AddressTranslator; -use super::topology::{PeerEndpoint, UntranslatedEndpoint, UntranslatedPeer}; -use super::NodeAddr; #[cfg(feature = "cloud")] use crate::cloud::CloudConfig; +use crate::cluster::metadata::{PeerEndpoint, UntranslatedEndpoint, UntranslatedPeer}; +use crate::cluster::NodeAddr; +use crate::execution::errors::{ProtocolError, SchemaVersionFetchError, UseKeyspaceProtocolError}; +use crate::execution::pager::QueryPager; +use crate::response::query_result::QueryResult; +use crate::routing::locator::tablets::{RawTablet, TabletParsingError}; use crate::batch::{Batch, BatchStatement}; +use crate::connection::Compression; use crate::frame::protocol_features::ProtocolFeatures; use crate::frame::{ self, request::{self, batch, execute, query, register, SerializableRequest}, - response::{event::Event, result, NonErrorResponse, Response, ResponseOpcode}, + response::{event::Event, result, Response, ResponseOpcode}, server_event_type::EventType, FrameParams, SerializedRequest, }; use crate::query::Query; -use crate::routing::ShardInfo; +use crate::routing::{Shard, ShardInfo, Sharder}; use crate::statement::prepared_statement::PreparedStatement; use crate::statement::{Consistency, PageSize, PagingState, PagingStateResponse}; -use crate::transport::Compression; // Queries for schema agreement const LOCAL_VERSION: &str = "SELECT schema_version FROM system.local WHERE key='local'"; @@ -212,105 +214,6 @@ struct TaskResponse { body: Bytes, } -pub(crate) struct QueryResponse { - pub(crate) response: Response, - pub(crate) tracing_id: Option, - pub(crate) warnings: Vec, - #[allow(dead_code)] // This is not exposed to user (yet?) - pub(crate) custom_payload: Option>, -} - -// A QueryResponse in which response can not be Response::Error -pub(crate) struct NonErrorQueryResponse { - pub(crate) response: NonErrorResponse, - pub(crate) tracing_id: Option, - pub(crate) warnings: Vec, -} - -impl QueryResponse { - pub(crate) fn into_non_error_query_response( - self, - ) -> Result { - Ok(NonErrorQueryResponse { - response: self.response.into_non_error_response()?, - tracing_id: self.tracing_id, - warnings: self.warnings, - }) - } - - pub(crate) fn into_query_result_and_paging_state( - self, - ) -> Result<(QueryResult, PagingStateResponse), UserRequestError> { - self.into_non_error_query_response()? - .into_query_result_and_paging_state() - } - - pub(crate) fn into_query_result(self) -> Result { - self.into_non_error_query_response()?.into_query_result() - } -} - -impl NonErrorQueryResponse { - pub(crate) fn as_set_keyspace(&self) -> Option<&result::SetKeyspace> { - match &self.response { - NonErrorResponse::Result(result::Result::SetKeyspace(sk)) => Some(sk), - _ => None, - } - } - - pub(crate) fn as_schema_change(&self) -> Option<&result::SchemaChange> { - match &self.response { - NonErrorResponse::Result(result::Result::SchemaChange(sc)) => Some(sc), - _ => None, - } - } - - pub(crate) fn into_query_result_and_paging_state( - self, - ) -> Result<(QueryResult, PagingStateResponse), UserRequestError> { - let (raw_rows, paging_state_response) = match self.response { - NonErrorResponse::Result(result::Result::Rows((rs, paging_state_response))) => { - (Some(rs), paging_state_response) - } - NonErrorResponse::Result(_) => (None, PagingStateResponse::NoMorePages), - _ => { - return Err(UserRequestError::UnexpectedResponse( - self.response.to_response_kind(), - )) - } - }; - - Ok(( - QueryResult::new(raw_rows, self.tracing_id, self.warnings), - paging_state_response, - )) - } - - pub(crate) fn into_query_result(self) -> Result { - let (result, paging_state) = self.into_query_result_and_paging_state()?; - - if !paging_state.finished() { - error!( - "Internal driver API misuse or a server bug: nonfinished paging state\ - would be discarded by `NonErrorQueryResponse::into_query_result`" - ); - return Err(ProtocolError::NonfinishedPagingState.into()); - } - - Ok(result) - } -} - -pub(crate) enum NonErrorStartupResponse { - Ready, - Authenticate(response::authenticate::Authenticate), -} - -pub(crate) enum NonErrorAuthResponse { - AuthChallenge(response::authenticate::AuthChallenge), - AuthSuccess(response::authenticate::AuthSuccess), -} - #[cfg(feature = "ssl")] mod ssl_config { use openssl::{ @@ -968,6 +871,7 @@ impl Connection { &self, query: impl Into, paging_state: PagingState, + timestamp: Option, ) -> Result<(QueryResult, PagingStateResponse), UserRequestError> { let query: Query = query.into(); @@ -982,6 +886,7 @@ impl Connection { paging_state, consistency, serial_consistency.flatten(), + timestamp, ) .await } @@ -993,6 +898,7 @@ impl Connection { paging_state: PagingState, consistency: Consistency, serial_consistency: Option, + timestamp: Option, ) -> Result<(QueryResult, PagingStateResponse), UserRequestError> { let query: Query = query.into(); let page_size = query.get_validated_page_size(); @@ -1003,6 +909,7 @@ impl Connection { serial_consistency, Some(page_size), paging_state, + timestamp, ) .await? .into_query_result_and_paging_state() @@ -1012,11 +919,12 @@ impl Connection { pub(crate) async fn query_unpaged( &self, query: impl Into, + timestamp: Option, ) -> Result { // This method is used only for driver internal queries, so no need to consult execution profile here. let query: Query = query.into(); - self.query_raw_unpaged(&query) + self.query_raw_unpaged(&query, timestamp) .await .map_err(Into::into) .and_then(QueryResponse::into_query_result) @@ -1025,6 +933,7 @@ impl Connection { pub(crate) async fn query_raw_unpaged( &self, query: &Query, + timestamp: Option, ) -> Result { // This method is used only for driver internal queries, so no need to consult execution profile here. self.query_raw_with_consistency( @@ -1035,6 +944,7 @@ impl Connection { query.config.serial_consistency.flatten(), None, PagingState::start(), + timestamp, ) .await } @@ -1046,6 +956,7 @@ impl Connection { serial_consistency: Option, page_size: Option, paging_state: PagingState, + timestamp: Option, ) -> Result { let query_frame = query::Query { contents: Cow::Borrowed(&query.contents), @@ -1056,7 +967,7 @@ impl Connection { page_size: page_size.map(Into::into), paging_state, skip_metadata: false, - timestamp: query.get_timestamp(), + timestamp, }, }; @@ -1072,9 +983,10 @@ impl Connection { &self, prepared: &PreparedStatement, values: SerializedValues, + timestamp: Option, ) -> Result { // This method is used only for driver internal queries, so no need to consult execution profile here. - self.execute_raw_unpaged(prepared, values) + self.execute_raw_unpaged(prepared, values, timestamp) .await .map_err(Into::into) .and_then(QueryResponse::into_query_result) @@ -1085,6 +997,7 @@ impl Connection { &self, prepared: &PreparedStatement, values: SerializedValues, + timestamp: Option, ) -> Result { // This method is used only for driver internal queries, so no need to consult execution profile here. self.execute_raw_with_consistency( @@ -1096,10 +1009,12 @@ impl Connection { prepared.config.serial_consistency.flatten(), None, PagingState::start(), + timestamp, ) .await } + #[allow(clippy::too_many_arguments)] pub(crate) async fn execute_raw_with_consistency( &self, prepared_statement: &PreparedStatement, @@ -1108,6 +1023,7 @@ impl Connection { serial_consistency: Option, page_size: Option, paging_state: PagingState, + timestamp: Option, ) -> Result { let execute_frame = execute::Execute { id: prepared_statement.get_id().to_owned(), @@ -1116,7 +1032,7 @@ impl Connection { serial_consistency, values: Cow::Borrowed(values), page_size: page_size.map(Into::into), - timestamp: prepared_statement.get_timestamp(), + timestamp, skip_metadata: prepared_statement.get_use_cached_result_metadata(), paging_state, }, @@ -1219,6 +1135,7 @@ impl Connection { &self, batch: &Batch, values: impl BatchValues, + timestamp: Option, ) -> Result { self.batch_with_consistency( batch, @@ -1227,6 +1144,7 @@ impl Connection { .config .determine_consistency(self.config.default_consistency), batch.config.serial_consistency.flatten(), + timestamp, ) .await } @@ -1237,6 +1155,7 @@ impl Connection { values: impl BatchValues, consistency: Consistency, serial_consistency: Option, + timestamp: Option, ) -> Result { let batch = self.prepare_batch(init_batch, &values).await?; @@ -1255,7 +1174,7 @@ impl Connection { batch_type: batch.get_type(), consistency, serial_consistency, - timestamp: batch.get_timestamp(), + timestamp, }; loop { @@ -1351,7 +1270,7 @@ impl Connection { false => format!("USE {}", keyspace_name.as_str()).into(), }; - let query_response = self.query_raw_unpaged(&query).await?; + let query_response = self.query_raw_unpaged(&query, None).await?; Self::verify_use_keyspace_result(keyspace_name, query_response) } @@ -1432,7 +1351,7 @@ impl Connection { pub(crate) async fn fetch_schema_version(&self) -> Result { let (version_id,) = self - .query_unpaged(LOCAL_VERSION) + .query_unpaged(LOCAL_VERSION, None) .await? .into_rows_result() .map_err(|err| { @@ -1940,6 +1859,71 @@ impl Connection { } } +/// Translates IP addresses received from ScyllaDB nodes into locally reachable addresses. +/// +/// The driver auto-detects new ScyllaDB nodes added to the cluster through server side pushed +/// notifications and through checking the system tables. For each node, the address the driver +/// receives corresponds to the address set as `rpc_address` in the node yaml file. In most +/// cases, this is the correct address to use by the driver and that is what is used by default. +/// However, sometimes the addresses received through this mechanism will either not be reachable +/// directly by the driver or should not be the preferred address to use to reach the node (for +/// instance, the `rpc_address` set on ScyllaDB nodes might be a private IP, but some clients +/// may have to use a public IP, or pass by a router, e.g. through NAT, to reach that node). +/// This interface allows to deal with such cases, by allowing to translate an address as sent +/// by a ScyllaDB node to another address to be used by the driver for connection. +/// +/// Please note that the "known nodes" addresses provided while creating +/// the [`Session`](crate::session::Session) instance are not translated, only IP addresses +/// retrieved from or sent by Cassandra nodes to the driver are. +#[async_trait] +pub trait AddressTranslator: Send + Sync { + async fn translate_address( + &self, + untranslated_peer: &UntranslatedPeer, + ) -> Result; +} + +#[async_trait] +impl AddressTranslator for HashMap { + async fn translate_address( + &self, + untranslated_peer: &UntranslatedPeer, + ) -> Result { + match self.get(&untranslated_peer.untranslated_address) { + Some(&translated_addr) => Ok(translated_addr), + None => Err(TranslationError::NoRuleForAddress( + untranslated_peer.untranslated_address, + )), + } + } +} + +#[async_trait] +// Notice: this is inefficient, but what else can we do with such poor representation as str? +// After all, the cluster size is small enough to make this irrelevant. +impl AddressTranslator for HashMap<&'static str, &'static str> { + async fn translate_address( + &self, + untranslated_peer: &UntranslatedPeer, + ) -> Result { + for (&rule_addr_str, &translated_addr_str) in self.iter() { + if let Ok(rule_addr) = SocketAddr::from_str(rule_addr_str) { + if rule_addr == untranslated_peer.untranslated_address { + return SocketAddr::from_str(translated_addr_str).map_err(|reason| { + TranslationError::InvalidAddressInRule { + translated_addr_str, + reason, + } + }); + } + } + } + Err(TranslationError::NoRuleForAddress( + untranslated_peer.untranslated_address, + )) + } +} + async fn maybe_translated_addr( endpoint: UntranslatedEndpoint, address_translator: Option<&dyn AddressTranslator>, @@ -2086,6 +2070,28 @@ pub(crate) async fn open_connection( Ok((connection, error_receiver)) } +pub(crate) async fn open_connection_to_shard_aware_port( + endpoint: UntranslatedEndpoint, + shard: Shard, + sharder: Sharder, + connection_config: &ConnectionConfig, +) -> Result<(Connection, ErrorReceiver), ConnectionError> { + // Create iterator over all possible source ports for this shard + let source_port_iter = sharder.iter_source_ports_for_shard(shard); + + for port in source_port_iter { + let connect_result = open_connection(endpoint.clone(), Some(port), connection_config).await; + + match connect_result { + Err(err) if err.is_address_unavailable_for_use() => continue, // If we can't use this port, try the next one + result => return result, + } + } + + // Tried all source ports for that shard, give up + Err(ConnectionError::NoSourcePortForShard(shard)) +} + async fn perform_authenticate( connection: &mut Connection, authenticate: &Authenticate, @@ -2391,12 +2397,11 @@ mod tests { use tokio::select; use tokio::sync::mpsc; - use super::ConnectionConfig; + use super::{open_connection, ConnectionConfig}; + use crate::cluster::metadata::UntranslatedEndpoint; + use crate::cluster::node::ResolvedContactPoint; use crate::query::Query; use crate::test_utils::setup_tracing; - use crate::transport::connection::open_connection; - use crate::transport::node::ResolvedContactPoint; - use crate::transport::topology::UntranslatedEndpoint; use crate::utils::test_utils::{unique_keyspace_name, PerformDDL}; use crate::SessionBuilder; use futures::{StreamExt, TryStreamExt}; @@ -2491,7 +2496,11 @@ mod tests { let mut insert_futures = Vec::new(); for v in &values { let values = prepared.serialize_values(&(*v,)).unwrap(); - let fut = async { connection.execute_raw_unpaged(&prepared, values).await }; + let fut = async { + connection + .execute_raw_unpaged(&prepared, values, None) + .await + }; insert_futures.push(fut); } @@ -2593,8 +2602,10 @@ mod tests { let values = prepared .serialize_values(&(j, vec![j as u8; j as usize])) .unwrap(); - let response = - conn.execute_raw_unpaged(&prepared, values).await.unwrap(); + let response = conn + .execute_raw_unpaged(&prepared, values, None) + .await + .unwrap(); // QueryResponse might contain an error - make sure that there were no errors let _nonerror_response = response.into_non_error_query_response().unwrap(); @@ -2611,7 +2622,7 @@ mod tests { // Check that everything was written properly let range_end = arithmetic_sequence_sum(NUM_BATCHES); let mut results = connection - .query_unpaged("SELECT p, v FROM t") + .query_unpaged("SELECT p, v FROM t", None) .await .unwrap() .into_rows_result() @@ -2721,7 +2732,7 @@ mod tests { #[ntest::timeout(20000)] #[cfg(not(scylla_cloud_tests))] async fn connection_is_closed_on_no_response_to_keepalives() { - use crate::transport::errors::BrokenConnectionErrorKind; + use crate::execution::errors::BrokenConnectionErrorKind; setup_tracing(); @@ -2768,7 +2779,7 @@ mod tests { // As everything is normal, these queries should succeed. for _ in 0..3 { tokio::time::sleep(Duration::from_millis(500)).await; - conn.query_unpaged("SELECT host_id FROM system.local") + conn.query_unpaged("SELECT host_id FROM system.local", None) .await .unwrap(); } @@ -2785,16 +2796,14 @@ mod tests { // Then, the error from keepaliver will be propagated to the error receiver. let err = error_receiver.await.unwrap(); let err_inner: &BrokenConnectionErrorKind = match err { - crate::transport::connection::ConnectionError::BrokenConnection(ref e) => { - e.downcast_ref().unwrap() - } + super::ConnectionError::BrokenConnection(ref e) => e.downcast_ref().unwrap(), _ => panic!("Bad error type. Expected keepalive timeout."), }; assert_matches!(err_inner, BrokenConnectionErrorKind::KeepaliveTimeout(_)); // As the router is invalidated, all further queries should immediately // return error. - conn.query_unpaged("SELECT host_id FROM system.local") + conn.query_unpaged("SELECT host_id FROM system.local", None) .await .unwrap_err(); diff --git a/scylla/src/transport/connection_pool.rs b/scylla/src/connection/connection_pool.rs similarity index 97% rename from scylla/src/transport/connection_pool.rs rename to scylla/src/connection/connection_pool.rs index 4b3de60c53..a54b40273b 100644 --- a/scylla/src/transport/connection_pool.rs +++ b/scylla/src/connection/connection_pool.rs @@ -1,22 +1,20 @@ #[cfg(feature = "cloud")] use crate::cloud::set_ssl_config_for_scylla_cloud_host; -use crate::routing::{Shard, ShardCount, Sharder}; -use crate::transport::errors::{ +use crate::connection::{self, Connection, ConnectionConfig, ErrorReceiver, VerifiedKeyspaceName}; +use crate::execution::errors::{ BrokenConnectionErrorKind, ConnectionError, ConnectionPoolError, QueryError, }; -use crate::transport::{ - connection, - connection::{Connection, ConnectionConfig, ErrorReceiver, VerifiedKeyspaceName}, -}; +use crate::routing::{Shard, ShardCount, Sharder}; + +use crate::cluster::metadata::{PeerEndpoint, UntranslatedEndpoint}; #[cfg(feature = "cloud")] -use super::node::resolve_hostname; +use crate::cluster::node::resolve_hostname; #[cfg(feature = "cloud")] -use super::node::ResolvedContactPoint; -use super::topology::{PeerEndpoint, UntranslatedEndpoint}; -use super::NodeAddr; +use crate::cluster::node::ResolvedContactPoint; +use crate::cluster::NodeAddr; use arc_swap::ArcSwap; use futures::{future::RemoteHandle, stream::FuturesUnordered, Future, FutureExt, StreamExt}; @@ -30,6 +28,8 @@ use std::time::Duration; use tokio::sync::{broadcast, mpsc, Notify}; use tracing::{debug, error, trace, warn}; +use super::connection::open_connection_to_shard_aware_port; + /// The target size of a per-node connection pool. #[derive(Debug, Clone, Copy)] pub enum PoolSize { @@ -1107,7 +1107,7 @@ impl PoolRefiller { .await .map_err(|_| QueryError::TimeoutError)?; - super::cluster::use_keyspace_result(use_keyspace_results.into_iter()) + crate::cluster::use_keyspace_result(use_keyspace_results.into_iter()) }; tokio::task::spawn(async move { @@ -1194,37 +1194,13 @@ struct OpenedConnectionEvent { keyspace_name: Option, } -async fn open_connection_to_shard_aware_port( - endpoint: UntranslatedEndpoint, - shard: Shard, - sharder: Sharder, - connection_config: &ConnectionConfig, -) -> Result<(Connection, ErrorReceiver), ConnectionError> { - // Create iterator over all possible source ports for this shard - let source_port_iter = sharder.iter_source_ports_for_shard(shard); - - for port in source_port_iter { - let connect_result = - connection::open_connection(endpoint.clone(), Some(port), connection_config).await; - - match connect_result { - Err(err) if err.is_address_unavailable_for_use() => continue, // If we can't use this port, try the next one - result => return result, - } - } - - // Tried all source ports for that shard, give up - Err(ConnectionError::NoSourcePortForShard(shard)) -} - #[cfg(test)] mod tests { - use super::open_connection_to_shard_aware_port; + use super::ConnectionConfig; + use crate::cluster::metadata::UntranslatedEndpoint; + use crate::cluster::node::ResolvedContactPoint; use crate::routing::{ShardCount, Sharder}; use crate::test_utils::setup_tracing; - use crate::transport::connection::ConnectionConfig; - use crate::transport::node::ResolvedContactPoint; - use crate::transport::topology::UntranslatedEndpoint; use std::net::{SocketAddr, ToSocketAddrs}; // Open many connections to a node @@ -1233,6 +1209,8 @@ mod tests { #[tokio::test] #[cfg(not(scylla_cloud_tests))] async fn many_connections() { + use crate::connection::connection::open_connection_to_shard_aware_port; + setup_tracing(); let connections_number = 512; diff --git a/scylla/src/connection/mod.rs b/scylla/src/connection/mod.rs new file mode 100644 index 0000000000..83c8938418 --- /dev/null +++ b/scylla/src/connection/mod.rs @@ -0,0 +1,21 @@ +//! This module holds entities that represent connections to the cluster +//! and management over those connections (connection pooling). +//! This includes two main abstractions: +//! - Connection - a single, possibly encrypted, connection to a Scylla node over CQL protocol, +//! - NodeConnectionPool - a manager that keeps a desired number of connections opened to each shard. + +#[allow(clippy::module_inception)] +mod connection; +mod connection_pool; + +pub use crate::execution::errors::TranslationError; +use connection::ErrorReceiver; +#[cfg(feature = "ssl")] +pub(crate) use connection::SslConfig; +pub(crate) use connection::{open_connection, Connection, ConnectionConfig, VerifiedKeyspaceName}; +pub use connection::{AddressTranslator, SelfIdentity}; + +pub use connection_pool::PoolSize; +pub(crate) use connection_pool::{NodeConnectionPool, PoolConfig}; + +pub use scylla_cql::frame::Compression; diff --git a/scylla/src/execution/driver_tracing.rs b/scylla/src/execution/driver_tracing.rs new file mode 100644 index 0000000000..65b0bded12 --- /dev/null +++ b/scylla/src/execution/driver_tracing.rs @@ -0,0 +1,179 @@ +use crate::cluster::node::Node; +use crate::connection::Connection; +use crate::routing::{Shard, Token}; +use crate::utils::pretty::{CommaSeparatedDisplayer, CqlValueDisplayer}; +use crate::QueryResult; +use itertools::Either; +use scylla_cql::frame::response::result::RawMetadataAndRawRows; +use scylla_cql::frame::response::result::{deser_cql_value, ColumnSpec}; +use std::borrow::Borrow; +use std::fmt::Display; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; +use std::sync::Arc; +use tracing::trace_span; + +pub(crate) struct RequestSpan { + span: tracing::Span, + speculative_executions: AtomicUsize, +} + +impl RequestSpan { + pub(crate) fn new_query(contents: &str) -> Self { + use tracing::field::Empty; + + let span = trace_span!( + "Request", + kind = "unprepared", + contents = contents, + // + request_size = Empty, + result_size = Empty, + result_rows = Empty, + replicas = Empty, + shard = Empty, + speculative_executions = Empty, + ); + + Self { + span, + speculative_executions: 0.into(), + } + } + + pub(crate) fn new_prepared<'ps, 'spec: 'ps>( + partition_key: Option)> + Clone>, + token: Option, + request_size: usize, + ) -> Self { + use tracing::field::Empty; + + let span = trace_span!( + "Request", + kind = "prepared", + partition_key = Empty, + token = Empty, + // + request_size = request_size, + result_size = Empty, + result_rows = Empty, + replicas = Empty, + shard = Empty, + speculative_executions = Empty, + ); + + if let Some(partition_key) = partition_key { + span.record( + "partition_key", + tracing::field::display( + format_args!("{}", partition_key_displayer(partition_key),), + ), + ); + } + if let Some(token) = token { + span.record("token", token.value()); + } + + Self { + span, + speculative_executions: 0.into(), + } + } + + pub(crate) fn new_batch() -> Self { + use tracing::field::Empty; + + let span = trace_span!( + "Request", + kind = "batch", + // + request_size = Empty, + result_size = Empty, + result_rows = Empty, + replicas = Empty, + shard = Empty, + speculative_executions = Empty, + ); + + Self { + span, + speculative_executions: 0.into(), + } + } + + pub(crate) fn record_shard_id(&self, conn: &Connection) { + if let Some(info) = conn.get_shard_info() { + self.span.record("shard", info.shard); + } + } + + pub(crate) fn record_raw_rows_fields(&self, raw_rows: &RawMetadataAndRawRows) { + self.span + .record("raw_result_size", raw_rows.metadata_and_rows_bytes_size()); + } + + pub(crate) fn record_result_fields(&self, query_result: &QueryResult) { + if let Some(raw_metadata_and_rows) = query_result.raw_metadata_and_rows() { + self.record_raw_rows_fields(raw_metadata_and_rows); + } + } + + pub(crate) fn record_replicas<'a>(&'a self, replicas: &'a [(impl Borrow>, Shard)]) { + struct ReplicaIps<'a, N>(&'a [(N, Shard)]); + impl Display for ReplicaIps<'_, N> + where + N: Borrow>, + { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut nodes_with_shards = self.0.iter(); + if let Some((node, shard)) = nodes_with_shards.next() { + write!(f, "{}-shard{}", node.borrow().address.ip(), shard)?; + + for (node, shard) in nodes_with_shards { + write!(f, ",{}-shard{}", node.borrow().address.ip(), shard)?; + } + } + Ok(()) + } + } + self.span + .record("replicas", tracing::field::display(&ReplicaIps(replicas))); + } + + pub(crate) fn record_request_size(&self, size: usize) { + self.span.record("request_size", size); + } + + pub(crate) fn inc_speculative_executions(&self) { + self.speculative_executions.fetch_add(1, Ordering::Relaxed); + } + + pub(crate) fn span(&self) -> &tracing::Span { + &self.span + } +} + +impl Drop for RequestSpan { + fn drop(&mut self) { + self.span.record( + "speculative_executions", + self.speculative_executions.load(Ordering::Relaxed), + ); + } +} + +fn partition_key_displayer<'ps, 'res, 'spec: 'ps>( + mut pk_values_iter: impl Iterator)> + 'res + Clone, +) -> impl Display + 'res { + CommaSeparatedDisplayer( + std::iter::from_fn(move || { + pk_values_iter + .next() + .map(|(mut cell, spec)| deser_cql_value(spec.typ(), &mut cell)) + }) + .map(|c| match c { + Ok(c) => Either::Left(CqlValueDisplayer(c)), + Err(_) => Either::Right(""), + }), + ) +} diff --git a/scylla/src/transport/errors.rs b/scylla/src/execution/errors.rs similarity index 98% rename from scylla/src/transport/errors.rs rename to scylla/src/execution/errors.rs index fdd5b9aa05..4ee230e5a7 100644 --- a/scylla/src/transport/errors.rs +++ b/scylla/src/execution/errors.rs @@ -1,4 +1,4 @@ -//! This module contains various errors which can be returned by [`Session`](crate::transport::session::Session). +//! This module contains various errors which can be returned by [`Session`](crate::session::Session). // Re-export DbError type and types that it depends on // so they can be found in `scylla::errors`. @@ -35,10 +35,10 @@ use thiserror::Error; use crate::{authentication::AuthError, frame::response}; -use super::iterator::NextRowError; +use crate::execution::pager::NextRowError; #[allow(deprecated)] -use super::legacy_query_result::IntoLegacyQueryResultError; -use super::query_result::{IntoRowsResultError, SingleRowError}; +use crate::response::legacy_query_result::IntoLegacyQueryResultError; +use crate::response::query_result::{IntoRowsResultError, SingleRowError}; /// Error that occurred during query execution #[derive(Error, Debug, Clone)] @@ -114,8 +114,8 @@ pub enum QueryError { #[error("An error occurred during async iteration over rows of result: {0}")] NextRowError(#[from] NextRowError), - /// Failed to convert [`QueryResult`][crate::transport::query_result::QueryResult] - /// into [`LegacyQueryResult`][crate::transport::legacy_query_result::LegacyQueryResult]. + /// Failed to convert [`QueryResult`][crate::response::query_result::QueryResult] + /// into [`LegacyQueryResult`][crate::response::legacy_query_result::LegacyQueryResult]. #[deprecated( since = "0.15.1", note = "Legacy deserialization API is inefficient and is going to be removed soon" @@ -293,8 +293,8 @@ pub enum NewSessionError { #[error("An error occurred during async iteration over rows of result: {0}")] NextRowError(#[from] NextRowError), - /// Failed to convert [`QueryResult`][crate::transport::query_result::QueryResult] - /// into [`LegacyQueryResult`][crate::transport::legacy_query_result::LegacyQueryResult]. + /// Failed to convert [`QueryResult`][crate::response::query_result::QueryResult] + /// into [`LegacyQueryResult`][crate::response::legacy_query_result::LegacyQueryResult]. #[deprecated( since = "0.15.1", note = "Legacy deserialization API is inefficient and is going to be removed soon" @@ -780,8 +780,8 @@ pub enum ConnectionSetupRequestErrorKind { AuthFinishError(AuthError), /// User did not provide authentication while the cluster requires it. - /// See [`SessionBuilder::user`](crate::transport::session_builder::SessionBuilder::user) - /// and/or [`SessionBuilder::authenticator_provider`](crate::transport::session_builder::SessionBuilder::authenticator_provider). + /// See [`SessionBuilder::user`](crate::session::session_builder::SessionBuilder::user) + /// and/or [`SessionBuilder::authenticator_provider`](crate::session::session_builder::SessionBuilder::authenticator_provider). #[error("Authentication is required. You can use SessionBuilder::user(\"user\", \"pass\") to provide credentials or SessionBuilder::authenticator_provider to provide custom authenticator")] MissingAuthentication, } @@ -1013,7 +1013,7 @@ pub(crate) enum ResponseParseError { mod tests { use scylla_cql::Consistency; - use crate::transport::errors::{DbError, QueryError, WriteType}; + use super::{DbError, QueryError, WriteType}; #[test] fn write_type_from_str() { diff --git a/scylla/src/transport/execution_profile.rs b/scylla/src/execution/execution_profile.rs similarity index 94% rename from scylla/src/transport/execution_profile.rs rename to scylla/src/execution/execution_profile.rs index a94addec5b..80aa0744e6 100644 --- a/scylla/src/transport/execution_profile.rs +++ b/scylla/src/execution/execution_profile.rs @@ -18,7 +18,7 @@ //! # async fn check_only_compiles() -> Result<(), Box> { //! use scylla::{Session, SessionBuilder}; //! use scylla::statement::Consistency; -//! use scylla::transport::ExecutionProfile; +//! use scylla::execution::ExecutionProfile; //! //! let profile = ExecutionProfile::builder() //! .consistency(Consistency::LocalOne) @@ -44,7 +44,7 @@ //! # async fn check_only_compiles() -> Result<(), Box> { //! use scylla::query::Query; //! use scylla::statement::Consistency; -//! use scylla::transport::ExecutionProfile; +//! use scylla::execution::ExecutionProfile; //! use std::time::Duration; //! //! let profile = ExecutionProfile::builder() @@ -71,7 +71,7 @@ //! # use std::error::Error; //! # async fn check_only_compiles() -> Result<(), Box> { //! use scylla::statement::Consistency; -//! use scylla::transport::ExecutionProfile; +//! use scylla::execution::ExecutionProfile; //! use std::time::Duration; //! //! let base_profile = ExecutionProfile::builder() @@ -112,7 +112,7 @@ //! use scylla::{Session, SessionBuilder}; //! use scylla::query::Query; //! use scylla::statement::Consistency; -//! use scylla::transport::ExecutionProfile; +//! use scylla::execution::ExecutionProfile; //! //! let profile1 = ExecutionProfile::builder() //! .consistency(Consistency::One) @@ -166,15 +166,15 @@ use arc_swap::ArcSwap; use scylla_cql::{frame::types::SerialConsistency, Consistency}; use crate::{ - load_balancing::LoadBalancingPolicy, retry_policy::RetryPolicy, + execution::retries::RetryPolicy, load_balancing::LoadBalancingPolicy, speculative_execution::SpeculativeExecutionPolicy, }; pub(crate) mod defaults { + use crate::execution::execution_profile::ExecutionProfileInner; + use crate::execution::retries::{DefaultRetryPolicy, RetryPolicy}; use crate::load_balancing::{self, LoadBalancingPolicy}; - use crate::retry_policy::{DefaultRetryPolicy, RetryPolicy}; use crate::speculative_execution::SpeculativeExecutionPolicy; - use crate::transport::execution_profile::ExecutionProfileInner; use scylla_cql::frame::types::SerialConsistency; use scylla_cql::Consistency; use std::sync::Arc; @@ -216,7 +216,8 @@ pub(crate) mod defaults { /// # Example /// /// ``` -/// # use scylla::transport::{ExecutionProfile, retry_policy::FallthroughRetryPolicy}; +/// # use scylla::execution::retries::FallthroughRetryPolicy; +/// # use scylla::execution::ExecutionProfile; /// # use scylla::statement::Consistency; /// # use std::sync::Arc; /// # fn example() -> Result<(), Box> { @@ -243,7 +244,7 @@ impl ExecutionProfileBuilder { /// /// # Example /// ``` - /// # use scylla::transport::ExecutionProfile; + /// # use scylla::execution::ExecutionProfile; /// # use std::time::Duration; /// # fn example() -> Result<(), Box> { /// let profile: ExecutionProfile = ExecutionProfile::builder() @@ -277,8 +278,8 @@ impl ExecutionProfileBuilder { /// /// # Example /// ``` - /// # use scylla::transport::ExecutionProfile; - /// # use scylla::transport::load_balancing::DefaultPolicy; + /// # use scylla::execution::ExecutionProfile; + /// # use scylla::execution::load_balancing::DefaultPolicy; /// # use std::sync::Arc; /// # fn example() -> Result<(), Box> { /// let profile: ExecutionProfile = ExecutionProfile::builder() @@ -296,13 +297,13 @@ impl ExecutionProfileBuilder { } /// Sets the [`RetryPolicy`] to use by default on queries. - /// The default is [DefaultRetryPolicy](crate::transport::retry_policy::DefaultRetryPolicy). + /// The default is [DefaultRetryPolicy](crate::execution::retries::DefaultRetryPolicy). /// It is possible to implement a custom retry policy by implementing the trait [`RetryPolicy`]. /// /// # Example /// ``` - /// use scylla::transport::retry_policy::DefaultRetryPolicy; - /// # use scylla::transport::ExecutionProfile; + /// use scylla::execution::retries::DefaultRetryPolicy; + /// # use scylla::execution::ExecutionProfile; /// # use std::sync::Arc; /// # fn example() -> Result<(), Box> { /// let profile: ExecutionProfile = ExecutionProfile::builder() @@ -324,9 +325,9 @@ impl ExecutionProfileBuilder { /// # use std::error::Error; /// # fn check_only_compiles() -> Result<(), Box> { /// use std::{sync::Arc, time::Duration}; - /// use scylla::{ - /// transport::ExecutionProfile, - /// transport::speculative_execution::SimpleSpeculativeExecutionPolicy, + /// use scylla::execution::{ + /// ExecutionProfile, + /// speculative_execution::SimpleSpeculativeExecutionPolicy, /// }; /// /// let policy = SimpleSpeculativeExecutionPolicy { @@ -352,8 +353,8 @@ impl ExecutionProfileBuilder { /// /// # Example /// ``` - /// use scylla::transport::retry_policy::DefaultRetryPolicy; - /// # use scylla::transport::ExecutionProfile; + /// use scylla::execution::retries::DefaultRetryPolicy; + /// # use scylla::execution::ExecutionProfile; /// # use std::sync::Arc; /// # fn example() -> Result<(), Box> { /// let profile: ExecutionProfile = ExecutionProfile::builder() diff --git a/scylla/src/history.rs b/scylla/src/execution/history.rs similarity index 99% rename from scylla/src/history.rs rename to scylla/src/execution/history.rs index b80dcf15ec..1969b745ef 100644 --- a/scylla/src/history.rs +++ b/scylla/src/execution/history.rs @@ -7,7 +7,7 @@ use std::{ time::SystemTime, }; -use crate::{retry_policy::RetryDecision, transport::errors::QueryError}; +use crate::{execution::errors::QueryError, execution::retries::RetryDecision}; use chrono::{DateTime, Utc}; use tracing::warn; @@ -452,9 +452,9 @@ mod tests { use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use crate::{ - retry_policy::RetryDecision, + execution::errors::{DbError, QueryError}, + execution::retries::RetryDecision, test_utils::setup_tracing, - transport::errors::{DbError, QueryError}, }; use super::{ diff --git a/scylla/src/transport/load_balancing/default.rs b/scylla/src/execution/load_balancing/default.rs similarity index 99% rename from scylla/src/transport/load_balancing/default.rs rename to scylla/src/execution/load_balancing/default.rs index 16fd6ac9aa..9a668b866b 100644 --- a/scylla/src/transport/load_balancing/default.rs +++ b/scylla/src/execution/load_balancing/default.rs @@ -2,10 +2,13 @@ use self::latency_awareness::LatencyAwareness; pub use self::latency_awareness::LatencyAwarenessBuilder; use super::{FallbackPlan, LoadBalancingPolicy, NodeRef, RoutingInfo}; +use crate::cluster::ClusterData; use crate::{ + cluster::metadata::Strategy, + cluster::node::Node, + execution::errors::QueryError, + routing::locator::ReplicaSet, routing::{Shard, Token}, - transport::errors::QueryError, - transport::{cluster::ClusterData, locator::ReplicaSet, node::Node, topology::Strategy}, }; use itertools::{Either, Itertools}; use rand::{prelude::SliceRandom, thread_rng, Rng}; @@ -1162,18 +1165,18 @@ mod tests { ExpectedGroups, ExpectedGroupsBuilder, }; use crate::host_filter::HostFilter; - use crate::transport::locator::tablets::TabletsInfo; - use crate::transport::locator::test::{ + use crate::routing::locator::tablets::TabletsInfo; + use crate::routing::locator::test::{ id_to_invalid_addr, mock_metadata_for_token_aware_tests, TABLE_NTS_RF_2, TABLE_NTS_RF_3, TABLE_SS_RF_2, }; use crate::{ + cluster::ClusterData, load_balancing::{ default::tests::framework::mock_cluster_data_for_token_aware_tests, Plan, RoutingInfo, }, routing::Token, test_utils::setup_tracing, - transport::ClusterData, }; use super::{DefaultPolicy, NodeLocationPreference}; @@ -1184,19 +1187,18 @@ mod tests { use uuid::Uuid; use crate::{ + cluster::{ + metadata::{Metadata, Peer}, + ClusterData, + }, load_balancing::{LoadBalancingPolicy, Plan, RoutingInfo}, + routing::locator::test::{id_to_invalid_addr, mock_metadata_for_token_aware_tests}, routing::Token, test_utils::setup_tracing, - transport::{ - locator::{ - tablets::TabletsInfo, - test::{id_to_invalid_addr, mock_metadata_for_token_aware_tests}, - }, - topology::{Metadata, Peer}, - ClusterData, - }, }; + use super::TabletsInfo; + #[derive(Debug)] enum ExpectedGroup { NonDeterministic(HashSet), @@ -1543,7 +1545,7 @@ mod tests { async fn test_default_policy_with_token_aware_statements() { setup_tracing(); - use crate::transport::locator::test::{A, B, C, D, E, F, G}; + use crate::routing::locator::test::{A, B, C, D, E, F, G}; let cluster = mock_cluster_data_for_token_aware_tests().await; #[derive(Debug)] @@ -2016,7 +2018,7 @@ mod tests { #[tokio::test] async fn test_default_policy_with_lwt_statements() { setup_tracing(); - use crate::transport::locator::test::{A, B, C, D, E, F, G}; + use crate::routing::locator::test::{A, B, C, D, E, F, G}; let cluster = mock_cluster_data_for_token_aware_tests().await; struct Test<'a> { @@ -2481,7 +2483,7 @@ mod tests { { struct FHostFilter; impl HostFilter for FHostFilter { - fn accept(&self, peer: &crate::transport::topology::Peer) -> bool { + fn accept(&self, peer: &crate::cluster::metadata::Peer) -> bool { peer.address != id_to_invalid_addr(F) } } @@ -2550,10 +2552,10 @@ mod latency_awareness { use uuid::Uuid; use crate::{ + cluster::node::Node, + execution::errors::{DbError, QueryError}, load_balancing::NodeRef, routing::Shard, - transport::errors::{DbError, QueryError}, - transport::node::Node, }; use std::{ collections::HashMap, @@ -3127,21 +3129,20 @@ mod latency_awareness { }; use crate::{ + cluster::ClusterData, + cluster::NodeAddr, load_balancing::default::NodeLocationPreference, + routing::locator::test::{TABLE_INVALID, TABLE_NTS_RF_2, TABLE_NTS_RF_3}, routing::Shard, test_utils::setup_tracing, - transport::locator::test::{TABLE_INVALID, TABLE_NTS_RF_2, TABLE_NTS_RF_3}, }; use crate::{ load_balancing::{ default::tests::test_default_policy_with_given_cluster_and_routing_info, RoutingInfo, }, + routing::locator::test::{id_to_invalid_addr, A, B, C, D, E, F, G}, routing::Token, - transport::{ - locator::test::{id_to_invalid_addr, A, B, C, D, E, F, G}, - ClusterData, NodeAddr, - }, }; use tokio::time::Instant; diff --git a/scylla/src/transport/load_balancing/mod.rs b/scylla/src/execution/load_balancing/mod.rs similarity index 98% rename from scylla/src/transport/load_balancing/mod.rs rename to scylla/src/execution/load_balancing/mod.rs index 72aaa1000e..8d008d82e1 100644 --- a/scylla/src/transport/load_balancing/mod.rs +++ b/scylla/src/execution/load_balancing/mod.rs @@ -2,10 +2,10 @@ //! `Session` can use any load balancing policy which implements the `LoadBalancingPolicy` trait\ //! See [the book](https://rust-driver.docs.scylladb.com/stable/load-balancing/load-balancing.html) for more information -use super::{cluster::ClusterData, NodeRef}; +use crate::cluster::{ClusterData, NodeRef}; use crate::{ + execution::errors::QueryError, routing::{Shard, Token}, - transport::errors::QueryError, }; use scylla_cql::frame::{response::result::TableSpec, types}; diff --git a/scylla/src/transport/load_balancing/plan.rs b/scylla/src/execution/load_balancing/plan.rs similarity index 96% rename from scylla/src/transport/load_balancing/plan.rs rename to scylla/src/execution/load_balancing/plan.rs index 7ae247ab13..db27a6fa34 100644 --- a/scylla/src/transport/load_balancing/plan.rs +++ b/scylla/src/execution/load_balancing/plan.rs @@ -2,7 +2,8 @@ use rand::{thread_rng, Rng}; use tracing::error; use super::{FallbackPlan, LoadBalancingPolicy, NodeRef, RoutingInfo}; -use crate::{routing::Shard, transport::ClusterData}; +use crate::cluster::ClusterData; +use crate::routing::Shard; enum PlanState<'a> { Created, @@ -32,12 +33,12 @@ enum PlanState<'a> { /// /// ``` /// # use std::sync::Arc; +/// # use scylla::cluster::NodeRef; +/// # use scylla::load_balancing::FallbackPlan; /// # use scylla::load_balancing::LoadBalancingPolicy; /// # use scylla::load_balancing::RoutingInfo; -/// # use scylla::transport::ClusterData; -/// # use scylla::transport::NodeRef; /// # use scylla::routing::Shard; -/// # use scylla::load_balancing::FallbackPlan; +/// # use scylla::cluster::ClusterData; /// /// #[derive(Debug)] /// struct NonRandomLBP { @@ -166,11 +167,9 @@ mod tests { use std::{net::SocketAddr, str::FromStr, sync::Arc}; use crate::{ + cluster::{Node, NodeAddr}, + routing::locator::test::{create_locator, mock_metadata_for_token_aware_tests}, test_utils::setup_tracing, - transport::{ - locator::test::{create_locator, mock_metadata_for_token_aware_tests}, - Node, NodeAddr, - }, }; use super::*; diff --git a/scylla/src/transport/metrics.rs b/scylla/src/execution/metrics.rs similarity index 100% rename from scylla/src/transport/metrics.rs rename to scylla/src/execution/metrics.rs diff --git a/scylla/src/execution/mod.rs b/scylla/src/execution/mod.rs new file mode 100644 index 0000000000..1b9b1f0afc --- /dev/null +++ b/scylla/src/execution/mod.rs @@ -0,0 +1,26 @@ +//! This module holds entities that control, customize, trace, and measure statement execution. +//! This includes: +//! - automated query pager, +//! - execution profiles, +//! - policies: +//! - load balancing, +//! - retries, +//! - speculative execution, +//! - cluster-side request tracing, +//! - driver-side request tracing, +//! - driver metrics, +//! - request execution history, +//! - error types. + +pub(crate) mod driver_tracing; +pub mod errors; +pub mod execution_profile; +pub mod history; +pub mod load_balancing; +pub(crate) mod metrics; +pub mod pager; +pub mod retries; +pub mod speculative_execution; +pub mod tracing; + +pub use execution_profile::ExecutionProfile; diff --git a/scylla/src/transport/iterator.rs b/scylla/src/execution/pager.rs similarity index 97% rename from scylla/src/transport/iterator.rs rename to scylla/src/execution/pager.rs index f11d9dd73e..f01ef49453 100644 --- a/scylla/src/transport/iterator.rs +++ b/scylla/src/execution/pager.rs @@ -1,4 +1,4 @@ -//! Iterators over rows returned by paged queries +//! Streamed async iteration over rows returned by paged queries. use std::future::Future; use std::net::SocketAddr; @@ -9,37 +9,41 @@ use std::task::{Context, Poll}; use futures::Stream; use scylla_cql::frame::frame_errors::ResultMetadataAndRowsCountParseError; +use scylla_cql::frame::request::query::PagingState; use scylla_cql::frame::response::result::RawMetadataAndRawRows; use scylla_cql::frame::response::NonErrorResponse; +use scylla_cql::frame::types::SerialConsistency; use scylla_cql::types::deserialize::result::RawRowLendingIterator; use scylla_cql::types::deserialize::row::{ColumnIterator, DeserializeRow}; use scylla_cql::types::deserialize::{DeserializationError, TypeCheckError}; use scylla_cql::types::serialize::row::SerializedValues; +use scylla_cql::Consistency; use std::result::Result; use thiserror::Error; use tokio::sync::mpsc; -use super::execution_profile::ExecutionProfileInner; -use super::query_result::ColumnSpecs; -use super::session::RequestSpan; #[allow(deprecated)] use crate::cql_to_rust::{FromRow, FromRowError}; - use crate::deserialize::DeserializeOwnedRow; +use crate::execution::driver_tracing::RequestSpan; +use crate::execution::errors::{QueryError, UserRequestError}; +use crate::execution::execution_profile::ExecutionProfileInner; +use crate::response::query_result::ColumnSpecs; + +use crate::cluster::ClusterData; +use crate::cluster::NodeRef; +use crate::connection::Connection; +use crate::execution::errors::ProtocolError; +use crate::execution::history::{self, HistoryListener}; +use crate::execution::load_balancing::{self, RoutingInfo}; +use crate::execution::metrics::Metrics; +use crate::execution::retries::{QueryInfo, RetryDecision, RetrySession}; use crate::frame::response::{ result, result::{ColumnSpec, Row}, }; -use crate::history::{self, HistoryListener}; +use crate::response::{NonErrorQueryResponse, QueryResponse}; use crate::statement::{prepared_statement::PreparedStatement, query::Query}; -use crate::statement::{Consistency, PagingState, SerialConsistency}; -use crate::transport::cluster::ClusterData; -use crate::transport::connection::{Connection, NonErrorQueryResponse, QueryResponse}; -use crate::transport::errors::{ProtocolError, QueryError, UserRequestError}; -use crate::transport::load_balancing::{self, RoutingInfo}; -use crate::transport::metrics::Metrics; -use crate::transport::retry_policy::{QueryInfo, RetryDecision, RetrySession}; -use crate::transport::NodeRef; use tracing::{trace, trace_span, warn, Instrument}; use uuid::Uuid; @@ -78,7 +82,7 @@ mod checked_channel_sender { use tokio::sync::mpsc; use uuid::Uuid; - use crate::transport::errors::QueryError; + use crate::execution::errors::QueryError; use super::ReceivedPage; @@ -722,6 +726,7 @@ impl QueryPager { serial_consistency, Some(page_size), paging_state, + None, ) .await } @@ -820,6 +825,7 @@ impl QueryPager { serial_consistency, Some(page_size), paging_state, + None, ) .await }; @@ -896,6 +902,7 @@ impl QueryPager { serial_consistency, Some(page_size), paging_state, + None, ) }, }; @@ -927,6 +934,7 @@ impl QueryPager { serial_consistency, Some(page_size), paging_state, + None, ) }, }; diff --git a/scylla/src/transport/retry_policy.rs b/scylla/src/execution/retries/default_rp.rs similarity index 86% rename from scylla/src/transport/retry_policy.rs rename to scylla/src/execution/retries/default_rp.rs index 54f87380eb..76356cafca 100644 --- a/scylla/src/transport/retry_policy.rs +++ b/scylla/src/execution/retries/default_rp.rs @@ -1,76 +1,8 @@ -//! Query retries configurations\ -//! To decide when to retry a query the `Session` can use any object which implements -//! the `RetryPolicy` trait - -use crate::frame::types::Consistency; -use crate::transport::errors::{DbError, QueryError, WriteType}; - -/// Information about a failed query -pub struct QueryInfo<'a> { - /// The error with which the query failed - pub error: &'a QueryError, - /// A query is idempotent if it can be applied multiple times without changing the result of the initial application\ - /// If set to `true` we can be sure that it is idempotent\ - /// If set to `false` it is unknown whether it is idempotent - pub is_idempotent: bool, - /// Consistency with which the query failed - pub consistency: Consistency, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum RetryDecision { - RetrySameNode(Option), // None means that the same consistency should be used as before - RetryNextNode(Option), // ditto - DontRetry, - IgnoreWriteError, -} - -/// Specifies a policy used to decide when to retry a query -pub trait RetryPolicy: std::fmt::Debug + Send + Sync { - /// Called for each new query, starts a session of deciding about retries - fn new_session(&self) -> Box; -} - -/// Used throughout a single query to decide when to retry it -/// After this query is finished it is destroyed or reset -pub trait RetrySession: Send + Sync { - /// Called after the query failed - decide what to do next - fn decide_should_retry(&mut self, query_info: QueryInfo) -> RetryDecision; - - /// Reset before using for a new query - fn reset(&mut self); -} - -/// Forwards all errors directly to the user, never retries -#[derive(Debug)] -pub struct FallthroughRetryPolicy; -pub struct FallthroughRetrySession; - -impl FallthroughRetryPolicy { - pub fn new() -> FallthroughRetryPolicy { - FallthroughRetryPolicy - } -} +use scylla_cql::frame::response::error::{DbError, WriteType}; -impl Default for FallthroughRetryPolicy { - fn default() -> FallthroughRetryPolicy { - FallthroughRetryPolicy - } -} +use crate::execution::errors::QueryError; -impl RetryPolicy for FallthroughRetryPolicy { - fn new_session(&self) -> Box { - Box::new(FallthroughRetrySession) - } -} - -impl RetrySession for FallthroughRetrySession { - fn decide_should_retry(&mut self, _query_info: QueryInfo) -> RetryDecision { - RetryDecision::DontRetry - } - - fn reset(&mut self) {} -} +use super::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}; /// Default retry policy - retries when there is a high chance that a retry might help.\ /// Behaviour based on [DataStax Java Driver](https://docs.datastax.com/en/developer/java-driver/4.10/manual/core/retries/) @@ -203,12 +135,12 @@ impl RetrySession for DefaultRetrySession { #[cfg(test)] mod tests { use super::{DefaultRetryPolicy, QueryInfo, RetryDecision, RetryPolicy}; - use crate::statement::Consistency; - use crate::test_utils::setup_tracing; - use crate::transport::errors::{ + use crate::execution::errors::{ BadQuery, BrokenConnectionErrorKind, ConnectionPoolError, ProtocolError, QueryError, }; - use crate::transport::errors::{DbError, WriteType}; + use crate::execution::errors::{DbError, WriteType}; + use crate::statement::Consistency; + use crate::test_utils::setup_tracing; use bytes::Bytes; fn make_query_info(error: &QueryError, is_idempotent: bool) -> QueryInfo<'_> { diff --git a/scylla/src/transport/downgrading_consistency_retry_policy.rs b/scylla/src/execution/retries/downgrading_consistency_rp.rs similarity index 99% rename from scylla/src/transport/downgrading_consistency_retry_policy.rs rename to scylla/src/execution/retries/downgrading_consistency_rp.rs index e52a44cbf1..fcac8e744d 100644 --- a/scylla/src/transport/downgrading_consistency_retry_policy.rs +++ b/scylla/src/execution/retries/downgrading_consistency_rp.rs @@ -1,13 +1,11 @@ use scylla_cql::Consistency; use tracing::debug; -use crate::{ - retry_policy::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}, - transport::errors::{DbError, QueryError, WriteType}, -}; +use super::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}; +use crate::execution::errors::{DbError, QueryError, WriteType}; /// Downgrading consistency retry policy - retries with lower consistency level if it knows\ -/// that the initial CL is unreachable. Also, it behaves as [DefaultRetryPolicy](crate::retry_policy::DefaultRetryPolicy) +/// that the initial CL is unreachable. Also, it behaves as [DefaultRetryPolicy](crate::execution::retries::DefaultRetryPolicy) /// when it believes that the initial CL is reachable. /// Behaviour based on [DataStax Java Driver]\ ///() @@ -180,10 +178,10 @@ impl RetrySession for DowngradingConsistencyRetrySession { mod tests { use bytes::Bytes; - use crate::test_utils::setup_tracing; - use crate::transport::errors::{ + use crate::execution::errors::{ BadQuery, BrokenConnectionErrorKind, ConnectionPoolError, ProtocolError, }; + use crate::test_utils::setup_tracing; use super::*; diff --git a/scylla/src/execution/retries/fallthrough_rp.rs b/scylla/src/execution/retries/fallthrough_rp.rs new file mode 100644 index 0000000000..48a866e5fd --- /dev/null +++ b/scylla/src/execution/retries/fallthrough_rp.rs @@ -0,0 +1,32 @@ +use super::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}; + +/// Forwards all errors directly to the user, never retries +#[derive(Debug)] +pub struct FallthroughRetryPolicy; +pub struct FallthroughRetrySession; + +impl FallthroughRetryPolicy { + pub fn new() -> FallthroughRetryPolicy { + FallthroughRetryPolicy + } +} + +impl Default for FallthroughRetryPolicy { + fn default() -> FallthroughRetryPolicy { + FallthroughRetryPolicy + } +} + +impl RetryPolicy for FallthroughRetryPolicy { + fn new_session(&self) -> Box { + Box::new(FallthroughRetrySession) + } +} + +impl RetrySession for FallthroughRetrySession { + fn decide_should_retry(&mut self, _query_info: QueryInfo) -> RetryDecision { + RetryDecision::DontRetry + } + + fn reset(&mut self) {} +} diff --git a/scylla/src/execution/retries/mod.rs b/scylla/src/execution/retries/mod.rs new file mode 100644 index 0000000000..d4a95a5645 --- /dev/null +++ b/scylla/src/execution/retries/mod.rs @@ -0,0 +1,11 @@ +mod default_rp; +mod downgrading_consistency_rp; +mod fallthrough_rp; +mod retry_policy; + +pub use default_rp::{DefaultRetryPolicy, DefaultRetrySession}; +pub use downgrading_consistency_rp::{ + DowngradingConsistencyRetryPolicy, DowngradingConsistencyRetrySession, +}; +pub use fallthrough_rp::{FallthroughRetryPolicy, FallthroughRetrySession}; +pub use retry_policy::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}; diff --git a/scylla/src/execution/retries/retry_policy.rs b/scylla/src/execution/retries/retry_policy.rs new file mode 100644 index 0000000000..1ca0906b0a --- /dev/null +++ b/scylla/src/execution/retries/retry_policy.rs @@ -0,0 +1,42 @@ +//! Query retries configurations\ +//! To decide when to retry a query the `Session` can use any object which implements +//! the `RetryPolicy` trait + +use crate::execution::errors::QueryError; +use crate::frame::types::Consistency; + +/// Information about a failed query +pub struct QueryInfo<'a> { + /// The error with which the query failed + pub error: &'a QueryError, + /// A query is idempotent if it can be applied multiple times without changing the result of the initial application\ + /// If set to `true` we can be sure that it is idempotent\ + /// If set to `false` it is unknown whether it is idempotent + pub is_idempotent: bool, + /// Consistency with which the query failed + pub consistency: Consistency, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum RetryDecision { + RetrySameNode(Option), // None means that the same consistency should be used as before + RetryNextNode(Option), // ditto + DontRetry, + IgnoreWriteError, +} + +/// Specifies a policy used to decide when to retry a query +pub trait RetryPolicy: std::fmt::Debug + Send + Sync { + /// Called for each new query, starts a session of deciding about retries + fn new_session(&self) -> Box; +} + +/// Used throughout a single query to decide when to retry it +/// After this query is finished it is destroyed or reset +pub trait RetrySession: Send + Sync { + /// Called after the query failed - decide what to do next + fn decide_should_retry(&mut self, query_info: QueryInfo) -> RetryDecision; + + /// Reset before using for a new query + fn reset(&mut self); +} diff --git a/scylla/src/transport/speculative_execution.rs b/scylla/src/execution/speculative_execution.rs similarity index 99% rename from scylla/src/transport/speculative_execution.rs rename to scylla/src/execution/speculative_execution.rs index 756ed3d895..3b38612405 100644 --- a/scylla/src/transport/speculative_execution.rs +++ b/scylla/src/execution/speculative_execution.rs @@ -6,9 +6,8 @@ use scylla_cql::frame::response::error::DbError; use std::{future::Future, sync::Arc, time::Duration}; use tracing::{trace_span, warn, Instrument}; -use crate::transport::errors::QueryError; - -use super::metrics::Metrics; +use crate::execution::errors::QueryError; +use crate::execution::metrics::Metrics; /// Context is passed as an argument to `SpeculativeExecutionPolicy` methods pub struct Context { diff --git a/scylla/src/tracing.rs b/scylla/src/execution/tracing.rs similarity index 100% rename from scylla/src/tracing.rs rename to scylla/src/execution/tracing.rs diff --git a/scylla/src/lib.rs b/scylla/src/lib.rs index 8dc56420a9..9143c9e753 100644 --- a/scylla/src/lib.rs +++ b/scylla/src/lib.rs @@ -255,11 +255,13 @@ pub mod authentication; #[cfg(feature = "cloud")] pub mod cloud; -pub mod history; +pub mod cluster; +pub mod connection; +pub mod execution; +pub mod response; pub mod routing; +pub mod session; pub mod statement; -pub mod tracing; -pub mod transport; pub(crate) mod utils; @@ -273,23 +275,22 @@ pub use statement::query; #[allow(deprecated)] pub use frame::response::cql_to_rust::{self, FromRow}; +pub use execution::execution_profile::ExecutionProfile; #[allow(deprecated)] -pub use transport::caching_session::{CachingSession, GenericCachingSession, LegacyCachingSession}; -pub use transport::execution_profile::ExecutionProfile; +pub use response::legacy_query_result::LegacyQueryResult; +pub use response::query_result::{QueryResult, QueryRowsResult}; #[allow(deprecated)] -pub use transport::legacy_query_result::LegacyQueryResult; -pub use transport::query_result::{QueryResult, QueryRowsResult}; -#[allow(deprecated)] -pub use transport::session::{IntoTypedRows, LegacySession, Session, SessionConfig}; -pub use transport::session_builder::SessionBuilder; +pub use session::{ + CachingSession, GenericCachingSession, IntoTypedRows, LegacyCachingSession, LegacySession, + Session, SessionBuilder, SessionConfig, +}; #[cfg(feature = "cloud")] -pub use transport::session_builder::CloudSessionBuilder; +pub use session::CloudSessionBuilder; -pub use transport::execution_profile; -pub use transport::host_filter; -pub use transport::load_balancing; -pub use transport::retry_policy; -pub use transport::speculative_execution; +pub use cluster::host_filter; +pub use execution::execution_profile; +pub use execution::load_balancing; +pub use execution::speculative_execution; -pub use transport::metrics::{Metrics, MetricsError}; +pub use execution::metrics::{Metrics, MetricsError}; diff --git a/scylla/src/transport/legacy_query_result.rs b/scylla/src/response/legacy_query_result.rs similarity index 99% rename from scylla/src/transport/legacy_query_result.rs rename to scylla/src/response/legacy_query_result.rs index 91fe47a58b..ce76e29479 100644 --- a/scylla/src/transport/legacy_query_result.rs +++ b/scylla/src/response/legacy_query_result.rs @@ -192,7 +192,7 @@ impl LegacyQueryResult { } } -/// An error that occurred during [`QueryResult`](crate::transport::query_result::QueryResult) +/// An error that occurred during [`QueryResult`](crate::response::query_result::QueryResult) /// to [`LegacyQueryResult`] conversion. #[deprecated( since = "0.15.1", diff --git a/scylla/src/response/mod.rs b/scylla/src/response/mod.rs new file mode 100644 index 0000000000..4800bb37fc --- /dev/null +++ b/scylla/src/response/mod.rs @@ -0,0 +1,16 @@ +//! This module holds entities that represent responses to requests +//! sent to the cluster by the driver. +//! The following abstractions are involved: +//! - QueryResponse - a response to any kind of a CQL request. +//! - QueryResult - a result of a CQL QUERY/EXECUTE/BATCH request. +//! - QueryRowsResult - a result of CQL QUERY/EXECUTE/BATCH request that contains +//! some rows, which can be deserialized by the user. + +pub mod legacy_query_result; +pub mod query_result; +mod request_response; + +pub(crate) use request_response::{ + NonErrorAuthResponse, NonErrorQueryResponse, NonErrorStartupResponse, QueryResponse, +}; +pub use scylla_cql::frame::request::query::{PagingState, PagingStateResponse}; diff --git a/scylla/src/transport/query_result.rs b/scylla/src/response/query_result.rs similarity index 99% rename from scylla/src/transport/query_result.rs rename to scylla/src/response/query_result.rs index b76ec28e5a..f9d8e8bfd6 100644 --- a/scylla/src/transport/query_result.rs +++ b/scylla/src/response/query_result.rs @@ -207,7 +207,7 @@ impl QueryResult { /// Returns an error if the response is not of Rows kind or metadata deserialization failed. /// /// ```rust - /// # use scylla::transport::query_result::{QueryResult, QueryRowsResult}; + /// # use scylla::response::query_result::{QueryResult, QueryRowsResult}; /// # fn example(query_result: QueryResult) -> Result<(), Box> { /// let rows_result = query_result.into_rows_result()?; /// @@ -225,7 +225,7 @@ impl QueryResult { /// returned back to the user in the error type. See [`IntoRowsResultError`] documentation. /// /// ```rust - /// # use scylla::transport::query_result::{QueryResult, QueryRowsResult, IntoRowsResultError}; + /// # use scylla::response::query_result::{QueryResult, QueryRowsResult, IntoRowsResultError}; /// # fn example(non_rows_query_result: QueryResult) -> Result<(), Box> { /// let err = non_rows_query_result.into_rows_result().unwrap_err(); /// @@ -308,7 +308,7 @@ impl QueryResult { /// additionally asserting that it's the only one in the response. /// /// ```rust -/// # use scylla::transport::query_result::QueryResult; +/// # use scylla::response::query_result::QueryResult; /// # fn example(query_result: QueryResult) -> Result<(), Box> { /// let rows_result = query_result.into_rows_result()?; /// diff --git a/scylla/src/response/request_response.rs b/scylla/src/response/request_response.rs new file mode 100644 index 0000000000..f13f52c60f --- /dev/null +++ b/scylla/src/response/request_response.rs @@ -0,0 +1,110 @@ +use std::collections::HashMap; + +use bytes::Bytes; +use scylla_cql::frame::request::query::PagingStateResponse; +use scylla_cql::frame::response::{NonErrorResponse, Response}; +use tracing::error; +use uuid::Uuid; + +use crate::execution::errors::{ProtocolError, QueryError, UserRequestError}; +use crate::frame::response::{self, result}; +use crate::QueryResult; + +pub(crate) struct QueryResponse { + pub(crate) response: Response, + pub(crate) tracing_id: Option, + pub(crate) warnings: Vec, + #[allow(dead_code)] // This is not exposed to user (yet?) + pub(crate) custom_payload: Option>, +} + +// A QueryResponse in which response can not be Response::Error +pub(crate) struct NonErrorQueryResponse { + pub(crate) response: NonErrorResponse, + pub(crate) tracing_id: Option, + pub(crate) warnings: Vec, +} + +impl QueryResponse { + pub(crate) fn into_non_error_query_response( + self, + ) -> Result { + Ok(NonErrorQueryResponse { + response: self.response.into_non_error_response()?, + tracing_id: self.tracing_id, + warnings: self.warnings, + }) + } + + pub(crate) fn into_query_result_and_paging_state( + self, + ) -> Result<(QueryResult, PagingStateResponse), UserRequestError> { + self.into_non_error_query_response()? + .into_query_result_and_paging_state() + } + + pub(crate) fn into_query_result(self) -> Result { + self.into_non_error_query_response()?.into_query_result() + } +} + +impl NonErrorQueryResponse { + pub(crate) fn as_set_keyspace(&self) -> Option<&result::SetKeyspace> { + match &self.response { + NonErrorResponse::Result(result::Result::SetKeyspace(sk)) => Some(sk), + _ => None, + } + } + + pub(crate) fn as_schema_change(&self) -> Option<&result::SchemaChange> { + match &self.response { + NonErrorResponse::Result(result::Result::SchemaChange(sc)) => Some(sc), + _ => None, + } + } + + pub(crate) fn into_query_result_and_paging_state( + self, + ) -> Result<(QueryResult, PagingStateResponse), UserRequestError> { + let (raw_rows, paging_state_response) = match self.response { + NonErrorResponse::Result(result::Result::Rows((rs, paging_state_response))) => { + (Some(rs), paging_state_response) + } + NonErrorResponse::Result(_) => (None, PagingStateResponse::NoMorePages), + _ => { + return Err(UserRequestError::UnexpectedResponse( + self.response.to_response_kind(), + )) + } + }; + + Ok(( + QueryResult::new(raw_rows, self.tracing_id, self.warnings), + paging_state_response, + )) + } + + pub(crate) fn into_query_result(self) -> Result { + let (result, paging_state) = self.into_query_result_and_paging_state()?; + + if !paging_state.finished() { + error!( + "Internal driver API misuse or a server bug: nonfinished paging state\ + would be discarded by `NonErrorQueryResponse::into_query_result`" + ); + return Err(ProtocolError::NonfinishedPagingState.into()); + } + + Ok(result) + } +} + +pub(crate) enum NonErrorStartupResponse { + Ready, + Authenticate(response::authenticate::Authenticate), +} + +pub(crate) enum NonErrorAuthResponse { + AuthChallenge(response::authenticate::AuthChallenge), + AuthSuccess(response::authenticate::AuthSuccess), +} diff --git a/scylla/src/transport/locator/mod.rs b/scylla/src/routing/locator/mod.rs similarity index 99% rename from scylla/src/transport/locator/mod.rs rename to scylla/src/routing/locator/mod.rs index 6770b7b5b8..f33b99fa3a 100644 --- a/scylla/src/transport/locator/mod.rs +++ b/scylla/src/routing/locator/mod.rs @@ -12,7 +12,8 @@ pub use token_ring::TokenRing; use self::tablets::TabletsInfo; -use super::{topology::Strategy, Node, NodeRef}; +use crate::cluster::metadata::Strategy; +use crate::cluster::{Node, NodeRef}; use crate::routing::{Shard, Token}; use itertools::Itertools; use precomputed_replicas::PrecomputedReplicas; @@ -829,7 +830,7 @@ impl<'a> IntoIterator for ReplicasOrdered<'a> { #[cfg(test)] mod tests { - use crate::{routing::Token, test_utils::setup_tracing, transport::locator::test::*}; + use crate::{routing::locator::test::*, routing::Token, test_utils::setup_tracing}; #[tokio::test] async fn test_replicas_ordered() { diff --git a/scylla/src/transport/locator/precomputed_replicas.rs b/scylla/src/routing/locator/precomputed_replicas.rs similarity index 98% rename from scylla/src/transport/locator/precomputed_replicas.rs rename to scylla/src/routing/locator/precomputed_replicas.rs index 69851df507..4121b410ed 100644 --- a/scylla/src/transport/locator/precomputed_replicas.rs +++ b/scylla/src/routing/locator/precomputed_replicas.rs @@ -14,9 +14,9 @@ use super::replication_info::ReplicationInfo; use super::TokenRing; +use crate::cluster::metadata::Strategy; +use crate::cluster::node::Node; use crate::routing::Token; -use crate::transport::node::Node; -use crate::transport::topology::Strategy; use std::cmp; use std::collections::BTreeSet; @@ -215,12 +215,12 @@ mod tests { use std::collections::HashMap; use crate::{ + cluster::metadata::{Keyspace, Strategy}, + routing::locator::test::{ + create_ring, mock_metadata_for_token_aware_tests, A, C, D, E, F, G, + }, routing::Token, test_utils::setup_tracing, - transport::{ - locator::test::{create_ring, mock_metadata_for_token_aware_tests, A, C, D, E, F, G}, - topology::{Keyspace, Strategy}, - }, }; use super::{PrecomputedReplicas, ReplicationInfo}; diff --git a/scylla/src/transport/locator/replicas.rs b/scylla/src/routing/locator/replicas.rs similarity index 97% rename from scylla/src/transport/locator/replicas.rs rename to scylla/src/routing/locator/replicas.rs index 131402d113..a07e8104b2 100644 --- a/scylla/src/transport/locator/replicas.rs +++ b/scylla/src/routing/locator/replicas.rs @@ -1,6 +1,6 @@ use itertools::Either; -use crate::transport::{Node, NodeRef}; +use crate::cluster::{Node, NodeRef}; use std::{ops::Index, sync::Arc}; /// Container holding replicas, enabling unified use of both borrowed and owned `Node` sequences. diff --git a/scylla/src/transport/locator/replication_info.rs b/scylla/src/routing/locator/replication_info.rs similarity index 99% rename from scylla/src/transport/locator/replication_info.rs rename to scylla/src/routing/locator/replication_info.rs index 76747abf2c..16318dfd6d 100644 --- a/scylla/src/transport/locator/replication_info.rs +++ b/scylla/src/routing/locator/replication_info.rs @@ -1,8 +1,8 @@ use itertools::Itertools; use super::TokenRing; +use crate::cluster::node::Node; use crate::routing::Token; -use crate::transport::node::Node; use std::cmp; use std::collections::{BTreeSet, HashMap}; @@ -204,11 +204,11 @@ where #[cfg(test)] mod tests { use crate::{ - routing::Token, - test_utils::setup_tracing, - transport::locator::test::{ + routing::locator::test::{ create_ring, mock_metadata_for_token_aware_tests, A, B, C, D, E, F, G, }, + routing::Token, + test_utils::setup_tracing, }; use super::ReplicationInfo; diff --git a/scylla/src/transport/locator/tablets.rs b/scylla/src/routing/locator/tablets.rs similarity index 99% rename from scylla/src/transport/locator/tablets.rs rename to scylla/src/routing/locator/tablets.rs index 472351ac9c..25c67e661f 100644 --- a/scylla/src/transport/locator/tablets.rs +++ b/scylla/src/routing/locator/tablets.rs @@ -10,8 +10,8 @@ use thiserror::Error; use tracing::warn; use uuid::Uuid; +use crate::cluster::Node; use crate::routing::{Shard, Token}; -use crate::transport::Node; use std::collections::{HashMap, HashSet}; use std::ops::Deref; @@ -614,13 +614,13 @@ mod tests { use tracing::debug; use uuid::Uuid; - use crate::routing::Token; - use crate::test_utils::setup_tracing; - use crate::transport::locator::tablets::{ + use crate::cluster::Node; + use crate::routing::locator::tablets::{ RawTablet, RawTabletReplicas, TabletParsingError, CUSTOM_PAYLOAD_TABLETS_V1_KEY, RAW_TABLETS_CQL_TYPE, }; - use crate::transport::Node; + use crate::routing::Token; + use crate::test_utils::setup_tracing; use super::{TableTablets, Tablet, TabletReplicas, TabletsInfo}; diff --git a/scylla/src/transport/locator/test.rs b/scylla/src/routing/locator/test.rs similarity index 99% rename from scylla/src/transport/locator/test.rs rename to scylla/src/routing/locator/test.rs index 2622eb99a6..f4c7f58d64 100644 --- a/scylla/src/transport/locator/test.rs +++ b/scylla/src/routing/locator/test.rs @@ -5,14 +5,12 @@ use uuid::Uuid; use super::tablets::TabletsInfo; use super::{ReplicaLocator, ReplicaSet}; +use crate::cluster::metadata::{Keyspace, Metadata, Peer, Strategy}; +use crate::cluster::Node; +use crate::cluster::{NodeAddr, NodeRef}; +use crate::connection::PoolConfig; use crate::routing::Token; use crate::test_utils::setup_tracing; -use crate::transport::{ - connection_pool::PoolConfig, - topology::{Keyspace, Metadata, Peer, Strategy}, - Node, -}; -use crate::transport::{NodeAddr, NodeRef}; use std::collections::HashSet; use std::sync::Arc; diff --git a/scylla/src/transport/locator/token_ring.rs b/scylla/src/routing/locator/token_ring.rs similarity index 100% rename from scylla/src/transport/locator/token_ring.rs rename to scylla/src/routing/locator/token_ring.rs diff --git a/scylla/src/routing/mod.rs b/scylla/src/routing/mod.rs new file mode 100644 index 0000000000..0d56256118 --- /dev/null +++ b/scylla/src/routing/mod.rs @@ -0,0 +1,56 @@ +//! This module holds entities whose goal is to enable routing requests optimally, +//! that is, choosing a target node and a shard such that it is a replica for +//! given token. +//! +//! This includes: +//! - token representation, +//! - shard representation and shard computing logic, +//! - partitioners, which compute token based on a partition key, +//! - replica locator, which finds replicas (node + shard) for a given token. +//! + +pub mod locator; +pub mod partitioner; +mod sharding; + +pub(crate) use sharding::ShardInfo; +pub use sharding::{Shard, ShardCount, Sharder, ShardingError}; + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] + +/// Token is a result of computing a hash of a primary key +/// +/// It is basically an i64 with one caveat: i64::MIN is not +/// a valid token. It is used to represent infinity. +/// For this reason tokens are normalized - i64::MIN +/// is replaced with i64::MAX. See this fragment of +/// Scylla code for more information: +/// +/// +/// This struct is a wrapper over i64 that performs this normalization +/// when initialized using `new()` method. +pub struct Token { + value: i64, +} + +impl Token { + /// Creates a new token with given value, normalizing the value if necessary + #[inline] + pub fn new(value: i64) -> Self { + Self { + value: if value == i64::MIN { i64::MAX } else { value }, + } + } + + /// Invalid Token - contains i64::MIN as value. + /// + /// This is (currently) only required by CDCPartitioner. + /// See the following comment: + /// https://github.com/scylladb/scylla-rust-driver/blob/049dc3546d24e45106fed0fdb985ec2511ab5192/scylla/src/transport/partitioner.rs#L312-L322 + pub(crate) const INVALID: Self = Token { value: i64::MIN }; + + #[inline] + pub fn value(&self) -> i64 { + self.value + } +} diff --git a/scylla/src/transport/partitioner.rs b/scylla/src/routing/partitioner.rs similarity index 95% rename from scylla/src/transport/partitioner.rs rename to scylla/src/routing/partitioner.rs index ee36543b61..f73fb63987 100644 --- a/scylla/src/transport/partitioner.rs +++ b/scylla/src/routing/partitioner.rs @@ -1,3 +1,13 @@ +//! Partitioners are algorithms that can compute token for a given partition key, +//! ultimately allowing optimised routing of requests (such that a request is routed +//! to replicas, which are nodes and shards that really own the data the request concerns). +//! Currently, two partitioners are supported: +//! - Murmur3Partitioner +//! - the default partitioner, +//! - modified for compatibility with Cassandra's buggy implementation. +//! - CDCPartitioner +//! - the partitioner employed when using CDC (_Change Data Capture_). + use bytes::Buf; use scylla_cql::{frame::types::RawValue, types::serialize::row::SerializedValues}; use std::num::Wrapping; @@ -369,9 +379,9 @@ mod tests { use rand::Rng; use rand_pcg::Pcg32; - use crate::{test_utils::setup_tracing, transport::partitioner::PartitionerHasher}; + use crate::test_utils::setup_tracing; - use super::{CDCPartitioner, Murmur3Partitioner, Partitioner}; + use super::{CDCPartitioner, Murmur3Partitioner, Partitioner, PartitionerHasher}; fn assert_correct_murmur3_hash(pk: &'static str, expected_hash: i64) { let hash = Murmur3Partitioner.hash_one(pk.as_bytes()).value(); diff --git a/scylla/src/routing.rs b/scylla/src/routing/sharding.rs similarity index 83% rename from scylla/src/routing.rs rename to scylla/src/routing/sharding.rs index a5788c0b10..4c3dec691d 100644 --- a/scylla/src/routing.rs +++ b/scylla/src/routing/sharding.rs @@ -1,47 +1,10 @@ -use rand::Rng; use std::collections::HashMap; -use std::convert::TryFrom; use std::num::NonZeroU16; -use thiserror::Error; - -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] - -/// Token is a result of computing a hash of a primary key -/// -/// It is basically an i64 with one caveat: i64::MIN is not -/// a valid token. It is used to represent infinity. -/// For this reason tokens are normalized - i64::MIN -/// is replaced with i64::MAX. See this fragment of -/// Scylla code for more information: -/// -/// -/// This struct is a wrapper over i64 that performs this normalization -/// when initialized using `new()` method. -pub struct Token { - value: i64, -} -impl Token { - /// Creates a new token with given value, normalizing the value if necessary - #[inline] - pub fn new(value: i64) -> Self { - Self { - value: if value == i64::MIN { i64::MAX } else { value }, - } - } - - /// Invalid Token - contains i64::MIN as value. - /// - /// This is (currently) only required by CDCPartitioner. - /// See the following comment: - /// https://github.com/scylladb/scylla-rust-driver/blob/049dc3546d24e45106fed0fdb985ec2511ab5192/scylla/src/transport/partitioner.rs#L312-L322 - pub(crate) const INVALID: Self = Token { value: i64::MIN }; +use rand::Rng as _; +use thiserror::Error; - #[inline] - pub fn value(&self) -> i64 { - self.value - } -} +use super::Token; pub type Shard = u32; pub type ShardCount = NonZeroU16; diff --git a/scylla/src/transport/caching_session.rs b/scylla/src/session/caching_session.rs similarity index 94% rename from scylla/src/transport/caching_session.rs rename to scylla/src/session/caching_session.rs index a5b6416833..bd06902052 100644 --- a/scylla/src/transport/caching_session.rs +++ b/scylla/src/session/caching_session.rs @@ -1,11 +1,11 @@ use crate::batch::{Batch, BatchStatement}; +use crate::execution::errors::QueryError; +#[allow(deprecated)] +use crate::execution::pager::LegacyRowIterator; use crate::prepared_statement::PreparedStatement; use crate::query::Query; +use crate::routing::partitioner::PartitionerName; use crate::statement::{PagingState, PagingStateResponse}; -use crate::transport::errors::QueryError; -#[allow(deprecated)] -use crate::transport::iterator::LegacyRowIterator; -use crate::transport::partitioner::PartitionerName; #[allow(deprecated)] use crate::LegacyQueryResult; use crate::QueryResult; @@ -20,9 +20,9 @@ use std::fmt; use std::hash::BuildHasher; use std::sync::Arc; -use super::iterator::QueryPager; +use crate::execution::pager::QueryPager; #[allow(deprecated)] -use super::session::{ +use crate::session::{ CurrentDeserializationApi, DeserializationApiKind, GenericSession, LegacyDeserializationApi, }; @@ -122,6 +122,22 @@ where self.session.execute_unpaged(&prepared, values).await } + /// Does the same thing as + /// [`Session::execute_unpaged_with_timestamp`](GenericSession::execute_unpaged_with_timestamp) + /// but uses the prepared statement cache. + pub async fn execute_unpaged_with_timestamp( + &self, + query: impl Into, + values: impl SerializeRow, + timestamp: i64, + ) -> Result { + let query = query.into(); + let prepared = self.add_prepared_statement_owned(query).await?; + self.session + .execute_unpaged_with_timestamp(&prepared, values, timestamp) + .await + } + /// Does the same thing as [`Session::execute_iter`](GenericSession::execute_iter) /// but uses the prepared statement cache. pub async fn execute_iter( @@ -149,6 +165,23 @@ where .await } + /// Does the same thing as + /// [`Session::execute_single_page_with_timestamp`](GenericSession::execute_single_page_with_timestamp) + /// but uses the prepared statement cache. + pub async fn execute_single_page_with_timestamp( + &self, + query: impl Into, + values: impl SerializeRow, + paging_state: PagingState, + timestamp: i64, + ) -> Result<(QueryResult, PagingStateResponse), QueryError> { + let query = query.into(); + let prepared = self.add_prepared_statement_owned(query).await?; + self.session + .execute_single_page_with_timestamp(&prepared, values, paging_state, timestamp) + .await + } + /// Does the same thing as [`Session::batch`](GenericSession::batch) but uses the /// prepared statement cache.\ /// Prepares batch using [`CachingSession::prepare_batch`](GenericCachingSession::prepare_batch) @@ -342,12 +375,12 @@ where #[cfg(test)] mod tests { use crate::query::Query; + use crate::routing::partitioner::PartitionerName; + use crate::session::Session; use crate::statement::PagingState; use crate::test_utils::{ create_new_session_builder, scylla_supports_tablets, setup_tracing, PerformDDL, }; - use crate::transport::partitioner::PartitionerName; - use crate::transport::session::Session; use crate::utils::test_utils::unique_keyspace_name; #[allow(deprecated)] use crate::LegacyCachingSession; @@ -708,22 +741,16 @@ mod tests { let q = Query::new("INSERT INTO tbl (a, b) VALUES (?, ?)"); // Insert one row with timestamp 1000 - let mut q1 = q.clone(); - q1.set_timestamp(Some(1000)); - session - .execute_unpaged(q1, (1, 1)) + .execute_unpaged_with_timestamp(q.clone(), (1, 1), 1000) .await .unwrap() .result_not_rows() .unwrap(); // Insert another row with timestamp 2000 - let mut q2 = q.clone(); - q2.set_timestamp(Some(2000)); - session - .execute_unpaged(q2, (2, 2)) + .execute_unpaged_with_timestamp(q, (2, 2), 2000) .await .unwrap() .result_not_rows() diff --git a/scylla/src/session/mod.rs b/scylla/src/session/mod.rs new file mode 100644 index 0000000000..c3f4785698 --- /dev/null +++ b/scylla/src/session/mod.rs @@ -0,0 +1,24 @@ +//! This module holds entities that represent the whole configurable +//! driver session with the cluster. +//! The following abstractions are involved: +//! - Session - the main entity of the driver. It: +//! - contains and manages all driver configuration, +//! - launches and communicates with ClusterWorker (see cluster module for more info), +//! - enables executing CQL requests, taking all configuration into consideration. +//! - SessionBuilder - just a convenient builder for a Session. +//! - CachingSession - a wrapper over a Session that keeps and manages a cache +//! of prepared statements, so that a user can be free of such considerations. + +mod caching_session; +#[allow(clippy::module_inception)] +mod session; +pub mod session_builder; +#[cfg(test)] +mod session_test; + +#[allow(deprecated)] +pub use caching_session::{CachingSession, GenericCachingSession, LegacyCachingSession}; +pub use session::*; +#[cfg(feature = "cloud")] +pub use session_builder::CloudSessionBuilder; +pub use session_builder::SessionBuilder; diff --git a/scylla/src/transport/session.rs b/scylla/src/session/session.rs similarity index 89% rename from scylla/src/transport/session.rs rename to scylla/src/session/session.rs index 9cae1d6ad1..499dde6a44 100644 --- a/scylla/src/transport/session.rs +++ b/scylla/src/session/session.rs @@ -4,87 +4,77 @@ use crate::batch::batch_values; #[cfg(feature = "cloud")] use crate::cloud::CloudConfig; +use crate::execution::driver_tracing::RequestSpan; +use crate::response::{NonErrorQueryResponse, QueryResponse}; #[allow(deprecated)] use crate::LegacyQueryResult; -use crate::history; -use crate::history::HistoryListener; -pub use crate::transport::errors::TranslationError; -use crate::transport::errors::{ +use crate::execution::errors::{ BadQuery, NewSessionError, ProtocolError, QueryError, UserRequestError, }; -use crate::utils::pretty::{CommaSeparatedDisplayer, CqlValueDisplayer}; +use crate::execution::history::{self, HistoryListener}; use arc_swap::ArcSwapOption; -use async_trait::async_trait; use futures::future::join_all; use futures::future::try_join_all; -use itertools::{Either, Itertools}; -use scylla_cql::frame::response::result::RawMetadataAndRawRows; -use scylla_cql::frame::response::result::{deser_cql_value, ColumnSpec}; +use itertools::Itertools; use scylla_cql::frame::response::NonErrorResponse; use scylla_cql::types::serialize::batch::BatchValues; use scylla_cql::types::serialize::row::{SerializeRow, SerializedValues}; use std::borrow::Borrow; -use std::collections::HashMap; -use std::fmt::Display; use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::num::NonZeroU32; -use std::str::FromStr; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; + use std::sync::Arc; use std::time::Duration; use tokio::time::timeout; use tracing::{debug, error, trace, trace_span, Instrument}; use uuid::Uuid; -use super::connection::NonErrorQueryResponse; -use super::connection::QueryResponse; -#[cfg(feature = "ssl")] -use super::connection::SslConfig; -use super::errors::TracingProtocolError; -use super::execution_profile::{ExecutionProfile, ExecutionProfileHandle, ExecutionProfileInner}; -use super::iterator::QueryPager; +use crate::cluster::host_filter::HostFilter; #[cfg(feature = "cloud")] -use super::node::CloudEndpoint; -use super::node::{InternalKnownNode, KnownNode}; -use super::partitioner::PartitionerName; -use super::query_result::MaybeFirstRowError; -use super::query_result::RowsError; -use super::topology::UntranslatedPeer; -use super::{NodeRef, SelfIdentity}; +use crate::cluster::node::CloudEndpoint; +use crate::cluster::node::{InternalKnownNode, KnownNode}; +use crate::cluster::NodeRef; +use crate::cluster::{Cluster, ClusterData, ClusterNeatDebug}; +#[cfg(feature = "ssl")] +use crate::connection::SslConfig; +use crate::connection::{ + AddressTranslator, Compression, Connection, ConnectionConfig, PoolConfig, PoolSize, + SelfIdentity, VerifiedKeyspaceName, +}; +use crate::execution::errors::TracingProtocolError; +use crate::execution::execution_profile::{ + ExecutionProfile, ExecutionProfileHandle, ExecutionProfileInner, +}; +use crate::execution::load_balancing::{self, RoutingInfo}; +use crate::execution::metrics::Metrics; +use crate::execution::pager::QueryPager; +#[allow(deprecated)] +use crate::execution::pager::{LegacyRowIterator, PreparedIteratorConfig}; +use crate::execution::retries::{QueryInfo, RetryDecision, RetrySession}; +use crate::execution::speculative_execution; +use crate::execution::tracing::TracingInfo; use crate::frame::response::result; use crate::prepared_statement::PreparedStatement; use crate::query::Query; -use crate::routing::{Shard, Token}; +use crate::response::query_result::MaybeFirstRowError; +use crate::response::query_result::QueryResult; +use crate::response::query_result::RowsError; +use crate::routing::partitioner::PartitionerName; +use crate::routing::Shard; use crate::statement::{Consistency, PageSize, PagingState, PagingStateResponse}; -use crate::tracing::TracingInfo; -use crate::transport::cluster::{Cluster, ClusterData, ClusterNeatDebug}; -use crate::transport::connection::{Connection, ConnectionConfig, VerifiedKeyspaceName}; -use crate::transport::connection_pool::PoolConfig; -use crate::transport::host_filter::HostFilter; #[allow(deprecated)] -use crate::transport::iterator::{LegacyRowIterator, PreparedIteratorConfig}; -use crate::transport::load_balancing::{self, RoutingInfo}; -use crate::transport::metrics::Metrics; -use crate::transport::node::Node; -use crate::transport::query_result::QueryResult; -use crate::transport::retry_policy::{QueryInfo, RetryDecision, RetrySession}; -use crate::transport::speculative_execution; -use crate::transport::Compression; use crate::{ batch::{Batch, BatchStatement}, statement::StatementConfig, }; -pub use crate::transport::connection_pool::PoolSize; - // This re-export is to preserve backward compatibility. // Those items are no longer here not to clutter session.rs with legacy things. #[allow(deprecated)] -pub use crate::transport::legacy_query_result::{IntoTypedRows, TypedRowIter}; +pub use crate::response::legacy_query_result::{IntoTypedRows, TypedRowIter}; use crate::authentication::AuthenticatorProvider; #[cfg(feature = "ssl")] @@ -102,71 +92,6 @@ pub(crate) const TABLET_CHANNEL_SIZE: usize = 8192; const TRACING_QUERY_PAGE_SIZE: i32 = 1024; -/// Translates IP addresses received from ScyllaDB nodes into locally reachable addresses. -/// -/// The driver auto-detects new ScyllaDB nodes added to the cluster through server side pushed -/// notifications and through checking the system tables. For each node, the address the driver -/// receives corresponds to the address set as `rpc_address` in the node yaml file. In most -/// cases, this is the correct address to use by the driver and that is what is used by default. -/// However, sometimes the addresses received through this mechanism will either not be reachable -/// directly by the driver or should not be the preferred address to use to reach the node (for -/// instance, the `rpc_address` set on ScyllaDB nodes might be a private IP, but some clients -/// may have to use a public IP, or pass by a router, e.g. through NAT, to reach that node). -/// This interface allows to deal with such cases, by allowing to translate an address as sent -/// by a ScyllaDB node to another address to be used by the driver for connection. -/// -/// Please note that the "known nodes" addresses provided while creating the [`Session`] -/// instance are not translated, only IP address retrieved from or sent by Cassandra nodes -/// to the driver are. -#[async_trait] -pub trait AddressTranslator: Send + Sync { - async fn translate_address( - &self, - untranslated_peer: &UntranslatedPeer, - ) -> Result; -} - -#[async_trait] -impl AddressTranslator for HashMap { - async fn translate_address( - &self, - untranslated_peer: &UntranslatedPeer, - ) -> Result { - match self.get(&untranslated_peer.untranslated_address) { - Some(&translated_addr) => Ok(translated_addr), - None => Err(TranslationError::NoRuleForAddress( - untranslated_peer.untranslated_address, - )), - } - } -} - -#[async_trait] -// Notice: this is inefficient, but what else can we do with such poor representation as str? -// After all, the cluster size is small enough to make this irrelevant. -impl AddressTranslator for HashMap<&'static str, &'static str> { - async fn translate_address( - &self, - untranslated_peer: &UntranslatedPeer, - ) -> Result { - for (&rule_addr_str, &translated_addr_str) in self.iter() { - if let Ok(rule_addr) = SocketAddr::from_str(rule_addr_str) { - if rule_addr == untranslated_peer.untranslated_address { - return SocketAddr::from_str(translated_addr_str).map_err(|reason| { - TranslationError::InvalidAddressInRule { - translated_addr_str, - reason, - } - }); - } - } - } - Err(TranslationError::NoRuleForAddress( - untranslated_peer.untranslated_address, - )) - } -} - pub trait DeserializationApiKind: sealed::Sealed {} pub enum CurrentDeserializationApi {} @@ -540,7 +465,19 @@ impl GenericSession { query: impl Into, values: impl SerializeRow, ) -> Result { - self.do_query_unpaged(&query.into(), values).await + self.do_query_unpaged(&query.into(), values, None).await + } + + /// Same as [`Session::query_unpaged`](GenericSession::query_unpaged), + /// but with a custom timestamp set. + pub async fn query_unpaged_with_timestamp( + &self, + query: impl Into, + values: impl SerializeRow, + timestamp: i64, + ) -> Result { + self.do_query_unpaged(&query.into(), values, Some(timestamp)) + .await } /// Queries a single page from the database, optionally continuing from a saved point. @@ -600,7 +537,20 @@ impl GenericSession { values: impl SerializeRow, paging_state: PagingState, ) -> Result<(QueryResult, PagingStateResponse), QueryError> { - self.do_query_single_page(&query.into(), values, paging_state) + self.do_query_single_page(&query.into(), values, paging_state, None) + .await + } + + /// Same as [`Session::query_single_page`](GenericSession::query_single_page), + /// but with a custom timestamp set. + pub async fn query_single_page_with_timestamp( + &self, + query: impl Into, + values: impl SerializeRow, + paging_state: PagingState, + timestamp: i64, + ) -> Result<(QueryResult, PagingStateResponse), QueryError> { + self.do_query_single_page(&query.into(), values, paging_state, Some(timestamp)) .await } @@ -697,7 +647,19 @@ impl GenericSession { prepared: &PreparedStatement, values: impl SerializeRow, ) -> Result { - self.do_execute_unpaged(prepared, values).await + self.do_execute_unpaged(prepared, values, None).await + } + + /// Same as [`Session::execute_unpaged`](GenericSession::execute_unpaged), + /// but with a custom timestamp set. + pub async fn execute_unpaged_with_timestamp( + &self, + prepared: &PreparedStatement, + values: impl SerializeRow, + timestamp: i64, + ) -> Result { + self.do_execute_unpaged(prepared, values, Some(timestamp)) + .await } /// Executes a prepared statement, restricting results to single page. @@ -762,7 +724,20 @@ impl GenericSession { values: impl SerializeRow, paging_state: PagingState, ) -> Result<(QueryResult, PagingStateResponse), QueryError> { - self.do_execute_single_page(prepared, values, paging_state) + self.do_execute_single_page(prepared, values, paging_state, None) + .await + } + + /// Same as [`Session::execute_single_page`](GenericSession::execute_single_page), + /// but with a custom timestamp set. + pub async fn execute_single_page_with_timestamp( + &self, + prepared: &PreparedStatement, + values: impl SerializeRow, + paging_state: PagingState, + timestamp: i64, + ) -> Result<(QueryResult, PagingStateResponse), QueryError> { + self.do_execute_single_page(prepared, values, paging_state, Some(timestamp)) .await } @@ -864,7 +839,18 @@ impl GenericSession { batch: &Batch, values: impl BatchValues, ) -> Result { - self.do_batch(batch, values).await + self.do_batch(batch, values, None).await + } + + /// Same as [`Session::batch`](GenericSession::batch), + /// but with a custom timestamp set. + pub async fn batch_with_timestamp( + &self, + batch: &Batch, + values: impl BatchValues, + timestamp: i64, + ) -> Result { + self.do_batch(batch, values, Some(timestamp)).await } /// Creates a new Session instance that shared resources with @@ -911,7 +897,7 @@ impl GenericSession { values: impl SerializeRow, ) -> Result { Ok(self - .do_query_unpaged(&query.into(), values) + .do_query_unpaged(&query.into(), values, None) .await? .into_legacy_result()?) } @@ -923,7 +909,7 @@ impl GenericSession { paging_state: PagingState, ) -> Result<(LegacyQueryResult, PagingStateResponse), QueryError> { let (result, paging_state_response) = self - .do_query_single_page(&query.into(), values, paging_state) + .do_query_single_page(&query.into(), values, paging_state, None) .await?; Ok((result.into_legacy_result()?, paging_state_response)) } @@ -944,7 +930,7 @@ impl GenericSession { values: impl SerializeRow, ) -> Result { Ok(self - .do_execute_unpaged(prepared, values) + .do_execute_unpaged(prepared, values, None) .await? .into_legacy_result()?) } @@ -956,7 +942,7 @@ impl GenericSession { paging_state: PagingState, ) -> Result<(LegacyQueryResult, PagingStateResponse), QueryError> { let (result, paging_state_response) = self - .do_execute_single_page(prepared, values, paging_state) + .do_execute_single_page(prepared, values, paging_state, None) .await?; Ok((result.into_legacy_result()?, paging_state_response)) } @@ -976,7 +962,10 @@ impl GenericSession { batch: &Batch, values: impl BatchValues, ) -> Result { - Ok(self.do_batch(batch, values).await?.into_legacy_result()?) + Ok(self + .do_batch(batch, values, None) + .await? + .into_legacy_result()?) } /// Creates a new Session instance that shares resources with @@ -1017,7 +1006,7 @@ where { /// Estabilishes a CQL session with the database /// - /// Usually it's easier to use [SessionBuilder](crate::transport::session_builder::SessionBuilder) + /// Usually it's easier to use [SessionBuilder](crate::session::session_builder::SessionBuilder) /// instead of calling `Session::connect` directly, because it's more convenient. /// # Arguments /// * `config` - Connection configuration - known nodes, Compression, etc. @@ -1028,7 +1017,7 @@ where /// # use std::error::Error; /// # async fn check_only_compiles() -> Result<(), Box> { /// use scylla::{Session, SessionConfig}; - /// use scylla::transport::KnownNode; + /// use scylla::cluster::KnownNode; /// /// let mut config = SessionConfig::new(); /// config.known_nodes.push(KnownNode::Hostname("127.0.0.1:9042".to_string())); @@ -1140,9 +1129,10 @@ where &self, query: &Query, values: impl SerializeRow, + timestamp: Option, ) -> Result { let (result, paging_state_response) = self - .query(query, values, None, PagingState::start()) + .query(query, values, None, PagingState::start(), timestamp) .await?; if !paging_state_response.finished() { error!("Unpaged unprepared query returned a non-empty paging state! This is a driver-side or server-side bug."); @@ -1156,12 +1146,14 @@ where query: &Query, values: impl SerializeRow, paging_state: PagingState, + timestamp: Option, ) -> Result<(QueryResult, PagingStateResponse), QueryError> { self.query( query, values, Some(query.get_validated_page_size()), paging_state, + timestamp, ) .await } @@ -1183,6 +1175,7 @@ where values: impl SerializeRow, page_size: Option, paging_state: PagingState, + timestamp: Option, ) -> Result<(QueryResult, PagingStateResponse), QueryError> { let execution_profile = query .get_execution_profile_handle() @@ -1229,6 +1222,7 @@ where serial_consistency, page_size, paging_state_ref.clone(), + timestamp, ) .await .and_then(QueryResponse::into_non_error_query_response) @@ -1245,6 +1239,7 @@ where serial_consistency, page_size, paging_state_ref.clone(), + timestamp, ) .await .and_then(QueryResponse::into_non_error_query_response) @@ -1441,10 +1436,17 @@ where &self, prepared: &PreparedStatement, values: impl SerializeRow, + timestamp: Option, ) -> Result { let serialized_values = prepared.serialize_values(&values)?; let (result, paging_state) = self - .execute(prepared, &serialized_values, None, PagingState::start()) + .execute( + prepared, + &serialized_values, + None, + PagingState::start(), + timestamp, + ) .await?; if !paging_state.finished() { error!("Unpaged prepared query returned a non-empty paging state! This is a driver-side or server-side bug."); @@ -1458,11 +1460,18 @@ where prepared: &PreparedStatement, values: impl SerializeRow, paging_state: PagingState, + timestamp: Option, ) -> Result<(QueryResult, PagingStateResponse), QueryError> { let serialized_values = prepared.serialize_values(&values)?; let page_size = prepared.get_validated_page_size(); - self.execute(prepared, &serialized_values, Some(page_size), paging_state) - .await + self.execute( + prepared, + &serialized_values, + Some(page_size), + paging_state, + timestamp, + ) + .await } /// Sends a prepared request to the database, optionally continuing from a saved point. @@ -1481,6 +1490,7 @@ where serialized_values: &SerializedValues, page_size: Option, paging_state: PagingState, + timestamp: Option, ) -> Result<(QueryResult, PagingStateResponse), QueryError> { let values_ref = &serialized_values; let paging_state_ref = &paging_state; @@ -1547,6 +1557,7 @@ where serial_consistency, page_size, paging_state_ref.clone(), + timestamp, ) .await .and_then(QueryResponse::into_non_error_query_response) @@ -1602,6 +1613,7 @@ where &self, batch: &Batch, values: impl BatchValues, + timestamp: Option, ) -> Result { // Shard-awareness behavior for batch will be to pick shard based on first batch statement's shard // If users batch statements by shard, they will be rewarded with full shard awareness @@ -1669,6 +1681,7 @@ where values_ref, consistency, serial_consistency, + timestamp, ) .await } @@ -1756,7 +1769,7 @@ where /// # Example /// ```rust /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// # let session = SessionBuilder::new().known_node("127.0.0.1:9042").build().await?; /// session @@ -1858,18 +1871,20 @@ where consistency: Option, ) -> Result, QueryError> { // Query system_traces.sessions for TracingInfo - let mut traces_session_query = Query::new(crate::tracing::TRACES_SESSION_QUERY_STR); + let mut traces_session_query = + Query::new(crate::execution::tracing::TRACES_SESSION_QUERY_STR); traces_session_query.config.consistency = consistency; traces_session_query.set_page_size(TRACING_QUERY_PAGE_SIZE); // Query system_traces.events for TracingEvents - let mut traces_events_query = Query::new(crate::tracing::TRACES_EVENTS_QUERY_STR); + let mut traces_events_query = + Query::new(crate::execution::tracing::TRACES_EVENTS_QUERY_STR); traces_events_query.config.consistency = consistency; traces_events_query.set_page_size(TRACING_QUERY_PAGE_SIZE); let (traces_session_res, traces_events_res) = tokio::try_join!( - self.do_query_unpaged(&traces_session_query, (tracing_id,)), - self.do_query_unpaged(&traces_events_query, (tracing_id,)) + self.do_query_unpaged(&traces_session_query, (tracing_id,), None), + self.do_query_unpaged(&traces_events_query, (tracing_id,), None) )?; // Get tracing info @@ -2322,168 +2337,3 @@ impl ExecuteRequestContext<'_> { .log_attempt_error(*attempt_id, error, retry_decision); } } - -pub(crate) struct RequestSpan { - span: tracing::Span, - speculative_executions: AtomicUsize, -} - -impl RequestSpan { - pub(crate) fn new_query(contents: &str) -> Self { - use tracing::field::Empty; - - let span = trace_span!( - "Request", - kind = "unprepared", - contents = contents, - // - request_size = Empty, - result_size = Empty, - result_rows = Empty, - replicas = Empty, - shard = Empty, - speculative_executions = Empty, - ); - - Self { - span, - speculative_executions: 0.into(), - } - } - - pub(crate) fn new_prepared<'ps, 'spec: 'ps>( - partition_key: Option)> + Clone>, - token: Option, - request_size: usize, - ) -> Self { - use tracing::field::Empty; - - let span = trace_span!( - "Request", - kind = "prepared", - partition_key = Empty, - token = Empty, - // - request_size = request_size, - result_size = Empty, - result_rows = Empty, - replicas = Empty, - shard = Empty, - speculative_executions = Empty, - ); - - if let Some(partition_key) = partition_key { - span.record( - "partition_key", - tracing::field::display( - format_args!("{}", partition_key_displayer(partition_key),), - ), - ); - } - if let Some(token) = token { - span.record("token", token.value()); - } - - Self { - span, - speculative_executions: 0.into(), - } - } - - pub(crate) fn new_batch() -> Self { - use tracing::field::Empty; - - let span = trace_span!( - "Request", - kind = "batch", - // - request_size = Empty, - result_size = Empty, - result_rows = Empty, - replicas = Empty, - shard = Empty, - speculative_executions = Empty, - ); - - Self { - span, - speculative_executions: 0.into(), - } - } - - pub(crate) fn record_shard_id(&self, conn: &Connection) { - if let Some(info) = conn.get_shard_info() { - self.span.record("shard", info.shard); - } - } - - pub(crate) fn record_raw_rows_fields(&self, raw_rows: &RawMetadataAndRawRows) { - self.span - .record("raw_result_size", raw_rows.metadata_and_rows_bytes_size()); - } - - pub(crate) fn record_result_fields(&self, query_result: &QueryResult) { - if let Some(raw_metadata_and_rows) = query_result.raw_metadata_and_rows() { - self.record_raw_rows_fields(raw_metadata_and_rows); - } - } - - pub(crate) fn record_replicas<'a>(&'a self, replicas: &'a [(impl Borrow>, Shard)]) { - struct ReplicaIps<'a, N>(&'a [(N, Shard)]); - impl Display for ReplicaIps<'_, N> - where - N: Borrow>, - { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut nodes_with_shards = self.0.iter(); - if let Some((node, shard)) = nodes_with_shards.next() { - write!(f, "{}-shard{}", node.borrow().address.ip(), shard)?; - - for (node, shard) in nodes_with_shards { - write!(f, ",{}-shard{}", node.borrow().address.ip(), shard)?; - } - } - Ok(()) - } - } - self.span - .record("replicas", tracing::field::display(&ReplicaIps(replicas))); - } - - pub(crate) fn record_request_size(&self, size: usize) { - self.span.record("request_size", size); - } - - pub(crate) fn inc_speculative_executions(&self) { - self.speculative_executions.fetch_add(1, Ordering::Relaxed); - } - - pub(crate) fn span(&self) -> &tracing::Span { - &self.span - } -} - -impl Drop for RequestSpan { - fn drop(&mut self) { - self.span.record( - "speculative_executions", - self.speculative_executions.load(Ordering::Relaxed), - ); - } -} - -fn partition_key_displayer<'ps, 'res, 'spec: 'ps>( - mut pk_values_iter: impl Iterator)> + 'res + Clone, -) -> impl Display + 'res { - CommaSeparatedDisplayer( - std::iter::from_fn(move || { - pk_values_iter - .next() - .map(|(mut cell, spec)| deser_cql_value(spec.typ(), &mut cell)) - }) - .map(|c| match c { - Ok(c) => Either::Left(CqlValueDisplayer(c)), - Err(_) => Either::Right(""), - }), - ) -} diff --git a/scylla/src/transport/session_builder.rs b/scylla/src/session/session_builder.rs similarity index 96% rename from scylla/src/transport/session_builder.rs rename to scylla/src/session/session_builder.rs index 404e277335..8b24564c87 100644 --- a/scylla/src/transport/session_builder.rs +++ b/scylla/src/session/session_builder.rs @@ -1,23 +1,21 @@ //! SessionBuilder provides an easy way to create new Sessions -use super::connection::SelfIdentity; -use super::execution_profile::ExecutionProfileHandle; +use crate::connection::{AddressTranslator, Compression, SelfIdentity}; +use crate::execution::execution_profile::ExecutionProfileHandle; #[allow(deprecated)] -use super::session::{ - AddressTranslator, CurrentDeserializationApi, GenericSession, LegacyDeserializationApi, - SessionConfig, +use crate::session::{ + CurrentDeserializationApi, GenericSession, LegacyDeserializationApi, SessionConfig, }; -use super::Compression; #[cfg(feature = "cloud")] use crate::cloud::{CloudConfig, CloudConfigError}; -use crate::transport::errors::NewSessionError; +use crate::execution::errors::NewSessionError; #[cfg(feature = "cloud")] use crate::ExecutionProfile; +use crate::cluster::host_filter::HostFilter; +use crate::connection::PoolSize; use crate::statement::Consistency; -use crate::transport::connection_pool::PoolSize; -use crate::transport::host_filter::HostFilter; use std::borrow::Borrow; use std::marker::PhantomData; use std::net::SocketAddr; @@ -64,7 +62,7 @@ pub type CloudSessionBuilder = GenericSessionBuilder; /// /// ``` /// # use scylla::{Session, SessionBuilder}; -/// # use scylla::transport::Compression; +/// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: Session = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -188,7 +186,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: Session = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -216,7 +214,7 @@ impl GenericSessionBuilder { /// use scylla::{Session, SessionBuilder}; /// use async_trait::async_trait; /// use scylla::authentication::{AuthenticatorProvider, AuthenticatorSession, AuthError}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// /// struct CustomAuthenticator; /// @@ -268,8 +266,8 @@ impl GenericSessionBuilder { /// # use std::net::SocketAddr; /// # use std::sync::Arc; /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::session::{AddressTranslator, TranslationError}; - /// # use scylla::transport::topology::UntranslatedPeer; + /// # use scylla::connection::{AddressTranslator, TranslationError}; + /// # use scylla::cluster::metadata::UntranslatedPeer; /// struct IdentityTranslator; /// /// #[async_trait] @@ -298,7 +296,7 @@ impl GenericSessionBuilder { /// # use std::collections::HashMap; /// # use std::str::FromStr; /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::session::{AddressTranslator, TranslationError}; + /// # use scylla::connection::{AddressTranslator, TranslationError}; /// # /// # async fn example() -> Result<(), Box> { /// let mut translation_rules = HashMap::new(); @@ -388,7 +386,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: Session = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -508,7 +506,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: Session = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -532,7 +530,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{LegacySession, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: LegacySession = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -561,7 +559,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: Session = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -607,7 +605,7 @@ impl GenericSessionBuilder { /// # use scylla::{Session, SessionBuilder}; /// # async fn example() -> Result<(), Box> { /// use std::num::NonZeroUsize; - /// use scylla::transport::session::PoolSize; + /// use scylla::connection::PoolSize; /// /// // This session will establish 4 connections to each node. /// // For Scylla clusters, this number will be divided across shards @@ -810,7 +808,7 @@ impl GenericSessionBuilder { /// should be opened to the node or not. The driver will also avoid /// those nodes when re-establishing the control connection. /// - /// See the [host filter](crate::transport::host_filter) module for a list + /// See the [host filter](crate::cluster::host_filter) module for a list /// of pre-defined filters. It is also possible to provide a custom filter /// by implementing the HostFilter trait. /// @@ -820,8 +818,8 @@ impl GenericSessionBuilder { /// # use std::net::SocketAddr; /// # use std::sync::Arc; /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::session::{AddressTranslator, TranslationError}; - /// # use scylla::transport::host_filter::DcHostFilter; + /// # use scylla::connection::{AddressTranslator, TranslationError}; + /// # use scylla::cluster::host_filter::DcHostFilter; /// /// # async fn example() -> Result<(), Box> { /// // The session will only connect to nodes from "my-local-dc" @@ -858,7 +856,7 @@ impl GenericSessionBuilder { self } - /// Set the number of attempts to fetch [TracingInfo](crate::tracing::TracingInfo) + /// Set the number of attempts to fetch [TracingInfo](crate::execution::tracing::TracingInfo) /// in [`Session::get_tracing_info`](crate::Session::get_tracing_info). /// The default is 5 attempts. /// @@ -887,7 +885,7 @@ impl GenericSessionBuilder { self } - /// Set the delay between attempts to fetch [TracingInfo](crate::tracing::TracingInfo) + /// Set the delay between attempts to fetch [TracingInfo](crate::execution::tracing::TracingInfo) /// in [`Session::get_tracing_info`](crate::Session::get_tracing_info). /// The default is 3 milliseconds. /// @@ -916,7 +914,7 @@ impl GenericSessionBuilder { self } - /// Set the consistency level of fetching [TracingInfo](crate::tracing::TracingInfo) + /// Set the consistency level of fetching [TracingInfo](crate::execution::tracing::TracingInfo) /// in [`Session::get_tracing_info`](crate::Session::get_tracing_info). /// The default is [`Consistency::One`]. /// @@ -953,7 +951,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::Compression; + /// # use scylla::connection::Compression; /// # async fn example() -> Result<(), Box> { /// let session: Session = SessionBuilder::new() /// .known_node("127.0.0.1:9042") @@ -1001,7 +999,7 @@ impl GenericSessionBuilder { /// # Example /// ``` /// # use scylla::{Session, SessionBuilder}; - /// # use scylla::transport::SelfIdentity; + /// # use scylla::connection::SelfIdentity; /// # async fn example() -> Result<(), Box> { /// let (app_major, app_minor, app_patch) = (2, 1, 3); /// let app_version = format!("{app_major}.{app_minor}.{app_patch}"); @@ -1038,10 +1036,10 @@ mod tests { use scylla_cql::Consistency; use super::SessionBuilder; + use crate::cluster::node::KnownNode; + use crate::connection::Compression; + use crate::execution::execution_profile::{defaults, ExecutionProfile}; use crate::test_utils::setup_tracing; - use crate::transport::execution_profile::{defaults, ExecutionProfile}; - use crate::transport::node::KnownNode; - use crate::transport::Compression; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::time::Duration; diff --git a/scylla/src/transport/session_test.rs b/scylla/src/session/session_test.rs similarity index 98% rename from scylla/src/transport/session_test.rs rename to scylla/src/session/session_test.rs index 318848c576..9a40440503 100644 --- a/scylla/src/transport/session_test.rs +++ b/scylla/src/session/session_test.rs @@ -1,20 +1,18 @@ use crate::batch::{Batch, BatchStatement}; +use crate::cluster::metadata::Strategy::NetworkTopologyStrategy; +use crate::cluster::metadata::{CollectionType, ColumnKind, CqlType, NativeType, UserDefinedType}; use crate::deserialize::DeserializeOwnedValue; +use crate::execution::errors::{BadKeyspaceName, BadQuery, DbError, QueryError}; +use crate::execution::retries::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}; +use crate::execution::tracing::TracingInfo; use crate::prepared_statement::PreparedStatement; use crate::query::Query; -use crate::retry_policy::{QueryInfo, RetryDecision, RetryPolicy, RetrySession}; -use crate::routing::Token; -use crate::statement::Consistency; -use crate::tracing::TracingInfo; -use crate::transport::errors::{BadKeyspaceName, BadQuery, DbError, QueryError}; -use crate::transport::partitioner::{ +use crate::routing::partitioner::{ calculate_token_for_partition_key, Murmur3Partitioner, Partitioner, PartitionerName, }; -use crate::transport::session::Session; -use crate::transport::topology::Strategy::NetworkTopologyStrategy; -use crate::transport::topology::{ - CollectionType, ColumnKind, CqlType, NativeType, UserDefinedType, -}; +use crate::routing::Token; +use crate::session::Session; +use crate::statement::Consistency; use crate::utils::test_utils::{ create_new_session_builder, scylla_supports_tablets, setup_tracing, supports_feature, unique_keyspace_name, PerformDDL, @@ -37,7 +35,7 @@ use std::sync::Arc; use tokio::net::TcpListener; use uuid::Uuid; -use super::query_result::QueryRowsResult; +use crate::response::query_result::QueryRowsResult; #[tokio::test] async fn test_connection_failure() { @@ -1239,33 +1237,45 @@ async fn test_timestamp() { // test regular query timestamps - let mut regular_query = Query::new(query_str.to_string()); + let regular_query = Query::new(query_str.to_string()); - regular_query.set_timestamp(Some(420)); session - .query_unpaged(regular_query.clone(), ("regular query", "higher timestamp")) + .query_unpaged_with_timestamp( + regular_query.clone(), + ("regular query", "higher timestamp"), + 420, + ) .await .unwrap(); - regular_query.set_timestamp(Some(42)); session - .query_unpaged(regular_query.clone(), ("regular query", "lower timestamp")) + .query_unpaged_with_timestamp( + regular_query.clone(), + ("regular query", "lower timestamp"), + 42, + ) .await .unwrap(); // test prepared statement timestamps - let mut prepared_statement = session.prepare(query_str).await.unwrap(); + let prepared_statement = session.prepare(query_str).await.unwrap(); - prepared_statement.set_timestamp(Some(420)); session - .execute_unpaged(&prepared_statement, ("prepared query", "higher timestamp")) + .execute_unpaged_with_timestamp( + &prepared_statement, + ("prepared query", "higher timestamp"), + 420, + ) .await .unwrap(); - prepared_statement.set_timestamp(Some(42)); session - .execute_unpaged(&prepared_statement, ("prepared query", "lower timestamp")) + .execute_unpaged_with_timestamp( + &prepared_statement, + ("prepared query", "lower timestamp"), + 42, + ) .await .unwrap(); @@ -1275,26 +1285,26 @@ async fn test_timestamp() { batch.append_statement(regular_query); batch.append_statement(prepared_statement); - batch.set_timestamp(Some(420)); session - .batch( + .batch_with_timestamp( &batch, ( ("first query in batch", "higher timestamp"), ("second query in batch", "higher timestamp"), ), + 420, ) .await .unwrap(); - batch.set_timestamp(Some(42)); session - .batch( + .batch_with_timestamp( &batch, ( ("first query in batch", "lower timestamp"), ("second query in batch", "lower timestamp"), ), + 42, ) .await .unwrap(); @@ -2530,7 +2540,7 @@ async fn test_rate_limit_exceeded_exception() { } } - use crate::transport::errors::OperationType; + use crate::execution::errors::OperationType; match maybe_err.expect("Rate limit error didn't occur") { QueryError::DbError(DbError::RateLimitReached { op_type, .. }, _) => { diff --git a/scylla/src/statement/batch.rs b/scylla/src/statement/batch.rs index 62bbaab140..7712ee3f82 100644 --- a/scylla/src/statement/batch.rs +++ b/scylla/src/statement/batch.rs @@ -1,10 +1,10 @@ use std::borrow::Cow; use std::sync::Arc; -use crate::history::HistoryListener; -use crate::retry_policy::RetryPolicy; +use crate::execution::execution_profile::ExecutionProfileHandle; +use crate::execution::history::HistoryListener; +use crate::execution::retries::RetryPolicy; use crate::statement::{prepared_statement::PreparedStatement, query::Query}; -use crate::transport::execution_profile::ExecutionProfileHandle; use super::StatementConfig; use super::{Consistency, SerialConsistency}; @@ -109,18 +109,6 @@ impl Batch { self.config.tracing } - /// Sets the default timestamp for this batch in microseconds. - /// If not None, it will replace the server side assigned timestamp as default timestamp for - /// all the statements contained in the batch. - pub fn set_timestamp(&mut self, timestamp: Option) { - self.config.timestamp = timestamp - } - - /// Gets the default timestamp for this batch in microseconds. - pub fn get_timestamp(&self) -> Option { - self.config.timestamp - } - /// Set the retry policy for this batch, overriding the one from execution profile if not None. #[inline] pub fn set_retry_policy(&mut self, retry_policy: Option>) { @@ -216,8 +204,8 @@ pub(crate) mod batch_values { use scylla_cql::types::serialize::row::SerializedValues; use scylla_cql::types::serialize::{RowWriter, SerializationError}; + use crate::execution::errors::QueryError; use crate::routing::Token; - use crate::transport::errors::QueryError; use super::BatchStatement; diff --git a/scylla/src/statement/mod.rs b/scylla/src/statement/mod.rs index c396d91010..427d7a5f79 100644 --- a/scylla/src/statement/mod.rs +++ b/scylla/src/statement/mod.rs @@ -1,9 +1,17 @@ +//! This module holds entities representing various kinds of CQL statements, +//! together with their execution options. +//! The following statements are supported: +//! - Query (unprepared statements), +//! - PreparedStatement, +//! - Batch. + use std::{sync::Arc, time::Duration}; use thiserror::Error; -use crate::transport::execution_profile::ExecutionProfileHandle; -use crate::{history::HistoryListener, retry_policy::RetryPolicy}; +use crate::execution::execution_profile::ExecutionProfileHandle; +use crate::execution::history::HistoryListener; +use crate::execution::retries::RetryPolicy; pub mod batch; pub mod prepared_statement; @@ -25,7 +33,6 @@ pub(crate) struct StatementConfig { pub(crate) skip_result_metadata: bool, pub(crate) tracing: bool, - pub(crate) timestamp: Option, pub(crate) request_timeout: Option, pub(crate) history_listener: Option>, diff --git a/scylla/src/statement/prepared_statement.rs b/scylla/src/statement/prepared_statement.rs index 385fcdf074..77aa404465 100644 --- a/scylla/src/statement/prepared_statement.rs +++ b/scylla/src/statement/prepared_statement.rs @@ -13,30 +13,30 @@ use thiserror::Error; use uuid::Uuid; use super::{PageSize, StatementConfig}; +use crate::execution::errors::{BadQuery, ProtocolError, QueryError}; +use crate::execution::execution_profile::ExecutionProfileHandle; +use crate::execution::history::HistoryListener; +use crate::execution::retries::RetryPolicy; use crate::frame::response::result::PreparedMetadata; use crate::frame::types::{Consistency, SerialConsistency}; -use crate::history::HistoryListener; -use crate::retry_policy::RetryPolicy; +use crate::routing::partitioner::{Partitioner, PartitionerHasher, PartitionerName}; use crate::routing::Token; -use crate::transport::errors::{BadQuery, ProtocolError, QueryError}; -use crate::transport::execution_profile::ExecutionProfileHandle; -use crate::transport::partitioner::{Partitioner, PartitionerHasher, PartitionerName}; /// Represents a statement prepared on the server. /// -/// To prepare a statement, simply execute [`Session::prepare`](crate::transport::session::Session::prepare). +/// To prepare a statement, simply execute [`Session::prepare`](crate::session::Session::prepare). /// /// If you plan on reusing the statement, or bounding some values to it during execution, always /// prefer using prepared statements over `Session::query_*` methods, -/// e.g. [`Session::query_unpaged`](crate::transport::session::Session::query_unpaged). +/// e.g. [`Session::query_unpaged`](crate::session::Session::query_unpaged). /// /// Benefits that prepared statements have to offer: /// * Performance - a prepared statement holds information about metadata /// that allows to carry out a statement execution in a type safe manner. /// When any of `Session::query_*` methods is called with non-empty bound values, /// the driver has to prepare the statement before execution (to provide type safety). -/// This implies 2 round trips per [`Session::query_unpaged`](crate::transport::session::Session::query_unpaged). -/// On the other hand, the cost of [`Session::execute_unpaged`](crate::transport::session::Session::execute_unpaged) +/// This implies 2 round trips per [`Session::query_unpaged`](crate::session::Session::query_unpaged). +/// On the other hand, the cost of [`Session::execute_unpaged`](crate::session::Session::execute_unpaged) /// is only 1 round trip. /// * Increased type-safety - bound values' types are validated with /// the [`PreparedMetadata`] received from the server during the serialization. @@ -48,7 +48,7 @@ use crate::transport::partitioner::{Partitioner, PartitionerHasher, PartitionerN /// # Clone implementation /// Cloning a prepared statement is a cheap operation. It only /// requires copying a couple of small fields and some [Arc] pointers. -/// Always prefer cloning over executing [`Session::prepare`](crate::transport::session::Session::prepare) +/// Always prefer cloning over executing [`Session::prepare`](crate::session::Session::prepare) /// multiple times to save some roundtrips. /// /// # Statement repreparation @@ -57,7 +57,7 @@ use crate::transport::partitioner::{Partitioner, PartitionerHasher, PartitionerN /// the server will respond with an error. Users should not worry about it, since /// the driver handles it properly and tries to reprepare the statement. /// However, there are some cases when client-side prepared statement should be dropped -/// and prepared once again via [`Session::prepare`](crate::transport::session::Session::prepare) - +/// and prepared once again via [`Session::prepare`](crate::session::Session::prepare) - /// see the mention about altering schema below. /// /// # Altering schema @@ -370,19 +370,6 @@ impl PreparedStatement { self.config.skip_result_metadata } - /// Sets the default timestamp for this statement in microseconds. - /// If not None, it will replace the server side assigned timestamp as default timestamp - /// If a statement contains a `USING TIMESTAMP` clause, calling this method won't change - /// anything - pub fn set_timestamp(&mut self, timestamp: Option) { - self.config.timestamp = timestamp - } - - /// Gets the default timestamp for this statement in microseconds. - pub fn get_timestamp(&self) -> Option { - self.config.timestamp - } - /// Sets the client-side timeout for this statement. /// If not None, the driver will stop waiting for the request /// to finish after `timeout` passed. diff --git a/scylla/src/statement/query.rs b/scylla/src/statement/query.rs index 7fc2424d92..dbc3e157c3 100644 --- a/scylla/src/statement/query.rs +++ b/scylla/src/statement/query.rs @@ -1,8 +1,8 @@ use super::{PageSize, StatementConfig}; +use crate::execution::execution_profile::ExecutionProfileHandle; +use crate::execution::history::HistoryListener; +use crate::execution::retries::RetryPolicy; use crate::frame::types::{Consistency, SerialConsistency}; -use crate::history::HistoryListener; -use crate::retry_policy::RetryPolicy; -use crate::transport::execution_profile::ExecutionProfileHandle; use std::sync::Arc; use std::time::Duration; @@ -103,19 +103,6 @@ impl Query { self.config.tracing } - /// Sets the default timestamp for this statement in microseconds. - /// If not None, it will replace the server side assigned timestamp as default timestamp - /// If a statement contains a `USING TIMESTAMP` clause, calling this method won't change - /// anything - pub fn set_timestamp(&mut self, timestamp: Option) { - self.config.timestamp = timestamp - } - - /// Gets the default timestamp for this statement in microseconds. - pub fn get_timestamp(&self) -> Option { - self.config.timestamp - } - /// Sets the client-side timeout for this statement. /// If not None, the driver will stop waiting for the request /// to finish after `timeout` passed. diff --git a/scylla/src/transport/mod.rs b/scylla/src/transport/mod.rs deleted file mode 100644 index 55184aadc6..0000000000 --- a/scylla/src/transport/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -pub(crate) mod caching_session; -mod cluster; -pub(crate) mod connection; -mod connection_pool; -pub mod downgrading_consistency_retry_policy; -pub mod errors; -pub mod execution_profile; -pub mod host_filter; -pub mod iterator; -pub mod legacy_query_result; -pub mod load_balancing; -pub mod locator; -pub(crate) mod metrics; -mod node; -pub mod partitioner; -pub mod query_result; -pub mod retry_policy; -pub mod session; -pub mod session_builder; -pub mod speculative_execution; -pub mod topology; - -pub use crate::frame::{Authenticator, Compression}; -pub use connection::SelfIdentity; -pub use execution_profile::ExecutionProfile; -pub use scylla_cql::frame::request::query::{PagingState, PagingStateResponse}; - -#[cfg(test)] -mod session_test; - -pub use cluster::ClusterData; -pub use node::{KnownNode, Node, NodeAddr, NodeRef}; diff --git a/scylla/src/utils/test_utils.rs b/scylla/src/utils/test_utils.rs index 7e258c352c..14bda63260 100644 --- a/scylla/src/utils/test_utils.rs +++ b/scylla/src/utils/test_utils.rs @@ -1,10 +1,11 @@ +use crate::cluster::ClusterData; +use crate::cluster::NodeRef; +use crate::connection::Connection; +use crate::execution::errors::QueryError; use crate::load_balancing::{FallbackPlan, LoadBalancingPolicy, RoutingInfo}; use crate::query::Query; use crate::routing::Shard; -use crate::transport::connection::Connection; -use crate::transport::errors::QueryError; -use crate::transport::session_builder::{GenericSessionBuilder, SessionBuilderKind}; -use crate::transport::{ClusterData, NodeRef}; +use crate::session::session_builder::{GenericSessionBuilder, SessionBuilderKind}; use crate::{CachingSession, ExecutionProfile, Session}; use std::sync::Arc; use std::{num::NonZeroU32, time::Duration}; @@ -77,7 +78,7 @@ pub(crate) fn create_new_session_builder() -> GenericSessionBuilder + Send) -> Result<(), QueryError> { let mut query = query.into(); apply_ddl_lbp(&mut query); - self.query_unpaged(query).await.map(|_| ()) + self.query_unpaged(query, None).await.map(|_| ()) } } diff --git a/scylla/tests/integration/batch.rs b/scylla/tests/integration/batch.rs index d711cb5014..0f9260c70d 100644 --- a/scylla/tests/integration/batch.rs +++ b/scylla/tests/integration/batch.rs @@ -1,9 +1,9 @@ use scylla::batch::Batch; use scylla::batch::BatchType; +use scylla::execution::errors::QueryError; use scylla::frame::frame_errors::BatchSerializationError; use scylla::frame::frame_errors::CqlRequestSerializationError; use scylla::query::Query; -use scylla::transport::errors::QueryError; use crate::utils::create_new_session_builder; use crate::utils::setup_tracing; diff --git a/scylla/tests/integration/consistency.rs b/scylla/tests/integration/consistency.rs index a503fb7d3b..80056b97cb 100644 --- a/scylla/tests/integration/consistency.rs +++ b/scylla/tests/integration/consistency.rs @@ -1,11 +1,11 @@ use crate::utils::{setup_tracing, test_with_3_node_cluster, unique_keyspace_name, PerformDDL}; +use scylla::cluster::NodeRef; +use scylla::execution::retries::FallthroughRetryPolicy; use scylla::execution_profile::{ExecutionProfileBuilder, ExecutionProfileHandle}; use scylla::load_balancing::{DefaultPolicy, LoadBalancingPolicy, RoutingInfo}; use scylla::prepared_statement::PreparedStatement; -use scylla::retry_policy::FallthroughRetryPolicy; use scylla::routing::{Shard, Token}; -use scylla::transport::NodeRef; -use scylla::Session; +use scylla::session::Session; use scylla_cql::frame::response::result::TableSpec; use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; @@ -377,7 +377,7 @@ impl LoadBalancingPolicy for RoutingInfoReportingWrapper { fn pick<'a>( &'a self, query: &'a RoutingInfo, - cluster: &'a scylla::transport::ClusterData, + cluster: &'a scylla::cluster::ClusterData, ) -> Option<(NodeRef<'a>, Option)> { self.routing_info_tx .send(OwnedRoutingInfo::from(query.clone())) @@ -388,7 +388,7 @@ impl LoadBalancingPolicy for RoutingInfoReportingWrapper { fn fallback<'a>( &'a self, query: &'a RoutingInfo, - cluster: &'a scylla::transport::ClusterData, + cluster: &'a scylla::cluster::ClusterData, ) -> scylla::load_balancing::FallbackPlan<'a> { self.routing_info_tx .send(OwnedRoutingInfo::from(query.clone())) diff --git a/scylla/tests/integration/execution_profiles.rs b/scylla/tests/integration/execution_profiles.rs index dd58cdbae0..f3d5e104a0 100644 --- a/scylla/tests/integration/execution_profiles.rs +++ b/scylla/tests/integration/execution_profiles.rs @@ -5,15 +5,15 @@ use crate::utils::{setup_tracing, test_with_3_node_cluster, unique_keyspace_name use assert_matches::assert_matches; use scylla::batch::BatchStatement; use scylla::batch::{Batch, BatchType}; +use scylla::cluster::NodeRef; use scylla::query::Query; use scylla::routing::Shard; use scylla::statement::SerialConsistency; -use scylla::transport::NodeRef; use scylla::{ + cluster::ClusterData, + execution::retries::{RetryPolicy, RetrySession}, load_balancing::{LoadBalancingPolicy, RoutingInfo}, - retry_policy::{RetryPolicy, RetrySession}, speculative_execution::SpeculativeExecutionPolicy, - transport::ClusterData, ExecutionProfile, SessionBuilder, }; use scylla_cql::Consistency; @@ -80,7 +80,7 @@ impl LoadBalancingPolicy for BoundToPredefinedNodePolicy { _query: &RoutingInfo, _latency: std::time::Duration, _node: NodeRef<'_>, - _error: &scylla::transport::errors::QueryError, + _error: &scylla::execution::errors::QueryError, ) { } @@ -90,7 +90,7 @@ impl LoadBalancingPolicy for BoundToPredefinedNodePolicy { } impl RetryPolicy for BoundToPredefinedNodePolicy { - fn new_session(&self) -> Box { + fn new_session(&self) -> Box { self.report_node(Report::RetryPolicy); Box::new(self.clone()) } @@ -99,10 +99,10 @@ impl RetryPolicy for BoundToPredefinedNodePolicy { impl RetrySession for BoundToPredefinedNodePolicy { fn decide_should_retry( &mut self, - query_info: scylla::retry_policy::QueryInfo, - ) -> scylla::retry_policy::RetryDecision { + query_info: scylla::execution::retries::QueryInfo, + ) -> scylla::execution::retries::RetryDecision { self.report_consistency(query_info.consistency); - scylla::retry_policy::RetryDecision::DontRetry + scylla::execution::retries::RetryDecision::DontRetry } fn reset(&mut self) {} diff --git a/scylla/tests/integration/history.rs b/scylla/tests/integration/history.rs index 1bbd21e024..9aed79315e 100644 --- a/scylla/tests/integration/history.rs +++ b/scylla/tests/integration/history.rs @@ -3,12 +3,12 @@ use std::sync::Arc; use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc}; use futures::StreamExt; -use scylla::frame::response::result::Row; -use scylla::history::{ +use scylla::execution::errors::QueryError; +use scylla::execution::history::{ AttemptResult, HistoryCollector, QueryHistoryResult, StructuredHistory, TimePoint, }; +use scylla::frame::response::result::Row; use scylla::query::Query; -use scylla::transport::errors::QueryError; use crate::utils::{create_new_session_builder, setup_tracing, unique_keyspace_name, PerformDDL}; diff --git a/scylla/tests/integration/large_batch_statements.rs b/scylla/tests/integration/large_batch_statements.rs index 724d8c9496..8652b895a6 100644 --- a/scylla/tests/integration/large_batch_statements.rs +++ b/scylla/tests/integration/large_batch_statements.rs @@ -3,8 +3,8 @@ use assert_matches::assert_matches; use crate::utils::{create_new_session_builder, setup_tracing, unique_keyspace_name, PerformDDL}; use scylla::batch::Batch; use scylla::batch::BatchType; +use scylla::execution::errors::{BadQuery, QueryError}; use scylla::query::Query; -use scylla::transport::errors::{BadQuery, QueryError}; use scylla::{QueryResult, Session}; #[tokio::test] diff --git a/scylla/tests/integration/lwt_optimisation.rs b/scylla/tests/integration/lwt_optimisation.rs index 466120bce2..5446dbb9f4 100644 --- a/scylla/tests/integration/lwt_optimisation.rs +++ b/scylla/tests/integration/lwt_optimisation.rs @@ -2,8 +2,8 @@ use crate::utils::{ scylla_supports_tablets, setup_tracing, test_with_3_node_cluster, unique_keyspace_name, PerformDDL, }; -use scylla::retry_policy::FallthroughRetryPolicy; -use scylla::transport::session::Session; +use scylla::execution::retries::FallthroughRetryPolicy; +use scylla::session::Session; use scylla::{ExecutionProfile, SessionBuilder}; use scylla_cql::frame::protocol_features::ProtocolFeatures; use scylla_cql::frame::types; diff --git a/scylla/tests/integration/new_session.rs b/scylla/tests/integration/new_session.rs index 6f734f0dab..32e1617bb6 100644 --- a/scylla/tests/integration/new_session.rs +++ b/scylla/tests/integration/new_session.rs @@ -1,7 +1,7 @@ use crate::utils::setup_tracing; use assert_matches::assert_matches; -use scylla::transport::errors::NewSessionError; +use scylla::execution::errors::NewSessionError; use scylla::SessionBuilder; #[cfg(not(scylla_cloud_tests))] diff --git a/scylla/tests/integration/retries.rs b/scylla/tests/integration/retries.rs index 7c7d35c4d4..d88f9e6e7a 100644 --- a/scylla/tests/integration/retries.rs +++ b/scylla/tests/integration/retries.rs @@ -1,8 +1,8 @@ use crate::utils::{setup_tracing, test_with_3_node_cluster, unique_keyspace_name, PerformDDL}; +use scylla::execution::retries::FallthroughRetryPolicy; use scylla::query::Query; -use scylla::retry_policy::FallthroughRetryPolicy; +use scylla::session::Session; use scylla::speculative_execution::SimpleSpeculativeExecutionPolicy; -use scylla::transport::session::Session; use scylla::ExecutionProfile; use scylla::SessionBuilder; use std::sync::Arc; diff --git a/scylla/tests/integration/self_identity.rs b/scylla/tests/integration/self_identity.rs index cba46f7171..3bac22757c 100644 --- a/scylla/tests/integration/self_identity.rs +++ b/scylla/tests/integration/self_identity.rs @@ -5,7 +5,7 @@ use scylla_cql::frame::types; use std::sync::Arc; use tokio::sync::mpsc; -use scylla::transport::SelfIdentity; +use scylla::connection::SelfIdentity; use scylla_proxy::{ Condition, ProxyError, Reaction, RequestOpcode, RequestReaction, RequestRule, ShardAwareness, WorkerError, diff --git a/scylla/tests/integration/tablets.rs b/scylla/tests/integration/tablets.rs index fd56c7d939..15fde03e03 100644 --- a/scylla/tests/integration/tablets.rs +++ b/scylla/tests/integration/tablets.rs @@ -8,18 +8,18 @@ use crate::utils::{ use futures::future::try_join_all; use futures::TryStreamExt; use itertools::Itertools; +use scylla::cluster::ClusterData; +use scylla::cluster::Node; +use scylla::cluster::NodeRef; use scylla::load_balancing::FallbackPlan; use scylla::load_balancing::LoadBalancingPolicy; use scylla::load_balancing::RoutingInfo; use scylla::prepared_statement::PreparedStatement; use scylla::query::Query; use scylla::serialize::row::SerializeRow; -use scylla::transport::ClusterData; -use scylla::transport::Node; -use scylla::transport::NodeRef; use scylla::{ExecutionProfile, QueryResult, Session}; -use scylla::transport::errors::QueryError; +use scylla::execution::errors::QueryError; use scylla_proxy::{ Condition, ProxyError, Reaction, ResponseFrame, ResponseOpcode, ResponseReaction, ResponseRule, ShardAwareness, TargetShard, WorkerError, diff --git a/scylla/tests/integration/utils.rs b/scylla/tests/integration/utils.rs index 07d2079745..69f278dc09 100644 --- a/scylla/tests/integration/utils.rs +++ b/scylla/tests/integration/utils.rs @@ -1,11 +1,12 @@ use futures::Future; +use scylla::cluster::ClusterData; +use scylla::cluster::NodeRef; use scylla::deserialize::DeserializeValue; +use scylla::execution::errors::QueryError; use scylla::load_balancing::{FallbackPlan, LoadBalancingPolicy, RoutingInfo}; use scylla::query::Query; use scylla::routing::Shard; -use scylla::transport::errors::QueryError; -use scylla::transport::session_builder::{GenericSessionBuilder, SessionBuilderKind}; -use scylla::transport::{ClusterData, NodeRef}; +use scylla::session::session_builder::{GenericSessionBuilder, SessionBuilderKind}; use scylla::{ExecutionProfile, Session}; use std::collections::HashMap; use std::env; @@ -143,7 +144,7 @@ pub(crate) fn create_new_session_builder() -> GenericSessionBuilder