Skip to content

Commit

Permalink
Add RealtimeSyncOff and refactor interface of SyncMode
Browse files Browse the repository at this point in the history
  • Loading branch information
7hong13 committed Apr 15, 2024
1 parent f3005a9 commit f205eea
Show file tree
Hide file tree
Showing 12 changed files with 282 additions and 347 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.gson.Gson
import dev.yorkie.core.Client
import dev.yorkie.core.Client.SyncMode.Realtime
import dev.yorkie.core.Client.SyncMode.RealtimePushOnly
import dev.yorkie.core.PresenceInfo
import dev.yorkie.document.Document
import dev.yorkie.document.Document.Event.PresenceChange
Expand Down Expand Up @@ -137,11 +139,11 @@ class EditorViewModel(private val client: Client) : ViewModel(), YorkieEditText.
}

override fun handleHangulCompositionStart() {
client.pause(document)
client.changeSyncMode(document, RealtimePushOnly)
}

override fun handleHangulCompositionEnd() {
client.resume(document)
client.changeSyncMode(document, Realtime)
}

override fun onCleared() {
Expand Down
350 changes: 160 additions & 190 deletions yorkie/src/androidTest/kotlin/dev/yorkie/core/ClientTest.kt

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions yorkie/src/androidTest/kotlin/dev/yorkie/core/DocumentTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.yorkie.core

import androidx.test.ext.junit.runners.AndroidJUnit4
import dev.yorkie.assertJsonContentEquals
import dev.yorkie.core.Client.SyncMode.Manual
import dev.yorkie.document.Document
import dev.yorkie.document.Document.DocumentStatus
import dev.yorkie.document.Document.Event
Expand Down Expand Up @@ -152,11 +153,11 @@ class DocumentTest {
root["key"] = 1
}.await()
c1.activateAsync().await()
c1.attachAsync(d1, isRealTimeSync = false).await()
c1.attachAsync(d1, syncMode = Manual).await()
assertEquals("""{"key":1}""", d1.toJson())

c2.activateAsync().await()
c2.attachAsync(d2, isRealTimeSync = false).await()
c2.attachAsync(d2, syncMode = Manual).await()
assertEquals("""{"key":1}""", d2.toJson())

c1.removeAsync(d1).await()
Expand Down
19 changes: 10 additions & 9 deletions yorkie/src/androidTest/kotlin/dev/yorkie/core/GCTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.yorkie.core

import androidx.test.ext.junit.runners.AndroidJUnit4
import dev.yorkie.assertJsonContentEquals
import dev.yorkie.core.Client.SyncMode.Manual
import dev.yorkie.document.Document
import dev.yorkie.document.crdt.CrdtTreeNode
import dev.yorkie.document.json.JsonObject
Expand Down Expand Up @@ -208,7 +209,7 @@ class GCTest {

@Test
fun test_gc_with_tree_for_multi_client() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
d1.updateAsync { root, _ ->
root.setNewTree(
"t",
Expand Down Expand Up @@ -273,7 +274,7 @@ class GCTest {

@Test
fun test_gc_with_container_type_for_multi_client() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
d1.updateAsync { root, _ ->
root["1"] = 1
root.setNewArray("2").apply {
Expand Down Expand Up @@ -327,7 +328,7 @@ class GCTest {

@Test
fun test_gc_with_text_for_multi_client() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
d1.updateAsync { root, _ ->
root.setNewText("text").edit(0, 0, "Hello World")
root.setNewText("textWithAttr").edit(0, 0, "Hello World")
Expand Down Expand Up @@ -387,7 +388,7 @@ class GCTest {
fun test_gc_with_detached_document() {
withTwoClientsAndDocuments(
detachDocuments = false,
realTimeSync = false,
syncMode = Manual,
) { c1, c2, d1, d2, _ ->
d1.updateAsync { root, _ ->
root["1"] = 1
Expand Down Expand Up @@ -476,7 +477,7 @@ class GCTest {
val document = Document(documentKey)

client.activateAsync().await()
client.attachAsync(document, isRealTimeSync = false).await()
client.attachAsync(document, syncMode = Manual).await()

document.updateAsync { root, _ ->
root["point"] = gson.toJson(Point(0, 0))
Expand Down Expand Up @@ -513,7 +514,7 @@ class GCTest {
c1.activateAsync().await()
c2.activateAsync().await()

c1.attachAsync(d1, isRealTimeSync = false).await()
c1.attachAsync(d1, syncMode = Manual).await()
d1.updateAsync { root, _ ->
root.setNewObject("point").apply {
set("x", 0)
Expand All @@ -524,7 +525,7 @@ class GCTest {
assertEquals(1, d1.garbageLength)
c1.syncAsync().await()

c2.attachAsync(d2, isRealTimeSync = false).await()
c2.attachAsync(d2, syncMode = Manual).await()
assertEquals(1, d2.garbageLength)
d2.updateAsync { root, _ ->
root.getAs<JsonObject>("point")["x"] = 2
Expand Down Expand Up @@ -576,14 +577,14 @@ class GCTest {
c2.activateAsync().await()

// 1. initial state
c1.attachAsync(d1, isRealTimeSync = false).await()
c1.attachAsync(d1, syncMode = Manual).await()
d1.updateAsync { root, _ ->
val point = root.setNewObject("point")
point["x"] = 0
point["y"] = 0
}.await()
c1.syncAsync().await()
c2.attachAsync(d2, isRealTimeSync = false).await()
c2.attachAsync(d2, syncMode = Manual).await()

// 2. client1 updates doc
d1.updateAsync { root, _ ->
Expand Down
38 changes: 20 additions & 18 deletions yorkie/src/androidTest/kotlin/dev/yorkie/core/PresenceTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dev.yorkie.core

import androidx.test.ext.junit.runners.AndroidJUnit4
import dev.yorkie.core.Client.SyncMode.Manual
import dev.yorkie.core.Client.SyncMode.Realtime
import dev.yorkie.document.Document
import dev.yorkie.document.Document.Event.PresenceChange
import dev.yorkie.document.Document.Event.PresenceChange.MyPresence
Expand All @@ -26,7 +28,7 @@ class PresenceTest {

@Test
fun test_presence_from_snapshot() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
val snapshotThreshold = 500
repeat(snapshotThreshold) {
d1.updateAsync { _, presence ->
Expand All @@ -53,7 +55,7 @@ class PresenceTest {
fun test_presence_with_attach_and_detach() {
withTwoClientsAndDocuments(
detachDocuments = false,
realTimeSync = false,
syncMode = Manual,
presences = mapOf("key" to "key1") to mapOf("key" to "key2"),
) { c1, c2, d1, d2, _ ->
assertEquals(mapOf("key" to "key1"), d1.allPresences.value[c1.requireClientId()])
Expand All @@ -74,7 +76,7 @@ class PresenceTest {

@Test
fun test_initial_presence_value_without_manual_initialization() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
val emptyMap = emptyMap<String, String>()
assertEquals(emptyMap, d1.allPresences.value[c1.requireClientId()])
assertNull(d1.allPresences.value[c2.requireClientId()])
Expand Down Expand Up @@ -203,7 +205,7 @@ class PresenceTest {
val updatedCursor = gson.toJson(Cursor(1, 1))

withTwoClientsAndDocuments(
realTimeSync = false,
syncMode = Manual,
presences = mapOf("key" to "key1", "cursor" to previousCursor) to mapOf(
"key" to "key2",
"cursor" to previousCursor,
Expand Down Expand Up @@ -406,7 +408,7 @@ class PresenceTest {

// 01. c2 attaches doc in realtime sync, and c3 attached doc in manual sync.
c2.attachAsync(d2, initialPresence = mapOf("name" to "b1", "cursor" to cursor)).await()
c3.attachAsync(d3, mapOf("name" to "c1", "cursor" to cursor), false).await()
c3.attachAsync(d3, mapOf("name" to "c1", "cursor" to cursor), syncMode = Manual).await()

withTimeout(GENERAL_TIMEOUT) {
// c2 watched
Expand All @@ -423,7 +425,7 @@ class PresenceTest {
assertNull(d1.presences.value[c3ID])

// 02. c2 pauses the document (in manual sync), c3 resumes the document (in realtime sync).
c2.pause(d2)
c2.changeSyncMode(d2, Manual)

withTimeout(GENERAL_TIMEOUT) {
// c2 unwatched
Expand All @@ -433,7 +435,7 @@ class PresenceTest {
}

assertIs<Others.Unwatched>(d1Events.last())
c3.resume(d3)
c3.changeSyncMode(d3, Realtime)

withTimeout(GENERAL_TIMEOUT) {
// c3 watched
Expand Down Expand Up @@ -497,7 +499,7 @@ class PresenceTest {
// 01. c2 attaches doc in realtime sync, and c3 attached doc in manual sync.
// c1 receives the watched event from c2.
c2.attachAsync(d2, initialPresence = mapOf("name" to "b1", "cursor" to cursor)).await()
c3.attachAsync(d3, mapOf("name" to "c1", "cursor" to cursor), false).await()
c3.attachAsync(d3, mapOf("name" to "c1", "cursor" to cursor), syncMode = Manual).await()

withTimeout(GENERAL_TIMEOUT) {
// c2 watched
Expand Down Expand Up @@ -541,7 +543,7 @@ class PresenceTest {
)

// 03-1. c2 pauses the document, c1 receives an unwatched event from c2.
c2.pause(d2)
c2.changeSyncMode(d2, Manual)

withTimeout(GENERAL_TIMEOUT) {
// c2 unwatched
Expand All @@ -564,7 +566,7 @@ class PresenceTest {
c3.syncAsync().await()
c1.syncAsync().await()
delay(50)
c3.resume(d3)
c3.changeSyncMode(d3, Realtime)

withTimeout(GENERAL_TIMEOUT) {
// c3 watched
Expand Down Expand Up @@ -608,7 +610,7 @@ class PresenceTest {
)

// 05-1. c3 pauses the document, c1 receives an unwatched event from c3.
c3.pause(d3)
c3.changeSyncMode(d3, Manual)

withTimeout(GENERAL_TIMEOUT) {
// c3 unwatched
Expand All @@ -627,7 +629,7 @@ class PresenceTest {
c2.syncAsync().await()
c1.syncAsync().await()
delay(50)
c2.resume(d2)
c2.changeSyncMode(d2, Realtime)

withTimeout(GENERAL_TIMEOUT) {
// c2 watched
Expand Down Expand Up @@ -661,7 +663,7 @@ class PresenceTest {
@Test
fun test_receive_document_events_according_to_presence_changes() {
withTwoClientsAndDocuments(
realTimeSync = false,
syncMode = Manual,
detachDocuments = false,
) { c1, c2, d1, d2, _ ->
val d1Events = mutableListOf<PresenceChange>()
Expand Down Expand Up @@ -690,13 +692,13 @@ class PresenceTest {
}

// c1 in realtime sync
c1.resume(d1)
c1.changeSyncMode(d1, Realtime)
d2.updateAsync { _, presence ->
presence.put(mapOf("k1" to "v1"))
}.await()

// c2 in realtime sync
c2.resume(d2)
c2.changeSyncMode(d2, Realtime)

withTimeout(GENERAL_TIMEOUT) {
// watched, presence changed
Expand Down Expand Up @@ -726,14 +728,14 @@ class PresenceTest {

@Test
fun test_emit_the_same_presence_multiple_times() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
val d1Events = mutableListOf<PresenceChange>()
val collectJob = launch(start = CoroutineStart.UNDISPATCHED) {
d1.events.filterIsInstance<Others>().collect(d1Events::add)
}

c1.resume(d1)
c2.resume(d2)
c1.changeSyncMode(d1, Realtime)
c2.changeSyncMode(d2, Realtime)

d2.updateAsync { _, presence ->
presence.put(mapOf("a" to "b"))
Expand Down
6 changes: 3 additions & 3 deletions yorkie/src/androidTest/kotlin/dev/yorkie/core/TestUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fun String.toDocKey(): Document.Key {

fun withTwoClientsAndDocuments(
detachDocuments: Boolean = true,
realTimeSync: Boolean = true,
syncMode: Client.SyncMode = Client.SyncMode.Realtime,
presences: Pair<Map<String, String>, Map<String, String>> = Pair(emptyMap(), emptyMap()),
callback: suspend CoroutineScope.(Client, Client, Document, Document, Document.Key) -> Unit,
) {
Expand All @@ -41,12 +41,12 @@ fun withTwoClientsAndDocuments(

client1.attachAsync(
document1,
isRealTimeSync = realTimeSync,
syncMode = syncMode,
initialPresence = presences.first,
).await()
client2.attachAsync(
document2,
isRealTimeSync = realTimeSync,
syncMode = syncMode,
initialPresence = presences.second,
).await()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.yorkie.document.json

import androidx.test.ext.junit.runners.AndroidJUnit4
import dev.yorkie.assertJsonContentEquals
import dev.yorkie.core.Client.SyncMode.Manual
import dev.yorkie.core.withTwoClientsAndDocuments
import org.junit.Test
import org.junit.runner.RunWith
Expand All @@ -11,7 +12,7 @@ class JsonTextTest {

@Test
fun test_concurrent_insertion_and_deletion() {
withTwoClientsAndDocuments(realTimeSync = false) { c1, c2, d1, d2, _ ->
withTwoClientsAndDocuments(syncMode = Manual) { c1, c2, d1, d2, _ ->
d1.updateAsync { root, _ ->
root.setNewText("k1").apply {
edit(0, 0, "AB")
Expand Down
Loading

0 comments on commit f205eea

Please sign in to comment.