commonMain.io.realm.kotlin.mongodb.internal.RealmQueryExtImpl.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of library-sync Show documentation
Show all versions of library-sync Show documentation
Sync Library code for Realm Kotlin. This artifact is not supposed to be consumed directly, but through 'io.realm.kotlin:gradle-plugin:1.6.2' instead.
/*
* Copyright 2023 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.
*/
@file:Suppress("invisible_reference", "invisible_member")
package io.realm.kotlin.mongodb.internal
import io.realm.kotlin.Realm
import io.realm.kotlin.internal.RealmImpl
import io.realm.kotlin.internal.getRealm
import io.realm.kotlin.internal.query.ObjectQuery
import io.realm.kotlin.mongodb.exceptions.BadFlexibleSyncQueryException
import io.realm.kotlin.mongodb.subscriptions
import io.realm.kotlin.mongodb.sync.Subscription
import io.realm.kotlin.mongodb.sync.SubscriptionSet
import io.realm.kotlin.mongodb.sync.SyncConfiguration
import io.realm.kotlin.mongodb.sync.WaitForSync
import io.realm.kotlin.mongodb.syncSession
import io.realm.kotlin.query.RealmQuery
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.types.RealmObject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlin.time.Duration
internal suspend fun createSubscriptionFromQuery(
query: RealmQuery,
name: String?,
updateExisting: Boolean = false,
mode: WaitForSync,
timeout: Duration
): RealmResults {
if (query !is ObjectQuery) {
throw IllegalStateException("Only queries on objects are supported. This was: ${query::class}")
}
if (query.realmReference.owner !is RealmImpl) {
throw IllegalStateException("Calling `subscribe()` inside a write transaction is not allowed.")
}
val realm: Realm = query.getRealm()
val subscriptions = realm.subscriptions
val appDispatcher: CoroutineDispatcher = ((realm.configuration as SyncConfiguration).user.app as AppImpl).appNetworkDispatcher.dispatcher
return withTimeout(timeout) {
withContext(appDispatcher) {
val existingSubscription: Subscription? = findExistingQueryInSubscriptions(name, query, subscriptions)
if (existingSubscription == null || updateExisting) {
subscriptions.update {
add(query, name, updateExisting)
}
}
if ((mode == WaitForSync.FIRST_TIME || mode == WaitForSync.ALWAYS) && existingSubscription == null) {
subscriptions.waitForSynchronization()
} else if (mode == WaitForSync.ALWAYS) {
// The subscription should already exist, just make sure we downloaded all
// server data before continuing.
realm.syncSession.downloadAllServerChanges()
subscriptions.refresh()
subscriptions.errorMessage?.let { errorMessage: String ->
throw BadFlexibleSyncQueryException(errorMessage)
}
}
// Rerun the query on the latest Realm version.
realm.query(query.clazz, query.description()).find()
}
}
}
// A subscription only matches if name, type and query all matches
private fun findExistingQueryInSubscriptions(
name: String?,
query: ObjectQuery,
subscriptions: SubscriptionSet
): Subscription? {
return if (name != null) {
val sub: Subscription? = subscriptions.findByName(name)
val companion = io.realm.kotlin.internal.platform.realmObjectCompanionOrThrow(query.clazz)
val userTypeName = companion.io_realm_kotlin_className
if (sub?.queryDescription == query.description() && sub.objectType == userTypeName) {
sub
} else {
null
}
} else {
subscriptions.findByQuery(query)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy