rmawatson / flutter_isolate

Launch an isolate that can use flutter plugins.
MIT License
262 stars 80 forks source link

Saving data to Firestore not working ONLY ON PRODUCTION #112

Open eduardothiesen opened 2 years ago

eduardothiesen commented 2 years ago

Hi,

I'm using the FlutterIsolates to save mass data to my Firestore server. When I test it running from Android Studio, it works perfectly. But, when I send it to Internal Test, the data never reaches the firestore server.

void saveStall(String payload) async {
  final mainIsolatePort = ReceivePort();
  final saveIsolate = await FlutterIsolate.spawn(
      saveStallToFirestore, mainIsolatePort.sendPort);

  mainIsolatePort.listen(
      (messageFromSaveIsolate) {
        if (messageFromSaveIsolate is SendPort) {
          messageFromSaveIsolate.send(payload);
        }

        if (messageFromSaveIsolate is String) {
          if (messageFromSaveIsolate == 'ok') {
            saveIsolate.kill();
            mainIsolatePort.close();
          } else {
            //TODO: treat error
          }
        }
      },
      onDone: () {},
      onError: (e) {
        saveIsolate.kill();
        mainIsolatePort.close();
      });
}

saveStallToFirestore(SendPort mainIsolatePort) async {
  final saveStallToFirebaseIsolatePort = ReceivePort();
  try {
    mainIsolatePort.send(saveStallToFirebaseIsolatePort.sendPort);

    saveStallToFirebaseIsolatePort.listen((messageFromMainIsolate) async {
      if (messageFromMainIsolate is String) {
        var json = jsonDecode(messageFromMainIsolate, reviver: dateDecoder);

        WidgetsFlutterBinding.ensureInitialized();
        await Firebase.initializeApp();
        StallRepository.instance.update(
            farmId: json['farmId'], id: json['id'], json: json['stall']);
        List<dynamic> ovines =
            json['ovines'].map((e) => Ovine.fromJson(e['id'], e)).toList();
        for (Ovine o in ovines) {
          OvineRepository.instance
              .update(farmId: json['farmId'], id: o.id, json: o.toJson());
        }
        mainIsolatePort.send('ok');
      }
    });
  } catch (err) {
    mainIsolatePort.send('error');
  }
}

//Method called by OvineRepository.instance.update in the above snippet
Future<void>? update(
      {required String farmId,
      required String id,
      required Map<String, dynamic> json,
      SendPort? messenger}) {
    try {
      var result = FirebaseFirestore.instance
          .collection(farmsCollectionKey)
          .doc(farmId)
          .collection(ovinesCollectionKey)
          .doc(id)
          .update(json);
      if (messenger != null) {
        messenger.send('ok');
      }
      return result;
    } catch (e) {
      Get.snackbar(
        'error'.tr,
        e.toString(),
        snackPosition: SnackPosition.TOP,
        backgroundColor: Colors.white,
        colorText: Colors.black,
      );

      return null;
    }
  }

Any ideas what I may be doing wrong? Thanks in advance.

nmfisher commented 2 years ago

Does it work outside an isolate?

On 24 Jun 2022, at 9:17 PM, Carlos Eduardo Gomes Thiesen @.***> wrote:

 Hi,

I'm using the FlutterIsolates to save mass data to my Firestore server. When I test it running from Android Studio, it works perfectly. But, when I send it to Internal Test, the data never reaches the firestore server.

` void saveStall(String payload) async { final mainIsolatePort = ReceivePort(); final saveIsolate = await FlutterIsolate.spawn( saveStallToFirestore, mainIsolatePort.sendPort);

mainIsolatePort.listen( (messageFromSaveIsolate) { if (messageFromSaveIsolate is SendPort) { messageFromSaveIsolate.send(payload); }

if (messageFromSaveIsolate is String) {
  if (messageFromSaveIsolate == 'ok') {
    saveIsolate.kill();
    mainIsolatePort.close();
  } else {
    //TODO: treat error
  }
}

}, onDone: () {}, onError: (e) { saveIsolate.kill(); mainIsolatePort.close(); }); }

saveStallToFirestore(SendPort mainIsolatePort) async { final saveStallToFirebaseIsolatePort = ReceivePort(); try { mainIsolatePort.send(saveStallToFirebaseIsolatePort.sendPort);

saveStallToFirebaseIsolatePort.listen((messageFromMainIsolate) async { if (messageFromMainIsolate is String) { var json = jsonDecode(messageFromMainIsolate, reviver: dateDecoder);

WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
StallRepository.instance.update(
    farmId: json['farmId'], id: json['id'], json: json['stall']);
List<dynamic> ovines =
    json['ovines'].map((e) => Ovine.fromJson(e['id'], e)).toList();
for (Ovine o in ovines) {
  OvineRepository.instance
      .update(farmId: json['farmId'], id: o.id, json: o.toJson());
}
mainIsolatePort.send('ok');

} }); } catch (err) { mainIsolatePort.send('error'); } }

//Method called by OvineRepository.instance.update in the above snippet Future? update( {required String farmId, required String id, required Map<String, dynamic> json, SendPort? messenger}) { try { var result = FirebaseFirestore.instance .collection(farmsCollectionKey) .doc(farmId) .collection(ovinesCollectionKey) .doc(id) .update(json); if (messenger != null) { messenger.send('ok'); } return result; } catch (e) { Get.snackbar( 'error'.tr, e.toString(), snackPosition: SnackPosition.TOP, backgroundColor: Colors.white, colorText: Colors.black, );

return null; } } `

Any ideas what I may be doing wrong? Thanks in advance.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.

eduardothiesen commented 2 years ago

@nmfisher yes, they work outside the isolate in production. Inside only when debbuging

eduardothiesen commented 2 years ago

Here's my flutter doctor (obs: I also tested in stable branch, same issue)

[✓] Flutter (Channel master, 3.1.0-0.0.pre.1358, on macOS 12.4 21F79 darwin-x64, locale en-BR)
    • Flutter version 3.1.0-0.0.pre.1358 on channel master at /Users/eduardothiesen/developer/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9f4b9bfd49 (21 hours ago), 2022-06-23 12:27:09 -0500
    • Engine revision fc08bf45b0
    • Dart version 2.18.0 (build 2.18.0-216.0.dev)
    • DevTools version 2.14.0

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at /Users/eduardothiesen/Library/Android/sdk
    • Platform android-32, build-tools 32.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 13E113
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] Connected device (3 available)
    • SM G985F (mobile) • RQ8N403TWZL • android-arm64  • Android 12 (API 31)
    • macOS (desktop)   • macos       • darwin-x64     • macOS 12.4 21F79 darwin-x64
    • Chrome (web)      • chrome      • web-javascript • Google Chrome 103.0.5060.53

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

And pub spec

version: 1.0.0+1

environment:
  sdk: ">=2.14.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  # Core
  collection: ^1.16.0
  flutter_facebook_auth: ^4.0.0
  get: ^4.6.1
  get_storage: ^2.0.3
  google_sign_in: ^5.2.1
  http: ^0.13.4
  intl: ^0.17.0
  flutter_isolate: ^2.0.2
  package_info_plus: ^1.4.2
  path_provider: ^2.0.5
  path_provider_platform_interface: ^2.0.4
  purchases_flutter: ^3.10.0
  sign_in_with_apple: ^4.0.0
  uuid: ^3.0.4

  # Firebase
  cloud_firestore:
  cloud_functions: ^3.1.1
  firebase_analytics: ^9.0.4
  firebase_auth: ^3.3.17
  firebase_core: ^1.16.0
  firebase_crashlytics: ^2.2.0

  # Icons
  cupertino_icons: ^1.0.2
  font_awesome_flutter: ^8.11.0

  # Miscellaneous
  connectivity_plus: ^2.3.0
  device_info_plus: ^4.0.0
  g_recaptcha_v3: ^0.0.4
  universal_html: ^2.0.8
  url_launcher: ^6.0.12

  # UI
  country_code_picker: ^2.0.2
  easy_mask: ^2.0.1
  flutter_typeahead: ^4.0.0
  modal_progress_hud_nsn: ^0.2.1
  syncfusion_flutter_charts: ^20.1.52

  # Utils
  crypto: ^3.0.1
  extension_google_sign_in_as_googleapis_auth: ^2.0.4
  googleapis: ^9.1.0
  syncfusion_flutter_xlsio: ^20.1.52-beta

