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

🐛 [cloud_firestore] iOS: Rework is incompatible with multi-isolate Apps #4108

Closed
ened opened this issue Nov 12, 2020 · 9 comments · Fixed by #4209
Closed

🐛 [cloud_firestore] iOS: Rework is incompatible with multi-isolate Apps #4108

ened opened this issue Nov 12, 2020 · 9 comments · Fixed by #4209
Assignees
Labels

Comments

@ened
Copy link
Contributor

ened commented Nov 12, 2020

Bug report

Our iOS App runs the FG isolate (Flutter main application as usual) plus 1, sometimes 2, long-lived isolates in the background.
Upon registering the Firestore plugin for the second instance, the first instance's Dart side will loose connectivity to the native side, causing Snapshot listeners functionality to stop.

We need Firestore to work in both isolates, as one of them revolves about listening to document changes for user requested actions and the other one is pertinent to the background functionality of our App.

Steps to reproduce

Steps to reproduce the behavior:

You will need two isolates, to test this behavior.
You can try this using flutter_workmanager or flutter_uploader.
Attempt to listen to a document snapshots stream on both references, you will find that one of them can receive contents.

Expected behavior

Both isolates will subscribe to the value and receive it equally well.

Additional context

The issue seems to stem from how the plugin is instantiated on iOS, in the registerPluginsMethod:

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
  FLTFirebaseFirestoreReaderWriter *firestoreReaderWriter = [FLTFirebaseFirestoreReaderWriter new];
  FlutterMethodChannel *channel =
      [FlutterMethodChannel methodChannelWithName:kFLTFirebaseFirestoreChannelName
                                  binaryMessenger:[registrar messenger]
                                            codec:[FlutterStandardMethodCodec
                                                      codecWithReaderWriter:firestoreReaderWriter]];

  FLTFirebaseFirestorePlugin *instance = [FLTFirebaseFirestorePlugin sharedInstance];
  instance.channel = channel;
  [registrar addMethodCallDelegate:instance channel:channel];
#if TARGET_OS_OSX
// TODO(Salakar): Publish does not exist on MacOS version of FlutterPluginRegistrar.
#else
  [registrar publish:instance];
#endif
}

Pay close attention to the line instance.channel = channel. This is correct, however - because instance is a singleton object shared among the Apps isolates (retrieved via [FLTFirebaseFirestorePlugin sharedInstance]), one isolate instantiation and the plugin initialization of will override the previous one.

I'm omitting doctor / pub output as this should be a code level issue.

This used to work in the cloud firestore version before the rework; I assume with it's own caveats.

@Salakar

@ened ened added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Nov 12, 2020
@Salakar Salakar self-assigned this Nov 12, 2020
@markusaksli-nc markusaksli-nc added plugin: cloud_firestore and removed Needs Attention This issue needs maintainer attention. labels Nov 13, 2020
@ened
Copy link
Contributor Author

ened commented Nov 16, 2020

A alternative solution would be to use EventChannel for every "command" that the dart side sends to the plugin. That way, each command would get a dedicated sink to respond do and closes it when done.

That way you'd not need to keep a channel variable in the plugin altogether.

@Salakar WDYT

@Salakar
Copy link
Member

Salakar commented Nov 16, 2020

A alternative solution would be to use EventChannel for every "command" that the dart side sends to the plugin. That way, each command would get a dedicated sink to respond do and closes it when done.

That way you'd not need to keep a channel variable in the plugin altogether.

@Salakar WDYT

That could work also. If you're willing I'm open to receiving a PR to help speed this along quicker

@bhanuka96
Copy link

bhanuka96 commented Nov 27, 2020

@ened
Copy link
Contributor Author

ened commented Nov 27, 2020

@bhanuka96 from the SO description, the PR could help you.

Try adding this to pubspec.yaml:

dependency_overrides:
  cloud_firestore:
    git:
      url: https://github.com/ened/flutterfire.git
      ref: fix/4108-cloud-firestore
      path: packages/cloud_firestore/cloud_firestore
  cloud_firestore_platform_interface:
    git:
      url: https://github.com/ened/flutterfire.git
      ref: fix/4108-cloud-firestore
      path: packages/cloud_firestore/cloud_firestore_platform_interface

Then do a `flutter clean && flutter pub get`` - then build your iOS App again and try.

@bhanuka96
Copy link

@ened Thanks. no luck, no implemented found error, and I didn't use this plugin too cloud_firestore_platform_interface

@ened
Copy link
Contributor Author

ened commented Nov 27, 2020

@bhanuka96 you will need to use both..

@bhanuka96
Copy link

bhanuka96 commented Nov 27, 2020

@ened I cannot get package.

/Users/flutter/bin/flutter --no-color pub get
Running "flutter pub get" in...                  

Because orel_go_driver depends on cloud_firestore from git which depends on cloud_firestore_platform_interface ^2.2.0, cloud_firestore_platform_interface from hosted is required.
So, because packageName depends on cloud_firestore_platform_interface from git, version solving failed.
pub get failed (1; So, because packageName depends on cloud_firestore_platform_interface from git, version solving failed.)
Process finished with exit code 1

@ened
Copy link
Contributor Author

ened commented Nov 27, 2020

@bhanuka96 Did you add it to dependency_overrides (not dependencies)?

@alekseifm
Copy link

@ened
Adding the dependency_overrides solve my issue (similar to https://stackoverflow.com/questions/65032058/how-do-i-register-firestore-callback-in-ios). Thanks!

  cloud_firestore:
    git:
      url: https://github.com/ened/flutterfire.git
      ref: fix/4108-cloud-firestore
      path: packages/cloud_firestore/cloud_firestore
  cloud_firestore_platform_interface:
    git:
      url: https://github.com/ened/flutterfire.git
      ref: fix/4108-cloud-firestore
      path: packages/cloud_firestore/cloud_firestore_platform_interface

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants