2
2
/// We are pretending to the server in this scenario,
3
3
/// and this module implements that.
4
4
use bytes:: { Buf , BufMut , BytesMut } ;
5
+ use once_cell:: sync:: OnceCell ;
5
6
use regex:: Regex ;
6
7
use tokio:: io:: { AsyncReadExt , BufReader } ;
7
8
use tokio:: net:: tcp:: { OwnedReadHalf , OwnedWriteHalf } ;
@@ -14,8 +15,11 @@ use crate::pool::{ClientServerMap, ConnectionPool};
14
15
use crate :: server:: Server ;
15
16
use crate :: sharding:: Sharder ;
16
17
17
- const SHARDING_REGEX : & str = r"SET SHARDING KEY TO '[0-9]+';" ;
18
- const ROLE_REGEX : & str = r"SET SERVER ROLE TO '(PRIMARY|REPLICA)';" ;
18
+ pub const SHARDING_REGEX : & str = r"SET SHARDING KEY TO '[0-9]+';" ;
19
+ pub const ROLE_REGEX : & str = r"SET SERVER ROLE TO '(PRIMARY|REPLICA)';" ;
20
+
21
+ pub static SHARDING_REGEX_RE : OnceCell < Regex > = OnceCell :: new ( ) ;
22
+ pub static ROLE_REGEX_RE : OnceCell < Regex > = OnceCell :: new ( ) ;
19
23
20
24
/// The client state. One of these is created per client.
21
25
pub struct Client {
@@ -44,12 +48,6 @@ pub struct Client {
44
48
// Clients are mapped to servers while they use them. This allows a client
45
49
// to connect and cancel a query.
46
50
client_server_map : ClientServerMap ,
47
-
48
- // sharding regex
49
- sharding_regex : Regex ,
50
-
51
- // role detection regex
52
- role_regex : Regex ,
53
51
}
54
52
55
53
impl Client {
@@ -61,9 +59,6 @@ impl Client {
61
59
client_server_map : ClientServerMap ,
62
60
transaction_mode : bool ,
63
61
) -> Result < Client , Error > {
64
- let sharding_regex = Regex :: new ( SHARDING_REGEX ) . unwrap ( ) ;
65
- let role_regex = Regex :: new ( ROLE_REGEX ) . unwrap ( ) ;
66
-
67
62
loop {
68
63
// Could be StartupMessage or SSLRequest
69
64
// which makes this variable length.
@@ -119,8 +114,6 @@ impl Client {
119
114
process_id : process_id,
120
115
secret_key : secret_key,
121
116
client_server_map : client_server_map,
122
- sharding_regex : sharding_regex,
123
- role_regex : role_regex,
124
117
} ) ;
125
118
}
126
119
@@ -140,8 +133,6 @@ impl Client {
140
133
process_id : process_id,
141
134
secret_key : secret_key,
142
135
client_server_map : client_server_map,
143
- sharding_regex : sharding_regex,
144
- role_regex : role_regex,
145
136
} ) ;
146
137
}
147
138
@@ -414,8 +405,12 @@ impl Client {
414
405
415
406
let len = buf. get_i32 ( ) ;
416
407
let query = String :: from_utf8_lossy ( & buf[ ..len as usize - 4 - 1 ] ) . to_ascii_uppercase ( ) ; // Don't read the ternminating null
408
+ let rgx = match SHARDING_REGEX_RE . get ( ) {
409
+ Some ( r) => r,
410
+ None => return None ,
411
+ } ;
417
412
418
- if self . sharding_regex . is_match ( & query) {
413
+ if rgx . is_match ( & query) {
419
414
let shard = query. split ( "'" ) . collect :: < Vec < & str > > ( ) [ 1 ] ;
420
415
match shard. parse :: < i64 > ( ) {
421
416
Ok ( shard) => {
@@ -441,10 +436,14 @@ impl Client {
441
436
442
437
let len = buf. get_i32 ( ) ;
443
438
let query = String :: from_utf8_lossy ( & buf[ ..len as usize - 4 - 1 ] ) . to_ascii_uppercase ( ) ;
439
+ let rgx = match ROLE_REGEX_RE . get ( ) {
440
+ Some ( r) => r,
441
+ None => return None ,
442
+ } ;
444
443
445
444
// Copy / paste from above. If we get one more of these use cases,
446
445
// it'll be time to abstract :).
447
- if self . role_regex . is_match ( & query) {
446
+ if rgx . is_match ( & query) {
448
447
let role = query. split ( "'" ) . collect :: < Vec < & str > > ( ) [ 1 ] ;
449
448
match role {
450
449
"PRIMARY" => Some ( Role :: Primary ) ,
0 commit comments