dependency_overrides:
  font_awesome_flutter:
    path: "../font_awesome_flutter-master"

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^2.0.1
nmfisher commented 2 years ago

Have you tried calling await Firebase.initializeApp(); in the main isolate before trying to save anything in the spawned isolate?

eduardothiesen commented 2 years ago

@nmfisher thanks for the suggestion. I tried now and received the following error: Unhandled Exception: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()

nmfisher commented 2 years ago

Do you have authentication set up on your Firebase database, and if so, how/where in the app are you authenticating?

On 25 Jun 2022, at 4:16 AM, Carlos Eduardo Gomes Thiesen @.***> wrote:  @nmfisher thanks for the suggestion. I tried now and received the following error: Unhandled Exception: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.

eduardothiesen commented 2 years ago

Yes, I have authentication set up. When the user opens the app a listener checks the firebase credentials and if they are not valid, routes the user to the auth screen. It does not happen inside an isolate though

nmfisher commented 2 years ago

Sorry I did reply to this via e-mail but it looks like GitHub didn't put it through.

Can you try manually authenticating to Firebase inside the same isolate before saving the data?

eduardothiesen commented 2 years ago

Hi @nmfisher. That happened to me too ;D

I'll test that as soon as I can. But I don't see this working in a real scenario, since I have authentication via phone number, email and social networks.

nmfisher commented 2 years ago

Was this resolved?

eduardothiesen commented 2 years ago

Hey @nmfisher . I didn't have a change to test your latest suggestion. But, as I mentioned, it would not be a viable solution in my case. The funny thing is that I used flutter_isolate for a few weeks in production working perfectly. And now it only works in debug.

My solution was to remodel my database to have smaller objects.

Thanks for the attention and help.

nmfisher commented 2 years ago

That was not a solution, it was a debugging step to check whether authenticating to a Firebase instance outside an isolate also authenticates to the instance inside the isolate (I suspect it doesn't). I will leave this open so if anyone has a similar problem in future, please try this first and report here.

srmncnk commented 2 years ago

Try this PR, it might fix it. https://github.com/rmawatson/flutter_isolate/pull/118

deadsoul44 commented 1 year ago

I have the same problem. The app is working in debug model but not in release mode. Could you please publish a new version with the proposed fix?

eduardothiesen commented 1 year ago

Yes, I have authentication set up. When the user opens the app a listener checks the firebase credentials and if they are not valid, routes the user to the auth screen.

Em sáb., 25 de jun. de 2022 00:31, Nick Fisher @.***> escreveu:

Do you have authentication set up on your Firebase database, and if so, how/where in the app are you authenticating?

On 25 Jun 2022, at 4:16 AM, Carlos Eduardo Gomes Thiesen @.***> wrote:  @nmfisher thanks for the suggestion. I tried now and received the following error: Unhandled Exception: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.

— Reply to this email directly, view it on GitHub https://github.com/rmawatson/flutter_isolate/issues/112#issuecomment-1166182147, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABR3LYEDLHM6HD5GHT4HUN3VQZ4RPANCNFSM5ZX2L5AA . You are receiving this because you authored the thread.Message ID: @.***>

nmfisher commented 1 year ago

Can you try manually authenticating to Firebase inside the same isolate before saving the data?

On 26 Jun 2022, at 5:32 AM, Carlos Eduardo Gomes Thiesen @.***> wrote:

 Yes, I have authentication set up. When the user opens the app a listener checks the firebase credentials and if they are not valid, routes the user to the auth screen. It does not happen inside an isolate though

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.

nmfisher commented 1 year ago

@eduardothiesen we've recently published fixes for issues running Flutter > 3.3 in release mode, can you advise if these have fixed your issue?