@@ -330,4 +330,145 @@ describe("MessageChannel", function () {
330
330
} ) ;
331
331
} ) ;
332
332
} ) ;
333
+
334
+ describe ( "Sweeping incoming buffer" , ( ) => {
335
+ beforeEach ( ( ) => {
336
+ channelA = new MessageChannel ( channelId ) ;
337
+ channelB = new MessageChannel ( channelId ) ;
338
+ } ) ;
339
+
340
+ it ( "should detect messages with missing dependencies" , ( ) => {
341
+ const causalHistorySize = ( channelA as any ) . causalHistorySize ;
342
+ messagesA . forEach ( ( m ) => {
343
+ channelA . sendMessage ( utf8ToBytes ( m ) , callback ) ;
344
+ } ) ;
345
+
346
+ channelA . sendMessage ( utf8ToBytes ( messagesB [ 0 ] ) , ( message ) => {
347
+ channelB . receiveMessage ( message ) ;
348
+ return true ;
349
+ } ) ;
350
+
351
+ const incomingBuffer = ( channelB as any ) . incomingBuffer as Message [ ] ;
352
+ expect ( incomingBuffer . length ) . to . equal ( 1 ) ;
353
+ expect ( incomingBuffer [ 0 ] . messageId ) . to . equal (
354
+ MessageChannel . getMessageId ( utf8ToBytes ( messagesB [ 0 ] ) )
355
+ ) ;
356
+
357
+ const missingMessages = channelB . sweepIncomingBuffer ( ) ;
358
+ expect ( missingMessages . length ) . to . equal ( causalHistorySize ) ;
359
+ expect ( missingMessages [ 0 ] ) . to . equal (
360
+ MessageChannel . getMessageId ( utf8ToBytes ( messagesA [ 0 ] ) )
361
+ ) ;
362
+ } ) ;
363
+
364
+ it ( "should deliver messages after dependencies are met" , ( ) => {
365
+ const causalHistorySize = ( channelA as any ) . causalHistorySize ;
366
+ const sentMessages = new Array < Message > ( ) ;
367
+ messagesA . forEach ( ( m ) => {
368
+ channelA . sendMessage ( utf8ToBytes ( m ) , ( message ) => {
369
+ sentMessages . push ( message ) ;
370
+ return true ;
371
+ } ) ;
372
+ } ) ;
373
+
374
+ channelA . sendMessage ( utf8ToBytes ( messagesB [ 0 ] ) , ( message ) => {
375
+ channelB . receiveMessage ( message ) ;
376
+ return true ;
377
+ } ) ;
378
+
379
+ const missingMessages = channelB . sweepIncomingBuffer ( ) ;
380
+ expect ( missingMessages . length ) . to . equal ( causalHistorySize ) ;
381
+ expect ( missingMessages [ 0 ] ) . to . equal (
382
+ MessageChannel . getMessageId ( utf8ToBytes ( messagesA [ 0 ] ) )
383
+ ) ;
384
+
385
+ let incomingBuffer = ( channelB as any ) . incomingBuffer as Message [ ] ;
386
+ expect ( incomingBuffer . length ) . to . equal ( 1 ) ;
387
+
388
+ sentMessages . forEach ( ( m ) => {
389
+ channelB . receiveMessage ( m ) ;
390
+ } ) ;
391
+
392
+ const missingMessages2 = channelB . sweepIncomingBuffer ( ) ;
393
+ expect ( missingMessages2 . length ) . to . equal ( 0 ) ;
394
+
395
+ incomingBuffer = ( channelB as any ) . incomingBuffer as Message [ ] ;
396
+ expect ( incomingBuffer . length ) . to . equal ( 0 ) ;
397
+ } ) ;
398
+
399
+ it ( "should remove messages without delivering if timeout is exceeded" , async ( ) => {
400
+ const causalHistorySize = ( channelA as any ) . causalHistorySize ;
401
+ // Create a channel with very very short timeout
402
+ const channelC : MessageChannel = new MessageChannel (
403
+ channelId ,
404
+ causalHistorySize ,
405
+ true ,
406
+ 10
407
+ ) ;
408
+
409
+ messagesA . forEach ( ( m ) => {
410
+ channelA . sendMessage ( utf8ToBytes ( m ) , callback ) ;
411
+ } ) ;
412
+
413
+ channelA . sendMessage ( utf8ToBytes ( messagesB [ 0 ] ) , ( message ) => {
414
+ channelC . receiveMessage ( message ) ;
415
+ return true ;
416
+ } ) ;
417
+
418
+ const missingMessages = channelC . sweepIncomingBuffer ( ) ;
419
+ expect ( missingMessages . length ) . to . equal ( causalHistorySize ) ;
420
+ let incomingBuffer = ( channelC as any ) . incomingBuffer as Message [ ] ;
421
+ expect ( incomingBuffer . length ) . to . equal ( 1 ) ;
422
+
423
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 20 ) ) ;
424
+
425
+ channelC . sweepIncomingBuffer ( ) ;
426
+ incomingBuffer = ( channelC as any ) . incomingBuffer as Message [ ] ;
427
+ expect ( incomingBuffer . length ) . to . equal ( 0 ) ;
428
+ } ) ;
429
+ } ) ;
430
+
431
+ describe ( "Sweeping outgoing buffer" , ( ) => {
432
+ beforeEach ( ( ) => {
433
+ channelA = new MessageChannel ( channelId ) ;
434
+ channelB = new MessageChannel ( channelId ) ;
435
+ } ) ;
436
+
437
+ it ( "should partition messages based on acknowledgement status" , ( ) => {
438
+ const unacknowledgedMessages : Message [ ] = [ ] ;
439
+ messagesA . forEach ( ( m ) => {
440
+ channelA . sendMessage ( utf8ToBytes ( m ) , ( message ) => {
441
+ unacknowledgedMessages . push ( message ) ;
442
+ channelB . receiveMessage ( message ) ;
443
+ return true ;
444
+ } ) ;
445
+ } ) ;
446
+
447
+ let { unacknowledged, possiblyAcknowledged } =
448
+ channelA . sweepOutgoingBuffer ( ) ;
449
+ expect ( unacknowledged . length ) . to . equal ( messagesA . length ) ;
450
+ expect ( possiblyAcknowledged . length ) . to . equal ( 0 ) ;
451
+
452
+ // Make sure messages sent by channel A are not in causal history
453
+ const causalHistorySize = ( channelA as any ) . causalHistorySize ;
454
+ messagesB . slice ( 0 , causalHistorySize ) . forEach ( ( m ) => {
455
+ channelB . sendMessage ( utf8ToBytes ( m ) , callback ) ;
456
+ } ) ;
457
+
458
+ channelB . sendMessage (
459
+ utf8ToBytes ( messagesB [ causalHistorySize ] ) ,
460
+ ( message ) => {
461
+ channelA . receiveMessage ( message ) ;
462
+ return true ;
463
+ }
464
+ ) ;
465
+
466
+ // All messages that were previously unacknowledged should now be possibly acknowledged
467
+ // since they were included in one of the bloom filters sent from channel B
468
+ ( { unacknowledged, possiblyAcknowledged } =
469
+ channelA . sweepOutgoingBuffer ( ) ) ;
470
+ expect ( unacknowledged . length ) . to . equal ( 0 ) ;
471
+ expect ( possiblyAcknowledged . length ) . to . equal ( messagesA . length ) ;
472
+ } ) ;
473
+ } ) ;
333
474
} ) ;
0 commit comments