1
+ use std:: pin:: Pin ;
1
2
use std:: sync:: Arc ;
2
3
4
+ use futures:: Future ;
3
5
use futures_core:: future:: BoxFuture ;
4
6
use futures_core:: Stream ;
5
7
use libsql_replication:: rpc:: proxy:: proxy_client:: ProxyClient ;
@@ -8,7 +10,7 @@ use libsql_replication::rpc::proxy::{
8
10
} ;
9
11
use libsql_sys:: EncryptionConfig ;
10
12
use parking_lot:: Mutex as PMutex ;
11
- use tokio:: sync:: { mpsc, watch , Mutex } ;
13
+ use tokio:: sync:: { mpsc, Mutex } ;
12
14
use tokio_stream:: StreamExt ;
13
15
use tonic:: transport:: Channel ;
14
16
use tonic:: { Request , Streaming } ;
@@ -22,16 +24,21 @@ use crate::replication::FrameNo;
22
24
use crate :: stats:: Stats ;
23
25
use crate :: { Result , DEFAULT_AUTO_CHECKPOINT } ;
24
26
27
+ use super :: connection_core:: GetCurrentFrameNo ;
25
28
use super :: program:: DescribeResponse ;
26
29
use super :: { Connection , RequestContext } ;
27
30
use super :: { MakeConnection , Program } ;
28
31
29
32
pub type RpcStream = Streaming < ExecResp > ;
33
+ pub type WaitForFrameNo = Arc <
34
+ dyn Fn ( FrameNo ) -> Pin < Box < dyn Future < Output = ( ) > + Send + ' static > > + Send + ' static + Sync ,
35
+ > ;
30
36
31
37
pub struct MakeWriteProxyConn < M > {
32
38
client : ProxyClient < Channel > ,
33
39
stats : Arc < Stats > ,
34
- applied_frame_no_receiver : watch:: Receiver < Option < FrameNo > > ,
40
+ wait_for_frame_no : WaitForFrameNo ,
41
+ get_current_frame_no : GetCurrentFrameNo ,
35
42
max_response_size : u64 ,
36
43
max_total_response_size : u64 ,
37
44
primary_replication_index : Option < FrameNo > ,
@@ -46,23 +53,25 @@ impl<M> MakeWriteProxyConn<M> {
46
53
channel : Channel ,
47
54
uri : tonic:: transport:: Uri ,
48
55
stats : Arc < Stats > ,
49
- applied_frame_no_receiver : watch :: Receiver < Option < FrameNo > > ,
56
+ wait_for_frame_no : WaitForFrameNo ,
50
57
max_response_size : u64 ,
51
58
max_total_response_size : u64 ,
52
59
primary_replication_index : Option < FrameNo > ,
53
60
encryption_config : Option < EncryptionConfig > ,
54
61
make_read_only_conn : M ,
62
+ get_current_frame_no : GetCurrentFrameNo ,
55
63
) -> Self {
56
64
let client = ProxyClient :: with_origin ( channel, uri) ;
57
65
Self {
58
66
client,
59
67
stats,
60
- applied_frame_no_receiver ,
68
+ wait_for_frame_no ,
61
69
max_response_size,
62
70
max_total_response_size,
63
71
make_read_only_conn,
64
72
primary_replication_index,
65
73
encryption_config,
74
+ get_current_frame_no,
66
75
}
67
76
}
68
77
}
@@ -77,14 +86,15 @@ where
77
86
Ok ( WriteProxyConnection :: new (
78
87
self . client . clone ( ) ,
79
88
self . stats . clone ( ) ,
80
- self . applied_frame_no_receiver . clone ( ) ,
89
+ self . wait_for_frame_no . clone ( ) ,
81
90
QueryBuilderConfig {
82
91
max_size : Some ( self . max_response_size ) ,
83
92
max_total_size : Some ( self . max_total_response_size ) ,
84
93
auto_checkpoint : DEFAULT_AUTO_CHECKPOINT ,
85
94
encryption_config : self . encryption_config . clone ( ) ,
86
95
} ,
87
96
self . primary_replication_index ,
97
+ self . get_current_frame_no . clone ( ) ,
88
98
self . make_read_only_conn . create ( ) . await ?,
89
99
) ?)
90
100
}
@@ -99,8 +109,9 @@ pub struct WriteProxyConnection<R, C> {
99
109
/// any subsequent read on this connection must wait for the replicator to catch up with this
100
110
/// frame_no
101
111
last_write_frame_no : PMutex < Option < FrameNo > > ,
102
- /// Notifier from the repliator of the currently applied frameno
103
- applied_frame_no_receiver : watch:: Receiver < Option < FrameNo > > ,
112
+ /// Notifier from the replicator of the currently applied frame_no
113
+ wait_for_frame_no : WaitForFrameNo ,
114
+ get_current_frame_no : GetCurrentFrameNo ,
104
115
builder_config : QueryBuilderConfig ,
105
116
stats : Arc < Stats > ,
106
117
@@ -114,21 +125,23 @@ impl<C: Connection> WriteProxyConnection<RpcStream, C> {
114
125
fn new (
115
126
write_proxy : ProxyClient < Channel > ,
116
127
stats : Arc < Stats > ,
117
- applied_frame_no_receiver : watch :: Receiver < Option < FrameNo > > ,
128
+ wait_for_frame_no : WaitForFrameNo ,
118
129
builder_config : QueryBuilderConfig ,
119
130
primary_replication_index : Option < u64 > ,
131
+ get_current_frame_no : GetCurrentFrameNo ,
120
132
read_conn : C ,
121
133
) -> Result < Self > {
122
134
Ok ( Self {
123
135
read_conn,
124
136
write_proxy,
125
137
state : Mutex :: new ( TxnStatus :: Init ) ,
126
138
last_write_frame_no : Default :: default ( ) ,
127
- applied_frame_no_receiver ,
139
+ wait_for_frame_no ,
128
140
builder_config,
129
141
stats,
130
142
remote_conn : Default :: default ( ) ,
131
143
primary_replication_index,
144
+ get_current_frame_no,
132
145
} )
133
146
}
134
147
@@ -199,15 +212,7 @@ impl<C: Connection> WriteProxyConnection<RpcStream, C> {
199
212
let current_fno = replication_index. or_else ( || * self . last_write_frame_no . lock ( ) ) ;
200
213
match current_fno {
201
214
Some ( current_frame_no) => {
202
- let mut receiver = self . applied_frame_no_receiver . clone ( ) ;
203
- receiver
204
- . wait_for ( |last_applied| match last_applied {
205
- Some ( x) => * x >= current_frame_no,
206
- None => true ,
207
- } )
208
- . await
209
- . map_err ( |_| Error :: ReplicatorExited ) ?;
210
-
215
+ ( self . wait_for_frame_no ) ( current_frame_no) . await ;
211
216
Ok ( ( ) )
212
217
}
213
218
None => Ok ( ( ) ) ,
@@ -219,7 +224,7 @@ impl<C: Connection> WriteProxyConnection<RpcStream, C> {
219
224
fn should_proxy ( & self ) -> bool {
220
225
// There primary has data
221
226
if let Some ( primary_index) = self . primary_replication_index {
222
- let last_applied = * self . applied_frame_no_receiver . borrow ( ) ;
227
+ let last_applied = ( self . get_current_frame_no ) ( ) ;
223
228
// if we either don't have data while the primary has, or the data we have is
224
229
// anterior to that of the primary when we loaded the namespace, then proxy the
225
230
// request to the primary
0 commit comments