-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Keypath filtering in notifications #1547
Conversation
Added handling of char** to String[]
This PR depends on realm/realm-core#7087 being merged first. |
# Conflicts: # packages/external/core # packages/jni-swig-stub/realm.i # packages/jni-swig-stub/src/main/jni/realm_api_helpers.cpp # packages/jni-swig-stub/src/main/jni/realm_api_helpers.h
# Conflicts: # packages/external/core
packages/cinterop/src/jvm/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt
Outdated
Show resolved
Hide resolved
@@ -143,7 +143,9 @@ bool migration_callback(void *userdata, realm_t *old_realm, realm_t *new_realm, | |||
// TODO OPTIMIZE Abstract pattern for all notification registrations for collections that receives | |||
// changes as realm_collection_changes_t. | |||
realm_notification_token_t * | |||
register_results_notification_cb(realm_results_t *results, jobject callback) { | |||
register_results_notification_cb(realm_results_t *results, | |||
int64_t key_path_array_ptr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we use void*
on pointers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot in this case, as this is methods being called from the JVM which doesn't have that concept. We are using 0
in that case
reinterpret_cast<realm_object_t*>(collection_ptr), | ||
user_data, // Use the callback as user data | ||
user_data_free, | ||
NULL, // See https://github.com/realm/realm-kotlin/issues/661 | ||
(key_path_array_ptr == 0) ? NULL : reinterpret_cast<realm_key_path_array_t*>(key_path_array_ptr), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this nullability check required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly no, but it makes it easier to understand what is going on IMO
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/ObjectBoundRealmResults.kt
Outdated
Show resolved
Hide resolved
# Conflicts: # CHANGELOG.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice. I have a number of comments around internals but most notably around tests.
packages/cinterop/src/commonMain/kotlin/io/realm/kotlin/internal/interop/RealmInterop.kt
Outdated
Show resolved
Hide resolved
...e/src/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmNotificationsTests.kt
Outdated
Show resolved
Hide resolved
packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt
Show resolved
Hide resolved
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/types/RealmMap.kt
Outdated
Show resolved
Hide resolved
...onTest/kotlin/io/realm/kotlin/test/common/notifications/RealmDictionaryNotificationsTests.kt
Show resolved
Hide resolved
...c/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmListNotificationsTests.kt
Show resolved
Hide resolved
packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/utils/FlowableTests.kt
Outdated
Show resolved
Hide resolved
packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/utils/FlowableTests.kt
Outdated
Show resolved
Hide resolved
packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/utils/FlowableTests.kt
Outdated
Show resolved
Hide resolved
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/query/RealmElementQuery.kt
Show resolved
Hide resolved
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/query/RealmSingleQuery.kt
Show resolved
Hide resolved
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/types/RealmList.kt
Outdated
Show resolved
Hide resolved
*/ | ||
|
||
internal interface KeyPathFlowable<T> { | ||
fun asFlow(keyPaths: List<String>? = null): Flow<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason for using List
and not vararg
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the internal interface that just mirrors the public API which uses List
. I was considering whether to use vararg
or List
in the public API but ended up with List as it makes it easier to extend the API later. I.e. there is the potential that projections will end up adding arguments to the asFlow
method as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 🎉 minor comments 👍
packages/test-base/src/commonTest/kotlin/io/realm/kotlin/test/common/QueryTests.kt
Show resolved
Hide resolved
...c/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt
Outdated
Show resolved
Hide resolved
...c/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt
Outdated
Show resolved
Hide resolved
...c/commonTest/kotlin/io/realm/kotlin/test/common/notifications/BacklinksNotificationsTests.kt
Outdated
Show resolved
Hide resolved
findLatest(results.first())!!.booleanField = true | ||
} | ||
realm.write { | ||
// Update field that should trigger a notification |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following here, you're navigating to the top parent and updating it, whilst the query is on the leaf element? this should not trigger the notification while the previous update (booleanField = true
) should ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because I used the keypath listOf("objectBacklinks.objectBacklinks.objectBacklinks.objectBacklinks.objectBacklinks.stringField")
which only consider changes through the backlinks as things that should trigger a notification
...rc/commonTest/kotlin/io/realm/kotlin/test/common/notifications/RealmSetNotificationsTests.kt
Outdated
Show resolved
Hide resolved
* objects inside the set will result in a change being emitted. Nested properties can be | ||
* defined using a dotted syntax, e.g. `parent.child.name`. If no keypaths are provided, changes | ||
* to all top-level properties and nested properties up to 4 levels down will trigger a change. | ||
* Keypaths are only supported for sets of objects. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why only supported for sets of objects? it's also supported for List, RealmResults etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, but this doc is on the RealmSet. They key thing I wanted to spell out was that keyPaths only works on RealmSet<RealmObject>
but maybe it could be clarified better?
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/query/ScalarQuery.kt
Outdated
Show resolved
Hide resolved
@@ -61,7 +63,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>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why removing Flowable
interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was an internal interface that matched our public API. But with the KeyPath changes that is no longer the case and is actually harmful instead now as Notifier cannot use it to handle all flows the same.
const jclass clazz = jenv->FindClass("java/lang/String"); | ||
|
||
while ($1[len]) len++; | ||
jresult = jenv->NewObjectArray(len, clazz, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check for OOM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments about nested runBlocking
, etc.. Just wanted to highlight it, but don't think we need to bother fixing it and rerunning CI ... unless there is other reasons for doing so.
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmListInternal.kt
Outdated
Show resolved
Hide resolved
packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmMapInternal.kt
Outdated
Show resolved
Hide resolved
* to that type, otherwise an IllegalArgumentException is thrown with the provided error message. | ||
*/ | ||
@OptIn(ExperimentalContracts::class) | ||
public inline fun <reified T : Any?> isType(arg: Any?, errorMessage: String) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥇
Closes #661
This PR adds support for keypath filtering which makes it possible to select which fields should trigger the notifications, and enable notifications more than 4 levels deep.
TODO
List<String>()
,List<String>?
orvararg String
. Right now I'm leaning towardsList<String>?
but should be discussed.