@@ -435,6 +435,9 @@ describe('SyncEngineLevel', () => {
435
435
it ( 'silently ignores a messageCid that already exists on the local DWN' , async ( ) => {
436
436
// scenario: The messageCids returned from the remote eventLog contains a messageCid that already exists on the local DWN.
437
437
// During sync, when processing the messageCid the local DWN will return a conflict response, but the sync should continue
438
+ //
439
+ // NOTE: When deleting a message, the conflicting Delete will return a 404 instead of a 409,
440
+ // the sync should still mark the message as synced and continue
438
441
439
442
// create a record and store it locally and remotely
440
443
const remoteAndLocalRecord = await testHarness . agent . processDwnRequest ( {
@@ -456,6 +459,23 @@ describe('SyncEngineLevel', () => {
456
459
messageCid : remoteAndLocalRecord . messageCid ,
457
460
} ) ;
458
461
462
+ // delete the record both locally and remotely
463
+ const deleteMessage = await testHarness . agent . processDwnRequest ( {
464
+ author : alice . did . uri ,
465
+ target : alice . did . uri ,
466
+ messageType : DwnInterface . RecordsDelete ,
467
+ messageParams : {
468
+ recordId : remoteAndLocalRecord . message ! . recordId
469
+ }
470
+ } ) ;
471
+ // send the delete to the remote
472
+ await testHarness . agent . sendDwnRequest ( {
473
+ author : alice . did . uri ,
474
+ target : alice . did . uri ,
475
+ messageType : DwnInterface . RecordsDelete ,
476
+ messageCid : deleteMessage . messageCid ,
477
+ } ) ;
478
+
459
479
// create 2 records stored only remotely to later sync to the local DWN
460
480
const record1 = await testHarness . agent . sendDwnRequest ( {
461
481
author : alice . did . uri ,
@@ -481,7 +501,7 @@ describe('SyncEngineLevel', () => {
481
501
} ) ;
482
502
expect ( record2 . reply . status . code ) . to . equal ( 202 ) ;
483
503
484
- // confirm that only the single record exists locally
504
+ // confirm that only the record and it's delete exists locally
485
505
let localQueryResponse = await testHarness . agent . processDwnRequest ( {
486
506
author : alice . did . uri ,
487
507
target : alice . did . uri ,
@@ -492,12 +512,16 @@ describe('SyncEngineLevel', () => {
492
512
} ) ;
493
513
494
514
let localDwnQueryEntries = localQueryResponse . reply . entries ! ;
495
- expect ( localDwnQueryEntries . length ) . to . equal ( 1 ) ;
496
- expect ( localDwnQueryEntries ) . to . have . members ( [ remoteAndLocalRecord . messageCid ] ) ;
515
+ expect ( localDwnQueryEntries . length ) . to . equal ( 2 ) ;
516
+ expect ( localDwnQueryEntries ) . to . have . members ( [
517
+ remoteAndLocalRecord . messageCid ,
518
+ deleteMessage . messageCid
519
+ ] ) ;
497
520
498
521
// stub getDwnEventLog to return the messageCids of the records we want to sync
499
522
sinon . stub ( syncEngine as any , 'getDwnEventLog' ) . resolves ( [
500
523
remoteAndLocalRecord . messageCid ,
524
+ deleteMessage . messageCid ,
501
525
record1 . messageCid ,
502
526
record2 . messageCid
503
527
] ) ;
@@ -514,17 +538,19 @@ describe('SyncEngineLevel', () => {
514
538
// Execute Sync to push records to Alice's remote node
515
539
await syncEngine . pull ( ) ;
516
540
517
- // Verify sendDwnRequest is called for all 3 records
518
- expect ( sendDwnRequestSpy . callCount ) . to . equal ( 3 , 'sendDwnRequestSpy' ) ;
519
- // Verify that processMessage is called for all 3 records
520
- expect ( processMessageSpy . callCount ) . to . equal ( 3 , 'processMessageSpy' ) ;
541
+ // Verify sendDwnRequest is called for all 4 messages
542
+ expect ( sendDwnRequestSpy . callCount ) . to . equal ( 4 , 'sendDwnRequestSpy' ) ;
543
+ // Verify that processMessage is called for all 4 messages
544
+ expect ( processMessageSpy . callCount ) . to . equal ( 4 , 'processMessageSpy' ) ;
521
545
522
546
// Verify that the conflict response is returned for the record that already exists locally
523
547
expect ( ( await processMessageSpy . firstCall . returnValue ) . status . code ) . to . equal ( 409 ) ;
548
+ // Verify that the delete message returned a 404
549
+ expect ( ( await processMessageSpy . secondCall . returnValue ) . status . code ) . to . equal ( 404 ) ;
524
550
525
551
// Verify that the other 2 records are successfully processed
526
- expect ( ( await processMessageSpy . secondCall . returnValue ) . status . code ) . to . equal ( 202 ) ;
527
- expect ( ( await processMessageSpy . thirdCall . returnValue ) . status . code ) . to . equal ( 202 ) ;
552
+ expect ( ( await processMessageSpy . returnValues [ 2 ] ) . status . code ) . to . equal ( 202 ) ;
553
+ expect ( ( await processMessageSpy . returnValues [ 3 ] ) . status . code ) . to . equal ( 202 ) ;
528
554
529
555
// confirm the new records exist remotely
530
556
localQueryResponse = await testHarness . agent . processDwnRequest ( {
@@ -536,9 +562,10 @@ describe('SyncEngineLevel', () => {
536
562
} ,
537
563
} ) ;
538
564
localDwnQueryEntries = localQueryResponse . reply . entries ! ;
539
- expect ( localDwnQueryEntries . length ) . to . equal ( 3 ) ;
565
+ expect ( localDwnQueryEntries . length ) . to . equal ( 4 ) ;
540
566
expect ( localDwnQueryEntries ) . to . have . members ( [
541
567
remoteAndLocalRecord . messageCid ,
568
+ deleteMessage . messageCid ,
542
569
record1 . messageCid ,
543
570
record2 . messageCid
544
571
] ) ;
@@ -901,6 +928,8 @@ describe('SyncEngineLevel', () => {
901
928
902
929
// scenario: The messageCids returned from the local eventLog contains a Cid that already exists in the remote DWN.
903
930
// During sync, the remote DWN will return a conflict 409 status code and the sync should continue
931
+ // NOTE: if the messageCid is a delete message and it is already deleted,
932
+ // the remote DWN will return a 404 status code and the sync should continue
904
933
905
934
// create a record, store it and send it to the remote Dwn
906
935
const remoteAndLocalRecord = await testHarness . agent . processDwnRequest ( {
@@ -922,6 +951,23 @@ describe('SyncEngineLevel', () => {
922
951
messageCid : remoteAndLocalRecord . messageCid ,
923
952
} ) ;
924
953
954
+ // delete the record both locally and remotely
955
+ const deleteMessage = await testHarness . agent . processDwnRequest ( {
956
+ author : alice . did . uri ,
957
+ target : alice . did . uri ,
958
+ messageType : DwnInterface . RecordsDelete ,
959
+ messageParams : {
960
+ recordId : remoteAndLocalRecord . message ! . recordId
961
+ }
962
+ } ) ;
963
+ // send the delete to the remote
964
+ await testHarness . agent . sendDwnRequest ( {
965
+ author : alice . did . uri ,
966
+ target : alice . did . uri ,
967
+ messageType : DwnInterface . RecordsDelete ,
968
+ messageCid : deleteMessage . messageCid ,
969
+ } ) ;
970
+
925
971
// create 2 records stored only locally to sync to the remote DWN
926
972
const record1 = await testHarness . agent . processDwnRequest ( {
927
973
author : alice . did . uri ,
@@ -947,7 +993,7 @@ describe('SyncEngineLevel', () => {
947
993
} ) ;
948
994
expect ( record2 . reply . status . code ) . to . equal ( 202 ) ;
949
995
950
- // confirm that only the single record exists remotely
996
+ // confirm that only record and it's delete exist remotely
951
997
let remoteQueryResponse = await testHarness . agent . sendDwnRequest ( {
952
998
author : alice . did . uri ,
953
999
target : alice . did . uri ,
@@ -958,13 +1004,14 @@ describe('SyncEngineLevel', () => {
958
1004
} ) ;
959
1005
960
1006
let remoteDwnQueryEntries = remoteQueryResponse . reply . entries ! ;
961
- expect ( remoteDwnQueryEntries . length ) . to . equal ( 1 ) ;
962
- expect ( remoteDwnQueryEntries ) . to . have . members ( [ remoteAndLocalRecord . messageCid ] ) ;
1007
+ expect ( remoteDwnQueryEntries . length ) . to . equal ( 2 ) ;
1008
+ expect ( remoteDwnQueryEntries ) . to . have . members ( [ remoteAndLocalRecord . messageCid , deleteMessage . messageCid ] ) ;
963
1009
964
1010
// stub getDwnEventLog to return the messageCids of the records we want to sync
965
1011
// we stub this to avoid syncing the registered identity related messages
966
1012
sinon . stub ( syncEngine as any , 'getDwnEventLog' ) . resolves ( [
967
1013
remoteAndLocalRecord . messageCid ,
1014
+ deleteMessage . messageCid ,
968
1015
record1 . messageCid ,
969
1016
record2 . messageCid
970
1017
] ) ;
@@ -975,8 +1022,17 @@ describe('SyncEngineLevel', () => {
975
1022
// Execute Sync to push records to Alice's remote node
976
1023
await syncEngine . push ( ) ;
977
1024
978
- // Verify sendDwnRequest was called once for each record including the one that already exists remotely
979
- expect ( sendDwnRequestSpy . callCount ) . to . equal ( 3 ) ;
1025
+ // Verify sendDwnRequest was called once for each record including the ones that already exist remotely
1026
+ expect ( sendDwnRequestSpy . callCount ) . to . equal ( 4 ) ;
1027
+
1028
+ // Verify that the conflict response is returned for the record that already exists remotely
1029
+ expect ( ( await sendDwnRequestSpy . firstCall . returnValue ) . status . code ) . to . equal ( 409 ) ;
1030
+ // Verify that the delete message returned a 404
1031
+ expect ( ( await sendDwnRequestSpy . secondCall . returnValue ) . status . code ) . to . equal ( 404 ) ;
1032
+
1033
+ // Verify that the other 2 records are successfully processed
1034
+ expect ( ( await sendDwnRequestSpy . returnValues [ 2 ] ) . status . code ) . to . equal ( 202 ) ;
1035
+ expect ( ( await sendDwnRequestSpy . returnValues [ 3 ] ) . status . code ) . to . equal ( 202 ) ;
980
1036
981
1037
// confirm the new records exist remotely
982
1038
remoteQueryResponse = await testHarness . agent . sendDwnRequest ( {
@@ -988,9 +1044,10 @@ describe('SyncEngineLevel', () => {
988
1044
} ,
989
1045
} ) ;
990
1046
remoteDwnQueryEntries = remoteQueryResponse . reply . entries ! ;
991
- expect ( remoteDwnQueryEntries . length ) . to . equal ( 3 ) ;
1047
+ expect ( remoteDwnQueryEntries . length ) . to . equal ( 4 ) ;
992
1048
expect ( remoteDwnQueryEntries ) . to . have . members ( [
993
1049
remoteAndLocalRecord . messageCid ,
1050
+ deleteMessage . messageCid ,
994
1051
record1 . messageCid ,
995
1052
record2 . messageCid
996
1053
] ) ;
0 commit comments