Skip to content

Commit

Permalink
[RKOTLIN-1114] Fix sync client config not applied (#1779)
Browse files Browse the repository at this point in the history
  • Loading branch information
clementetb authored Aug 8, 2024
1 parent b6f141f commit 06aacec
Show file tree
Hide file tree
Showing 22 changed files with 237 additions and 76 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/include-static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
run: ./gradlew ktlintCheck

- name: Stash Ktlint results
if: always()
run: |
rm -rf /tmp/ktlint
rm -rf /tmp/detekt
Expand All @@ -50,6 +51,7 @@ jobs:
- name: Publish Ktlint results
uses: actions/upload-artifact@v4
if: always()
with:
name: Ktlint Analyzer report
path: /tmp/ktlint/*
Expand Down Expand Up @@ -85,7 +87,8 @@ jobs:
- name: Run Detekt
run: ./gradlew detekt

- name: Stash Detekt results
- name: Stash Detekt results
if: always()
run: |
rm -rf /tmp/detekt
mkdir /tmp/detekt
Expand All @@ -99,6 +102,7 @@ jobs:
- name: Publish Detekt results
uses: actions/upload-artifact@v4
if: always()
with:
name: Detekt Analyzer report
path: /tmp/detekt/*
Expand Down
34 changes: 25 additions & 9 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ jobs:
key: jni-linux-lib-${{ needs.check-cache.outputs.packages-sha }}

- name: Setup Java 11
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: ${{ vars.VERSION_JAVA_DISTRIBUTION }}
java-version: ${{ vars.VERSION_JAVA }}
Expand Down Expand Up @@ -431,11 +431,15 @@ jobs:
run: |-
echo "::add-matcher::.github/problem-matchers/kotlin.json"
- name: Setup Java 17
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: ${{ vars.VERSION_JAVA_DISTRIBUTION }}
java-version: '17'
# JVM 17 is required for android-actions/setup-android@v3
# Last version will be used and available globally. Other Java versions can be accessed through env variables with such specification as 'JAVA_HOME_{{ MAJOR_VERSION }}_{{ ARCHITECTURE }}'
java-version: |
17
${{ vars.VERSION_JAVA }}
- name: Setup Gradle and task/dependency caching
uses: gradle/actions/setup-gradle@v3
Expand Down Expand Up @@ -473,10 +477,14 @@ jobs:
echo '#!/bin/bash\nccache clang++ "$@"%"' > /usr/local/bin/ccache-clang++
- name: Setup Android SDK
uses: android-actions/setup-android@v2

env:
JAVA_HOME: ${{ env.JAVA_HOME_17_ARM64 }}
uses: android-actions/setup-android@v3

- name: Install NDK
run: sdkmanager --install "ndk;${{ env.NDK_VERSION }}"
env:
JAVA_HOME: ${{ env.JAVA_HOME_17_ARM64 }}

# We cannot use artifacts as they cannot be shared between workflows, so use cache instead.
- name: Setup build cache
Expand Down Expand Up @@ -543,11 +551,15 @@ jobs:
with:
submodules: "recursive"

- name: Setup Java 11
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: ${{ vars.VERSION_JAVA_DISTRIBUTION }}
java-version: ${{ vars.VERSION_JAVA }}
# JVM 17 is required for android-actions/setup-android@v3
# Last version will be used and available globally. Other Java versions can be accessed through env variables with such specification as 'JAVA_HOME_{{ MAJOR_VERSION }}_{{ ARCHITECTURE }}'
java-version: |
17
${{ vars.VERSION_JAVA }}
- name: Setup Gradle and task/dependency caching
uses: gradle/actions/setup-gradle@v3
Expand Down Expand Up @@ -602,9 +614,13 @@ jobs:
echo '#!/bin/bash\nccache clang++ "$@"%"' > /usr/local/bin/ccache-clang++
- name: Setup Android SDK
uses: android-actions/setup-android@v2

uses: android-actions/setup-android@v3
env:
JAVA_HOME: ${{ env.JAVA_HOME_17_X64 }}

- name: Install NDK
env:
JAVA_HOME: ${{ env.JAVA_HOME_17_X64 }}
run: sdkmanager --install "ndk;${{ env.NDK_VERSION }}"

- name: Build Android Base Test Apk
Expand Down
24 changes: 22 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,30 @@
* None.

### Enhancements
* Reduce the size of the local transaction log produced by creating objects, improving the performance of insertion-heavy transactions (Core issue [realm/realm-core#7734](https://github.com/realm/realm-core/pull/7734)).
* Performance has been improved for range queries on integers and timestamps. Requires that you use the "BETWEEN" operation in RQL or the Query::between() method when you build the query. (Core issue [realm/realm-core#7785](https://github.com/realm/realm-core/pull/7785))
* [Sync] Report the originating error that caused a client reset to occur. (Core issue [realm/realm-core#6154](https://github.com/realm/realm-core/issues/6154)).
* [Sync] It is no longer an error to set a base url for an App with a trailing slash - for example, `https://services.cloud.mongodb.com/` instead of `https://services.cloud.mongodb.com` - before this change that would result in a 404 error from the server (Core issue [realm/realm-core#7791](https://github.com/realm/realm-core/pull/7791)).
* [Sync] On Windows devices Device Sync will additionally look up SSL certificates in the Windows Trusted Root Certification Authorities certificate store when establishing a connection. (Core issue [realm/realm-core#7882](https://github.com/realm/realm-core/pull/7882))
* [Sync] Add support for switching users with `App.switchUser(User)`. (Issue [#1813](https://github.com/realm/realm-kotlin/issues/1813)/[RKOTLIN-1115](https://jira.mongodb.org/browse/RKOTLIN-1115)).

### Fixed
* None.
* Comparing a numeric property with an argument list containing a string would throw. (Core issue [realm/realm-core#7714](https://github.com/realm/realm-core/issues/7714), since v2.0.0).
* After compacting, a file upgrade would be triggered. This could cause loss of data if schema mode is SoftResetFile (Core issue [realm/realm-core#7747](https://github.com/realm/realm-core/issues/7747), since v1.15.0).
* Encrypted files on Windows had a maximum size of 2GB even on x64 due to internal usage of `off_t`, which is a 32-bit type on 64-bit Windows (Core issue [realm/realm-core#7698](https://github.com/realm/realm-core/pull/7698)).
* The encryption code no longer behaves differently depending on the system page size, which should entirely eliminate a recurring source of bugs related to copying encrypted Realm files between platforms with different page sizes. One known outstanding bug was ([RNET-1141](https://github.com/realm/realm-dotnet/issues/3592)), where opening files on a system with a larger page size than the writing system would attempt to read sections of the file which had never been written to (Core issue [realm/realm-core#7698](https://github.com/realm/realm-core/pull/7698)).
* There were several complicated scenarios which could result in stale reads from encrypted files in multiprocess scenarios. These were very difficult to hit and would typically lead to a crash, either due to an assertion failure or DecryptionFailure being thrown (Core issue [realm/realm-core#7698](https://github.com/realm/realm-core/pull/7698), since v1.8.0).
* Encrypted files have some benign data races where we can memcpy a block of memory while another thread is writing to a limited range of it. It is logically impossible to ever read from that range when this happens, but Thread Sanitizer quite reasonably complains about this. We now perform a slower operations when running with TSan which avoids this benign race (Core issue [realm/realm-core#7698](https://github.com/realm/realm-core/pull/7698)).
* Tokenizing strings for full-text search could pass values outside the range [-1, 255] to `isspace()`, which is undefined behavior (Core issue [realm/realm-core#7698](https://github.com/realm/realm-core/pull/7698), since the introduction of FTS).
* Clearing a List of RealmAnys in an upgraded file would lead to an assertion failing (Core issue [realm/realm-core#7771](https://github.com/realm/realm-core/issues/7771), since v1.15.0)
* You could get unexpected merge results when assigning to a nested collection (Core issue [realm/realm-core#7809](https://github.com/realm/realm-core/issues/7809), since v1.15.0)
* Fixed removing backlinks from the wrong objects if the link came from a nested list, nested dictionary, top-level dictionary, or list of mixed, and the source table had more than 256 objects. This could manifest as `array_backlink.cpp:112: Assertion failed: int64_t(value >> 1) == key.value` when removing an object. (Core issue [realm/realm-core#7594](https://github.com/realm/realm-core/issues/7594), since Core v11 for dictionaries)
* Fixed the collapse/rejoin of clusters which contained nested collections with links. This could manifest as `array.cpp:319: Array::move() Assertion failed: begin <= end [2, 1]` when removing an object. (Core issue [realm/realm-core#7839](https://github.com/realm/realm-core/issues/7839), since the introduction of nested collections in v1.15.0)
* [Sync] Platform networking was not enabled even if setting `AppConfiguration.Builder.usePlatformNetworking`. (Issue [#1811](https://github.com/realm/realm-kotlin/issues/1811)/[RKOTLIN-1114](https://jira.mongodb.org/browse/RKOTLIN-1114)).
* [Sync] Fix some client resets (such as migrating to flexible sync) potentially failing with AutoClientResetFailed if a new client reset condition (such as rolling back a flexible sync migration) occurred before the first one completed. (Core issue [realm/realm-core#7542](https://github.com/realm/realm-core/pull/7542), since v1.9.0)
* [Sync] Fixed a change of mode from Strong to All when removing links from an embedded object that links to a tombstone. This affects sync apps that use embedded objects which have a `Lst<Mixed>` that contains a link to another top level object which has been deleted by another sync client (creating a tombstone locally). In this particular case, the switch would cause any remaining link removals to recursively delete the destination object if there were no other links to it. (Core issue [realm/realm-core#7828](https://github.com/realm/realm-core/issues/7828), since v1.15.0)
* [Sync] `SyncSession.uploadAllLocalChanges` was inconsistent in how it handled commits which did not produce any changesets to upload. Previously it would sometimes complete immediately if all commits waiting to be uploaded were empty, and at other times it would wait for a server roundtrip. It will now always complete immediately. (Core issue [realm/realm-core#7796](https://github.com/realm/realm-core/pull/7796)).
* [Sync] Sync client can crash if a session is resumed while the session is being suspended. (Core issue [realm/realm-core#7860](https://github.com/realm/realm-core/issues/7860), since v1.0.0)

### Compatibility
* File format: Generates Realms with file format v24 (reads and upgrades file format v10 or later).
Expand All @@ -25,7 +45,7 @@
* Minimum R8: 8.0.34.

### Internal
* None.
* Updated to Realm Core 14.10.4 commit 4f83c590c4340dd7760d5f070e2e81613eb536aa.


## 2.1.1-SNAPSHOT (YYYY-MM-DD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,6 @@ expect object RealmInterop {
// App
fun realm_app_get(
appConfig: RealmAppConfigurationPointer,
syncClientConfig: RealmSyncClientConfigurationPointer,
basePath: String,
): RealmAppPointer
fun realm_app_get_current_user(app: RealmAppPointer): RealmUserPointer?
Expand Down Expand Up @@ -600,8 +599,7 @@ expect object RealmInterop {
fun realm_user_refresh_custom_data(app: RealmAppPointer, user: RealmUserPointer, callback: AppCallback<Unit>)

// Sync client config
fun realm_sync_client_config_new(): RealmSyncClientConfigurationPointer

fun realm_app_config_get_sync_client_config(configPointer: RealmAppConfigurationPointer): RealmSyncClientConfigurationPointer
fun realm_sync_client_config_set_default_binding_thread_observer(
syncClientConfig: RealmSyncClientConfigurationPointer,
appId: String
Expand Down Expand Up @@ -652,6 +650,8 @@ expect object RealmInterop {
user: RealmUserPointer,
partition: String
): RealmSyncConfigurationPointer
// Flexible Sync
fun realm_flx_sync_config_new(user: RealmUserPointer): RealmSyncConfigurationPointer
fun realm_sync_config_set_error_handler(
syncConfig: RealmSyncConfigurationPointer,
errorHandler: SyncErrorCallback
Expand Down Expand Up @@ -789,9 +789,6 @@ expect object RealmInterop {
syncConfiguration: RealmSyncConfigurationPointer
)

// Flexible Sync
fun realm_flx_sync_config_new(user: RealmUserPointer): RealmSyncConfigurationPointer

// Flexible Sync Subscription
fun realm_sync_subscription_id(subscription: RealmSubscriptionPointer): ObjectId
fun realm_sync_subscription_name(subscription: RealmSubscriptionPointer): String?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,6 @@ actual object RealmInterop {

actual fun realm_app_get(
appConfig: RealmAppConfigurationPointer,
syncClientConfig: RealmSyncClientConfigurationPointer,
basePath: String
): RealmAppPointer {
return LongPointerWrapper(realmc.realm_app_create(appConfig.cptr()), managed = true)
Expand Down Expand Up @@ -1314,8 +1313,9 @@ actual object RealmInterop {
)
}

actual fun realm_sync_client_config_new(): RealmSyncClientConfigurationPointer {
return LongPointerWrapper(realmc.realm_sync_client_config_new())
actual fun realm_app_config_get_sync_client_config(configPointer: RealmAppConfigurationPointer): RealmSyncClientConfigurationPointer {
// The configuration is owned by Core so don't track and release it through garbage collection of the NativePointer
return LongPointerWrapper(realmc.realm_app_config_get_sync_client_config(configPointer.cptr()), false)
}

actual fun realm_sync_client_config_set_default_binding_thread_observer(syncClientConfig: RealmSyncClientConfigurationPointer, appId: String) {
Expand Down Expand Up @@ -1762,6 +1762,10 @@ actual object RealmInterop {
}
}

actual fun realm_flx_sync_config_new(user: RealmUserPointer): RealmSyncConfigurationPointer {
return LongPointerWrapper<RealmSyncConfigT>(realmc.realm_flx_sync_config_new(user.cptr()))
}

actual fun realm_config_set_sync_config(realmConfiguration: RealmConfigurationPointer, syncConfiguration: RealmSyncConfigurationPointer) {
realmc.realm_config_set_sync_config(realmConfiguration.cptr(), syncConfiguration.cptr())
}
Expand Down Expand Up @@ -1984,10 +1988,6 @@ actual object RealmInterop {
realmc.realm_object_delete(obj.cptr())
}

actual fun realm_flx_sync_config_new(user: RealmUserPointer): RealmSyncConfigurationPointer {
return LongPointerWrapper(realmc.realm_flx_sync_config_new(user.cptr()))
}

actual fun realm_sync_subscription_id(subscription: RealmSubscriptionPointer): ObjectId {
val nativeBytes: ShortArray = realmc.realm_sync_subscription_id(subscription.cptr()).bytes
val byteArray = ByteArray(nativeBytes.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2062,7 +2062,6 @@ actual object RealmInterop {

actual fun realm_app_get(
appConfig: RealmAppConfigurationPointer,
syncClientConfig: RealmSyncClientConfigurationPointer,
basePath: String
): RealmAppPointer {
return CPointerWrapper(realm_wrapper.realm_app_create(appConfig.cptr()), managed = true)
Expand Down Expand Up @@ -2469,8 +2468,9 @@ actual object RealmInterop {
)
}

actual fun realm_sync_client_config_new(): RealmSyncClientConfigurationPointer {
return CPointerWrapper(realm_wrapper.realm_sync_client_config_new())
actual fun realm_app_config_get_sync_client_config(configPointer: RealmAppConfigurationPointer): RealmSyncClientConfigurationPointer {
// The configuration is owned by Core so don't track and release it through garbage collection of the NativePointer
return CPointerWrapper(realm_wrapper.realm_app_config_get_sync_client_config(configPointer.cptr()), false)
}

actual fun realm_sync_client_config_set_default_binding_thread_observer(
Expand Down Expand Up @@ -3321,6 +3321,10 @@ actual object RealmInterop {
}
}

actual fun realm_flx_sync_config_new(user: RealmUserPointer): RealmSyncConfigurationPointer {
return CPointerWrapper<RealmSyncConfigT>(realm_wrapper.realm_flx_sync_config_new((user.cptr())))
}

actual fun realm_app_sync_client_reconnect(app: RealmAppPointer) {
realm_wrapper.realm_app_sync_client_reconnect(app.cptr())
}
Expand All @@ -3336,10 +3340,6 @@ actual object RealmInterop {
realm_wrapper.realm_config_set_sync_config(realmConfiguration.cptr(), syncConfiguration.cptr())
}

actual fun realm_flx_sync_config_new(user: RealmUserPointer): RealmSyncConfigurationPointer {
return CPointerWrapper(realm_wrapper.realm_flx_sync_config_new((user.cptr())))
}

actual fun realm_sync_subscription_id(subscription: RealmSubscriptionPointer): ObjectId {
return ObjectId(realm_wrapper.realm_sync_subscription_id(subscription.cptr()).getBytes())
}
Expand Down
2 changes: 1 addition & 1 deletion packages/external/core
Submodule core updated 267 files
2 changes: 0 additions & 2 deletions packages/jni-swig-stub/realm.i
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,6 @@ $result = SWIG_JavaArrayOutLonglong(jenv, (long long *)result, 2);
%ignore "realm_dictionary_add_notification_callback";
%ignore "realm_results_add_notification_callback";

%ignore "realm_app_config_get_sync_client_config";

// Swig doesn't understand __attribute__ so eliminate it
#define __attribute__(x)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public open class UnrecoverableSyncException internal constructor(message: Strin
* Thrown when the type of sync used by the server does not match the one used by the client, i.e.
* the server and client disagrees whether to use Partition-based or Flexible Sync.
*/
@Suppress("DEPRECATION")
public class WrongSyncTypeException internal constructor(message: String) :
UnrecoverableSyncException(message)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class)
applicationInfo = info.toString()
}
val sdkInfo = "RealmKotlin/$SDK_VERSION"

val synClientConfig: RealmSyncClientConfigurationPointer = initializeSyncClientConfig(
appConfigPointer,
websocketTransport,
sdkInfo,
applicationInfo.toString()
Expand All @@ -101,7 +103,6 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class)
websocketTransport,
RealmInterop.realm_app_get(
appConfigPointer,
synClientConfig,
appFilesDirectory()
)
)
Expand Down Expand Up @@ -158,11 +159,12 @@ public class AppConfigurationImpl @OptIn(ExperimentalKBsonSerializerApi::class)
}

private fun initializeSyncClientConfig(
appConfigPointer: RealmAppConfigurationPointer,
webSocketTransport: WebSocketTransport?,
sdkInfo: String?,
applicationInfo: String?
): RealmSyncClientConfigurationPointer =
RealmInterop.realm_sync_client_config_new()
RealmInterop.realm_app_config_get_sync_client_config(appConfigPointer)
.also { syncClientConfig ->
// Initialize client configuration first
RealmInterop.realm_sync_client_config_set_default_binding_thread_observer(syncClientConfig, appId)
Expand Down
Loading

0 comments on commit 06aacec

Please sign in to comment.