Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform networking #1528

Merged
merged 53 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
88c9565
Using platform networking for Sync Websocket
nhachicha Sep 25, 2023
49c757d
Merge remote-tracking branch 'origin/main' into nh/platform_networking
nhachicha Sep 25, 2023
2470859
Disabling removed C-API method
nhachicha Sep 26, 2023
824e049
Completing appropriately the Sync callbacks
nhachicha Oct 5, 2023
e521d62
Fixes
nhachicha Oct 6, 2023
455ab2e
Merge remote-tracking branch 'origin/main' into nh/platform_networking
nhachicha Oct 6, 2023
698e86a
Fixing Swig
nhachicha Oct 6, 2023
d64b0b2
Fixing indentation
nhachicha Oct 6, 2023
16b62ab
Fixing test
nhachicha Oct 6, 2023
3505926
Adding a flag to run new platform selectively on CI
nhachicha Oct 6, 2023
aa38a74
Fixing tests/cleanup
nhachicha Oct 9, 2023
01e6d62
Using daemon thread for sync client while Core add support to Thread …
nhachicha Oct 10, 2023
c92871c
Proguard fix
nhachicha Oct 10, 2023
2c68075
Update changelog
nhachicha Oct 11, 2023
bb4105b
Initial PR feedback
nhachicha Oct 12, 2023
4de15a9
Fix indentation
nhachicha Oct 12, 2023
da49df3
Bump Core
nhachicha Oct 12, 2023
7133797
Fixing renamed types
nhachicha Oct 12, 2023
5098395
Bump core to version 13.23.0
clementetb Oct 12, 2023
c0180c5
Remove workaround for realm file name
clementetb Oct 16, 2023
5234ba4
Update metadata schema version
clementetb Oct 16, 2023
ed8e5f9
Update name test cases
clementetb Oct 16, 2023
8da19a0
Update test cases
clementetb Oct 17, 2023
19bc7c8
Update core
nhachicha Oct 17, 2023
ed1b5a9
Disabling path tests until they are fixed on main
nhachicha Oct 17, 2023
dc02b10
Bump core commit
clementetb Oct 18, 2023
98e718d
Update packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mo…
nhachicha Oct 18, 2023
8fc52a9
Fix client reset flaky test
clementetb Oct 18, 2023
ee4fe03
bump baas
clementetb Oct 18, 2023
bacf3b0
Fix test case
clementetb Oct 18, 2023
f0b5f6a
PR feedback
nhachicha Oct 18, 2023
5e141da
Merge remote-tracking branch 'origin/ct/bump-core-13.23.0' into nh/pl…
nhachicha Oct 18, 2023
b62ba74
Merge remote-tracking branch 'origin/main' into nh/platform_networking
nhachicha Oct 19, 2023
dd37a22
Fixing tests
nhachicha Oct 19, 2023
073e4be
Fixing test
nhachicha Oct 20, 2023
0e41956
- Update Core
nhachicha Oct 23, 2023
0105a73
unused import
nhachicha Oct 23, 2023
aecef93
Reverting changes
nhachicha Oct 24, 2023
1120c1b
- Revert engines to OkHttp for JVM and Android and CIO for Darwin
nhachicha Nov 1, 2023
ea50805
Merge remote-tracking branch 'origin/main' into nh/platform_networking
nhachicha Nov 1, 2023
fed3971
Disabling Darwin Sync tests
nhachicha Nov 1, 2023
fdb717a
- Update Core commit
nhachicha Nov 1, 2023
50639db
Reworked the Ktor Websocket Trasnport to use OkHttp for JVM and Andro…
nhachicha Nov 25, 2023
042eb8a
- Cancelled callback when Websocket is closed
nhachicha Nov 30, 2023
ccda0ec
Merge remote-tracking branch 'origin/main' into nh/platform_networking
nhachicha Dec 4, 2023
71359d3
fixing compile error
nhachicha Dec 4, 2023
a55e9ed
fixing test
nhachicha Dec 5, 2023
96be9c1
PR feedback
nhachicha Dec 6, 2023
486686c
Merge remote-tracking branch 'origin/main' into nh/platform_networking
nhachicha Dec 6, 2023
0ae12f8
Added removed configuration
nhachicha Dec 6, 2023
d491fee
PR feedback
nhachicha Dec 11, 2023
e423e3e
Merge branch 'main' into nh/platform_networking
nhachicha Dec 11, 2023
0c8dca8
- Unused imports
nhachicha Dec 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ This release upgrades the Sync metadata in a way that is not compatible with old
* Fix error in `RealmAny.equals` that would sometimes return `true` when comparing RealmAnys wrapping same type but different values. (Issue [#1523](https://github.com/realm/realm-kotlin/pull/1523))
* [Sync] If calling a function on App Services that resulted in a redirect, it would only redirect for GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517))
* [Sync] Manual client reset on Windows would not trigger correctly when run inside `onManualResetFallback`. (Issue [#1515](https://github.com/realm/realm-kotlin/pull/1515))
* [Sync] `ClientResetRequiredException.executeClientReset()` now returns a boolean indicating if the manual reset fully succeded or not. (Issue [#1515](https://github.com/realm/realm-kotlin/pull/1515))
* [Sync] `ClientResetRequiredException.executeClientReset()` now returns a boolean indicating if the manual reset fully succeeded or not. (Issue [#1515](https://github.com/realm/realm-kotlin/pull/1515))
* [Sync] If calling a function on App Services that resulted in a redirect, it would only redirect for
GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517))
* [Sync] If calling a function on App Services that resulted in a redirect, it would only redirect for GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517))
* [Sync] Added option to use managed WebSockets via Ktor instead of Realm's built-in WebSocket client for Sync traffic. Managed WebSockets offer improved support for proxies and firewalls that require authentication. This feature is currently opt-in and can be enabled by using `AppConfiguration.usePlatformNetworking()`. Managed WebSockets will become the default in a future version. (PR [#1528](https://github.com/realm/realm-kotlin/pull/1528)).

### Compatibility
* File format: Generates Realms with file format v23.
Expand All @@ -35,6 +36,9 @@ GET requests. (Issue [#1517](https://github.com/realm/realm-kotlin/pull/1517))

### Internal
* Updated to Realm Core 13.23.2, commit e6271d72308b40399890060f58a88cf568c2ee22.
* Update to Ktor 2.3.4.
* Switched Ktor engine to CIO for Darwin to work around https://youtrack.jetbrains.com/issue/KTOR-6267.
* Updated to CMake 3.27.7


## 1.11.1 (2023-09-07)
Expand Down
6 changes: 3 additions & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ pipeline {
"integrationtest",
{
forwardAdbPorts()
testAndCollect("packages", "cleanAllTests -PincludeSdkModules=false connectedAndroidTest")
testAndCollect("packages", "cleanAllTests -PsyncUsePlatformNetworking=true -PincludeSdkModules=false connectedAndroidTest")
}
)
}
Expand All @@ -212,7 +212,7 @@ pipeline {
steps {
testWithServer([
{
testAndCollect("packages", 'cleanAllTests jvmTest -PincludeSdkModules=false ')
testAndCollect("packages", 'cleanAllTests jvmTest -PsyncUsePlatformNetworking=true -PincludeSdkModules=false ')
}
])
}
Expand All @@ -232,7 +232,7 @@ pipeline {
steps {
testWithServer([
{
testAndCollect("packages", 'cleanAllTests :test-sync:connectedAndroidtest -PincludeSdkModules=false -PtestBuildType=debugMinified')
testAndCollect("packages", 'cleanAllTests :test-sync:connectedAndroidtest -PsyncUsePlatformNetworking=true -PincludeSdkModules=false -PtestBuildType=debugMinified')
}
])
sh 'rm mapping.zip || true'
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ object Versions {
const val buildkonfig = "0.13.3" // https://github.com/yshrsmz/BuildKonfig
// Not currently used, so mostly here for documentation. Core requires minimum 3.15, but 3.18.1 is available through the Android SDK.
// Build also tested successfully with 3.21.4 (latest release).
const val cmake = "3.22.1"
const val cmake = "3.27.7"
const val coroutines = "1.7.0" // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core
const val datetime = "0.4.0" // https://github.com/Kotlin/kotlinx-datetime
const val detektPlugin = "1.22.0-RC2" // https://github.com/detekt/detekt
Expand All @@ -131,7 +131,7 @@ object Versions {
const val latestKotlin = "1.9.20-Beta" // https://kotlinlang.org/docs/eap.html#build-details
const val kotlinCompileTesting = "1.5.0" // https://github.com/tschuchortdev/kotlin-compile-testing
const val ktlint = "0.45.2" // https://github.com/pinterest/ktlint
const val ktor = "2.1.2" // https://github.com/ktorio/ktor
const val ktor = "2.3.4" // https://github.com/ktorio/ktor
nhachicha marked this conversation as resolved.
Show resolved Hide resolved
const val multidex = "2.0.1" // https://developer.android.com/jetpack/androidx/releases/multidex
const val nexusPublishPlugin = "1.1.0" // https://github.com/gradle-nexus/publish-plugin
const val okio = "3.2.0" // https://square.github.io/okio/#releases
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import io.realm.kotlin.internal.interop.sync.NetworkTransport
import io.realm.kotlin.internal.interop.sync.ProgressDirection
import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode
import io.realm.kotlin.internal.interop.sync.SyncUserIdentity
import io.realm.kotlin.internal.interop.sync.WebSocketTransport
import io.realm.kotlin.internal.interop.sync.WebsocketCallbackResult
import io.realm.kotlin.internal.interop.sync.WebsocketErrorCode
import kotlinx.coroutines.CoroutineDispatcher
import org.mongodb.kbson.ObjectId
import kotlin.jvm.JvmInline
Expand Down Expand Up @@ -101,9 +104,15 @@ interface RealmUserT : CapiT
interface RealmNetworkTransportT : CapiT
interface RealmSyncSessionT : CapiT
interface RealmSubscriptionT : CapiT
interface RealmSyncSocketObserverPointerT : CapiT
interface RealmSyncSocketCallbackPointerT : CapiT

interface RealmBaseSubscriptionSet : CapiT
interface RealmSyncSocket : CapiT
interface RealmSubscriptionSetT : RealmBaseSubscriptionSet
interface RealmMutableSubscriptionSetT : RealmBaseSubscriptionSet
interface RealmSyncSocketT : RealmSyncSocket

// Public type aliases binding to internal verbose type safe type definitions. This should allow us
// to easily change implementation details later on.
typealias RealmAsyncOpenTaskPointer = NativePointer<RealmAsyncOpenTaskT>
Expand All @@ -119,7 +128,11 @@ typealias RealmSubscriptionPointer = NativePointer<RealmSubscriptionT>
typealias RealmBaseSubscriptionSetPointer = NativePointer<out RealmBaseSubscriptionSet>
typealias RealmSubscriptionSetPointer = NativePointer<RealmSubscriptionSetT>
typealias RealmMutableSubscriptionSetPointer = NativePointer<RealmMutableSubscriptionSetT>

typealias RealmSyncSocketPointer = NativePointer<RealmSyncSocketT>
typealias RealmSyncSocketObserverPointer = NativePointer<RealmSyncSocketObserverPointerT>
typealias RealmSyncSocketCallbackPointer = NativePointer<RealmSyncSocketCallbackPointerT>
typealias RealmWebsocketHandlerCallbackPointer = NativePointer<CapiT>
typealias RealmWebsocketProviderPointer = NativePointer<CapiT>
/**
* Class for grouping and normalizing values we want to send as part of
* logging in Sync Users.
Expand Down Expand Up @@ -486,7 +499,6 @@ expect object RealmInterop {
fun realm_app_link_credentials(app: RealmAppPointer, user: RealmUserPointer, credentials: RealmCredentialsPointer, callback: AppCallback<RealmUserPointer>)
fun realm_clear_cached_apps()
fun realm_app_sync_client_get_default_file_path_for_realm(
app: RealmAppPointer,
syncConfig: RealmSyncConfigurationPointer,
overriddenName: String?
): String
Expand Down Expand Up @@ -785,4 +797,22 @@ expect object RealmInterop {
fun realm_sync_subscriptionset_commit(
mutableSubscriptionSet: RealmMutableSubscriptionSetPointer
): RealmSubscriptionSetPointer

fun realm_sync_set_websocket_transport(
syncClientConfig: RealmSyncClientConfigurationPointer,
webSocketTransport: WebSocketTransport
)

fun realm_sync_socket_callback_complete(nativePointer: RealmWebsocketHandlerCallbackPointer, cancelled: Boolean = false, status: WebsocketCallbackResult = WebsocketCallbackResult.RLM_ERR_SYNC_SOCKET_SUCCESS, reason: String = "")

fun realm_sync_socket_websocket_connected(nativePointer: RealmWebsocketProviderPointer, protocol: String)

fun realm_sync_socket_websocket_error(nativePointer: RealmWebsocketProviderPointer)

fun realm_sync_socket_websocket_message(
nativePointer: RealmWebsocketProviderPointer,
data: ByteArray
): Boolean

fun realm_sync_socket_websocket_closed(nativePointer: RealmWebsocketProviderPointer, wasClean: Boolean, errorCode: WebsocketErrorCode, reason: String = "")
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ expect enum class WebsocketErrorCode : CodeDescription {
RLM_ERR_WEBSOCKET_FATAL_ERROR;

companion object {
internal fun of(nativeValue: Int): WebsocketErrorCode?
fun of(nativeValue: Int): WebsocketErrorCode?
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package io.realm.kotlin.internal.interop.sync
nhachicha marked this conversation as resolved.
Show resolved Hide resolved

import io.realm.kotlin.internal.interop.RealmInterop
import io.realm.kotlin.internal.interop.RealmWebsocketHandlerCallbackPointer
import io.realm.kotlin.internal.interop.RealmWebsocketProviderPointer
import kotlinx.coroutines.Job

interface WebSocketTransport {
nhachicha marked this conversation as resolved.
Show resolved Hide resolved
fun post(handlerCallback: RealmWebsocketHandlerCallbackPointer)

fun createTimer(
delayInMilliseconds: Long,
handlerCallback: RealmWebsocketHandlerCallbackPointer,
): CancellableTimer

@Suppress("LongParameterList")
fun connect(
observer: WebSocketObserver,
path: String,
address: String,
port: Long,
isSsl: Boolean,
numProtocols: Long,
supportedProtocols: String
): WebSocketClient

fun write(
webSocketClient: WebSocketClient,
data: ByteArray,
length: Long,
handlerCallback: RealmWebsocketHandlerCallbackPointer
)

fun runCallback(
handlerCallback: RealmWebsocketHandlerCallbackPointer,
cancelled: Boolean = false,
status: WebsocketCallbackResult = WebsocketCallbackResult.RLM_ERR_SYNC_SOCKET_SUCCESS,
reason: String = ""
) {
RealmInterop.realm_sync_socket_callback_complete(
handlerCallback,
cancelled,
status,
reason
)
}

fun close()
}

class CancellableTimer(
private val job: Job,
private val cancelCallback: () -> Unit
) {
fun cancel() {
job.cancel()
cancelCallback()
}
}

interface WebSocketClient {
fun send(message: ByteArray, handlerCallback: RealmWebsocketHandlerCallbackPointer)
fun closeWebsocket()
}

class WebSocketObserver(private val webSocketObserverPointer: RealmWebsocketProviderPointer) {
fun onConnected(protocol: String) {
RealmInterop.realm_sync_socket_websocket_connected(webSocketObserverPointer, protocol)
}

fun onError() {
RealmInterop.realm_sync_socket_websocket_error(webSocketObserverPointer)
}

fun onNewMessage(data: ByteArray): Boolean {
return RealmInterop.realm_sync_socket_websocket_message(webSocketObserverPointer, data)
}

fun onClose(wasClean: Boolean, errorCode: WebsocketErrorCode, reason: String) {
RealmInterop.realm_sync_socket_websocket_closed(
webSocketObserverPointer,
wasClean,
errorCode,
reason
)
}
}
12 changes: 12 additions & 0 deletions packages/cinterop/src/jvm/jni/java_class_global_def.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class JavaClassGlobalDef {
, m_io_realm_kotlin_internal_interop_app_callback(env, "io/realm/kotlin/internal/interop/AppCallback", false)
, m_io_realm_kotlin_internal_interop_connection_state_change_callback(env, "io/realm/kotlin/internal/interop/ConnectionStateChangeCallback", false)
, m_io_realm_kotlin_internal_interop_sync_thread_observer(env, "io/realm/kotlin/internal/interop/SyncThreadObserver", false)
, m_io_realm_kotlin_internal_interop_sync_websocket_transport(env, "io/realm/kotlin/internal/interop/sync/WebSocketTransport", false)
, m_io_realm_kotlin_internal_interop_sync_websocket_client(env, "io/realm/kotlin/internal/interop/sync/WebSocketClient", false)
{
}

Expand All @@ -92,6 +94,8 @@ class JavaClassGlobalDef {
jni_util::JavaClass m_io_realm_kotlin_internal_interop_app_callback;
jni_util::JavaClass m_io_realm_kotlin_internal_interop_connection_state_change_callback;
jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_thread_observer;
jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_websocket_transport;
jni_util::JavaClass m_io_realm_kotlin_internal_interop_sync_websocket_client;

inline static std::unique_ptr<JavaClassGlobalDef>& instance()
{
Expand Down Expand Up @@ -228,6 +232,14 @@ class JavaClassGlobalDef {
return jni_util::JavaMethod(env, instance()->m_kotlin_jvm_functions_function1, "invoke",
"(Ljava/lang/Object;)Ljava/lang/Object;");
}

inline static const jni_util::JavaClass& sync_websocket_transport() {
return instance()->m_io_realm_kotlin_internal_interop_sync_websocket_transport;
}

inline static const jni_util::JavaClass& sync_websocket_client() {
return instance()->m_io_realm_kotlin_internal_interop_sync_websocket_client;
}
};

} // namespace realm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import io.realm.kotlin.internal.interop.sync.NetworkTransport
import io.realm.kotlin.internal.interop.sync.ProgressDirection
import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode
import io.realm.kotlin.internal.interop.sync.SyncUserIdentity
import io.realm.kotlin.internal.interop.sync.WebSocketTransport
import io.realm.kotlin.internal.interop.sync.WebsocketCallbackResult
import io.realm.kotlin.internal.interop.sync.WebsocketErrorCode
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -1153,7 +1156,6 @@ actual object RealmInterop {
}

actual fun realm_app_sync_client_get_default_file_path_for_realm(
app: RealmAppPointer,
syncConfig: RealmSyncConfigurationPointer,
overriddenName: String?
): String {
Expand Down Expand Up @@ -1973,6 +1975,36 @@ actual object RealmInterop {
return LongPointerWrapper(realmc.realm_sync_subscription_set_commit(mutableSubscriptionSet.cptr()))
}

actual fun realm_sync_set_websocket_transport(
syncClientConfig: RealmSyncClientConfigurationPointer,
webSocketTransport: WebSocketTransport
) {
realmc.realm_sync_websocket_new(syncClientConfig.cptr(), webSocketTransport)
}

actual fun realm_sync_socket_callback_complete(nativePointer: RealmWebsocketHandlerCallbackPointer, cancelled: Boolean, status: WebsocketCallbackResult, reason: String) {
realmc.realm_sync_websocket_callback_complete(cancelled, nativePointer.cptr(), status.nativeValue, reason)
}

actual fun realm_sync_socket_websocket_connected(nativePointer: RealmWebsocketProviderPointer, protocol: String) {
realmc.realm_sync_websocket_connected(nativePointer.cptr(), protocol)
}

actual fun realm_sync_socket_websocket_error(nativePointer: RealmWebsocketProviderPointer) {
realmc.realm_sync_websocket_error(nativePointer.cptr())
}

actual fun realm_sync_socket_websocket_message(
nativePointer: RealmWebsocketProviderPointer,
data: ByteArray
): Boolean {
return realmc.realm_sync_websocket_message(nativePointer.cptr(), data, data.size.toLong())
}

actual fun realm_sync_socket_websocket_closed(nativePointer: RealmWebsocketProviderPointer, wasClean: Boolean, errorCode: WebsocketErrorCode, reason: String) {
realmc.realm_sync_websocket_closed(nativePointer.cptr(), wasClean, errorCode.nativeValue, reason)
}

fun <T : CapiT> NativePointer<T>.cptr(): Long {
return (this as LongPointerWrapper).ptr
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ actual enum class WebsocketErrorCode(
RLM_ERR_WEBSOCKET_FATAL_ERROR("FatalError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_FATAL_ERROR);

actual companion object {
internal actual fun of(nativeValue: Int): WebsocketErrorCode? =
actual fun of(nativeValue: Int): WebsocketErrorCode? =
values().firstOrNull { value ->
value.nativeValue == nativeValue
}
Expand Down
4 changes: 4 additions & 0 deletions packages/cinterop/src/native/realm.def
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ headerFilter = realm.h realm/error_codes.h
// libraryPaths.ios_x64 = ../external/core/build-macos_x64/src/realm/object-store/c_api ../external/core/build-macos_x64/src/realm ../external/core/build-macos_x64/src/realm/parser ../external/core/build-macos_x64/src/realm/object-store/
linkerOpts = -lcompression -lz -framework Foundation -framework CoreFoundation -framework Security
strictEnums = realm_errno realm_error_category realm_sync_errno_client realm_sync_errno_connection realm_sync_errno_session realm_web_socket_errno realm_sync_socket_callback_result

// We don't want to convert Websocket binary data to String
noStringConversion = realm_sync_socket_websocket_message

---
#include <pthread.h>
#include <time.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import realm_wrapper.realm_errno

actual enum class ErrorCode(
override val description: String,
private val nativeError: realm_errno
nativeError: realm_errno
) : CodeDescription {
RLM_ERR_NONE("None", realm_errno.RLM_ERR_NONE),
RLM_ERR_RUNTIME("Runtime", realm_errno.RLM_ERR_RUNTIME),
Expand Down
Loading