Skip to content
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

Example using Riverpod across isolates or flutter engines #1166

Closed
zmoshansky opened this issue Feb 9, 2022 · 10 comments
Closed

Example using Riverpod across isolates or flutter engines #1166

zmoshansky opened this issue Feb 9, 2022 · 10 comments
Labels
documentation Improvements or additions to documentation

Comments

@zmoshansky
Copy link

Describe what scenario you think is uncovered by the existing examples/articles
Can one use Riverpod to manage state across isolates/flutter engines? Similar to https://pub.dev/packages/isolate_bloc for bloc? Riverpod is attractive due to not depending on Flutter, thus being able to run in an isolate.

Describe why existing examples/articles do not cover this case
So far all examples seen only have a single isolate and a single instance of ProviderScope. In the case of multiple flutter engines, there will likely be more than one call to RunApp that should be wrapped by a ProviderScope, but this seems like it would duplicate state instead of share it. In the case of an isolate, I would create a ProviderContainer();, but then how do I setup a ProviderScope that shares this ProviderContainer? Is it safe to access this across isolates, and will that access result in state that is kept up-to-date?

Additional context
This may relate to/affect the underlying persistence support in riverpod:
#1032

Use case:
I would like to either spin up an additional flutter engine, or isolate, in order to run background tasks in my flutter application.

I then need to share state between the main "UI" App, and the background worker. As a result of actions run in the background, I would expect that my UI reacts appropriately to any changes. Likewise, if the UI portion of the app updates state, that should be made available to my background worker so that it may react.

@zmoshansky zmoshansky added documentation Improvements or additions to documentation needs triage labels Feb 9, 2022
@rrousselGit
Copy link
Owner

Isolates by definition do not share state.

Sharing the state of providers across isolates is as such anti pattern

@zmoshansky
Copy link
Author

While isolates don't share state implicitly, to avoid data-races, it's not to say they can't share state whatsoever, just that it should be done using the message passing mechanism to ensure it's done in a lock-free way, and ideally avoiding mutable shared objects, inline with the actor model. The dart team has even optimized the sharing of immutable objects between isolates to help performantly share state (dart-lang/sdk#36097, dart-lang/sdk#46623).

The following image shows how isolate_bloc uses the isolate friendly means of message passing to sync state across isolates:
image

Problematically, due to underlying platform constraints (Android/iOS), multiple flutter engines/isolates are the only way to successfully run parts of an app in the background, across activities with multiple entry points (Android), or achieve decent levels of parallelism (outside of dart's non-blocking I/O). I'd argue that these are fairly common requirements for larger/more complex apps.

A strong reason to use a reactive data model, or FRP, is to reliably handle asynchronous changes to data, whether that is using Firebase to sync with a remote DB, or handling changes to data from a different worker. Having to duplicate state-management layers to resolve the issue is a huge duplication of effort and not workable.

--

All that aside, if you truly don't feel that this is a good fit for Riverpod, I understand. I commend you on an excellent job writing a very powerful library. We'll likely have to switch to Bloc otherwise and attempt to use it's cross-isolate state sharing.

@TimWhiting
Copy link
Collaborator

@rrousselGit
It would probably be feasible to have a proxy container that initiates subscriptions across an isolate to a separate container and receives notifications from the isolate when things change. Would this be a good design that someone could contribute if they wanted?

@rrousselGit
Copy link
Owner

That won't work. To begin with, you wouldn't have access to the same Provider(...) instance inside the isolate

Since providers are not constants (yet. They will once we have metaprogramming), then even if you shared the ProviderContainer across isolates and tried to read the same provider, it'd still behave as if you tried to read two different providers

@rrousselGit
Copy link
Owner

So for now, there's nothing that can be done. Once we have metaprogramming, this can be reconsidered though.

@rrousselGit
Copy link
Owner

I'll close it for now since there's nothing I can act on immediately

@JulianBissekkou
Copy link

@rrousselGit Can you explain why this is possible using meta programming?

@rrousselGit
Copy link
Owner

Metaprogramming would change the syntax for defining providers, which would make them constants. As such, they would be shared cross isolates

We'd still need to pass the ProviderContainer around somehow and find a thread-safe way to notify listeners. But that's probably doable

@lifeapps-42
Copy link

@rrousselGit Is it safe to use riverpod's provider just for DI purposes inside non-root isolate without sharing any instances with other isolates? It's not very clear how isolates behave with global variables. I assume, that it is totally ok, but still wondering if there some hidden issues with it. Thanks in advance!

@abnerh69
Copy link

abnerh69 commented Jun 7, 2024

Is there some news about Riverpod across Isolates?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

6 participants