Skip to content

database-ktx: add callbackFlow for eventlisteners#4012

Merged
thatfiredev merged 11 commits intomasterfrom
rpf-add-rtdb-flow
Sep 23, 2022
Merged

database-ktx: add callbackFlow for eventlisteners#4012
thatfiredev merged 11 commits intomasterfrom
rpf-add-rtdb-flow

Conversation

@thatfiredev
Copy link
Copy Markdown
Member

Part of go/kotlin-flows-firebase-android

This PR should add callbackFlows for RTDB's ValueEventListener and ChildEventListener.

@google-oss-bot
Copy link
Copy Markdown
Collaborator

google-oss-bot commented Aug 19, 2022

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Aug 19, 2022

Unit Test Results

  4 files   -    391    4 suites   - 391   14s ⏱️ - 16m 31s
13 tests  - 4 702  13 ✔️  - 4 678  0 💤  - 22  0  - 2 
13 runs   - 4 718  13 ✔️  - 4 694  0 💤  - 22  0  - 2 

Results for commit b2b7b7b. ± Comparison against base commit 4f24be3.

♻️ This comment has been updated with latest results.

@google-oss-bot
Copy link
Copy Markdown
Collaborator

google-oss-bot commented Aug 19, 2022

fun Query.snapshots() = callbackFlow<DataSnapshot> {
val listener = addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
trySend(snapshot)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For 7235473 we went with trySendBlocking is there any difference between cases?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using trySendBlocking Android Studio shows me this warning:

Screenshot 2022-08-19 at 16 26 25

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I think it is a false positive in the linter.
  2. That said, it looks like the events are dispatched on the UI thread, so it's not ok to directly trySendBlocking:

imo instead we can do the same thing we did for firestore, something like

Suggested change
trySend(snapshot)
someExecutor.execute(() -> trySendBlocking(snapshot));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vkryachko Looks like firestore's background executor uses a ThreadPool with 4 threads:

public static final Executor BACKGROUND_EXECUTOR =
new ThrottledForwardingExecutor(
ASYNC_THREAD_POOL_MAXIMUM_CONCURRENCY, AsyncTask.THREAD_POOL_EXECUTOR);

private static final int ASYNC_THREAD_POOL_MAXIMUM_CONCURRENCY = 4;

Should we also use a ThreadPool for RTDB?

Suggested change
trySend(snapshot)
Executors.newFixedThreadPool(nThreads = 4).execute {
trySendBlocking(ChildEvent.Added(snapshot, previousChildName))
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vkryachko You were right, it was a false-positive in the linter. After the AGP7 update, the lint warning went away.

But my question on what executor we'll want to use remains.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if that is safe, i.e. isn't in happening on the UI thread?

@maneesht what are your thoughts?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like scheduleNow() delegates to DefaultRunLoop which uses a ScheduledThreadPoolExecutor , so it doesn't block the UI Thread.

public DefaultRunLoop() {
int threadsInPool = 1;
ThreadFactory threadFactory = new FirebaseThreadFactory();
executor =
new ScheduledThreadPoolExecutor(threadsInPool, threadFactory) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only concern with this is that we would end up blocking other operations within the Repo's actions. Maybe we should create a new executor solely for this? As RTDB only has one ATM

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this through a bit more, and let's go ahead and just use the default run loop. If we feel like there's a performance gain, we can always change this in a future patch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into it @maneesht !

@vkryachko vkryachko requested a review from maneesht August 19, 2022 18:43
@thatfiredev
Copy link
Copy Markdown
Member Author

@vkryachko I changed the Flows to be properties instead of functions. Please take a second look

@thatfiredev thatfiredev merged commit 3872957 into master Sep 23, 2022
@thatfiredev thatfiredev deleted the rpf-add-rtdb-flow branch September 23, 2022 12:56
@firebase firebase locked and limited conversation to collaborators Oct 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants