Skip to content

Commit

Permalink
Prevent remote-change events in RealtimeSyncOff mode
Browse files Browse the repository at this point in the history
  • Loading branch information
7hong13 committed May 29, 2024
1 parent b552be7 commit 74d7268
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
71 changes: 71 additions & 0 deletions yorkie/src/androidTest/kotlin/dev/yorkie/core/ClientTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -697,4 +697,75 @@ class ClientTest {
d1.close()
}
}

@Test
fun test_prevent_remote_changes_in_sync_off() {
withTwoClientsAndDocuments { c1, c2, d1, d2, _ ->
val d1Events = mutableListOf<Document.Event>()
val d2Events = mutableListOf<Document.Event>()
val collectJobs = listOf(
launch(start = CoroutineStart.UNDISPATCHED) {
d1.events.filter { it is RemoteChange || it is LocalChange }
.collect(d1Events::add)
},
launch(start = CoroutineStart.UNDISPATCHED) {
d2.events.filter { it is RemoteChange || it is LocalChange }
.collect(d2Events::add)
},
)

d1.updateAsync { root, _ ->
root.setNewTree(
"t",
element("doc") {
element("p") { text { "12" } }
element("p") { text { "34" } }
},
)
}.await()

withTimeout(GENERAL_TIMEOUT) {
while (d2Events.isEmpty()) {
delay(50)
}
}
assertIs<RemoteChange>(d2Events.first())
assertTreesXmlEquals("<doc><p>12</p><p>34</p></doc>", d1, d2)

d1.updateAsync { root, _ ->
root.rootTree().edit(2, 2, text { "a" })
}.await()
c1.syncAsync().await()

// Simulate the situation in the runSyncLoop where a pushpull request has been sent
// but a response has not yet been received.
d2Events.clear()
val deferred = c2.syncAsync()
c2.changeSyncMode(d2, RealtimeSyncOff)
deferred.await()

// In push-only mode, remote-change events should not occur.
d2Events.clear()
c2.changeSyncMode(d2, RealtimeSyncOff)

delay(100) // Keep the sync-off state.
assertTrue(d2Events.none { it is RemoteChange })

c2.changeSyncMode(d2, Realtime)

d2.updateAsync { root, _ ->
root.rootTree().edit(2, 2, text { "b" })
}.await()

withTimeout(GENERAL_TIMEOUT) {
while (d1Events.size < 3) {
delay(50)
}
}
assertIs<RemoteChange>(d1Events.last())
assertTreesXmlEquals("<doc><p>1ba2</p><p>34</p></doc>", d1)

collectJobs.forEach(Job::cancel)
}
}
}
4 changes: 3 additions & 1 deletion yorkie/src/main/kotlin/dev/yorkie/core/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,10 @@ public class Client @VisibleForTesting internal constructor(
val responsePack = response.changePack.toChangePack()
// NOTE(7hong13, chacha912, hackerwins): If syncLoop already executed with
// PushPull, ignore the response when the syncMode is PushOnly.
val currentSyncMode = attachments.value[document.key]?.syncMode
if (responsePack.hasChanges &&
attachments.value[document.key]?.syncMode == SyncMode.RealtimePushOnly
currentSyncMode == SyncMode.RealtimePushOnly ||
currentSyncMode == SyncMode.RealtimeSyncOff
) {
return@runCatching
}
Expand Down

0 comments on commit 74d7268

Please sign in to comment.