@@ -13,10 +13,10 @@ use crate::config::get_config;
13
13
use crate :: constants:: * ;
14
14
use crate :: errors:: Error ;
15
15
use crate :: messages:: * ;
16
- use crate :: pool:: { ClientServerMap , ConnectionPool } ;
16
+ use crate :: pool:: { get_pool , ClientServerMap } ;
17
17
use crate :: query_router:: { Command , QueryRouter } ;
18
18
use crate :: server:: Server ;
19
- use crate :: stats:: Reporter ;
19
+ use crate :: stats:: { get_reporter , Reporter } ;
20
20
21
21
/// The client state. One of these is created per client.
22
22
pub struct Client {
@@ -69,12 +69,11 @@ impl Client {
69
69
pub async fn startup (
70
70
mut stream : TcpStream ,
71
71
client_server_map : ClientServerMap ,
72
- server_info : BytesMut ,
73
- stats : Reporter ,
74
72
) -> Result < Client , Error > {
75
- let config = get_config ( ) . clone ( ) ;
76
- let transaction_mode = config. general . pool_mode . starts_with ( "t" ) ;
77
- // drop(config);
73
+ let config = get_config ( ) ;
74
+ let transaction_mode = config. general . pool_mode == "transaction" ;
75
+ let stats = get_reporter ( ) ;
76
+
78
77
loop {
79
78
trace ! ( "Waiting for StartupMessage" ) ;
80
79
@@ -154,9 +153,10 @@ impl Client {
154
153
debug ! ( "Password authentication successful" ) ;
155
154
156
155
auth_ok ( & mut stream) . await ?;
157
- write_all ( & mut stream, server_info) . await ?;
156
+ write_all ( & mut stream, get_pool ( ) . server_info ( ) ) . await ?;
158
157
backend_key_data ( & mut stream, process_id, secret_key) . await ?;
159
158
ready_for_query ( & mut stream) . await ?;
159
+
160
160
trace ! ( "Startup OK" ) ;
161
161
162
162
let database = parameters
@@ -221,7 +221,7 @@ impl Client {
221
221
}
222
222
223
223
/// Handle a connected and authenticated client.
224
- pub async fn handle ( & mut self , mut pool : ConnectionPool ) -> Result < ( ) , Error > {
224
+ pub async fn handle ( & mut self ) -> Result < ( ) , Error > {
225
225
// The client wants to cancel a query it has issued previously.
226
226
if self . cancel_mode {
227
227
trace ! ( "Sending CancelRequest" ) ;
@@ -252,13 +252,19 @@ impl Client {
252
252
return Ok ( Server :: cancel ( & address, & port, process_id, secret_key) . await ?) ;
253
253
}
254
254
255
+ // The query router determines where the query is going to go,
256
+ // e.g. primary, replica, which shard.
255
257
let mut query_router = QueryRouter :: new ( ) ;
258
+ let mut round_robin = 0 ;
256
259
257
260
// Our custom protocol loop.
258
261
// We expect the client to either start a transaction with regular queries
259
262
// or issue commands for our sharding and server selection protocol.
260
263
loop {
261
- trace ! ( "Client idle, waiting for message" ) ;
264
+ trace ! (
265
+ "Client idle, waiting for message, transaction mode: {}" ,
266
+ self . transaction_mode
267
+ ) ;
262
268
263
269
// Read a complete message from the client, which normally would be
264
270
// either a `Q` (query) or `P` (prepare, extended protocol).
@@ -267,32 +273,63 @@ impl Client {
267
273
// SET SHARDING KEY TO 'bigint';
268
274
let mut message = read_message ( & mut self . read ) . await ?;
269
275
276
+ // Get a pool instance referenced by the most up-to-date
277
+ // pointer. This ensures we always read the latest config
278
+ // when starting a query.
279
+ let mut pool = get_pool ( ) ;
280
+
270
281
// Avoid taking a server if the client just wants to disconnect.
271
282
if message[ 0 ] as char == 'X' {
272
- trace ! ( "Client disconnecting" ) ;
283
+ debug ! ( "Client disconnecting" ) ;
273
284
return Ok ( ( ) ) ;
274
285
}
275
286
276
287
// Handle admin database queries.
277
288
if self . admin {
278
- trace ! ( "Handling admin command" ) ;
279
- handle_admin ( & mut self . write , message, pool. clone ( ) ) . await ?;
289
+ debug ! ( "Handling admin command" ) ;
290
+ handle_admin (
291
+ & mut self . write ,
292
+ message,
293
+ pool. clone ( ) ,
294
+ self . client_server_map . clone ( ) ,
295
+ )
296
+ . await ?;
280
297
continue ;
281
298
}
282
299
300
+ let current_shard = query_router. shard ( ) ;
301
+
283
302
// Handle all custom protocol commands, if any.
284
303
match query_router. try_execute_command ( message. clone ( ) ) {
285
304
// Normal query, not a custom command.
286
- None => {
287
- // Attempt to infer which server we want to query, i.e. primary or replica.
288
- if query_router. query_parser_enabled ( ) && query_router. role ( ) == None {
289
- query_router. infer_role ( message. clone ( ) ) ;
290
- }
291
- }
305
+ None => ( ) ,
292
306
293
307
// SET SHARD TO
294
308
Some ( ( Command :: SetShard , _) ) => {
295
- custom_protocol_response_ok ( & mut self . write , "SET SHARD" ) . await ?;
309
+ // Selected shard is not configured.
310
+ if query_router. shard ( ) >= pool. shards ( ) {
311
+ // Set the shard back to what it was.
312
+ query_router. set_shard ( current_shard) ;
313
+
314
+ error_response (
315
+ & mut self . write ,
316
+ & format ! (
317
+ "shard {} is more than configured {}, staying on shard {}" ,
318
+ query_router. shard( ) ,
319
+ pool. shards( ) ,
320
+ current_shard,
321
+ ) ,
322
+ )
323
+ . await ?;
324
+ } else {
325
+ custom_protocol_response_ok ( & mut self . write , "SET SHARD" ) . await ?;
326
+ }
327
+ continue ;
328
+ }
329
+
330
+ // SET PRIMARY READS TO
331
+ Some ( ( Command :: SetPrimaryReads , _) ) => {
332
+ custom_protocol_response_ok ( & mut self . write , "SET PRIMARY READS" ) . await ?;
296
333
continue ;
297
334
}
298
335
@@ -319,27 +356,24 @@ impl Client {
319
356
show_response ( & mut self . write , "shard" , & value) . await ?;
320
357
continue ;
321
358
}
322
- } ;
323
359
324
- // Make sure we selected a valid shard.
325
- if query_router. shard ( ) >= pool. shards ( ) {
326
- error_response (
327
- & mut self . write ,
328
- & format ! (
329
- "shard {} is more than configured {}" ,
330
- query_router. shard( ) ,
331
- pool. shards( )
332
- ) ,
333
- )
334
- . await ?;
335
- continue ;
336
- }
360
+ // SHOW PRIMARY READS
361
+ Some ( ( Command :: ShowPrimaryReads , value) ) => {
362
+ show_response ( & mut self . write , "primary reads" , & value) . await ?;
363
+ continue ;
364
+ }
365
+ } ;
337
366
338
367
debug ! ( "Waiting for connection from pool" ) ;
339
368
340
369
// Grab a server from the pool.
341
370
let connection = match pool
342
- . get ( query_router. shard ( ) , query_router. role ( ) , self . process_id )
371
+ . get (
372
+ query_router. shard ( ) ,
373
+ query_router. role ( ) ,
374
+ self . process_id ,
375
+ round_robin,
376
+ )
343
377
. await
344
378
{
345
379
Ok ( conn) => {
@@ -358,6 +392,8 @@ impl Client {
358
392
let address = connection. 1 ;
359
393
let server = & mut * reference;
360
394
395
+ round_robin += 1 ;
396
+
361
397
// Server is assigned to the client in case the client wants to
362
398
// cancel a query later.
363
399
server. claim ( self . process_id , self . secret_key ) ;
0 commit comments