From 0c6a6afe74c25a75cc3bafb19b68a742b600a4d5 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Wed, 23 Aug 2023 11:36:52 +0200 Subject: [PATCH 01/12] Rework sync exceptions based on new error codes. --- CHANGELOG.md | 3 +- .../realm/kotlin/test/sync/SyncEnumTests.kt | 35 +++--- .../realm/kotlin/internal/interop/Callback.kt | 3 +- .../kotlin/internal/interop/CoreError.kt | 68 ++++++++++++ .../internal/interop/CoreErrorConverter.kt | 6 +- .../kotlin/internal/interop/ErrorCategory.kt | 3 +- .../kotlin/internal/interop/ErrorCode.kt | 20 +++- .../kotlin/internal/interop/RealmInterop.kt | 11 +- .../interop/sync/ProtocolErrorCode.kt | 90 ++++++++-------- .../kotlin/internal/interop/sync/SyncError.kt | 17 ++- .../internal/interop/sync/SyncErrorCode.kt | 55 ---------- .../interop/sync/SyncErrorCodeCategory.kt | 36 ------- .../kotlin/internal/interop/ErrorCategory.kt | 3 +- .../kotlin/internal/interop/ErrorCode.kt | 22 +++- .../kotlin/internal/interop/RealmInterop.kt | 14 +-- ...VMSyncSessionTransferCompletionCallback.kt | 5 +- .../interop/sync/ProtocolErrorCode.kt | 96 ++++++++--------- .../interop/sync/SyncErrorCodeCategory.kt | 37 ------- packages/cinterop/src/native/realm.def | 2 +- .../kotlin/internal/interop/ErrorCategory.kt | 3 +- .../kotlin/internal/interop/ErrorCode.kt | 28 +++-- .../kotlin/internal/interop/RealmInterop.kt | 44 +++----- .../interop/sync/ProtocolErrorCode.kt | 96 ++++++++--------- .../interop/sync/SyncErrorCodeCategory.kt | 40 ------- packages/external/core | 2 +- .../src/main/jni/realm_api_helpers.cpp | 21 ++-- .../src/main/jni/realm_api_helpers.h | 2 +- .../kotlin/mongodb/internal/RealmSyncUtils.kt | 100 +++++------------- .../mongodb/internal/SyncSessionImpl.kt | 15 ++- .../common/SyncClientResetIntegrationTests.kt | 43 ++------ .../common/internal/RealmSyncUtilsTest.kt | 93 +++++++++------- 31 files changed, 424 insertions(+), 589 deletions(-) create mode 100644 packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt delete mode 100644 packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt delete mode 100644 packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt delete mode 100644 packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt delete mode 100644 packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index e0380bda7c..a73832bba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ childA == childC ``` ### Enhancements +* Fulltext queries now support prefix search by using the * operator, like `description TEXT 'alex*'`. (Core issue [#6860](https://github.com/realm/realm-core/issues/6860)) * Realm model classes now generate custom `toString`, `equals` and `hashCode` implementations. This makes it possible to compare by object reference across multiple collections. Note that two objects at different versions will not be considered equal, even if the content is the same. Custom implementations of these methods will be respected if they are present. (Issue [#1097](https://github.com/realm/realm-kotlin/issues/1097)) * Support for performing geospatial queries using the new classes: `GeoPoint`, `GeoCircle`, `GeoBox`, and `GeoPolygon`. See `GeoPoint` documentation on how to persist locations. (Issue [#1403](https://github.com/realm/realm-kotlin/pull/1403)) @@ -46,7 +47,7 @@ if the content is the same. Custom implementations of these methods will be resp * Minimum Android SDK: 16. ### Internal -* None. +* Updated to Realm Core 13.18.0, commit 48d6d672cb30f86976ba19a44ffffe25ed447128. ## 1.10.2 (2023-07-21) diff --git a/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt b/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt index 4f9490dbe9..1effc3cd32 100644 --- a/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt +++ b/packages/cinterop/src/androidInstrumentedTest/kotlin/io/realm/kotlin/test/sync/SyncEnumTests.kt @@ -16,6 +16,7 @@ package io.realm.kotlin.test.sync +import io.realm.kotlin.internal.interop.CategoryFlags import io.realm.kotlin.internal.interop.ErrorCategory import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.realm_auth_provider_e @@ -23,23 +24,21 @@ import io.realm.kotlin.internal.interop.realm_errno_e import io.realm.kotlin.internal.interop.realm_error_category_e import io.realm.kotlin.internal.interop.realm_sync_client_metadata_mode_e import io.realm.kotlin.internal.interop.realm_sync_connection_state_e -import io.realm.kotlin.internal.interop.realm_sync_errno_client_e import io.realm.kotlin.internal.interop.realm_sync_errno_connection_e import io.realm.kotlin.internal.interop.realm_sync_errno_session_e -import io.realm.kotlin.internal.interop.realm_sync_error_category_e import io.realm.kotlin.internal.interop.realm_sync_session_resync_mode_e import io.realm.kotlin.internal.interop.realm_sync_session_state_e import io.realm.kotlin.internal.interop.realm_user_state_e +import io.realm.kotlin.internal.interop.realm_web_socket_errno_e import io.realm.kotlin.internal.interop.sync.AuthProvider import io.realm.kotlin.internal.interop.sync.CoreConnectionState import io.realm.kotlin.internal.interop.sync.CoreSyncSessionState import io.realm.kotlin.internal.interop.sync.CoreUserState import io.realm.kotlin.internal.interop.sync.MetadataMode -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.ProtocolConnectionErrorCode -import io.realm.kotlin.internal.interop.sync.ProtocolSessionErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory +import io.realm.kotlin.internal.interop.sync.SyncConnectionErrorCode +import io.realm.kotlin.internal.interop.sync.SyncSessionErrorCode import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode +import io.realm.kotlin.internal.interop.sync.WebsocketErrorCode import org.junit.Test import kotlin.reflect.KClass import kotlin.test.BeforeTest @@ -59,10 +58,11 @@ class SyncEnumTests { } @Test - fun appErrorCategory() { + fun errorCategory() { checkEnum(realm_error_category_e::class) { nativeValue -> ErrorCategory.of(nativeValue) } + assertEquals(ErrorCategory.values().size, CategoryFlags.CATEGORY_ORDER.size) } @Test @@ -94,30 +94,23 @@ class SyncEnumTests { } @Test - fun protocolClientErrorCode() { - checkEnum(realm_sync_errno_client_e::class) { nativeValue -> - ProtocolClientErrorCode.of(nativeValue) - } - } - - @Test - fun protocolConnectionErrorCode() { + fun syncConnectionErrorCode() { checkEnum(realm_sync_errno_connection_e::class) { nativeValue -> - ProtocolConnectionErrorCode.of(nativeValue) + SyncConnectionErrorCode.of(nativeValue) } } @Test - fun protocolSessionErrorCode() { + fun syncSessionErrorCode() { checkEnum(realm_sync_errno_session_e::class) { nativeValue -> - ProtocolSessionErrorCode.of(nativeValue) + SyncSessionErrorCode.of(nativeValue) } } @Test - fun syncErrorCodeCategory() { - checkEnum(realm_sync_error_category_e::class) { nativeValue -> - SyncErrorCodeCategory.of(nativeValue) + fun websocketErrorCode() { + checkEnum(realm_web_socket_errno_e::class) { nativeValue -> + WebsocketErrorCode.of(nativeValue) } } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt index b8534d0b67..4d262f206d 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/Callback.kt @@ -19,7 +19,6 @@ package io.realm.kotlin.internal.interop import io.realm.kotlin.internal.interop.sync.AppError import io.realm.kotlin.internal.interop.sync.CoreSubscriptionSetState import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode // TODO Could be replace by lambda. See realm_app_config_new networkTransportFactory for example. interface Callback { @@ -39,7 +38,7 @@ fun interface SyncErrorCallback { // Interface exposed towards `library-sync` interface SyncSessionTransferCompletionCallback { - fun invoke(error: SyncErrorCode?) + fun invoke(error: CoreError?) } interface LogCallback { diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt new file mode 100644 index 0000000000..0e6821cba1 --- /dev/null +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt @@ -0,0 +1,68 @@ +package io.realm.kotlin.internal.interop + +/** + * Wrapper for C-API `realm_error_t`. + * See https://github.com/realm/realm-core/blob/master/src/realm.h#L231 + */ +class CoreError( + categoriesNativeValue: Int, + val errorCodeNativeValue: Int, + messageNativeValue: String?, + path: String, + userError: Throwable? +) { + val categories: CategoryFlags = CategoryFlags((categoriesNativeValue)) + val errorCode: ErrorCode? = ErrorCode.of(errorCodeNativeValue) + val message = messageNativeValue + val realmPath: String = path + val userError: Throwable? = userError + + operator fun contains(category: ErrorCategory): Boolean = category in categories +} + +data class CategoryFlags(val categoryFlags: Int) { + + companion object { + /** + * See error code mapping to categories here: + * https://github.com/realm/realm-core/blob/master/src/realm/error_codes.cpp#L29 + * + * In most cases, only 1 category is assigned, but some errors have multiple. So instead of + * overwhelming the user with many categories, we only select the most important to show + * in the error message. "important" is of course tricky to define, but generally + * we consider vague categories like [ErrorCategory.RLM_ERR_CAT_RUNTIME] as less important + * than more specific ones like [ErrorCategory.RLM_ERR_CAT_JSON_ERROR]. + * + * In the current implementation, categories between index 0 and 7 are considered equal + * and the order is somewhat arbitrary. No error codes has multiple of these categories + * associated either. + */ + val CATEGORY_ORDER: List = listOf( + ErrorCategory.RLM_ERR_CAT_CUSTOM_ERROR, + ErrorCategory.RLM_ERR_CAT_WEBSOCKET_ERROR, + ErrorCategory.RLM_ERR_CAT_SERVICE_ERROR, + ErrorCategory.RLM_ERR_CAT_JSON_ERROR, + ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR, + ErrorCategory.RLM_ERR_CAT_SYSTEM_ERROR, + ErrorCategory.RLM_ERR_CAT_FILE_ACCESS, + ErrorCategory.RLM_ERR_CAT_HTTP_ERROR, + ErrorCategory.RLM_ERR_CAT_INVALID_ARG, + ErrorCategory.RLM_ERR_CAT_APP_ERROR, + ErrorCategory.RLM_ERR_CAT_LOGIC, + ErrorCategory.RLM_ERR_CAT_RUNTIME, + ) + } + + /** + * Returns a description of the most important category defined in [categoryFlags]. + * If no known categories are found, "Unknown[categoryFlags]" is returned. + */ + val description: String = CATEGORY_ORDER.firstOrNull { category -> + category in this + }?.description ?: "$categoryFlags" + + /** + * Check whether a given [ErrorCategory] is included in the [categoryFlags]. + */ + operator fun contains(category: ErrorCategory): Boolean = (categoryFlags and category.nativeValue) != 0 +} diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt index fddf363cdf..36174fb949 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt @@ -31,7 +31,7 @@ object CoreErrorConverter { path: String?, userError: Throwable? ): Throwable { - val categories: CategoryFlag = CategoryFlag(categoriesNativeValue) + val categories: CategoryFlags = CategoryFlags(categoriesNativeValue) val errorCode: ErrorCode? = ErrorCode.of(errorCodeNativeValue) val message: String = "[$errorCode]: $messageNativeValue" @@ -45,8 +45,4 @@ object CoreErrorConverter { else -> Error(message) // This can happen when propagating user level exceptions. } } - - data class CategoryFlag(val categoryCode: Int) { - operator fun contains(other: ErrorCategory): Boolean = categoryCode and other.nativeValue != 0 - } } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt index fb1716377d..53053fc1da 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt @@ -32,7 +32,8 @@ expect enum class ErrorCategory : CodeDescription { RLM_ERR_CAT_SERVICE_ERROR, RLM_ERR_CAT_HTTP_ERROR, RLM_ERR_CAT_CUSTOM_ERROR, - RLM_ERR_CAT_WEBSOCKET_ERROR; + RLM_ERR_CAT_WEBSOCKET_ERROR, + RLM_ERR_CAT_SYNC_ERROR; companion object { internal fun of(nativeValue: Int): ErrorCategory? diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt index 13138a5605..b4d95acbf2 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt @@ -50,6 +50,22 @@ expect enum class ErrorCode : CodeDescription { RLM_ERR_SCHEMA_VERSION_MISMATCH, RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE, RLM_ERR_OPERATION_ABORTED, + RLM_ERR_AUTO_CLIENT_RESET_FAILED, + RLM_ERR_BAD_SYNC_PARTITION_VALUE, + RLM_ERR_CONNECTION_CLOSED, + RLM_ERR_INVALID_SUBSCRIPTION_QUERY, + RLM_ERR_SYNC_CLIENT_RESET_REQUIRED, + RLM_ERR_SYNC_COMPENSATING_WRITE, + RLM_ERR_SYNC_CONNECT_FAILED, + RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE, + RLM_ERR_SYNC_PERMISSION_DENIED, + RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED, + RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED, + RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED, + RLM_ERR_SYNC_USER_MISMATCH, + RLM_ERR_TLS_HANDSHAKE_FAILED, + RLM_ERR_WRONG_SYNC_TYPE, + RLM_ERR_SYNC_WRITE_NOT_ALLOWED, RLM_ERR_SYSTEM_ERROR, RLM_ERR_LOGIC, RLM_ERR_NOT_SUPPORTED, @@ -162,9 +178,7 @@ expect enum class ErrorCode : CodeDescription { RLM_ERR_MAINTENANCE_IN_PROGRESS, RLM_ERR_USERPASS_TOKEN_INVALID, RLM_ERR_INVALID_SERVER_RESPONSE, - RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR, - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR, - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR, + REALM_ERR_APP_SERVER_ERROR, RLM_ERR_CALLBACK, RLM_ERR_UNKNOWN; diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 33332f2450..731a6a1e57 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -27,8 +27,6 @@ import io.realm.kotlin.internal.interop.sync.CoreUserState import io.realm.kotlin.internal.interop.sync.MetadataMode import io.realm.kotlin.internal.interop.sync.NetworkTransport import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode import io.realm.kotlin.internal.interop.sync.SyncUserIdentity import kotlinx.coroutines.CoroutineDispatcher @@ -127,8 +125,6 @@ typealias RealmMutableSubscriptionSetPointer = NativePointer ) : this( - SyncErrorCode.newInstance(category, value, message), - detailedMessage, + CoreError(categoryFlags, value, message, path, null), originalFilePath, recoveryFilePath, isFatal, diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt deleted file mode 100644 index 93a9b78052..0000000000 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCode.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription -import io.realm.kotlin.internal.interop.UnknownCodeDescription - -/** - * Wrapper for C-API `realm_sync_error_code`. - * See https://github.com/realm/realm-core/blob/master/src/realm.h#L3306 - */ -data class SyncErrorCode internal constructor( - val category: CodeDescription, - val code: CodeDescription, - val message: String -) { - companion object { - fun newInstance( - categoryCode: Int, - errorCode: Int, - message: String - ): SyncErrorCode { - val category = SyncErrorCodeCategory.of(categoryCode) ?: UnknownCodeDescription(categoryCode) - - val code: CodeDescription = when (category) { - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT -> ProtocolClientErrorCode.of(errorCode) - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CONNECTION -> ProtocolConnectionErrorCode.of(errorCode) - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SESSION -> ProtocolSessionErrorCode.of(errorCode) - // SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SYSTEM -> // no mapping available - // SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN -> // no mapping available - else -> null - } ?: UnknownCodeDescription(errorCode) - - return SyncErrorCode( - category, - code, - message - ) - } - } -} diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt deleted file mode 100644 index 049e3fbd1b..0000000000 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2022 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription - -/** - * Wrapper for C-API `realm_sync_error_category`. - * See https://github.com/realm/realm-core/blob/master/src/realm.h#L3198 - */ -expect enum class SyncErrorCodeCategory : CodeDescription { - RLM_SYNC_ERROR_CATEGORY_CLIENT, - RLM_SYNC_ERROR_CATEGORY_CONNECTION, - RLM_SYNC_ERROR_CATEGORY_SESSION, - RLM_SYNC_ERROR_CATEGORY_WEBSOCKET, - RLM_SYNC_ERROR_CATEGORY_SYSTEM, - RLM_SYNC_ERROR_CATEGORY_UNKNOWN; - - companion object { - internal fun of(nativeValue: Int): SyncErrorCodeCategory? - } -} diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt index 423f657111..5319d0bc90 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt @@ -31,7 +31,8 @@ actual enum class ErrorCategory( RLM_ERR_CAT_SERVICE_ERROR("Service", realm_error_category_e.RLM_ERR_CAT_SERVICE_ERROR), RLM_ERR_CAT_HTTP_ERROR("Http", realm_error_category_e.RLM_ERR_CAT_HTTP_ERROR), RLM_ERR_CAT_CUSTOM_ERROR("Custom", realm_error_category_e.RLM_ERR_CAT_CUSTOM_ERROR), - RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category_e.RLM_ERR_CAT_WEBSOCKET_ERROR); + RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category_e.RLM_ERR_CAT_WEBSOCKET_ERROR), + RLM_ERR_CAT_SYNC_ERROR("Sync", realm_error_category_e.RLM_ERR_CAT_SYNC_ERROR); actual companion object { internal actual fun of(nativeValue: Int): ErrorCategory? = diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt index 935354e9cb..36bcd30327 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt @@ -47,6 +47,22 @@ actual enum class ErrorCode(override val description: String, override val nativ RLM_ERR_SCHEMA_VERSION_MISMATCH("SchemaVersionMismatch", realm_errno_e.RLM_ERR_SCHEMA_VERSION_MISMATCH), RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE("NoSubscriptionForWrite", realm_errno_e.RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE), RLM_ERR_OPERATION_ABORTED("OperationAborted", realm_errno_e.RLM_ERR_OPERATION_ABORTED), + RLM_ERR_AUTO_CLIENT_RESET_FAILED("AutoClientResetFailed", realm_errno_e.RLM_ERR_AUTO_CLIENT_RESET_FAILED), + RLM_ERR_BAD_SYNC_PARTITION_VALUE("BadSyncPartitionValue", realm_errno_e.RLM_ERR_BAD_SYNC_PARTITION_VALUE), + RLM_ERR_CONNECTION_CLOSED("ConnectionClosed", realm_errno_e.RLM_ERR_CONNECTION_CLOSED), + RLM_ERR_INVALID_SUBSCRIPTION_QUERY("InvalidSubscriptionQuery", realm_errno_e.RLM_ERR_INVALID_SUBSCRIPTION_QUERY), + RLM_ERR_SYNC_CLIENT_RESET_REQUIRED("SyncClientResetRequired", realm_errno_e.RLM_ERR_SYNC_CLIENT_RESET_REQUIRED), + RLM_ERR_SYNC_COMPENSATING_WRITE("CompensatingWrite", realm_errno_e.RLM_ERR_SYNC_COMPENSATING_WRITE), + RLM_ERR_SYNC_CONNECT_FAILED("SyncConnectFailed", realm_errno_e.RLM_ERR_SYNC_CONNECT_FAILED), + RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE("SyncInvalidSchemaChange", realm_errno_e.RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE), + RLM_ERR_SYNC_PERMISSION_DENIED("SyncPermissionDenied", realm_errno_e.RLM_ERR_SYNC_PERMISSION_DENIED), + RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED("SyncProtocolInvariantFailed", realm_errno_e.RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED), + RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED("SyncProtocolNegotiationFailed", realm_errno_e.RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED), + RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED("SyncServerPermissionsChanged", realm_errno_e.RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED), + RLM_ERR_SYNC_USER_MISMATCH("SyncUserMismatch", realm_errno_e.RLM_ERR_SYNC_USER_MISMATCH), + RLM_ERR_TLS_HANDSHAKE_FAILED("TLSHandshakeFailed", realm_errno_e.RLM_ERR_TLS_HANDSHAKE_FAILED), + RLM_ERR_WRONG_SYNC_TYPE("WrongSyncType", realm_errno_e.RLM_ERR_WRONG_SYNC_TYPE), + RLM_ERR_SYNC_WRITE_NOT_ALLOWED("SyncWriteNotAllowed", realm_errno_e.RLM_ERR_SYNC_WRITE_NOT_ALLOWED), RLM_ERR_SYSTEM_ERROR("SystemError", realm_errno_e.RLM_ERR_SYSTEM_ERROR), RLM_ERR_LOGIC("Logic", realm_errno_e.RLM_ERR_LOGIC), RLM_ERR_NOT_SUPPORTED("NotSupported", realm_errno_e.RLM_ERR_NOT_SUPPORTED), @@ -118,7 +134,7 @@ actual enum class ErrorCode(override val description: String, override val nativ RLM_ERR_MONGODB_ERROR("MongodbError", realm_errno_e.RLM_ERR_MONGODB_ERROR), RLM_ERR_ARGUMENTS_NOT_ALLOWED("ArgumentsNotAllowed", realm_errno_e.RLM_ERR_ARGUMENTS_NOT_ALLOWED), RLM_ERR_FUNCTION_EXECUTION_ERROR("FunctionExecutionError", realm_errno_e.RLM_ERR_FUNCTION_EXECUTION_ERROR), - RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno_e.RLM_ERR_NO_MATCHING_RULE), + RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno_e.RLM_ERR_NO_MATCHING_RULE_FOUND), RLM_ERR_INTERNAL_SERVER_ERROR("InternalServerError", realm_errno_e.RLM_ERR_INTERNAL_SERVER_ERROR), RLM_ERR_AUTH_PROVIDER_NOT_FOUND("AuthProviderNotFound", realm_errno_e.RLM_ERR_AUTH_PROVIDER_NOT_FOUND), RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS("AuthProviderAlreadyExists", realm_errno_e.RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS), @@ -159,9 +175,7 @@ actual enum class ErrorCode(override val description: String, override val nativ RLM_ERR_MAINTENANCE_IN_PROGRESS("MaintenanceInProgress", realm_errno_e.RLM_ERR_MAINTENANCE_IN_PROGRESS), RLM_ERR_USERPASS_TOKEN_INVALID("UserpassTokenInvalid", realm_errno_e.RLM_ERR_USERPASS_TOKEN_INVALID), RLM_ERR_INVALID_SERVER_RESPONSE("InvalidServerResponse", realm_errno_e.RLM_ERR_INVALID_SERVER_RESPONSE), - RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR("ResolveFailedError", realm_errno_e.RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR("ConnectionClosedClientError", realm_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR("ConnectionClosedServerError", realm_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR), + REALM_ERR_APP_SERVER_ERROR("AppServerError", realm_errno_e.RLM_ERR_APP_SERVER_ERROR), RLM_ERR_CALLBACK("Callback", realm_errno_e.RLM_ERR_CALLBACK), RLM_ERR_UNKNOWN("Unknown", realm_errno_e.RLM_ERR_UNKNOWN); diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 88b254ca0b..35a6a7e8b2 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -27,8 +27,6 @@ import io.realm.kotlin.internal.interop.sync.JVMSyncSessionTransferCompletionCal import io.realm.kotlin.internal.interop.sync.MetadataMode import io.realm.kotlin.internal.interop.sync.NetworkTransport import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode import io.realm.kotlin.internal.interop.sync.SyncUserIdentity import kotlinx.coroutines.CoroutineDispatcher @@ -1340,15 +1338,13 @@ actual object RealmInterop { actual fun realm_sync_session_handle_error_for_testing( syncSession: RealmSyncSessionPointer, - errorCode: ProtocolClientErrorCode, - category: SyncErrorCodeCategory, + error: ErrorCode, errorMessage: String, isFatal: Boolean ) { realmc.realm_sync_session_handle_error_for_testing( syncSession.cptr(), - errorCode.nativeValue, - category.nativeValue, + error.nativeValue, errorMessage, isFatal ) @@ -1396,12 +1392,6 @@ actual object RealmInterop { baseUrl?.let { realmc.realm_app_config_set_base_url(config, it) } // Sync Connection Parameters - connectionParams.localAppName?.let { appName -> - realmc.realm_app_config_set_local_app_name(config, appName) - } - connectionParams.localAppVersion?.let { appVersion -> - realmc.realm_app_config_set_local_app_name(config, appVersion) - } realmc.realm_app_config_set_sdk(config, connectionParams.sdkName) realmc.realm_app_config_set_sdk_version(config, connectionParams.sdkVersion) realmc.realm_app_config_set_platform_version(config, connectionParams.platformVersion) diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt index d06b775d09..94df1f403e 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt @@ -16,6 +16,7 @@ package io.realm.kotlin.internal.interop.sync +import io.realm.kotlin.internal.interop.CoreError import io.realm.kotlin.internal.interop.SyncSessionTransferCompletionCallback // Interface used internally as a bridge between Kotlin (JVM) and JNI. @@ -28,7 +29,7 @@ internal class JVMSyncSessionTransferCompletionCallback( fun onSuccess() { callback.invoke(null) } - fun onError(category: Int, value: Int, message: String) { - callback.invoke(SyncErrorCode.newInstance(category, value, message)) + fun onError(categoryFlags: Int, value: Int, message: String, path: String) { + callback.invoke(CoreError(categoryFlags, value, message, path, null)) } } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index bfc9f20ec5..8ba8028fa8 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -17,55 +17,11 @@ package io.realm.kotlin.internal.interop.sync import io.realm.kotlin.internal.interop.CodeDescription -import io.realm.kotlin.internal.interop.realm_sync_errno_client_e import io.realm.kotlin.internal.interop.realm_sync_errno_connection_e import io.realm.kotlin.internal.interop.realm_sync_errno_session_e +import io.realm.kotlin.internal.interop.realm_web_socket_errno_e -actual enum class ProtocolClientErrorCode( - override val description: String, - override val nativeValue: Int -) : CodeDescription { - RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED("ConnectionClosed", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED), - RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE("UnknownMessage", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE), - RLM_SYNC_ERR_CLIENT_BAD_SYNTAX("BadSyntax", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_SYNTAX), - RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED("LimitsExceeded", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED), - RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT("BadSessionIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER("BadMessageOrder", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT("BadClientFileIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_PROGRESS("BadProgress", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_PROGRESS), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX("BadChangesetHeaderSyntax", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE("BadChangesetSize", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE), - RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT("BadOriginFileIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION("BadServerVersion", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET("BadChangeset", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET), - RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT("BadRequestIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE("BadErrorCode", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE), - RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION("BadCompression", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION("BadClientVersion", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION), - RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED("SslServerCertRejected", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED), - RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT("PongTimeout", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT("BadClientFileIdentSalt", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT), - RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT("BadFileIdent", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT("ConnectTimeout", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP("BadTimestamp", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP), - RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER("BadProtocolFromServer", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER("ClientTooOldForServer", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER("ClientTooNewForServer", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH("ProtocolMismatch", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH), - RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE("BadStateMessage", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE), - RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE("MissingProtocolFeature", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE), - RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED("HttpTunnelFailed", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED), - RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE("AutoClientResetFailure", realm_sync_errno_client_e.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE); - - actual companion object { - internal actual fun of(nativeValue: Int): ProtocolClientErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} - -actual enum class ProtocolConnectionErrorCode( +actual enum class SyncConnectionErrorCode( override val description: String, override val nativeValue: Int ) : CodeDescription { @@ -74,7 +30,7 @@ actual enum class ProtocolConnectionErrorCode( RLM_SYNC_ERR_CONNECTION_UNKNOWN_MESSAGE("UnknownMessage", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_UNKNOWN_MESSAGE), RLM_SYNC_ERR_CONNECTION_BAD_SYNTAX("BadSyntax", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_BAD_SYNTAX), RLM_SYNC_ERR_CONNECTION_LIMITS_EXCEEDED("LimitsExceeded", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_LIMITS_EXCEEDED), - RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION("WrongProtocolVersion", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION), + RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION("WrongBadSyncPartitionValueProtocolVersion", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION), RLM_SYNC_ERR_CONNECTION_BAD_SESSION_IDENT("BadSessionIdent", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_BAD_SESSION_IDENT), RLM_SYNC_ERR_CONNECTION_REUSE_OF_SESSION_IDENT("ReuseOfSessionIdent", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_REUSE_OF_SESSION_IDENT), RLM_SYNC_ERR_CONNECTION_BOUND_IN_OTHER_SESSION("BoundInOtherSession", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_BOUND_IN_OTHER_SESSION), @@ -86,14 +42,14 @@ actual enum class ProtocolConnectionErrorCode( RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS("SwitchToPbs", realm_sync_errno_connection_e.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS); actual companion object { - internal actual fun of(nativeValue: Int): ProtocolConnectionErrorCode? = + internal actual fun of(nativeValue: Int): SyncConnectionErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } } } -actual enum class ProtocolSessionErrorCode( +actual enum class SyncSessionErrorCode( override val description: String, override val nativeValue: Int ) : CodeDescription { @@ -133,7 +89,47 @@ actual enum class ProtocolSessionErrorCode( RLM_SYNC_ERR_SESSION_REVERT_TO_PBS("RevertToPartitionBasedSync", realm_sync_errno_session_e.RLM_SYNC_ERR_SESSION_REVERT_TO_PBS); actual companion object { - internal actual fun of(nativeValue: Int): ProtocolSessionErrorCode? = + internal actual fun of(nativeValue: Int): SyncSessionErrorCode? = + values().firstOrNull { value -> + value.nativeValue == nativeValue + } + } +} + +actual enum class WebsocketErrorCode( + override val description: String, + override val nativeValue: Int +) : CodeDescription { + RLM_ERR_WEBSOCKET_OK("Ok", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_OK), + RLM_ERR_WEBSOCKET_GOINGAWAY("GoingAway", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_GOINGAWAY), + RLM_ERR_WEBSOCKET_PROTOCOLERROR("ProtocolError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_PROTOCOLERROR), + RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA("UnsupportedData", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA), + RLM_ERR_WEBSOCKET_RESERVED("Reserved", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RESERVED), + RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED("NoStatusReceived", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED), + RLM_ERR_WEBSOCKET_ABNORMALCLOSURE("AbnormalClosure", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_ABNORMALCLOSURE), + RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA("InvalidPayloadData", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA), + RLM_ERR_WEBSOCKET_POLICYVIOLATION("PolicyViolation", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_POLICYVIOLATION), + RLM_ERR_WEBSOCKET_MESSAGETOOBIG("MessageToBig", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_MESSAGETOOBIG), + RLM_ERR_WEBSOCKET_INAVALIDEXTENSION("InvalidExtension", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_INAVALIDEXTENSION), + RLM_ERR_WEBSOCKET_INTERNALSERVERERROR("InternalServerError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_INTERNALSERVERERROR), + RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED("TlsHandshakeFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED), + + RLM_ERR_WEBSOCKET_UNAUTHORIZED("Unauthorized", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_UNAUTHORIZED), + RLM_ERR_WEBSOCKET_FORBIDDEN("Forbidden", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_FORBIDDEN), + RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY("MovedPermanently", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY), + RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD("ClientTooOld", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD), + RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW("ClientTooNew", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW), + RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH("ProtocolMismatch", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH), + + RLM_ERR_WEBSOCKET_RESOLVE_FAILED("ResolveFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RESOLVE_FAILED), + RLM_ERR_WEBSOCKET_CONNECTION_FAILED("ConnectionFailed", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_CONNECTION_FAILED), + RLM_ERR_WEBSOCKET_READ_ERROR("ReadError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_READ_ERROR), + RLM_ERR_WEBSOCKET_WRITE_ERROR("WriteError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_WRITE_ERROR), + RLM_ERR_WEBSOCKET_RETRY_ERROR("RetryError", realm_web_socket_errno_e.RLM_ERR_WEBSOCKET_RETRY_ERROR), + 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? = values().firstOrNull { value -> value.nativeValue == nativeValue } diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt deleted file mode 100644 index 6c66bfbd38..0000000000 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription -import io.realm.kotlin.internal.interop.realm_sync_error_category_e - -actual enum class SyncErrorCodeCategory(override val description: String, override val nativeValue: Int) : - CodeDescription { - RLM_SYNC_ERROR_CATEGORY_CLIENT("Client", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_CLIENT), - RLM_SYNC_ERROR_CATEGORY_CONNECTION("Connection", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_CONNECTION), - RLM_SYNC_ERROR_CATEGORY_SESSION("Session", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_SESSION), - RLM_SYNC_ERROR_CATEGORY_WEBSOCKET("Websocket", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_WEBSOCKET), - RLM_SYNC_ERROR_CATEGORY_SYSTEM("System", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_SYSTEM), - RLM_SYNC_ERROR_CATEGORY_UNKNOWN("Unknown", realm_sync_error_category_e.RLM_SYNC_ERROR_CATEGORY_UNKNOWN); - - actual companion object { - internal actual fun of(nativeValue: Int): SyncErrorCodeCategory? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} diff --git a/packages/cinterop/src/native/realm.def b/packages/cinterop/src/native/realm.def index d5f34c6379..0c92edfbee 100644 --- a/packages/cinterop/src/native/realm.def +++ b/packages/cinterop/src/native/realm.def @@ -11,7 +11,7 @@ headerFilter = realm.h realm/error_codes.h // libraryPaths.macos_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/ // 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 +strictEnums = realm_errno realm_error_category realm_sync_errno_client realm_sync_errno_connection realm_sync_errno_session realm_web_socket_errno --- #include #include diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt index a792b233d7..ab2a7bfad5 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCategory.kt @@ -35,7 +35,8 @@ actual enum class ErrorCategory( RLM_ERR_CAT_SERVICE_ERROR("Service", realm_error_category.RLM_ERR_CAT_SERVICE_ERROR.value.toInt()), RLM_ERR_CAT_HTTP_ERROR("Http", realm_error_category.RLM_ERR_CAT_HTTP_ERROR.value.toInt()), RLM_ERR_CAT_CUSTOM_ERROR("Custom", realm_error_category.RLM_ERR_CAT_CUSTOM_ERROR.value.toInt()), - RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category.RLM_ERR_CAT_WEBSOCKET_ERROR.value.toInt()); + RLM_ERR_CAT_WEBSOCKET_ERROR("Websocket", realm_error_category.RLM_ERR_CAT_WEBSOCKET_ERROR.value.toInt()), + RLM_ERR_CAT_SYNC_ERROR("Sync", realm_error_category.RLM_ERR_CAT_SYNC_ERROR.value.toInt()); actual companion object { diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt index 70987acd03..3fb35d665c 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/ErrorCode.kt @@ -20,7 +20,7 @@ import realm_wrapper.realm_errno actual enum class ErrorCode( override val description: String, - error: realm_errno + private val nativeError: realm_errno ) : CodeDescription { RLM_ERR_NONE("None", realm_errno.RLM_ERR_NONE), RLM_ERR_RUNTIME("Runtime", realm_errno.RLM_ERR_RUNTIME), @@ -51,6 +51,22 @@ actual enum class ErrorCode( RLM_ERR_SCHEMA_VERSION_MISMATCH("SchemaVersionMismatch", realm_errno.RLM_ERR_SCHEMA_VERSION_MISMATCH), RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE("NoSubscriptionForWrite", realm_errno.RLM_ERR_NO_SUBSCRIPTION_FOR_WRITE), RLM_ERR_OPERATION_ABORTED("OperationAborted", realm_errno.RLM_ERR_OPERATION_ABORTED), + RLM_ERR_AUTO_CLIENT_RESET_FAILED("AutoClientResetFailed", realm_errno.RLM_ERR_AUTO_CLIENT_RESET_FAILED), + RLM_ERR_BAD_SYNC_PARTITION_VALUE("BadSyncPartitionValue", realm_errno.RLM_ERR_BAD_SYNC_PARTITION_VALUE), + RLM_ERR_CONNECTION_CLOSED("ConnectionClosed", realm_errno.RLM_ERR_CONNECTION_CLOSED), + RLM_ERR_INVALID_SUBSCRIPTION_QUERY("InvalidSubscriptionQuery", realm_errno.RLM_ERR_INVALID_SUBSCRIPTION_QUERY), + RLM_ERR_SYNC_CLIENT_RESET_REQUIRED("SyncClientResetRequired", realm_errno.RLM_ERR_SYNC_CLIENT_RESET_REQUIRED), + RLM_ERR_SYNC_COMPENSATING_WRITE("CompensatingWrite", realm_errno.RLM_ERR_SYNC_COMPENSATING_WRITE), + RLM_ERR_SYNC_CONNECT_FAILED("SyncConnectFailed", realm_errno.RLM_ERR_SYNC_CONNECT_FAILED), + RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE("SyncInvalidSchemaChange", realm_errno.RLM_ERR_SYNC_INVALID_SCHEMA_CHANGE), + RLM_ERR_SYNC_PERMISSION_DENIED("SyncPermissionDenied", realm_errno.RLM_ERR_SYNC_PERMISSION_DENIED), + RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED("SyncProtocolInvariantFailed", realm_errno.RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED), + RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED("SyncProtocolNegotiationFailed", realm_errno.RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED), + RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED("SyncServerPermissionsChanged", realm_errno.RLM_ERR_SYNC_SERVER_PERMISSIONS_CHANGED), + RLM_ERR_SYNC_USER_MISMATCH("SyncUserMismatch", realm_errno.RLM_ERR_SYNC_USER_MISMATCH), + RLM_ERR_TLS_HANDSHAKE_FAILED("TLSHandshakeFailed", realm_errno.RLM_ERR_TLS_HANDSHAKE_FAILED), + RLM_ERR_WRONG_SYNC_TYPE("WrongSyncType", realm_errno.RLM_ERR_WRONG_SYNC_TYPE), + RLM_ERR_SYNC_WRITE_NOT_ALLOWED("SyncWriteNotAllowed", realm_errno.RLM_ERR_SYNC_WRITE_NOT_ALLOWED), RLM_ERR_SYSTEM_ERROR("SystemError", realm_errno.RLM_ERR_SYSTEM_ERROR), RLM_ERR_LOGIC("Logic", realm_errno.RLM_ERR_LOGIC), RLM_ERR_NOT_SUPPORTED("NotSupported", realm_errno.RLM_ERR_NOT_SUPPORTED), @@ -122,7 +138,7 @@ actual enum class ErrorCode( RLM_ERR_MONGODB_ERROR("MongodbError", realm_errno.RLM_ERR_MONGODB_ERROR), RLM_ERR_ARGUMENTS_NOT_ALLOWED("ArgumentsNotAllowed", realm_errno.RLM_ERR_ARGUMENTS_NOT_ALLOWED), RLM_ERR_FUNCTION_EXECUTION_ERROR("FunctionExecutionError", realm_errno.RLM_ERR_FUNCTION_EXECUTION_ERROR), - RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno.RLM_ERR_NO_MATCHING_RULE), + RLM_ERR_NO_MATCHING_RULE("NoMatchingRule", realm_errno.RLM_ERR_NO_MATCHING_RULE_FOUND), RLM_ERR_INTERNAL_SERVER_ERROR("InternalServerError", realm_errno.RLM_ERR_INTERNAL_SERVER_ERROR), RLM_ERR_AUTH_PROVIDER_NOT_FOUND("AuthProviderNotFound", realm_errno.RLM_ERR_AUTH_PROVIDER_NOT_FOUND), RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS("AuthProviderAlreadyExists", realm_errno.RLM_ERR_AUTH_PROVIDER_ALREADY_EXISTS), @@ -163,13 +179,13 @@ actual enum class ErrorCode( RLM_ERR_MAINTENANCE_IN_PROGRESS("MaintenanceInProgress", realm_errno.RLM_ERR_MAINTENANCE_IN_PROGRESS), RLM_ERR_USERPASS_TOKEN_INVALID("UserpassTokenInvalid", realm_errno.RLM_ERR_USERPASS_TOKEN_INVALID), RLM_ERR_INVALID_SERVER_RESPONSE("InvalidServerResponse", realm_errno.RLM_ERR_INVALID_SERVER_RESPONSE), - RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR("ResolveFailedError", realm_errno.RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR("ConnectionClosedClientError", realm_errno.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR), - RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR("ConnectionClosedServerError", realm_errno.RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR), + REALM_ERR_APP_SERVER_ERROR("AppServerError", realm_errno.RLM_ERR_APP_SERVER_ERROR), RLM_ERR_CALLBACK("Callback", realm_errno.RLM_ERR_CALLBACK), RLM_ERR_UNKNOWN("Unknown", realm_errno.RLM_ERR_UNKNOWN); - override val nativeValue: Int = error.value.toInt() + override val nativeValue: Int = nativeError.value.toInt() + + val asNativeEnum: realm_errno = nativeError actual companion object { actual fun of(nativeValue: Int): ErrorCode? = diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 96a5d86e00..d5e4780534 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -19,9 +19,9 @@ package io.realm.kotlin.internal.interop import io.realm.kotlin.internal.interop.Constants.ENCRYPTION_KEY_LENGTH -import io.realm.kotlin.internal.interop.RealmInterop.safeKString import io.realm.kotlin.internal.interop.sync.ApiKeyWrapper import io.realm.kotlin.internal.interop.sync.AppError +import io.realm.kotlin.internal.interop.sync.AppError.Companion.newInstance import io.realm.kotlin.internal.interop.sync.AuthProvider import io.realm.kotlin.internal.interop.sync.CoreCompensatingWriteInfo import io.realm.kotlin.internal.interop.sync.CoreConnectionState @@ -31,11 +31,8 @@ import io.realm.kotlin.internal.interop.sync.CoreUserState import io.realm.kotlin.internal.interop.sync.MetadataMode import io.realm.kotlin.internal.interop.sync.NetworkTransport import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode import io.realm.kotlin.internal.interop.sync.Response import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.interop.sync.SyncSessionResyncMode import io.realm.kotlin.internal.interop.sync.SyncUserIdentity import kotlinx.atomicfu.AtomicBoolean @@ -121,7 +118,6 @@ import realm_wrapper.realm_scheduler_t import realm_wrapper.realm_set_t import realm_wrapper.realm_string_t import realm_wrapper.realm_sync_client_metadata_mode -import realm_wrapper.realm_sync_error_code_t import realm_wrapper.realm_sync_session_resync_mode import realm_wrapper.realm_sync_session_state_e import realm_wrapper.realm_sync_session_stop_policy_e @@ -562,7 +558,7 @@ actual object RealmInterop { ) err.usercode_error?.let { disposeUserData(it) } } else { - realm_wrapper.realm_release(realm) + realm_release(realm) } safeUserData(userData).invoke(exception) } @@ -2391,10 +2387,12 @@ actual object RealmInterop { syncConfig.cptr(), staticCFunction { userData, syncSession, error -> val syncError: SyncError = error.useContents { - val code = SyncErrorCode.newInstance( - error_code.category.value.toInt(), - error_code.value, - error_code.message.safeKString() + val code = CoreError( + this.status.categories.toInt(), + this.status.error.value.toInt(), + this.status.message.safeKString(), + this.status.path.safeKString(), + null ) val userInfoMap = (0 until user_info_length.toInt()) @@ -2421,7 +2419,6 @@ actual object RealmInterop { SyncError( errorCode = code, - detailedMessage = detailed_message.safeKString(), originalFilePath = userInfoMap[c_original_file_path_key.safeKString()], recoveryFilePath = userInfoMap[c_recovery_file_path_key.safeKString()], isFatal = is_fatal, @@ -2527,7 +2524,7 @@ actual object RealmInterop { ) { realm_wrapper.realm_sync_session_wait_for_download_completion( syncSession.cptr(), - staticCFunction?, Unit> { userData, error -> + staticCFunction?, Unit> { userData, error -> handleCompletionCallback(userData, error) }, StableRef.create(callback).asCPointer(), @@ -2543,7 +2540,7 @@ actual object RealmInterop { ) { realm_wrapper.realm_sync_session_wait_for_upload_completion( syncSession.cptr(), - staticCFunction?, Unit> { userData, error -> + staticCFunction?, Unit> { userData, error -> handleCompletionCallback(userData, error) }, StableRef.create(callback).asCPointer(), @@ -2574,15 +2571,13 @@ actual object RealmInterop { actual fun realm_sync_session_handle_error_for_testing( syncSession: RealmSyncSessionPointer, - errorCode: ProtocolClientErrorCode, - category: SyncErrorCodeCategory, + error: ErrorCode, errorMessage: String, isFatal: Boolean ) { realm_wrapper.realm_sync_session_handle_error_for_testing( syncSession.cptr(), - errorCode.nativeValue.toInt(), - category.nativeValue, + error.asNativeEnum, errorMessage, isFatal ) @@ -2636,14 +2631,15 @@ actual object RealmInterop { private fun handleCompletionCallback( userData: CPointer?, - error: CPointer? + error: CPointer? ) { val completionCallback = safeUserData(userData) if (error != null) { - val category = error.pointed.category.value.toInt() - val value: Int = error.pointed.value + val category = error.pointed.categories.toInt() + val value: Int = error.pointed.error.value.toInt() val message = error.pointed.message.safeKString() - completionCallback.invoke(SyncErrorCode.newInstance(category, value, message)) + val path = error.pointed.path.safeKString() + completionCallback.invoke(CoreError(category, value, message, path, null)) } else { completionCallback.invoke(null) } @@ -2672,12 +2668,6 @@ actual object RealmInterop { baseUrl?.let { realm_wrapper.realm_app_config_set_base_url(appConfig, it) } // Sync Connection Parameters - connectionParams.localAppName?.let { appName -> - realm_wrapper.realm_app_config_set_local_app_name(appConfig, appName) - } - connectionParams.localAppVersion?.let { appVersion -> - realm_wrapper.realm_app_config_set_local_app_name(appConfig, appVersion) - } realm_wrapper.realm_app_config_set_sdk(appConfig, connectionParams.sdkName) realm_wrapper.realm_app_config_set_sdk_version(appConfig, connectionParams.sdkVersion) realm_wrapper.realm_app_config_set_platform_version(appConfig, connectionParams.platformVersion) diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt index 6504d9b0ea..20817a0ae5 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/ProtocolErrorCode.kt @@ -16,57 +16,11 @@ package io.realm.kotlin.internal.interop.sync import io.realm.kotlin.internal.interop.CodeDescription -import realm_wrapper.realm_sync_errno_client import realm_wrapper.realm_sync_errno_connection import realm_wrapper.realm_sync_errno_session +import realm_wrapper.realm_web_socket_errno -actual enum class ProtocolClientErrorCode( - override val description: String, - errorCode: realm_sync_errno_client -) : CodeDescription { - RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED("ConnectionClosed", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CONNECTION_CLOSED), - RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE("UnknownMessage", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_UNKNOWN_MESSAGE), - RLM_SYNC_ERR_CLIENT_BAD_SYNTAX("BadSyntax", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_SYNTAX), - RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED("LimitsExceeded", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_LIMITS_EXCEEDED), - RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT("BadSessionIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_SESSION_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER("BadMessageOrder", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_MESSAGE_ORDER), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT("BadClientFileIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_PROGRESS("BadProgress", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_PROGRESS), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX("BadChangesetHeaderSyntax", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_HEADER_SYNTAX), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE("BadChangesetSize", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET_SIZE), - RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT("BadOriginFileIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_ORIGIN_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION("BadServerVersion", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_SERVER_VERSION), - RLM_SYNC_ERR_CLIENT_BAD_CHANGESET("BadChangeset", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CHANGESET), - RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT("BadRequestIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_REQUEST_IDENT), - RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE("BadErrorCode", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_ERROR_CODE), - RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION("BadCompression", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_COMPRESSION), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION("BadClientVersion", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_VERSION), - RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED("SslServerCertRejected", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_SSL_SERVER_CERT_REJECTED), - RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT("PongTimeout", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_PONG_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT("BadClientFileIdentSalt", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_CLIENT_FILE_IDENT_SALT), - RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT("BadFileIdent", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_FILE_IDENT), - RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT("ConnectTimeout", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CONNECT_TIMEOUT), - RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP("BadTimestamp", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_TIMESTAMP), - RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER("BadProtocolFromServer", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_PROTOCOL_FROM_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER("ClientTooOldForServer", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_OLD_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER("ClientTooNewForServer", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_CLIENT_TOO_NEW_FOR_SERVER), - RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH("ProtocolMismatch", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_PROTOCOL_MISMATCH), - RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE("BadStateMessage", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_BAD_STATE_MESSAGE), - RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE("MissingProtocolFeature", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_MISSING_PROTOCOL_FEATURE), - RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED("HttpTunnelFailed", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_HTTP_TUNNEL_FAILED), - RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE("AutoClientResetFailure", realm_sync_errno_client.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE); - - override val nativeValue: Int = errorCode.value.toInt() - - actual companion object { - internal actual fun of(nativeValue: Int): ProtocolClientErrorCode? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} - -actual enum class ProtocolConnectionErrorCode( +actual enum class SyncConnectionErrorCode( override val description: String, errorCode: realm_sync_errno_connection ) : CodeDescription { @@ -89,14 +43,14 @@ actual enum class ProtocolConnectionErrorCode( override val nativeValue: Int = errorCode.value.toInt() actual companion object { - internal actual fun of(nativeValue: Int): ProtocolConnectionErrorCode? = + internal actual fun of(nativeValue: Int): SyncConnectionErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } } } -actual enum class ProtocolSessionErrorCode( +actual enum class SyncSessionErrorCode( override val description: String, errorCode: realm_sync_errno_session ) : CodeDescription { @@ -138,7 +92,47 @@ actual enum class ProtocolSessionErrorCode( override val nativeValue: Int = errorCode.value.toInt() actual companion object { - internal actual fun of(nativeValue: Int): ProtocolSessionErrorCode? = + internal actual fun of(nativeValue: Int): SyncSessionErrorCode? = + values().firstOrNull { value -> + value.nativeValue == nativeValue + } + } +} + +actual enum class WebsocketErrorCode( + override val description: String, + errorCode: realm_web_socket_errno, +) : CodeDescription { + RLM_ERR_WEBSOCKET_OK("Ok", realm_web_socket_errno.RLM_ERR_WEBSOCKET_OK), + RLM_ERR_WEBSOCKET_GOINGAWAY("GoingAway", realm_web_socket_errno.RLM_ERR_WEBSOCKET_GOINGAWAY), + RLM_ERR_WEBSOCKET_PROTOCOLERROR("ProtocolError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_PROTOCOLERROR), + RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA("UnsupportedData", realm_web_socket_errno.RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA), + RLM_ERR_WEBSOCKET_RESERVED("Reserved", realm_web_socket_errno.RLM_ERR_WEBSOCKET_RESERVED), + RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED("NoStatusReceived", realm_web_socket_errno.RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED), + RLM_ERR_WEBSOCKET_ABNORMALCLOSURE("AbnormalClosure", realm_web_socket_errno.RLM_ERR_WEBSOCKET_ABNORMALCLOSURE), + RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA("InvalidPayloadData", realm_web_socket_errno.RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA), + RLM_ERR_WEBSOCKET_POLICYVIOLATION("PolicyViolation", realm_web_socket_errno.RLM_ERR_WEBSOCKET_POLICYVIOLATION), + RLM_ERR_WEBSOCKET_MESSAGETOOBIG("MessageToBig", realm_web_socket_errno.RLM_ERR_WEBSOCKET_MESSAGETOOBIG), + RLM_ERR_WEBSOCKET_INAVALIDEXTENSION("InvalidExtension", realm_web_socket_errno.RLM_ERR_WEBSOCKET_INAVALIDEXTENSION), + RLM_ERR_WEBSOCKET_INTERNALSERVERERROR("InternalServerError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_INTERNALSERVERERROR), + RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED("TlsHandshakeFailed", realm_web_socket_errno.RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED), + RLM_ERR_WEBSOCKET_UNAUTHORIZED("Unauthorized", realm_web_socket_errno.RLM_ERR_WEBSOCKET_UNAUTHORIZED), + RLM_ERR_WEBSOCKET_FORBIDDEN("Forbidden", realm_web_socket_errno.RLM_ERR_WEBSOCKET_FORBIDDEN), + RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY("MovedPermanently", realm_web_socket_errno.RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY), + RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD("ClientTooOld", realm_web_socket_errno.RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD), + RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW("ClientTooNew", realm_web_socket_errno.RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW), + RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH("ProtocolMismatch", realm_web_socket_errno.RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH), + RLM_ERR_WEBSOCKET_RESOLVE_FAILED("ResolveFailed", realm_web_socket_errno.RLM_ERR_WEBSOCKET_RESOLVE_FAILED), + RLM_ERR_WEBSOCKET_CONNECTION_FAILED("ConnectionFailed", realm_web_socket_errno.RLM_ERR_WEBSOCKET_CONNECTION_FAILED), + RLM_ERR_WEBSOCKET_READ_ERROR("ReadError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_READ_ERROR), + RLM_ERR_WEBSOCKET_WRITE_ERROR("WriteError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_WRITE_ERROR), + RLM_ERR_WEBSOCKET_RETRY_ERROR("RetryError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_RETRY_ERROR), + RLM_ERR_WEBSOCKET_FATAL_ERROR("FatalError", realm_web_socket_errno.RLM_ERR_WEBSOCKET_FATAL_ERROR); + + override val nativeValue: Int = errorCode.value.toInt() + + actual companion object { + internal actual fun of(nativeValue: Int): WebsocketErrorCode? = values().firstOrNull { value -> value.nativeValue == nativeValue } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt deleted file mode 100644 index 80254655ff..0000000000 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/sync/SyncErrorCodeCategory.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2022 Realm Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.realm.kotlin.internal.interop.sync - -import io.realm.kotlin.internal.interop.CodeDescription -import realm_wrapper.realm_sync_error_category - -actual enum class SyncErrorCodeCategory( - override val description: String, - override val nativeValue: Int -) : CodeDescription { - RLM_SYNC_ERROR_CATEGORY_CLIENT("Client", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_CLIENT.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_CONNECTION("Connection", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_CONNECTION.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_SESSION("Session", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_SESSION.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_WEBSOCKET("Websocket", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_WEBSOCKET.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_SYSTEM("System", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_SYSTEM.value.toInt()), - RLM_SYNC_ERROR_CATEGORY_UNKNOWN("Unknown", realm_sync_error_category.RLM_SYNC_ERROR_CATEGORY_UNKNOWN.value.toInt()); - - actual companion object { - - internal actual fun of(nativeValue: Int): SyncErrorCodeCategory? = - values().firstOrNull { value -> - value.nativeValue == nativeValue - } - } -} diff --git a/packages/external/core b/packages/external/core index f1e962cd44..d1ace25101 160000 --- a/packages/external/core +++ b/packages/external/core @@ -1 +1 @@ -Subproject commit f1e962cd447f8b69f8f7cf46a188b1c6246923c5 +Subproject commit d1ace25101b638520be8fbcbe7ed14f50e74c23d diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp index 9848fc99c4..8359e823ce 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp @@ -716,10 +716,10 @@ jobject convert_to_jvm_sync_error(JNIEnv* jenv, const realm_sync_error_t& error) "", "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ[Lio/realm/kotlin/internal/interop/sync/CoreCompensatingWriteInfo;)V"); - jint category = static_cast(error.error_code.category); - jint value = error.error_code.value; - jstring msg = to_jstring(jenv, error.error_code.message); - jstring detailed_msg = to_jstring(jenv, error.detailed_message); + jint category = static_cast(error.status.categories); + jint value = static_cast(error.status.error); + jstring msg = to_jstring(jenv, error.status.message); + jstring path = to_jstring(jenv, error.status.path); jstring joriginal_file_path = nullptr; jstring jrecovery_file_path = nullptr; jboolean is_fatal = error.is_fatal; @@ -793,7 +793,7 @@ jobject convert_to_jvm_sync_error(JNIEnv* jenv, const realm_sync_error_t& error) category, value, msg, - detailed_msg, + path, joriginal_file_path, jrecovery_file_path, is_fatal, @@ -827,7 +827,7 @@ void sync_set_error_handler(realm_sync_config_t* sync_config, jobject error_hand }); } -void transfer_completion_callback(void* userdata, realm_sync_error_code_t* error) { +void transfer_completion_callback(void* userdata, realm_error_t* error) { auto env = get_env(true); static JavaMethod java_success_callback_method(env, JavaClassGlobalDef::sync_session_transfer_completion_callback(), @@ -836,12 +836,13 @@ void transfer_completion_callback(void* userdata, realm_sync_error_code_t* error static JavaMethod java_error_callback_method(env, JavaClassGlobalDef::sync_session_transfer_completion_callback(), "onError", - "(IILjava/lang/String;)V"); + "(IILjava/lang/String;Ljava/lang/String;)V"); if (error) { - jint category = static_cast(error->category); - jint value = error->value; + jint category = static_cast(error->categories); + jint value = error->error; jstring msg = to_jstring(env, error->message); - env->CallVoidMethod(static_cast(userdata), java_error_callback_method, category, value, msg); + jstring path = to_jstring(env, error->path); + env->CallVoidMethod(static_cast(userdata), java_error_callback_method, category, value, msg, path); } else { env->CallVoidMethod(static_cast(userdata), java_success_callback_method); } diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h index 0854631d72..133b0095ee 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.h @@ -72,7 +72,7 @@ void complete_http_request(void* request_context, jobject j_response); void -transfer_completion_callback(void* userdata, realm_sync_error_code_t* error); +transfer_completion_callback(void* userdata, realm_error_t* error); void realm_subscriptionset_changed_callback(void* userdata, diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt index e5c3d424bb..db0313cfb2 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt @@ -1,14 +1,11 @@ package io.realm.kotlin.mongodb.internal import io.realm.kotlin.internal.interop.AppCallback +import io.realm.kotlin.internal.interop.CoreError import io.realm.kotlin.internal.interop.ErrorCategory import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.sync.AppError -import io.realm.kotlin.internal.interop.sync.ProtocolConnectionErrorCode -import io.realm.kotlin.internal.interop.sync.ProtocolSessionErrorCode import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.mongodb.exceptions.AppException import io.realm.kotlin.mongodb.exceptions.AuthException import io.realm.kotlin.mongodb.exceptions.BadFlexibleSyncQueryException @@ -80,64 +77,26 @@ internal fun channelResultCallback( internal fun convertSyncError(syncError: SyncError): SyncException { val errorCode = syncError.errorCode - // FIXME Client Reset errors are just reported as normal Sync Errors for now. - // Will be fixed by https://github.com/realm/realm-kotlin/issues/417 val message = createMessageFromSyncError(errorCode) - return when (errorCode.category) { - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT -> { - // See https://github.com/realm/realm-core/blob/master/src/realm/sync/client_base.hpp#L73 - // For now, it is unclear how to categorize these, so for now, just report as generic - // errors. - SyncException(message) - } - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CONNECTION -> { - // See https://github.com/realm/realm-core/blob/master/src/realm/sync/protocol.hpp#L200 - // Use https://docs.google.com/spreadsheets/d/1SmiRxhFpD1XojqCKC-xAjjV-LKa9azeeWHg-zgr07lE/edit - // as guide for how to categorize Connection type errors. - when (errorCode.code) { - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_UNKNOWN_MESSAGE, // Unknown type of input message - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_SYNTAX, // Bad syntax in input message head - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_WRONG_PROTOCOL_VERSION, // Wrong protocol version (CLIENT) (obsolete) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_SESSION_IDENT, // Bad session identifier in input message - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_REUSE_OF_SESSION_IDENT, // Overlapping reuse of session identifier (BIND) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BOUND_IN_OTHER_SESSION, // Client file bound in other session (IDENT) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_MESSAGE_ORDER, // Bad input message order - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_DECOMPRESSION, // Error in decompression (UPLOAD) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_CHANGESET_HEADER_SYNTAX, // Bad syntax in a changeset header (UPLOAD) - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_BAD_CHANGESET_SIZE -> { // Bad size specified in changeset header (UPLOAD) - UnrecoverableSyncException(message) - } - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_FLX_SYNC, // Connected with wrong wire protocol - should switch to FLX sync - ProtocolConnectionErrorCode.RLM_SYNC_ERR_CONNECTION_SWITCH_TO_PBS -> { // Connected with wrong wire protocol - should switch to PBS - WrongSyncTypeException(message) - } - else -> SyncException(message) - } - } - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SESSION -> { - // See https://github.com/realm/realm-core/blob/master/src/realm/sync/protocol.hpp#L217 - // Use https://docs.google.com/spreadsheets/d/1SmiRxhFpD1XojqCKC-xAjjV-LKa9azeeWHg-zgr07lE/edit - // as guide for how to categorize Session type errors. - when (errorCode.code) { - ProtocolSessionErrorCode.RLM_SYNC_ERR_SESSION_BAD_QUERY -> { // Flexible Sync Query was rejected by the server - BadFlexibleSyncQueryException(message) - } - ProtocolSessionErrorCode.RLM_SYNC_ERR_SESSION_PERMISSION_DENIED -> - // Permission denied errors should be unrecoverable according to Core, i.e. the - // client will disconnect sync and transition to the "inactive" state - UnrecoverableSyncException(message) - ProtocolSessionErrorCode.RLM_SYNC_ERR_SESSION_COMPENSATING_WRITE -> - CompensatingWriteException(message, syncError.compensatingWrites) - else -> SyncException(message) - } + return when (errorCode.errorCode) { + ErrorCode.RLM_ERR_WRONG_SYNC_TYPE -> WrongSyncTypeException(message) + + ErrorCode.RLM_ERR_INVALID_SUBSCRIPTION_QUERY -> { + // Flexible Sync Query was rejected by the server + BadFlexibleSyncQueryException(message) } - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SYSTEM, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN -> { - // It is unclear how to handle system level errors, so even though some of them - // are probably benign, report as top-level errors for now. - SyncException(message) + ErrorCode.RLM_ERR_SYNC_COMPENSATING_WRITE -> CompensatingWriteException(message, syncError.compensatingWrites) + + ErrorCode.RLM_ERR_SYNC_PROTOCOL_INVARIANT_FAILED, + ErrorCode.RLM_ERR_SYNC_PROTOCOL_NEGOTIATION_FAILED, + ErrorCode.RLM_ERR_SYNC_PERMISSION_DENIED -> { + // Permission denied errors should be unrecoverable according to Core, i.e. the + // client will disconnect sync and transition to the "inactive" state + UnrecoverableSyncException(message) } else -> { + // An error happened we are not sure how to handle. Just report as a generic + // SyncException. SyncException(message) } } @@ -277,28 +236,25 @@ internal fun convertAppError(appError: AppError): Throwable { } } -internal fun createMessageFromSyncError(error: SyncErrorCode): String { - val categoryDesc = error.category.description ?: error.category.nativeValue.toString() - val errorCodeDesc: String? = error.code.description ?: when (error.category) { - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_SYSTEM, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN, - -> { - // We lack information about these kinds of errors, - // so rather than returning a potentially misleading - // name, just return nothing. - null - } - else -> "Unknown" +internal fun createMessageFromSyncError(error: CoreError): String { + val categoryDesc = error.categories.description + val errorCodeDesc: String? = error.errorCode?.description ?: if (ErrorCategory.RLM_ERR_CAT_SYSTEM_ERROR in error.categories) { + // We lack information about these kinds of errors, + // so rather than returning a potentially misleading + // name, just return nothing. + null + } else { + "Unknown" } // Combine all the parts to form an error format that is human-readable. // An example could be this: `[Connection][WrongProtocolVersion(104)] Wrong protocol version was used: 25` val errorDesc: String = - if (errorCodeDesc == null) error.code.nativeValue.toString() else "$errorCodeDesc(${error.code.nativeValue})" + if (errorCodeDesc == null) error.errorCodeNativeValue.toString() else "$errorCodeDesc(${error.errorCodeNativeValue})" // Make sure that messages are uniformly formatted, so it looks nice if we append the // server log. - val msg = error.message.let { message: String -> + val msg = error.message!!.let { message: String -> " $message${if (!message.endsWith(".")) "." else ""}" } diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt index 8409b7c556..720d2e4de2 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/SyncSessionImpl.kt @@ -19,16 +19,15 @@ package io.realm.kotlin.mongodb.internal import io.realm.kotlin.internal.InternalConfiguration import io.realm.kotlin.internal.NotificationToken import io.realm.kotlin.internal.RealmImpl +import io.realm.kotlin.internal.interop.CoreError +import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.RealmInterop import io.realm.kotlin.internal.interop.RealmSyncSessionPointer import io.realm.kotlin.internal.interop.SyncSessionTransferCompletionCallback import io.realm.kotlin.internal.interop.sync.CoreConnectionState import io.realm.kotlin.internal.interop.sync.CoreSyncSessionState import io.realm.kotlin.internal.interop.sync.ProgressDirection -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.internal.util.Validation import io.realm.kotlin.internal.util.trySendWithBufferOverflowCheck import io.realm.kotlin.mongodb.User @@ -165,15 +164,13 @@ internal open class SyncSessionImpl( /** * Simulates a sync error. Internal visibility only for testing. */ - internal fun simulateError( - errorCode: ProtocolClientErrorCode, - category: SyncErrorCodeCategory, + internal fun simulateSyncError( + error: ErrorCode, message: String = "Simulate Client Reset" ) { RealmInterop.realm_sync_session_handle_error_for_testing( nativePointer, - errorCode, - category, + error, message, true ) @@ -201,7 +198,7 @@ internal open class SyncSessionImpl( val result: Any = withTimeout(timeout) { withContext(realm.notificationDispatcherHolder.dispatcher) { val callback = object : SyncSessionTransferCompletionCallback { - override fun invoke(errorCode: SyncErrorCode?) { + override fun invoke(errorCode: CoreError?) { if (errorCode != null) { // Transform the errorCode into a dummy syncError so we can have a // common path. diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt index 6dbadc3571..3cf2b72d18 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt @@ -25,8 +25,7 @@ import io.realm.kotlin.entities.sync.flx.FlexChildObject import io.realm.kotlin.entities.sync.flx.FlexEmbeddedObject import io.realm.kotlin.entities.sync.flx.FlexParentObject import io.realm.kotlin.ext.query -import io.realm.kotlin.internal.interop.sync.ProtocolClientErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory +import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.platform.fileExists import io.realm.kotlin.internal.platform.runBlocking import io.realm.kotlin.log.LogLevel @@ -609,10 +608,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) @@ -682,10 +678,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) @@ -898,9 +891,8 @@ class SyncClientResetIntegrationTests { ) // assertEquals(ClientResetLogEvents.DISCARD_LOCAL_ON_AFTER_RESET, logChannel.receiveOrFail()) - (realm.syncSession as SyncSessionImpl).simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT + (realm.syncSession as SyncSessionImpl).simulateSyncError( + ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED ) // Validate that we receive logs on the error callback val actual = logChannel.receiveOrFail() @@ -948,10 +940,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with((realm.syncSession as SyncSessionImpl)) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) val exception = channel.receiveOrFail() val originalFilePath = assertNotNull(exception.originalFilePath) @@ -1002,10 +991,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) val exception = channel.receiveOrFail() @@ -1121,10 +1107,7 @@ class SyncClientResetIntegrationTests { runBlocking { realm.syncSession.downloadAllServerChanges(defaultTimeout) - (realm.syncSession as SyncSessionImpl).simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + (realm.syncSession as SyncSessionImpl).simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) val exception = channel.receiveOrFail() assertNotNull(exception.recoveryFilePath) @@ -1248,10 +1231,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) @@ -1449,10 +1429,7 @@ class SyncClientResetIntegrationTests { realm.syncSession.downloadAllServerChanges(defaultTimeout) with(realm.syncSession as SyncSessionImpl) { - simulateError( - ProtocolClientErrorCode.RLM_SYNC_ERR_CLIENT_AUTO_CLIENT_RESET_FAILURE, - SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CLIENT - ) + simulateSyncError(ErrorCode.RLM_ERR_AUTO_CLIENT_RESET_FAILED) // TODO Twice until the deprecated method is removed assertEquals(ClientResetEvents.ON_MANUAL_RESET_FALLBACK, channel.receiveOrFail()) diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt index 9cf0bd49fd..7ed110597c 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt @@ -18,67 +18,80 @@ package io.realm.kotlin.test.mongodb.common.internal +import io.realm.kotlin.internal.interop.CoreError import io.realm.kotlin.internal.interop.ErrorCategory +import io.realm.kotlin.internal.interop.ErrorCode import io.realm.kotlin.internal.interop.UnknownCodeDescription import io.realm.kotlin.internal.interop.sync.AppError import io.realm.kotlin.internal.interop.sync.SyncError -import io.realm.kotlin.internal.interop.sync.SyncErrorCode -import io.realm.kotlin.internal.interop.sync.SyncErrorCodeCategory import io.realm.kotlin.mongodb.internal.convertAppError import io.realm.kotlin.mongodb.internal.convertSyncError import kotlin.test.Test import kotlin.test.assertEquals -const val UNMAPPED_CODE: Int = 0 +const val UNMAPPED_CATEGORY_CODE: Int = 0 +const val UNMAPPED_ERROR_CODE: Int = -1 class RealmSyncUtilsTest { + @Test - fun convertSyncErrorCode_unmappedErrorCode_categoryTypeUnknown() { + fun convertSyncErrorCode_unmappedErrorCode2() { val syncException = convertSyncError( SyncError( - SyncErrorCode( - category = SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_UNKNOWN, - code = UnknownCodeDescription(UNMAPPED_CODE), - message = "Placeholder message" + CoreError( + categoriesNativeValue = ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR.nativeValue, + errorCodeNativeValue = UNMAPPED_ERROR_CODE, + messageNativeValue = "Placeholder message", + path = "no-path", + userError = null ) ) ) - assertEquals("[Unknown][$UNMAPPED_CODE] Placeholder message.", syncException.message) + assertEquals( + "[Client][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", + syncException.message + ) } @Test - fun convertSyncErrorCode_unmappedErrorCode2() { + fun convertSyncErrorCode_unmappedErrorCategory() { val syncException = convertSyncError( SyncError( - SyncErrorCode( - category = SyncErrorCodeCategory.RLM_SYNC_ERROR_CATEGORY_CONNECTION, - code = UnknownCodeDescription(UNMAPPED_CODE), - message = "Placeholder message" + CoreError( + categoriesNativeValue = UNMAPPED_CATEGORY_CODE, + errorCodeNativeValue = UNMAPPED_ERROR_CODE, + messageNativeValue = "Placeholder message", + path = "no-path", + userError = null ) ) ) assertEquals( - "[Connection][Unknown($UNMAPPED_CODE)] Placeholder message.", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", syncException.message ) } + // Core also has a concept of an "unknown" error code. It is being reported the same way + // as a truly unknown code with the description "Unknown()" @Test - fun convertSyncErrorCode_unmappedErrorCategory() { + fun convertSyncErrorCode_unknownNativeErrrorCode() { val syncException = convertSyncError( SyncError( - SyncErrorCode( - category = UnknownCodeDescription(UNMAPPED_CODE), - code = UnknownCodeDescription(UNMAPPED_CODE), - message = "Placeholder message" + CoreError( + categoriesNativeValue = ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR.nativeValue, + errorCodeNativeValue = ErrorCode.RLM_ERR_UNKNOWN.nativeValue, + messageNativeValue = "Placeholder message", + path = "no-path", + userError = null ) ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Placeholder message.", + "[Client][Unknown(2000000)] Placeholder message.", syncException.message ) } @@ -88,30 +101,30 @@ class RealmSyncUtilsTest { val appException = convertAppError( AppError( categoryFlags = ErrorCategory.RLM_ERR_CAT_CUSTOM_ERROR.nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = "Placeholder message", - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = null ) ) - assertEquals("[Custom][Unknown($UNMAPPED_CODE)] Placeholder message.", appException.message) + assertEquals("[Custom][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", appException.message) } @Test fun convertAppError_unmappedErrorCategory() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = "Placeholder message", - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = null ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Placeholder message.", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message.", appException.message ) } @@ -120,31 +133,31 @@ class RealmSyncUtilsTest { fun convertAppError_unmappedErrorCategoryAndErrorCode_noMessage() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = null, - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = null ) ) - assertEquals("[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)]", appException.message) + assertEquals("[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)]", appException.message) } @Test fun convertAppError_unmappedErrorCategoryAndErrorCode_linkServerLog() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = "Placeholder message", - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = "http://realm.io" ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Placeholder message. Server log entry: http://realm.io", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Placeholder message. Server log entry: http://realm.io", appException.message ) } @@ -153,16 +166,16 @@ class RealmSyncUtilsTest { fun convertAppError_unmappedErrorCategoryAndErrorCode_noMessage_linkServerLog() { val appException = convertAppError( AppError( - categoryFlags = UnknownCodeDescription(UNMAPPED_CODE).nativeValue, - code = UnknownCodeDescription(UNMAPPED_CODE), + categoryFlags = UnknownCodeDescription(UNMAPPED_CATEGORY_CODE).nativeValue, + code = UnknownCodeDescription(UNMAPPED_ERROR_CODE), message = null, - httpStatusCode = UNMAPPED_CODE, + httpStatusCode = UNMAPPED_ERROR_CODE, linkToServerLog = "http://realm.io" ) ) assertEquals( - "[$UNMAPPED_CODE][Unknown($UNMAPPED_CODE)] Server log entry: http://realm.io", + "[$UNMAPPED_CATEGORY_CODE][Unknown($UNMAPPED_ERROR_CODE)] Server log entry: http://realm.io", appException.message ) } From 384c34ceef2589e8d166eab9c794d274d54740ae Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Wed, 23 Aug 2023 11:42:50 +0200 Subject: [PATCH 02/12] Cleanup of CategoryFlags --- .../kotlin/io/realm/kotlin/internal/interop/CoreError.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt index 0e6821cba1..721a03d6cd 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt @@ -40,6 +40,7 @@ data class CategoryFlags(val categoryFlags: Int) { val CATEGORY_ORDER: List = listOf( ErrorCategory.RLM_ERR_CAT_CUSTOM_ERROR, ErrorCategory.RLM_ERR_CAT_WEBSOCKET_ERROR, + ErrorCategory.RLM_ERR_CAT_SYNC_ERROR, ErrorCategory.RLM_ERR_CAT_SERVICE_ERROR, ErrorCategory.RLM_ERR_CAT_JSON_ERROR, ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR, @@ -55,7 +56,8 @@ data class CategoryFlags(val categoryFlags: Int) { /** * Returns a description of the most important category defined in [categoryFlags]. - * If no known categories are found, "Unknown[categoryFlags]" is returned. + * If no known categories are found, the integer values for all the categories is returned + * as debugging information. */ val description: String = CATEGORY_ORDER.firstOrNull { category -> category in this From bf196df3649b2760ac476c4a3be74ca510335e0d Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Wed, 23 Aug 2023 12:40:53 +0200 Subject: [PATCH 03/12] Fix compilation --- .../realm/kotlin/mongodb/internal/AppConfigurationImpl.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt index 98f9edb155..cb8fa12c7a 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AppConfigurationImpl.kt @@ -73,7 +73,7 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class) val appDispatcher = appNetworkDispatcherFactory.create() val networkTransport = networkTransportFactory(appDispatcher) val appConfigPointer: RealmAppConfigurationPointer = - initializeRealmAppConfig(appName, appVersion, bundleId, networkTransport) + initializeRealmAppConfig(bundleId, networkTransport) var applicationInfo: String? = null // Define user agent strings sent when making the WebSocket connection to Device Sync if (appName != null || appVersion == null) { @@ -121,8 +121,6 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class) // Only freeze anything after all properties are setup as this triggers freezing the actual // AppConfigurationImpl instance itself private fun initializeRealmAppConfig( - localAppName: String?, - localAppVersion: String?, bundleId: String, networkTransport: NetworkTransport ): RealmAppConfigurationPointer { @@ -133,8 +131,6 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class) connectionParams = SyncConnectionParams( sdkVersion = SDK_VERSION, bundleId = bundleId, - localAppName = localAppName, - localAppVersion = localAppVersion, platformVersion = OS_VERSION, device = DEVICE_MANUFACTURER, deviceVersion = DEVICE_MODEL, From 585e084c9c20d657f2b009911afd088e1a5599c5 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Wed, 23 Aug 2023 15:33:53 +0200 Subject: [PATCH 04/12] Fix test --- .../test/mongodb/common/internal/SyncConnectionParamsTests.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt index 6ef9b2f491..4ece5ae87c 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/SyncConnectionParamsTests.kt @@ -29,8 +29,6 @@ internal class SyncConnectionParamsTests { fun allProperties() { val props = SyncConnectionParams( sdkVersion = "sdkVersion", - localAppName = "appName", - localAppVersion = "appVersion", bundleId = "bundleId", platformVersion = "platformVersion", device = "device", @@ -40,8 +38,6 @@ internal class SyncConnectionParamsTests { ) assertEquals("Kotlin", props.sdkName) assertEquals("sdkVersion", props.sdkVersion) - assertEquals("appName", props.localAppName) - assertEquals("appVersion", props.localAppVersion) assertEquals("bundleId", props.bundleId) assertEquals("platformVersion", props.platformVersion) assertEquals("device", props.device) From 53aa41baa82d8b2e5d5f46e3d99565901d7f0918 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Thu, 24 Aug 2023 09:15:04 +0200 Subject: [PATCH 05/12] Fix test --- .../commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt index 23745dbffc..3f7267c8a0 100644 --- a/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt +++ b/packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt @@ -2361,7 +2361,7 @@ class QueryTests { assertEquals(1, realm.query("fulltextField TEXT 'quick dog'").find().size) // words at different locations assertEquals(0, realm.query("fulltextField TEXT 'brown -fox'").find().size) // exclusion - assertEquals(0, realm.query("fulltextField TEXT 'fo*'").find().size) // token prefix search does not work + assertEquals(2, realm.query("fulltextField TEXT 'fo*'").find().size) // token prefix search is supported. assertEquals(1, realm.query("fulltextField TEXT 'cafe big'").find().size) // case- and diacritics-insensitive assertEquals(1, realm.query("fulltextField TEXT 'rødgrød'").find().size) // Latin-1 supplement assertEquals(0, realm.query("fulltextField TEXT '😊'").find().size) // Searching outside supported chars return nothing From 90f99ebbc8e604fefc35cd3e6fee9145bf2b1258 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Thu, 24 Aug 2023 14:13:05 +0200 Subject: [PATCH 06/12] Remove unused error fields --- .../io/realm/kotlin/internal/interop/CoreError.kt | 7 +++---- .../realm/kotlin/internal/interop/sync/SyncError.kt | 3 +-- .../sync/JVMSyncSessionTransferCompletionCallback.kt | 4 ++-- .../io/realm/kotlin/internal/interop/RealmInterop.kt | 4 +--- .../jni-swig-stub/src/main/jni/realm_api_helpers.cpp | 9 +++------ .../mongodb/common/FlexibleSyncIntegrationTests.kt | 5 +++-- .../mongodb/common/internal/RealmSyncUtilsTest.kt | 12 +++--------- 7 files changed, 16 insertions(+), 28 deletions(-) diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt index 721a03d6cd..2790a0d825 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt @@ -8,14 +8,13 @@ class CoreError( categoriesNativeValue: Int, val errorCodeNativeValue: Int, messageNativeValue: String?, - path: String, - userError: Throwable? + // These are represent in the C-API, but not populated by Core. + // path: String, + // userError: Throwable? ) { val categories: CategoryFlags = CategoryFlags((categoriesNativeValue)) val errorCode: ErrorCode? = ErrorCode.of(errorCodeNativeValue) val message = messageNativeValue - val realmPath: String = path - val userError: Throwable? = userError operator fun contains(category: ErrorCategory): Boolean = category in categories } diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncError.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncError.kt index 77fa3a4d23..dfe69d2ea3 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncError.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/sync/SyncError.kt @@ -51,7 +51,6 @@ data class SyncError constructor( categoryFlags: Int, value: Int, message: String, - path: String, originalFilePath: String?, recoveryFilePath: String?, isFatal: Boolean, @@ -59,7 +58,7 @@ data class SyncError constructor( isClientResetRequested: Boolean, compensatingWrites: Array ) : this( - CoreError(categoryFlags, value, message, path, null), + CoreError(categoryFlags, value, message), originalFilePath, recoveryFilePath, isFatal, diff --git a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt index 94df1f403e..8c3cf2c981 100644 --- a/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt +++ b/packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/sync/JVMSyncSessionTransferCompletionCallback.kt @@ -29,7 +29,7 @@ internal class JVMSyncSessionTransferCompletionCallback( fun onSuccess() { callback.invoke(null) } - fun onError(categoryFlags: Int, value: Int, message: String, path: String) { - callback.invoke(CoreError(categoryFlags, value, message, path, null)) + fun onError(categoryFlags: Int, value: Int, message: String) { + callback.invoke(CoreError(categoryFlags, value, message)) } } diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index d5e4780534..23ac249849 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -2390,9 +2390,7 @@ actual object RealmInterop { val code = CoreError( this.status.categories.toInt(), this.status.error.value.toInt(), - this.status.message.safeKString(), - this.status.path.safeKString(), - null + this.status.message.safeKString() ) val userInfoMap = (0 until user_info_length.toInt()) diff --git a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp index 8359e823ce..bc8a0ed658 100644 --- a/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp +++ b/packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp @@ -714,12 +714,11 @@ jobject convert_to_jvm_sync_error(JNIEnv* jenv, const realm_sync_error_t& error) static JavaMethod sync_error_constructor(jenv, JavaClassGlobalDef::sync_error(), "", - "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ[Lio/realm/kotlin/internal/interop/sync/CoreCompensatingWriteInfo;)V"); + "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ[Lio/realm/kotlin/internal/interop/sync/CoreCompensatingWriteInfo;)V"); jint category = static_cast(error.status.categories); jint value = static_cast(error.status.error); jstring msg = to_jstring(jenv, error.status.message); - jstring path = to_jstring(jenv, error.status.path); jstring joriginal_file_path = nullptr; jstring jrecovery_file_path = nullptr; jboolean is_fatal = error.is_fatal; @@ -793,7 +792,6 @@ jobject convert_to_jvm_sync_error(JNIEnv* jenv, const realm_sync_error_t& error) category, value, msg, - path, joriginal_file_path, jrecovery_file_path, is_fatal, @@ -836,13 +834,12 @@ void transfer_completion_callback(void* userdata, realm_error_t* error) { static JavaMethod java_error_callback_method(env, JavaClassGlobalDef::sync_session_transfer_completion_callback(), "onError", - "(IILjava/lang/String;Ljava/lang/String;)V"); + "(IILjava/lang/String;)V"); if (error) { jint category = static_cast(error->categories); jint value = error->error; jstring msg = to_jstring(env, error->message); - jstring path = to_jstring(env, error->path); - env->CallVoidMethod(static_cast(userdata), java_error_callback_method, category, value, msg, path); + env->CallVoidMethod(static_cast(userdata), java_error_callback_method, category, value, msg); } else { env->CallVoidMethod(static_cast(userdata), java_success_callback_method); } diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt index 661a2538fb..1922c55e7a 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/FlexibleSyncIntegrationTests.kt @@ -22,6 +22,7 @@ import io.realm.kotlin.entities.sync.flx.FlexEmbeddedObject import io.realm.kotlin.entities.sync.flx.FlexParentObject import io.realm.kotlin.ext.query import io.realm.kotlin.internal.platform.runBlocking +import io.realm.kotlin.log.LogLevel import io.realm.kotlin.mongodb.exceptions.CompensatingWriteException import io.realm.kotlin.mongodb.exceptions.DownloadingRealmTimeOutException import io.realm.kotlin.mongodb.exceptions.SyncException @@ -63,7 +64,7 @@ class FlexibleSyncIntegrationTests { @BeforeTest fun setup() { - app = TestApp(appName = TEST_APP_FLEX) + app = TestApp(appName = TEST_APP_FLEX, logLevel = LogLevel.ALL) val (email, password) = TestHelper.randomEmail() to "password1234" runBlocking { app.createUserAndLogIn(email, password) @@ -332,7 +333,7 @@ class FlexibleSyncIntegrationTests { val exception: CompensatingWriteException = channel.receiveOrFail() - assertEquals("[Session][CompensatingWrite(231)] Client attempted a write that is disallowed by permissions, or modifies an object outside the current query, and the server undid the change.", exception.message) + assertTrue(exception.message!!.startsWith("[Sync][CompensatingWrite(1033)] Client attempted a write that is outside of permissions or query filters; it has been reverted Logs:"), exception.message) assertEquals(1, exception.writes.size) exception.writes[0].run { diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt index 7ed110597c..6c6f5a1fc0 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/internal/RealmSyncUtilsTest.kt @@ -41,9 +41,7 @@ class RealmSyncUtilsTest { CoreError( categoriesNativeValue = ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR.nativeValue, errorCodeNativeValue = UNMAPPED_ERROR_CODE, - messageNativeValue = "Placeholder message", - path = "no-path", - userError = null + messageNativeValue = "Placeholder message" ) ) ) @@ -61,9 +59,7 @@ class RealmSyncUtilsTest { CoreError( categoriesNativeValue = UNMAPPED_CATEGORY_CODE, errorCodeNativeValue = UNMAPPED_ERROR_CODE, - messageNativeValue = "Placeholder message", - path = "no-path", - userError = null + messageNativeValue = "Placeholder message" ) ) ) @@ -83,9 +79,7 @@ class RealmSyncUtilsTest { CoreError( categoriesNativeValue = ErrorCategory.RLM_ERR_CAT_CLIENT_ERROR.nativeValue, errorCodeNativeValue = ErrorCode.RLM_ERR_UNKNOWN.nativeValue, - messageNativeValue = "Placeholder message", - path = "no-path", - userError = null + messageNativeValue = "Placeholder message" ) ) ) From 8f6a142683a0885cae6cf7dd63ce77dca8c79d2f Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Thu, 24 Aug 2023 14:37:08 +0200 Subject: [PATCH 07/12] Fix darwin --- .../kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt index 23ac249849..1f25cf704d 100644 --- a/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt +++ b/packages/cinterop/src/nativeDarwin/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt @@ -21,7 +21,6 @@ package io.realm.kotlin.internal.interop import io.realm.kotlin.internal.interop.Constants.ENCRYPTION_KEY_LENGTH import io.realm.kotlin.internal.interop.sync.ApiKeyWrapper import io.realm.kotlin.internal.interop.sync.AppError -import io.realm.kotlin.internal.interop.sync.AppError.Companion.newInstance import io.realm.kotlin.internal.interop.sync.AuthProvider import io.realm.kotlin.internal.interop.sync.CoreCompensatingWriteInfo import io.realm.kotlin.internal.interop.sync.CoreConnectionState @@ -2636,8 +2635,7 @@ actual object RealmInterop { val category = error.pointed.categories.toInt() val value: Int = error.pointed.error.value.toInt() val message = error.pointed.message.safeKString() - val path = error.pointed.path.safeKString() - completionCallback.invoke(CoreError(category, value, message, path, null)) + completionCallback.invoke(CoreError(category, value, message)) } else { completionCallback.invoke(null) } From 1dcfc72aad28cd9729380bd1576ff572b4b7149e Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Thu, 24 Aug 2023 16:20:27 +0200 Subject: [PATCH 08/12] Fix client reset tests --- .../common/SyncClientResetIntegrationTests.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt index 3cf2b72d18..d1e362e6f0 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncClientResetIntegrationTests.kt @@ -595,7 +595,7 @@ class SyncClientResetIntegrationTests { // testing the server will send a different message. This just ensures that // we don't accidentally modify or remove the message. assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) @@ -728,7 +728,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -740,7 +740,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -812,7 +812,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -824,7 +824,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -948,7 +948,7 @@ class SyncClientResetIntegrationTests { assertTrue(fileExists(originalFilePath)) assertFalse(fileExists(recoveryFilePath)) assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) } @@ -1114,7 +1114,7 @@ class SyncClientResetIntegrationTests { assertNotNull(exception.originalFilePath) assertFalse(fileExists(exception.recoveryFilePath)) assertTrue(fileExists(exception.originalFilePath)) - assertTrue(exception.message!!.contains("Automatic recovery from client reset failed")) + assertTrue(exception.message!!.contains("Simulate Client Reset")) } } } @@ -1157,7 +1157,7 @@ class SyncClientResetIntegrationTests { ) { // Notify that this callback has been invoked assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] A fatal error occurred during client reset: 'User-provided callback failed'.", exception.message ) channel.trySend(ClientResetEvents.ON_MANUAL_RESET_FALLBACK) @@ -1218,7 +1218,7 @@ class SyncClientResetIntegrationTests { assertTrue(fileExists(recoveryFilePath)) assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) @@ -1416,7 +1416,7 @@ class SyncClientResetIntegrationTests { assertTrue(fileExists(recoveryFilePath)) assertEquals( - "[Client][AutoClientResetFailure(132)] Automatic recovery from client reset failed.", + "[Sync][AutoClientResetFailed(1028)] Simulate Client Reset.", exception.message ) From 1fbfc7ba1372a330061faf032087ee03e5119e27 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Thu, 24 Aug 2023 17:29:19 +0200 Subject: [PATCH 09/12] Fix more tests --- .../kotlin/internal/interop/CoreErrorConverter.kt | 5 ++++- packages/external/core | 2 +- .../kotlin/test/mongodb/common/SyncedRealmTests.kt | 12 +++--------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt index 36174fb949..0a60a8aa7b 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreErrorConverter.kt @@ -38,8 +38,11 @@ object CoreErrorConverter { return userError ?: when { ErrorCode.RLM_ERR_INDEX_OUT_OF_BOUNDS == errorCode -> IndexOutOfBoundsException(message) - ErrorCategory.RLM_ERR_CAT_INVALID_ARG in categories -> + ErrorCategory.RLM_ERR_CAT_INVALID_ARG in categories && ErrorCategory.RLM_ERR_CAT_SYNC_ERROR !in categories -> { + // Some sync errors flagged as both logical and illegal. In our case, we consider those + // IllegalState, so discard them them here and let them fall through to the bottom case IllegalArgumentException(message) + } ErrorCategory.RLM_ERR_CAT_LOGIC in categories || ErrorCategory.RLM_ERR_CAT_RUNTIME in categories -> IllegalStateException(message) else -> Error(message) // This can happen when propagating user level exceptions. diff --git a/packages/external/core b/packages/external/core index d1ace25101..10b235d9a6 160000 --- a/packages/external/core +++ b/packages/external/core @@ -1 +1 @@ -Subproject commit d1ace25101b638520be8fbcbe7ed14f50e74c23d +Subproject commit 10b235d9a60b5fe20440d4ed5807b26bfb5231b5 diff --git a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt index 38e0fa85b4..8ddaa64cb7 100644 --- a/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt +++ b/packages/test-sync/src/commonTest/kotlin/io/realm/kotlin/test/mongodb/common/SyncedRealmTests.kt @@ -386,15 +386,9 @@ class SyncedRealmTests { exception.message.let { errorMessage -> assertNotNull(errorMessage) // Some race on JVM in particular mean that different errors can be reported. - if (errorMessage.contains("[Client]")) { - assertTrue(errorMessage.contains("[BadChangeset(112)]"), errorMessage) - assertTrue(errorMessage.contains("Bad changeset (DOWNLOAD)"), errorMessage) - } else if (errorMessage.contains("[Session]")) { - assertTrue(errorMessage.contains("InvalidSchemaChange(225)"), errorMessage) - assertTrue( - errorMessage.contains("Invalid schema change (UPLOAD)"), - errorMessage - ) + if (errorMessage.contains("[Sync]")) { + assertTrue(errorMessage.contains("[BadChangeset(1015)]"), errorMessage) + assertTrue(errorMessage.contains("Schema mismatch"), errorMessage) } else { fail("Unexpected error message: $errorMessage") } From 3e806330076416c8931826ac130a98218ae27678 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Thu, 24 Aug 2023 17:42:25 +0200 Subject: [PATCH 10/12] Fix core commit --- packages/external/core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/external/core b/packages/external/core index 10b235d9a6..2829f5ceae 160000 --- a/packages/external/core +++ b/packages/external/core @@ -1 +1 @@ -Subproject commit 10b235d9a60b5fe20440d4ed5807b26bfb5231b5 +Subproject commit 2829f5ceaebcee5250bdd032b67b72d65308d29a From e47a4ad0ddd501dc1fa3585e839c641437604469 Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 25 Aug 2023 07:34:02 +0200 Subject: [PATCH 11/12] Update core --- CHANGELOG.md | 2 +- packages/external/core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a73832bba9..a659cc213e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,7 @@ if the content is the same. Custom implementations of these methods will be resp * Minimum Android SDK: 16. ### Internal -* Updated to Realm Core 13.18.0, commit 48d6d672cb30f86976ba19a44ffffe25ed447128. +* Updated to Realm Core 13.19.0, commit ea7c5d5e2900b8411a295aea3d1aa56aa55fff1d. ## 1.10.2 (2023-07-21) diff --git a/packages/external/core b/packages/external/core index 2829f5ceae..ea7c5d5e29 160000 --- a/packages/external/core +++ b/packages/external/core @@ -1 +1 @@ -Subproject commit 2829f5ceaebcee5250bdd032b67b72d65308d29a +Subproject commit ea7c5d5e2900b8411a295aea3d1aa56aa55fff1d From 8f6fc3d174c1ca80f3e52fa36069fb2bd8bc623a Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 25 Aug 2023 11:24:28 +0200 Subject: [PATCH 12/12] PR feedback --- .../kotlin/io/realm/kotlin/internal/interop/CoreError.kt | 5 +---- .../io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt index 2790a0d825..3d7334fcd7 100644 --- a/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt +++ b/packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/CoreError.kt @@ -8,9 +8,6 @@ class CoreError( categoriesNativeValue: Int, val errorCodeNativeValue: Int, messageNativeValue: String?, - // These are represent in the C-API, but not populated by Core. - // path: String, - // userError: Throwable? ) { val categories: CategoryFlags = CategoryFlags((categoriesNativeValue)) val errorCode: ErrorCode? = ErrorCode.of(errorCodeNativeValue) @@ -59,7 +56,7 @@ data class CategoryFlags(val categoryFlags: Int) { * as debugging information. */ val description: String = CATEGORY_ORDER.firstOrNull { category -> - category in this + this.contains(category) }?.description ?: "$categoryFlags" /** diff --git a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt index db0313cfb2..fb72304c78 100644 --- a/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt +++ b/packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncUtils.kt @@ -254,9 +254,9 @@ internal fun createMessageFromSyncError(error: CoreError): String { // Make sure that messages are uniformly formatted, so it looks nice if we append the // server log. - val msg = error.message!!.let { message: String -> + val msg = error.message?.let { message: String -> " $message${if (!message.endsWith(".")) "." else ""}" - } + } ?: "" return "[$categoryDesc][$errorDesc]$msg" }