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

Issue with Store.attach() throwing UnsupportedError on iOS physical device #653

Open
edrbtsyn opened this issue Jul 11, 2024 · 3 comments
Open
Labels
documentation Improvements or additions to documentation

Comments

@edrbtsyn
Copy link

Hello,

I am using the objectbox-dart library in my Flutter application, which also utilizes Firebase Cloud Messaging for background notifications. When handling notifications in the background on a physical iOS device, I encounter an exception when calling the Store.attach() method. This issue does not occur on an Android emulator.

Here is how I use the library:

Future<String> getDatabaseDirectoryPath() async {
  final dir = await getApplicationDocumentsDirectory();
  return '${dir.path}${Platform.pathSeparator}objectbox';
}
static Future<Store> tryOpenStore(String dbPath,
      {required int maxRetries}) async {
    try {
      if (maxRetries > 0) {
        return await openStore(directory: dbPath);
      } else {
        const exceptionMessage =
            "Couldn't open store because of recurring SchemaExceptions.";
        globalLogger.i(exceptionMessage);
        throw Exception(exceptionMessage);
      }
    } on SchemaException catch (_) {
      maxRetries--;
      await deleteDatabaseFiles(dbPath);
      return await tryOpenStore(dbPath, maxRetries: maxRetries);
    }
}
static Future<Store> createStore() async {
  final dbPath = await getDatabaseDirectoryPath();
  final isOpen = Store.isOpen(dbPath);
  if (isOpen) {
    final store = Store.attach(getObjectBoxModel(), dbPath);
    return store;
  } else {
    final store = await tryOpenStore(dbPath, maxRetries: 2);
    return store;
  }
}

The crash occurs in an event triggered when the application is in the background (receiving a Firebase notification):

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // Initialize some stuff here…
  final store = await RubisObjectBox.createStore(); // works on Android, not on iOS
  MessagingHelper.handleMessage(
    DataMessage.fromJson(message.data), message.data, store, runFromBackground: true
  );
}

On iOS, the Store.attach() method throws an UnsupportedError with the message:

Cannot create multiple Store instances for the same directory in the same isolate. Please use a single Store, close() the previous instance before opening another one or attach to it in another isolate.

I tried using Isolate.run to return the store, but it seems not possible since the getApplicationDocumentsDirectory() method cannot be called within an isolate.

Environment:

  • Flutter version: 3.22.2
  • Dart version: 3.4.3
  • objectbox version: ^4.0.1
  • For the Android Platform, I used an Emulator directly on Android Studio (Pixel_3a_API_34_extension_level_7_x86_64)
  • For the iOS Platform, I used a Physical Device (iPhone 11 with iOS version 17.5.1)

Steps to reproduce:

  • Set up a Flutter application using objectbox 4.0.1
  • Create a store with the method openStore()
  • Get a new instance of the same store using attach() without closing the previous store
  • Observe the exception.

Any guidance or solution for this issue would be greatly appreciated. Thank you!

@edrbtsyn edrbtsyn added the bug Something isn't working label Jul 11, 2024
@greenrobot-team
Copy link
Member

greenrobot-team commented Jul 15, 2024

As the message says, it is not supported to attach to a store that is already opened in the current isolate. The code should either keep a reference to an open store and re-use that. Or make sure to close it before opening/attaching it again.

Note: labeled this issue with "more info required" so it will auto-close in a few days if there are no follow-up comments.

@greenrobot-team greenrobot-team added more info required Needs more info to become actionable. Auto-closed if no response. and removed bug Something isn't working labels Jul 15, 2024
@edrbtsyn
Copy link
Author

I made some tests on the library, and observed that when Store.isOpen() returns true, the _openStoreDirectories (a HashSet) used in the library method _checkStoreDirectoryNotOpen is not empty, so it does not throw an exception. However, on iOS, when Store.isOpen() returns true, the _openStoreDirectories variable is NOT empty, causing the UnsupportedError exception to be thrown.

The latter seems to be the intended behavior, but isn't it a bug on the Android side ?

@github-actions github-actions bot removed the more info required Needs more info to become actionable. Auto-closed if no response. label Jul 16, 2024
@greenrobot-team
Copy link
Member

Thanks for asking. This is indeed a little confusing. The Store.isOpen() check works on the process level (you can see it calls a C API), so across Dart isolates. The open directories check when creating/attaching a Store works per isolate (as no Dart state is shared across isolates).

Maybe we should update the API docs to clarify this.

@greenrobot-team greenrobot-team added the documentation Improvements or additions to documentation label Jul 16, 2024
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

2 participants