Skip to content

Commit 9ffca7d

Browse files
authored
Sync android-sdk with js-sdk: Implement updates to v0.6.1 (#223)
* Add keepAlive option when detach a document * Set Yorkie Server Url in gh-pages and publish CI/CD
1 parent 3ea6827 commit 9ffca7d

File tree

4 files changed

+74
-13
lines changed

4 files changed

+74
-13
lines changed

.github/workflows/gh-pages.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ jobs:
1515
java-version: '17'
1616
distribution: 'temurin'
1717
cache: gradle
18+
- name: Set Yorkie Server Url
19+
run: echo YORKIE_SERVER_URL="https://api.yorkie.dev" > ./local.properties
1820
- run: ./gradlew dokkaHtml --no-configuration-cache
1921
- uses: JamesIves/[email protected]
2022
with:

.github/workflows/publish.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ jobs:
1313
java-version: "17"
1414
distribution: "temurin"
1515
cache: gradle
16+
- name: Set Yorkie Server Url
17+
run: echo YORKIE_SERVER_URL="https://api.yorkie.dev" > ./local.properties
1618
- run: chmod +x gradlew
1719
- uses: gradle/gradle-build-action@v2
1820
with:

yorkie/src/main/kotlin/dev/yorkie/core/Client.kt

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -684,20 +684,24 @@ public class Client(
684684
* the changes should be applied to other replicas before GC time. For this,
685685
* if the [document] is no longer used by this [Client], it should be detached.
686686
*/
687-
public fun detachAsync(document: Document): Deferred<OperationResult> {
688-
return scope.async {
689-
checkYorkieError(
690-
isActive,
691-
YorkieException(ErrClientNotActivated, "client is not active"),
687+
@OptIn(DelicateCoroutinesApi::class)
688+
public fun detachAsync(
689+
document: Document,
690+
keepalive: Boolean = false,
691+
): Deferred<OperationResult> {
692+
checkYorkieError(
693+
isActive,
694+
YorkieException(ErrClientNotActivated, "client is not active"),
695+
)
696+
697+
val attachment = attachments.value[document.key]
698+
?: throw YorkieException(
699+
ErrDocumentNotAttached,
700+
"document(${document.key}) is not attached",
692701
)
693702

703+
val task = suspend suspend@{
694704
document.mutex.withLock {
695-
val attachment = attachments.value[document.key]
696-
?: throw YorkieException(
697-
ErrDocumentNotAttached,
698-
"document(${document.key}) is not attached",
699-
)
700-
701705
document.updateAsync { _, presence ->
702706
presence.clear()
703707
}.await()
@@ -711,14 +715,13 @@ public class Client(
711715
request,
712716
document.key.documentBasedRequestHeader,
713717
).getOrElse {
714-
ensureActive()
715718
handleConnectException(it) { exception ->
716719
if (errorCodeOf(exception) == ErrUnauthenticated.codeString) {
717720
shouldRefreshToken = true
718721
}
719722
deactivateInternal()
720723
}
721-
return@async Result.failure(it)
724+
return@suspend Result.failure(it)
722725
}
723726
val pack = response.changePack.toChangePack()
724727
document.applyChangePack(pack)
@@ -729,6 +732,18 @@ public class Client(
729732
}
730733
SUCCESS
731734
}
735+
736+
return if (keepalive) {
737+
GlobalScope.async(Dispatchers.IO) {
738+
withContext(NonCancellable) {
739+
task()
740+
}
741+
}
742+
} else {
743+
scope.async {
744+
task()
745+
}
746+
}
732747
}
733748

734749
private fun detachInternal(document: Document) {

yorkie/src/test/kotlin/dev/yorkie/core/ClientTest.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import dev.yorkie.core.MockYorkieService.Companion.TEST_KEY
2323
import dev.yorkie.core.MockYorkieService.Companion.TEST_USER_ID
2424
import dev.yorkie.core.MockYorkieService.Companion.WATCH_SYNC_ERROR_DOCUMENT_KEY
2525
import dev.yorkie.document.Document
26+
import dev.yorkie.document.Document.DocStatus
2627
import dev.yorkie.document.Document.Event.StreamConnectionChanged
2728
import dev.yorkie.document.Document.Event.SyncStatusChanged
2829
import dev.yorkie.document.Document.Key
@@ -407,6 +408,47 @@ class ClientTest {
407408
}
408409
}
409410

411+
@Test
412+
fun `detachAsync with keepalive true should work even after client close`() = runTest {
413+
val service = spyk(MockYorkieService())
414+
val client = Client(
415+
options = Client.Options(
416+
key = TEST_KEY,
417+
apiKey = TEST_KEY,
418+
),
419+
unaryClient = OkHttpClient(),
420+
streamClient = OkHttpClient(),
421+
dispatcher = createSingleThreadDispatcher("Client Test"),
422+
host = "0.0.0.0",
423+
)
424+
client.service = service
425+
426+
val document = Document(Key(NORMAL_DOCUMENT_KEY))
427+
428+
// Activate and attach document
429+
client.activateAsync().await()
430+
client.attachAsync(document, syncMode = Manual).await()
431+
assertEquals(DocStatus.Attached, document.status)
432+
433+
// Start detach with keepalive = true
434+
val detachDeferred = async {
435+
client.detachAsync(document, keepalive = true).await()
436+
}
437+
438+
// Add a small delay to ensure the detach has started
439+
delay(10)
440+
441+
// Close the client while detach might still be in progress
442+
client.close()
443+
444+
// Wait for detach to complete
445+
val result = detachDeferred.await()
446+
447+
// Verify that detach completed successfully despite client being closed
448+
assertTrue(result.isSuccess)
449+
assertEquals(DocStatus.Detached, document.status)
450+
}
451+
410452
private fun assertIsTestActorID(clientId: String) {
411453
assertEquals(TEST_ACTOR_ID, ActorID(clientId))
412454
}

0 commit comments

Comments
 (0)