1
+ use crate :: disk:: Storage ;
1
2
use crate :: link:: local:: { LinkError , LinkRx , LinkTx } ;
2
3
use crate :: link:: network;
3
4
use crate :: link:: network:: Network ;
4
5
use crate :: local:: Link ;
5
- use crate :: protocol:: { Protocol , Connect , LastWill , Packet , self } ;
6
- use crate :: router:: { Event , Notification } ;
7
- use crate :: { ConnectionId , ConnectionSettings } ;
8
- use crate :: disk:: Storage ;
6
+ use crate :: protocol:: { self , Connect , LastWill , Packet , Protocol } ;
7
+ use crate :: router:: { Event , FilterIdx , Notification } ;
8
+ use crate :: { ConnectionId , ConnectionSettings , Offset } ;
9
9
10
10
use flume:: { Receiver , RecvError , SendError , Sender , TrySendError } ;
11
- use tracing:: { info, error, trace} ;
12
- use std:: collections:: { VecDeque } ;
13
- use std:: { io, fs} ;
11
+ use std:: collections:: { HashMap , VecDeque } ;
14
12
use std:: sync:: Arc ;
15
13
use std:: time:: Duration ;
14
+ use std:: { fs, io} ;
16
15
use tokio:: time:: error:: Elapsed ;
17
16
use tokio:: { select, time} ;
17
+ use tracing:: { error, info, trace} ;
18
18
19
19
#[ derive( Debug , thiserror:: Error ) ]
20
20
pub enum Error {
@@ -55,6 +55,7 @@ pub struct PersistanceLink<P: Protocol> {
55
55
disk_handler : DiskHandler < P > ,
56
56
network_update_rx : Receiver < Network < P > > ,
57
57
connack : Notification ,
58
+ inflight_publishes : VecDeque < Notification > ,
58
59
}
59
60
60
61
pub ( super ) struct DiskHandler < P : Protocol > {
@@ -74,19 +75,43 @@ impl<P: Protocol> DiskHandler<P> {
74
75
} )
75
76
}
76
77
77
- pub fn write ( & mut self , notifications : & mut VecDeque < Notification > ) {
78
+ pub fn write (
79
+ & mut self ,
80
+ notifications : & mut VecDeque < Notification > ,
81
+ ) -> HashMap < FilterIdx , Offset > {
82
+ // let ack_list = VecDeque::new();
83
+
84
+ let mut stored_filter_offset_map: HashMap < FilterIdx , Offset > = HashMap :: new ( ) ;
78
85
for notif in notifications. drain ( ..) {
79
- let packet_or_unscheduled = notif. into ( ) ;
86
+ let packet_or_unscheduled = notif. clone ( ) . into ( ) ;
80
87
if let Some ( packet) = packet_or_unscheduled {
81
88
if let Err ( e) = self . protocol . write ( packet, self . storage . writer ( ) ) {
82
89
error ! ( "Failed to write to storage: {e}" ) ;
90
+ continue ;
83
91
}
84
92
85
93
if let Err ( e) = self . storage . flush_on_overflow ( ) {
86
94
error ! ( "Failed to flush storage: {e}" ) ;
95
+ continue ;
96
+ }
97
+
98
+ match & notif {
99
+ Notification :: Forward ( forward) => {
100
+ stored_filter_offset_map
101
+ . entry ( forward. filter_idx )
102
+ . and_modify ( |cursor| {
103
+ if forward. next_cursor > * cursor {
104
+ * cursor = forward. next_cursor
105
+ }
106
+ } )
107
+ . or_insert ( forward. next_cursor ) ;
108
+ }
109
+ _ => continue ,
87
110
}
88
111
}
89
112
}
113
+
114
+ stored_filter_offset_map
90
115
}
91
116
92
117
pub fn read ( & mut self , buffer : & mut VecDeque < Packet > ) {
@@ -105,7 +130,7 @@ impl<P: Protocol> DiskHandler<P> {
105
130
let connection_buffer_length = buffer. len ( ) ;
106
131
//TODO: Don't hardcode max_connection_buffer_len
107
132
if connection_buffer_length >= 100 {
108
- return
133
+ return
109
134
}
110
135
}
111
136
Err ( protocol:: Error :: InsufficientBytes ( _) ) => {
@@ -180,6 +205,7 @@ impl<P: Protocol> PersistanceLink<P> {
180
205
disk_handler : DiskHandler :: new ( & client_id, protocol) ?,
181
206
network_update_rx,
182
207
connack : notification,
208
+ inflight_publishes : VecDeque :: with_capacity ( 100 ) ,
183
209
} ,
184
210
) )
185
211
}
@@ -220,38 +246,68 @@ impl<P: Protocol> PersistanceLink<P> {
220
246
// write to disk
221
247
o = self . link_rx. exchange( & mut self . notifications) => {
222
248
o?;
223
- self . disk_handler. write( & mut self . notifications) ;
249
+ // TODO: write only publishes
250
+ self . write_to_disconnected_client( ) . await ?;
224
251
}
225
252
}
226
253
}
227
254
}
228
255
229
- async fn write_to_client ( & mut self ) -> Result < ( ) , Error > {
230
- // separate publish notifications out
231
- let mut publish = VecDeque :: new ( ) ;
232
- let mut non_publish = VecDeque :: new ( ) ;
256
+ async fn write_to_disconnected_client ( & mut self ) -> Result < ( ) , Error > {
233
257
for notif in self . notifications . drain ( ..) {
234
258
match notif {
235
- Notification :: Forward ( _) | Notification :: ForwardWithProperties ( _, _) => publish. push_back ( notif) ,
236
- _ => non_publish. push_back ( notif) ,
259
+ Notification :: Forward ( _) | Notification :: ForwardWithProperties ( _, _) => {
260
+ self . inflight_publishes . push_back ( notif)
261
+ }
262
+ _ => continue ,
237
263
}
238
- } ;
264
+ }
239
265
240
- // write non-publishes to network
241
- let unscheduled = self . network . writev ( & mut non_publish) . await ?;
266
+ // write publishes to disk
267
+ if !self . inflight_publishes . is_empty ( ) {
268
+ let acked_offsets = self . disk_handler . write ( & mut self . inflight_publishes ) ;
269
+ if let Err ( e) = self . link_tx . ack ( acked_offsets) . await {
270
+ error ! ( "Failed to inform router of read progress: {e}" )
271
+ } ;
272
+ }
273
+ Ok ( ( ) )
274
+ }
275
+
276
+ async fn write_to_active_client ( & mut self ) -> Result < ( ) , Error > {
277
+ // separate notifications out
278
+ let mut unpersisted_messages = VecDeque :: new ( ) ;
279
+ // let mut acked_publishes = VecDeque::new();
280
+ for notif in self . notifications . drain ( ..) {
281
+ match notif {
282
+ Notification :: Forward ( _) | Notification :: ForwardWithProperties ( _, _) => {
283
+ self . inflight_publishes . push_back ( notif)
284
+ }
285
+ Notification :: AckDone => {
286
+ continue ;
287
+ }
288
+ _ => unpersisted_messages. push_back ( notif) ,
289
+ }
290
+ }
291
+
292
+ let unscheduled = self . network . writev ( & mut unpersisted_messages) . await ?;
242
293
if unscheduled {
243
294
self . link_rx . wake ( ) . await ?;
244
295
} ;
245
296
246
297
// write publishes to disk
247
- if !publish. is_empty ( ) {
248
- self . disk_handler . write ( & mut publish) ;
298
+ if !self . inflight_publishes . is_empty ( ) {
299
+ let acked_offsets = self . disk_handler . write ( & mut self . inflight_publishes ) ;
300
+ if let Err ( e) = self . link_tx . ack ( acked_offsets) . await {
301
+ error ! ( "Failed to inform router of read progress: {e}" )
302
+ } ;
249
303
}
250
304
// read publishes from disk
251
305
let mut buffer = VecDeque :: new ( ) ;
252
306
self . disk_handler . read ( & mut buffer) ;
307
+
253
308
// TODO: if network write throws an error then this means we again got network I/O error
254
309
// write publishes to network
310
+
255
311
let unscheduled = self . network . writev ( & mut buffer) . await ?;
256
312
if unscheduled {
257
313
self . link_rx . wake ( ) . await ?;
@@ -285,9 +341,12 @@ impl<P: Protocol> PersistanceLink<P> {
285
341
Ok ( packet) => self . read_from_client( packet) . await ?,
286
342
// change state to disconnected on I/O connection errors and
287
343
// wait for a reconnection
288
- Err ( e) => match e. kind( ) {
289
- io:: ErrorKind :: ConnectionAborted | io:: ErrorKind :: ConnectionReset => return Ok ( State :: Disconnected ) ,
290
- _ => return Err ( e. into( ) )
344
+ Err ( e) => {
345
+ println!( "some error while reading from the network? {e:?}" ) ;
346
+ match e. kind( ) {
347
+ io:: ErrorKind :: ConnectionAborted | io:: ErrorKind :: ConnectionReset => return Ok ( State :: Disconnected ) ,
348
+ _ => return Err ( e. into( ) )
349
+ }
291
350
}
292
351
} ;
293
352
}
@@ -296,7 +355,7 @@ impl<P: Protocol> PersistanceLink<P> {
296
355
// exchange will through error if all senders to router are dropped
297
356
// which is not possible since Persistent Link always lives
298
357
o?;
299
- self . write_to_client ( ) . await ?;
358
+ self . write_to_active_client ( ) . await ?;
300
359
}
301
360
}
302
361
}
0 commit comments