@@ -59,13 +59,21 @@ impl PushMessage {
5959 }
6060 }
6161
62- pub fn debounce_time ( & self , connection_count : usize , max_debounce_time : usize ) -> Duration {
62+ pub fn debounce_time (
63+ & self ,
64+ connection_count : usize ,
65+ max_debounce_time : usize ,
66+ debounce_factor : f32 ,
67+ ) -> Duration {
6368 // scale the debounce time between 1s and 15s based on the number of active connections
64- // this provide a decent balance between performance and load
65- let time = max ( 1 , min ( connection_count / 10 , max_debounce_time) ) ;
69+ // this provides a decent balance between performance and load.
70+ // Additionally, each connection will have a random debounce_factor between 0.5 and 1.5
71+ // to spread out the load of notifications.
72+ let time = max ( 1 , min ( connection_count / 10 , max_debounce_time) ) as f32 ;
73+ let time = time * debounce_factor;
6674 match self {
67- PushMessage :: File ( _) => Duration :: from_secs ( time as u64 ) ,
68- PushMessage :: Activity => Duration :: from_secs ( time as u64 ) ,
75+ PushMessage :: File ( _) => Duration :: from_secs_f32 ( time) ,
76+ PushMessage :: Activity => Duration :: from_secs_f32 ( time) ,
6977 PushMessage :: Notification => Duration :: from_secs ( 1 ) ,
7078 PushMessage :: Custom ( ..) => Duration :: from_millis ( 1 ) , // no debouncing for custom messages
7179 }
@@ -132,14 +140,23 @@ impl Default for SendQueueItem {
132140 }
133141}
134142
135- #[ derive( Default , Debug ) ]
143+ /// Queue for sending outgoing messages to a user for debounce
144+ ///
145+ /// The server maintains once queue per connection
146+ #[ derive( Debug ) ]
136147pub struct SendQueue {
148+ max_debounce_time : usize ,
149+ debounce_factor : f32 ,
137150 items : [ SendQueueItem ; 3 ] ,
138151}
139152
140153impl SendQueue {
141- pub fn new ( ) -> Self {
142- SendQueue :: default ( )
154+ pub fn new ( max_debounce_time : usize , debounce_factor : f32 ) -> Self {
155+ SendQueue {
156+ max_debounce_time,
157+ debounce_factor,
158+ items : Default :: default ( ) ,
159+ }
143160 }
144161
145162 fn item_mut ( & mut self , message : & PushMessage ) -> Option < & mut SendQueueItem > {
@@ -177,13 +194,15 @@ impl SendQueue {
177194 & mut self ,
178195 now : Instant ,
179196 connection_count : usize ,
180- max_debounce_time : usize ,
181197 ) -> impl Iterator < Item = PushMessage > + ' _ {
198+ let max_debounce_time = self . max_debounce_time ;
199+ let debounce_factor = self . debounce_factor ;
182200 self . items . iter_mut ( ) . filter_map ( move |item| {
183- let debounce_time = item
184- . message
185- . as_ref ( ) ?
186- . debounce_time ( connection_count, max_debounce_time) ;
201+ let debounce_time = item. message . as_ref ( ) ?. debounce_time (
202+ connection_count,
203+ max_debounce_time,
204+ debounce_factor,
205+ ) ;
187206 if now. duration_since ( item. sent ) > debounce_time {
188207 if now. duration_since ( item. received ) > Duration :: from_millis ( 100 ) {
189208 item. sent = now;
@@ -201,7 +220,7 @@ impl SendQueue {
201220#[ test]
202221fn test_send_queue_100 ( ) {
203222 let base_time = Instant :: now ( ) ;
204- let mut queue = SendQueue :: new ( ) ;
223+ let mut queue = SendQueue :: new ( 15 , 1.0 ) ;
205224 queue. push ( PushMessage :: Activity , base_time) ;
206225 queue. push (
207226 PushMessage :: File ( UpdatedFiles :: Known ( vec ! [ 1 ] . into ( ) ) ) ,
@@ -216,7 +235,7 @@ fn test_send_queue_100() {
216235 assert_eq ! (
217236 Vec :: <PushMessage >:: new( ) ,
218237 queue
219- . drain( base_time + Duration :: from_millis( 20 ) , 100 , 15 )
238+ . drain( base_time + Duration :: from_millis( 20 ) , 100 )
220239 . collect:: <Vec <_>>( )
221240 ) ;
222241
@@ -227,7 +246,7 @@ fn test_send_queue_100() {
227246 PushMessage :: Activity
228247 ] ,
229248 queue
230- . drain( base_time + Duration :: from_millis( 200 ) , 100 , 15 )
249+ . drain( base_time + Duration :: from_millis( 200 ) , 100 )
231250 . collect:: <Vec <_>>( )
232251 ) ;
233252
@@ -243,31 +262,31 @@ fn test_send_queue_100() {
243262 assert_eq ! (
244263 Vec :: <PushMessage >:: new( ) ,
245264 queue
246- . drain( base_time + Duration :: from_secs( 10 ) , 100 , 15 )
265+ . drain( base_time + Duration :: from_secs( 10 ) , 100 )
247266 . collect:: <Vec <_>>( )
248267 ) ;
249268
250269 // after debounce time we get the merged messages from the timeframe
251270 assert_eq ! (
252271 vec![ PushMessage :: File ( UpdatedFiles :: Known ( vec![ 3 , 4 ] . into( ) ) ) ] ,
253272 queue
254- . drain( base_time + Duration :: from_secs( 70 ) , 100 , 15 )
273+ . drain( base_time + Duration :: from_secs( 70 ) , 100 )
255274 . collect:: <Vec <_>>( )
256275 ) ;
257276
258277 // nothing left
259278 assert_eq ! (
260279 Vec :: <PushMessage >:: new( ) ,
261280 queue
262- . drain( base_time + Duration :: from_secs( 300 ) , 100 , 15 )
281+ . drain( base_time + Duration :: from_secs( 300 ) , 100 )
263282 . collect:: <Vec <_>>( )
264283 ) ;
265284}
266285
267286#[ test]
268287fn test_send_queue_1 ( ) {
269288 let base_time = Instant :: now ( ) ;
270- let mut queue = SendQueue :: new ( ) ;
289+ let mut queue = SendQueue :: new ( 15 , 1.0 ) ;
271290 queue. push ( PushMessage :: Activity , base_time) ;
272291 queue. push (
273292 PushMessage :: File ( UpdatedFiles :: Known ( vec ! [ 1 ] . into ( ) ) ) ,
@@ -282,7 +301,7 @@ fn test_send_queue_1() {
282301 assert_eq ! (
283302 Vec :: <PushMessage >:: new( ) ,
284303 queue
285- . drain( base_time + Duration :: from_millis( 20 ) , 1 , 15 )
304+ . drain( base_time + Duration :: from_millis( 20 ) , 1 )
286305 . collect:: <Vec <_>>( )
287306 ) ;
288307
@@ -293,7 +312,7 @@ fn test_send_queue_1() {
293312 PushMessage :: Activity
294313 ] ,
295314 queue
296- . drain( base_time + Duration :: from_millis( 200 ) , 1 , 15 )
315+ . drain( base_time + Duration :: from_millis( 200 ) , 1 )
297316 . collect:: <Vec <_>>( )
298317 ) ;
299318
@@ -309,23 +328,23 @@ fn test_send_queue_1() {
309328 assert_eq ! (
310329 Vec :: <PushMessage >:: new( ) ,
311330 queue
312- . drain( base_time + Duration :: from_secs( 1 ) , 1 , 15 )
331+ . drain( base_time + Duration :: from_secs( 1 ) , 1 )
313332 . collect:: <Vec <_>>( )
314333 ) ;
315334
316335 // after debounce time we get the merged messages from the timeframe
317336 assert_eq ! (
318337 vec![ PushMessage :: File ( UpdatedFiles :: Known ( vec![ 3 , 4 ] . into( ) ) ) ] ,
319338 queue
320- . drain( base_time + Duration :: from_secs( 3 ) , 1 , 15 )
339+ . drain( base_time + Duration :: from_secs( 3 ) , 1 )
321340 . collect:: <Vec <_>>( )
322341 ) ;
323342
324343 // nothing left
325344 assert_eq ! (
326345 Vec :: <PushMessage >:: new( ) ,
327346 queue
328- . drain( base_time + Duration :: from_secs( 5 ) , 1 , 15 )
347+ . drain( base_time + Duration :: from_secs( 5 ) , 1 )
329348 . collect:: <Vec <_>>( )
330349 ) ;
331350}
0 commit comments