1
- use std:: sync:: Arc ;
2
-
3
1
use futures:: future:: TryFutureExt ;
4
2
use futures:: stream:: FuturesUnordered ;
5
3
use futures:: stream:: StreamExt ;
@@ -32,24 +30,6 @@ use crate::RaftStorage;
32
30
use crate :: RaftTypeConfig ;
33
31
use crate :: StorageError ;
34
32
35
- /// A wrapper around a ClientRequest which has been transformed into an Entry, along with its response channel.
36
- pub ( super ) struct ClientRequestEntry < C : RaftTypeConfig > {
37
- /// The Arc'd entry of the ClientRequest.
38
- ///
39
- /// This value is Arc'd so that it may be sent across thread boundaries for replication
40
- /// without having to clone the data payload itself.
41
- pub entry : Arc < Entry < C > > ,
42
-
43
- /// The response channel for the request.
44
- pub tx : Option < RaftRespTx < ClientWriteResponse < C > , ClientWriteError < C :: NodeId > > > ,
45
- }
46
-
47
- impl < C : RaftTypeConfig > MessageSummary for ClientRequestEntry < C > {
48
- fn summary ( & self ) -> String {
49
- format ! ( "entry:{}" , self . entry. summary( ) )
50
- }
51
- }
52
-
53
33
impl < ' a , C : RaftTypeConfig , N : RaftNetworkFactory < C > , S : RaftStorage < C > > LeaderState < ' a , C , N , S > {
54
34
/// Commit the initial entry which new leaders are obligated to create when first coming to power, per §8.
55
35
#[ tracing:: instrument( level = "trace" , skip( self ) ) ]
@@ -58,12 +38,7 @@ impl<'a, C: RaftTypeConfig, N: RaftNetworkFactory<C>, S: RaftStorage<C>> LeaderS
58
38
59
39
self . core . metrics_flags . set_data_changed ( ) ;
60
40
61
- let cr_entry = ClientRequestEntry {
62
- entry : Arc :: new ( entry) ,
63
- tx : None ,
64
- } ;
65
-
66
- self . replicate_client_request ( cr_entry) . await ?;
41
+ self . replicate_client_request ( entry, None ) . await ?;
67
42
68
43
Ok ( ( ) )
69
44
}
@@ -194,14 +169,10 @@ impl<'a, C: RaftTypeConfig, N: RaftNetworkFactory<C>, S: RaftStorage<C>> LeaderS
194
169
tx : RaftRespTx < ClientWriteResponse < C > , ClientWriteError < C :: NodeId > > ,
195
170
) -> Result < ( ) , StorageError < C :: NodeId > > {
196
171
let entry = self . core . append_payload_to_log ( rpc. payload ) . await ?;
197
- let entry = ClientRequestEntry {
198
- entry : Arc :: new ( entry) ,
199
- tx : Some ( tx) ,
200
- } ;
201
172
202
173
self . core . metrics_flags . set_data_changed ( ) ;
203
174
204
- self . replicate_client_request ( entry) . await ?;
175
+ self . replicate_client_request ( entry, Some ( tx ) ) . await ?;
205
176
Ok ( ( ) )
206
177
}
207
178
@@ -210,15 +181,20 @@ impl<'a, C: RaftTypeConfig, N: RaftNetworkFactory<C>, S: RaftStorage<C>> LeaderS
210
181
/// NOTE WELL: this routine does not wait for the request to actually finish replication, it
211
182
/// merely beings the process. Once the request is committed to the cluster, its response will
212
183
/// be generated asynchronously.
213
- #[ tracing:: instrument( level = "debug" , skip( self , req ) , fields( req=%req . summary( ) ) ) ]
184
+ #[ tracing:: instrument( level = "debug" , skip( self , entry , resp_tx ) , fields( req=%entry . summary( ) ) ) ]
214
185
pub ( super ) async fn replicate_client_request (
215
186
& mut self ,
216
- req : ClientRequestEntry < C > ,
187
+ entry : Entry < C > ,
188
+ resp_tx : Option < RaftRespTx < ClientWriteResponse < C > , ClientWriteError < C :: NodeId > > > ,
217
189
) -> Result < ( ) , StorageError < C :: NodeId > > {
218
190
// Replicate the request if there are other cluster members. The client response will be
219
191
// returned elsewhere after the entry has been committed to the cluster.
220
192
221
- let log_id = req. entry . log_id ;
193
+ let log_id = entry. log_id ;
194
+ if let Some ( tx) = resp_tx {
195
+ self . client_resp_channels . insert ( log_id. index , tx) ;
196
+ }
197
+
222
198
let quorum_granted = self . core . effective_membership . membership . is_majority ( & btreeset ! { self . core. id} ) ;
223
199
224
200
if quorum_granted {
@@ -228,9 +204,7 @@ impl<'a, C: RaftTypeConfig, N: RaftNetworkFactory<C>, S: RaftStorage<C>> LeaderS
228
204
tracing:: debug!( ?self . core. committed, "update committed, no need to replicate" ) ;
229
205
230
206
self . core . metrics_flags . set_data_changed ( ) ;
231
- self . client_request_post_commit ( req) . await ?;
232
- } else {
233
- self . awaiting_committed . push ( req) ;
207
+ self . client_request_post_commit ( log_id. index ) . await ?;
234
208
}
235
209
236
210
for node in self . nodes . values ( ) {
@@ -247,16 +221,16 @@ impl<'a, C: RaftTypeConfig, N: RaftNetworkFactory<C>, S: RaftStorage<C>> LeaderS
247
221
}
248
222
249
223
/// Handle the post-commit logic for a client request.
250
- #[ tracing:: instrument( level = "debug" , skip( self , req ) ) ]
251
- pub ( super ) async fn client_request_post_commit (
252
- & mut self ,
253
- req : ClientRequestEntry < C > ,
254
- ) -> Result < ( ) , StorageError < C :: NodeId > > {
255
- let entry = & req . entry ;
224
+ #[ tracing:: instrument( level = "debug" , skip( self ) ) ]
225
+ pub ( super ) async fn client_request_post_commit ( & mut self , log_index : u64 ) -> Result < ( ) , StorageError < C :: NodeId > > {
226
+ let entries = self . core . storage . get_log_entries ( log_index..=log_index ) . await ? ;
227
+ let entry = & entries [ 0 ] ;
228
+
229
+ let tx = self . client_resp_channels . remove ( & log_index ) ;
256
230
257
231
let apply_res = self . apply_entry_to_state_machine ( entry) . await ?;
258
232
259
- self . send_response ( entry, apply_res, req . tx ) . await ;
233
+ self . send_response ( entry, apply_res, tx) . await ;
260
234
261
235
// Trigger log compaction if needed.
262
236
self . core . trigger_log_compaction_if_needed ( false ) . await ;
0 commit comments