Skip to content

Commit abf4dd8

Browse files
committed
Modify the graph interface to make possible select the type of operation to perform (read or write)
1 parent 79722b5 commit abf4dd8

File tree

2 files changed

+108
-10
lines changed

2 files changed

+108
-10
lines changed

lib/src/graph.rs

Lines changed: 107 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum ConnectionPoolManager {
2929
}
3030

3131
impl ConnectionPoolManager {
32+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
3233
async fn get(&self, operation: Option<Operation>) -> Result<ManagedConnection> {
3334
match self {
3435
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
@@ -37,6 +38,15 @@ impl ConnectionPoolManager {
3738
}
3839
}
3940

41+
#[cfg(not(feature = "unstable-bolt-protocol-impl-v2"))]
42+
async fn get(&self) -> Result<ManagedConnection> {
43+
match self {
44+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
45+
Routed(manager) => manager.get(operation).await,
46+
Normal(pool) => pool.get().await.map_err(crate::Error::from),
47+
}
48+
}
49+
4050
fn backoff(&self) -> ExponentialBackoff {
4151
match self {
4252
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
@@ -134,7 +144,19 @@ impl Graph {
134144
///
135145
/// Transactions will not be automatically retried on any failure.
136146
pub async fn start_txn(&self) -> Result<Txn> {
137-
self.impl_start_txn_on(self.config.db.clone()).await
147+
self.impl_start_txn_on(self.config.db.clone(), Operation::Write)
148+
.await
149+
}
150+
151+
/// Starts a new transaction on the configured database specifying the desired operation.
152+
/// All queries that needs to be run/executed within the transaction
153+
/// should be executed using either [`Txn::run`] or [`Txn::execute`]
154+
///
155+
/// Transactions will not be automatically retried on any failure.
156+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
157+
pub async fn start_txn_as(&self, operation: Operation) -> Result<Txn> {
158+
self.impl_start_txn_on(self.config.db.clone(), operation)
159+
.await
138160
}
139161

140162
/// Starts a new transaction on the provided database.
@@ -143,11 +165,16 @@ impl Graph {
143165
///
144166
/// Transactions will not be automatically retried on any failure.
145167
pub async fn start_txn_on(&self, db: impl Into<Database>) -> Result<Txn> {
146-
self.impl_start_txn_on(Some(db.into())).await
168+
self.impl_start_txn_on(Some(db.into()), Operation::Write)
169+
.await
147170
}
148171

149-
async fn impl_start_txn_on(&self, db: Option<Database>) -> Result<Txn> {
150-
let connection = self.pool.get(Some(Operation::Write)).await?;
172+
#[allow(unused_variables)]
173+
async fn impl_start_txn_on(&self, db: Option<Database>, operation: Operation) -> Result<Txn> {
174+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
175+
let connection = self.pool.get(Some(operation)).await?;
176+
#[cfg(not(feature = "unstable-bolt-protocol-impl-v2"))]
177+
let connection = self.pool.get().await?;
151178
Txn::new(db, self.config.fetch_size, connection).await
152179
}
153180

@@ -163,6 +190,22 @@ impl Graph {
163190
///
164191
/// use [`Graph::execute`] when you are interested in the result stream
165192
pub async fn run(&self, q: Query) -> Result<()> {
193+
self.impl_run_on(self.config.db.clone(), q, Operation::Write)
194+
.await
195+
}
196+
197+
/// Runs a READ ONLY query on the configured database using a connection from the connection pool,
198+
/// It doesn't return any [`DetachedRowStream`] as the `run` abstraction discards any stream.
199+
///
200+
/// This operation retires the query on certain failures.
201+
/// All errors with the `Transient` error class as well as a few other error classes are considered retryable.
202+
/// This includes errors during a leader election or when the transaction resources on the server (memory, handles, ...) are exhausted.
203+
/// Retries happen with an exponential backoff until a retry delay exceeds 60s, at which point the query fails with the last error as it would without any retry.
204+
///
205+
/// Use [`Graph::run`] for cases where you just want a write operation
206+
///
207+
/// use [`Graph::execute`] when you are interested in the result stream
208+
pub async fn run_read(&self, q: Query) -> Result<()> {
166209
self.impl_run_on(self.config.db.clone(), q, Operation::Read)
167210
.await
168211
}
@@ -178,10 +221,26 @@ impl Graph {
178221
/// Use [`Graph::run`] for cases where you just want a write operation
179222
///
180223
/// use [`Graph::execute`] when you are interested in the result stream
181-
pub async fn run_on(&self, db: impl Into<Database>, q: Query) -> Result<()> {
182-
self.impl_run_on(Some(db.into()), q, Operation::Read).await
224+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
225+
pub async fn run_on(
226+
&self,
227+
db: impl Into<Database>,
228+
q: Query,
229+
operation: Operation,
230+
) -> Result<()> {
231+
self.impl_run_on(Some(db.into()), q, operation).await
232+
}
233+
234+
#[cfg(not(feature = "unstable-bolt-protocol-impl-v2"))]
235+
pub async fn run_on(
236+
&self,
237+
db: impl Into<Database>,
238+
q: Query,
239+
) -> Result<()> {
240+
self.impl_run_on(Some(db.into()), q, Operation::Write).await
183241
}
184242

243+
#[allow(unused_variables)]
185244
async fn impl_run_on(
186245
&self,
187246
db: Option<Database>,
@@ -196,7 +255,10 @@ impl Graph {
196255
let db = db.as_deref();
197256
let operation = operation.clone();
198257
async move {
258+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
199259
let mut connection = pool.get(Some(operation)).await?;
260+
#[cfg(not(feature = "unstable-bolt-protocol-impl-v2"))]
261+
let mut connection = pool.get().await?;
200262
query.run_retryable(db, &mut connection).await
201263
}
202264
},
@@ -205,7 +267,7 @@ impl Graph {
205267
.await
206268
}
207269

208-
/// Executes a query on the configured database and returns a [`DetachedRowStream`]
270+
/// Executes a READ/WRITE query on the configured database and returns a [`DetachedRowStream`]
209271
///
210272
/// This operation retires the query on certain failures.
211273
/// All errors with the `Transient` error class as well as a few other error classes are considered retryable.
@@ -216,17 +278,48 @@ impl Graph {
216278
.await
217279
}
218280

219-
/// Executes a query on the provided database and returns a [`DetachedRowStream`]
281+
/// Executes a query READ on the configured database and returns a [`DetachedRowStream`]
220282
///
221283
/// This operation retires the query on certain failures.
222284
/// All errors with the `Transient` error class as well as a few other error classes are considered retryable.
223285
/// This includes errors during a leader election or when the transaction resources on the server (memory, handles, ...) are exhausted.
224286
/// Retries happen with an exponential backoff until a retry delay exceeds 60s, at which point the query fails with the last error as it would without any retry.
225-
pub async fn execute_on(&self, db: impl Into<Database>, q: Query) -> Result<DetachedRowStream> {
226-
self.impl_execute_on(Some(db.into()), q, Operation::Write)
287+
pub async fn execute_read(&self, q: Query) -> Result<DetachedRowStream> {
288+
self.impl_execute_on(self.config.db.clone(), q, Operation::Read)
227289
.await
228290
}
229291

292+
/// Executes a query on the provided database and returns a [`DetachedRowStream`]
293+
///
294+
/// This operation retires the query on certain failures.
295+
/// All errors with the `Transient` error class as well as a few other error classes are considered retryable.
296+
/// This includes errors during a leader election or when the transaction resources on the server (memory, handles, ...) are exhausted.
297+
/// Retries happen with an exponential backoff until a retry delay exceeds 60s, at which point the query fails with the last error as it would without any retry.
298+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
299+
pub async fn execute_on(
300+
&self,
301+
db: impl Into<Database>,
302+
q: Query,
303+
operation: Operation,
304+
) -> Result<DetachedRowStream> {
305+
self.impl_execute_on(Some(db.into()), q, operation).await
306+
}
307+
308+
/// Executes a query on the provided database and returns a [`DetachedRowStream`]
309+
///
310+
/// This operation retires the query on certain failures.
311+
/// All errors with the `Transient` error class as well as a few other error classes are considered retryable.
312+
/// This includes errors during a leader election or when the transaction resources on the server (memory, handles, ...) are exhausted.
313+
#[cfg(not(feature = "unstable-bolt-protocol-impl-v2"))]
314+
pub async fn execute_on(
315+
&self,
316+
db: impl Into<Database>,
317+
q: Query,
318+
) -> Result<DetachedRowStream> {
319+
self.impl_execute_on(Some(db.into()), q, Operation::Write).await
320+
}
321+
322+
#[allow(unused_variables)]
230323
async fn impl_execute_on(
231324
&self,
232325
db: Option<Database>,
@@ -240,9 +333,13 @@ impl Graph {
240333
let fetch_size = self.config.fetch_size;
241334
let query = &q;
242335
let db = db.as_deref();
336+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
243337
let operation = operation.clone();
244338
async move {
339+
#[cfg(feature = "unstable-bolt-protocol-impl-v2")]
245340
let connection = pool.get(Some(operation)).await?;
341+
#[cfg(not(feature = "unstable-bolt-protocol-impl-v2"))]
342+
let connection = pool.get().await?;
246343
query.execute_retryable(db, fetch_size, connection).await
247344
}
248345
},

lib/src/routing/routed_connection_manager.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ impl RoutedConnectionManager {
117117
.load_balancing_strategy
118118
.select_reader(available_servers.as_slice()),
119119
} {
120+
debug!("requesting connection for server: {:?}", server);
120121
if let Some(pool) = self.registry.get_pool(&server) {
121122
match pool.get().await {
122123
Ok(connection) => return Ok(connection),

0 commit comments

Comments
 (0)