Skip to content

Commit

Permalink
Backup
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Melchior committed Oct 13, 2023
1 parent 0c22cdb commit 6885aa3
Show file tree
Hide file tree
Showing 18 changed files with 44 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ expect class RealmQueryArgumentList
sealed interface RealmQueryArgument
class RealmQuerySingleArgument(val argument: RealmValue) : RealmQueryArgument
class RealmQueryListArgument(val arguments: RealmValueList) : RealmQueryArgument

/**
* Inline class used for handling C-API `realm_key_path_array_t` structs when registering notifications
*/
1 change: 1 addition & 0 deletions packages/jni-swig-stub/realm.i
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ bool realm_object_is_valid(const realm_object_t*);
%array_functions(realm_query_arg_t, queryArgArray);
%array_functions(realm_user_identity_t, identityArray);
%array_functions(realm_app_user_apikey_t, apiKeyArray);
%array_functions(realm_key_path_array_t, keyPathArray);

// Work around issues with realm_size_t on Windows https://jira.mongodb.org/browse/RKOTLIN-332
%apply int64_t[] { size_t* };
Expand Down
3 changes: 0 additions & 3 deletions packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,6 @@ register_notification_cb(int64_t collection_ptr, realm_collection_type_e collect

switch (collection_type) {
case RLM_COLLECTION_TYPE_NONE:
auto obj = reinterpret_cast<realm_object_t*>(collection_ptr)
ob

return realm_object_add_notification_callback(
reinterpret_cast<realm_object_t*>(collection_ptr),
user_data, // Use the callback as user data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,13 @@ public fun BaseRealmObject.isValid(): Boolean = runIfManaged {
* the elements in a timely manner the coroutine scope will be cancelled with a
* [CancellationException].
*
* @param keyPaths TODO
* @return a flow representing changes to the object.
* @throws UnsupportedOperationException if called on a live [RealmObject] or [EmbeddedRealmObject]
* from a write transaction ([Realm.write]) or on a [DynamicRealmObject] inside a migration
* ([AutomaticSchemaMigration.migrate]).
*/
public fun <T : BaseRealmObject> T.asFlow(vararg keyPaths: String): Flow<ObjectChange<T>> = runIfManaged {
public fun <T : BaseRealmObject> T.asFlow(keyPaths: List<String>? = null): Flow<ObjectChange<T>> = runIfManaged {
checkNotificationsAvailable()
return owner.owner.registerObserver(this, keyPaths) as Flow<ObjectChange<T>>
} ?: throw IllegalStateException("Changes cannot be observed on unmanaged objects.")
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public abstract class BaseRealmImpl internal constructor(
return RealmInterop.realm_get_schema_version(realmReference.dbPointer)
}

internal open fun <T : CoreNotifiable<T, C>, C> registerObserver(t: Observable<T, C>, keyPath: Array<out String>): Flow<C> {
internal open fun <T : CoreNotifiable<T, C>, C> registerObserver(t: Observable<T, C>, keyPaths: List<String>?): Flow<C> {
throw UnsupportedOperationException(OBSERVABLE_NOT_SUPPORTED_MESSAGE)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import kotlinx.coroutines.flow.Flow
* A __flowable__ is an internal entity that supports listening to changes on the type [T] as a
* [Flow].
*/
internal interface Flowable<T> {
internal interface KeyPathFlowable<T> {
fun asFlow(keyPaths: List<String>? = null): Flow<T>
}

internal interface SimpleFlowable<T> {
fun asFlow(): Flow<T>
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public abstract class ChangeFlow<T, C>(private val producerScope: ProducerScope<
* @param T the type of entity that is observed.
* @param C the type of change events emitted for the T entity.
*/
internal interface CoreNotifiable<T, C> : Notifiable<T, C>, Observable<T, C>, Versioned, Flowable<C>
internal interface CoreNotifiable<T, C> : Notifiable<T, C>, Observable<T, C>, Versioned, KeyPathFlowable<C>
where T : CoreNotifiable<T, C> {
public fun thaw(liveRealm: RealmReference): T?
public fun registerForNotification(callback: Callback<RealmChangesPointer>): RealmNotificationTokenPointer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.Flow
internal class ObjectBoundRealmResults<E : BaseRealmObject>(
val targetObject: RealmObjectReference<*>,
val realmResults: RealmResults<E>,
) : RealmResults<E> by realmResults, InternalDeleteable, Flowable<ResultsChange<E>> {
) : RealmResults<E> by realmResults, InternalDeleteable, KeyPathFlowable<ResultsChange<E>> {

override val size: Int by realmResults::size

Expand Down Expand Up @@ -61,7 +61,7 @@ internal class ObjectBoundRealmResults<E : BaseRealmObject>(
*/

override fun asFlow(): Flow<ResultsChange<E>> {
return realmResults.asFlow().bind(targetObject)
return realmResults.asFlow().bind(targetObject, keyPaths)
}

override fun delete() {
Expand All @@ -78,5 +78,8 @@ internal class ObjectBoundRealmResults<E : BaseRealmObject>(
* Binds a flow to an object lifecycle. It allows flows on queries to complete once the object gets
* deleted. It is used on sub-queries and backlinks.
*/
internal fun <T> Flow<T>.bind(reference: RealmObjectReference<out BaseRealmObject>): Flow<T> =
this.terminateWhen(reference.asFlow()) { it is DeletedObject }
internal fun <T> Flow<T>.bind(
reference: RealmObjectReference<out BaseRealmObject>,
keyPaths: List<String>?
): Flow<T> =
this.terminateWhen(reference.asFlow(keyPaths)) { it is DeletedObject }
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,13 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.withLock
import kotlin.reflect.KClass

// TODO API-PUBLIC Document platform specific internals (RealmInitializer, etc.)
// TODO Public due to being accessed from `SyncedRealmContext`
public class RealmImpl private constructor(
configuration: InternalConfiguration,
) : BaseRealmImpl(configuration), Realm, InternalTypedRealm, Flowable<RealmChange<Realm>> {
) : BaseRealmImpl(configuration), Realm, InternalTypedRealm, KeyPathFlowable<RealmChange<Realm>> {

public val notificationScheduler: LiveRealmContext =
configuration.notificationDispatcherFactory.createLiveRealmContext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import kotlin.reflect.KClass
internal class UnmanagedRealmList<E>(
private val backingList: MutableList<E> = mutableListOf()
) : RealmList<E>, InternalDeleteable, MutableList<E> by backingList {
override fun asFlow(): Flow<ListChange<E>> =
override fun asFlow(keyPaths: List<String>?): Flow<ListChange<E>> =
throw UnsupportedOperationException("Unmanaged lists cannot be observed.")

override fun delete() {
Expand Down Expand Up @@ -113,9 +113,9 @@ internal class ManagedRealmList<E>(
return operator.set(index, element)
}

override fun asFlow(): Flow<ListChange<E>> {
override fun asFlow(keyPaths: List<String>?): Flow<ListChange<E>> {
operator.realmReference.checkClosed()
return operator.realmReference.owner.registerObserver(this, arrayOf())
return operator.realmReference.owner.registerObserver(this, keyPaths)
}

override fun freeze(frozenRealm: RealmReference): ManagedRealmList<E>? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ internal abstract class ManagedRealmMap<K, V> constructor(
internal val parent: RealmObjectReference<*>,
internal val nativePointer: RealmMapPointer,
val operator: MapOperator<K, V>
) : AbstractMutableMap<K, V>(), RealmMap<K, V>, CoreNotifiable<ManagedRealmMap<K, V>, MapChange<K, V>>, Flowable<MapChange<K, V>> {
) : AbstractMutableMap<K, V>(), RealmMap<K, V>, CoreNotifiable<ManagedRealmMap<K, V>, MapChange<K, V>>, KeyPathFlowable<MapChange<K, V>> {

private val keysPointer by lazy { RealmInterop.realm_dictionary_get_keys(nativePointer) }
private val valuesPointer by lazy { RealmInterop.realm_dictionary_to_results(nativePointer) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public class RealmObjectReference<T : BaseRealmObject>(
}.toTypedArray()
}

override fun asFlow(vararg keyPath: String): Flow<ObjectChange<T>> {
override fun asFlow(keyPath: List<String>?): Flow<ObjectChange<T>> {
return this.owner.owner.registerObserver(this, keyPath)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ internal class ObjectBoundQuery<E : BaseRealmObject>(
realmQuery.query(filter, *arguments)
)

override fun asFlow(): Flow<ResultsChange<E>> = realmQuery.asFlow().bind(targetObject)
// TODO
override fun asFlow(keyPath: List<String>?): Flow<ResultsChange<E>> = realmQuery.asFlow().bind(
targetObject,
keyPaths
)

override fun sort(property: String, sortOrder: Sort): RealmQuery<E> = ObjectBoundQuery(
targetObject,
Expand Down Expand Up @@ -107,19 +111,19 @@ internal class ObjectBoundRealmSingleQuery<E : BaseRealmObject>(
val targetObject: RealmObjectReference<*>,
val realmQuery: RealmSingleQuery<E>
) : RealmSingleQuery<E> by realmQuery {
override fun asFlow(): Flow<SingleQueryChange<E>> = realmQuery.asFlow().bind(targetObject)
override fun asFlow(keyPaths: List<String>?): Flow<SingleQueryChange<E>> = realmQuery.asFlow(keyPaths).bind(targetObject, keyPaths)
}

internal class ObjectBoundRealmScalarNullableQuery<E>(
val targetObject: RealmObjectReference<*>,
val realmQuery: RealmScalarNullableQuery<E>
) : RealmScalarNullableQuery<E> by realmQuery {
override fun asFlow(): Flow<E?> = realmQuery.asFlow().bind(targetObject)
override fun asFlow(keyPaths: List<String>?): Flow<E?> = realmQuery.asFlow().bind(targetObject, keyPaths)
}

internal class ObjectBoundRealmScalarQuery<E>(
val targetObject: RealmObjectReference<*>,
val realmQuery: RealmScalarQuery<E>
) : RealmScalarQuery<E> by realmQuery {
override fun asFlow(): Flow<E> = realmQuery.asFlow().bind(targetObject)
override fun asFlow(): Flow<E> = realmQuery.asFlow().bind(targetObject, keyPaths)
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ internal class ObjectQuery<E : BaseRealmObject> constructor(
override fun notifiable(): Notifiable<RealmResultsImpl<E>, ResultsChange<E>> =
QueryResultNotifiable(resultsPointer, classKey, clazz, mediator)

override fun asFlow(): Flow<ResultsChange<E>> {
override fun asFlow(keyPath: List<String>?): Flow<ResultsChange<E>> {
return realmReference.owner
.registerObserver(this, arrayOf())
.registerObserver(this, keyPath)
}

override fun delete() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public interface RealmElementQuery<T : BaseRealmObject> : Deleteable {
*
* **It is not allowed to call [asFlow] on queries generated from a [MutableRealm].**
*
* @param keyPath TODO
* @return a flow representing changes to the [RealmResults] resulting from running this query.
*/
public fun asFlow(): Flow<ResultsChange<T>>
public fun asFlow(keyPath: List<String>? = null): Flow<ResultsChange<T>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ public interface RealmResults<T : BaseRealmObject> : List<T>, Deleteable, Versio
* the elements in a timely manner the coroutine scope will be cancelled with a
* [CancellationException].
*
* @param keyPath TODO
* @return a flow representing changes to the RealmResults.
*/
public fun asFlow(): Flow<ResultsChange<T>>
public fun asFlow(keyPath: List<String>?): Flow<ResultsChange<T>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,5 @@ public interface RealmSingleQuery<T : BaseRealmObject> : Deleteable {
* @return a flow representing changes to the [RealmObject] or [EmbeddedRealmObject] resulting from
* running this query.
*/
public fun asFlow(vararg keyPaths: String): Flow<SingleQueryChange<T>>
public fun asFlow(keyPaths: List<String>? = null): Flow<SingleQueryChange<T>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ public interface RealmList<E> : MutableList<E>, Deleteable {
* the elements in a timely manner the coroutine scope will be cancelled with a
* [CancellationException].
*
* @param keyPaths TODO
* @return a flow representing changes to the list.
* @throws CancellationException if the stream produces changes faster than the consumer can
* consume them and results in a buffer overflow.
*/
public fun asFlow(): Flow<ListChange<E>>
public fun asFlow(keyPaths: List<String>?): Flow<ListChange<E>>
}

0 comments on commit 6885aa3

Please sign in to comment.