isar / hive

Lightweight and blazing fast key-value database written in pure Dart.
Apache License 2.0
3.95k stars 392 forks source link

Can I keep Hive boxes synced between threads? #561

Open jmshrv opened 3 years ago

jmshrv commented 3 years ago

Question I'm making a music app that does the music login on one thread and the rest of the app is run on another. In the app, I let users download songs locally. I'm using Hive to keep track of what songs are downloaded. I'm running into an issue where if the user downloads a song, the box on the music thread won't get these changes, causing the music thread to assume the item is not downloaded. The music is made using audio_service.

Is there a way for me to tell the box to sync itself with whatever is on the disk?

Code sample On the main thread:

Box<DownloadedSong> downloadedItemsBox = Hive.box("DownloadedItems");
...
Future<void> addDownloads(...) {
    ...
    // Adds the current song to the downloaded items box with its media info and download id
    downloadedItemsBox.put(item.id, songInfo);
    ...
}

On the music thread:

Box<DownloadedSong> downloadedItemsBox = Hive.box("DownloadedItems");
...
Future<void> addItemToQueue(...) {
    ...
    if (_downloadedItemsBox.containsKey(mediaItem.id)) {...}
    ...
}

If the music thread is running, the new item may not show in the music thread and the if statement will return false, even though the item has been added to the box.

Version

thevikke commented 3 years ago

My understanding is that you would need to close the box while updating it in the other thread. Since two applications can't use the same box.

stilyng94 commented 3 years ago

@thevikke I am running into the same issue when storing notifications in the background which also runs in another isolate. i called Hive.close() before application goes to the background but upon app resuming data is still not found in the database until app is restarted

thevikke commented 3 years ago

I don't quite understand the use case. What is the thing that runs in background and how? What notifications are you storing? Preferably give us a code example. :)

stilyng94 commented 3 years ago

I don't quite understand the use case. What is the thing that runs in background and how? What notifications are you storing? Preferably give us a code example. :)

I am handling FirebaseMessaging.onBackgroundMessage. `///!Firebase background handler Future firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); await initHiveDB(); Get.put(NotificationController( iNotificationRepository: NotificationRepository( NotificationLocalDataSource(), NoticeCountLocalDataSource())));

await FCMMessagingHandlers.persistNotice(message.data); await killHive();

return Future.value(); }`

I initialise Hive again and kill the boxes when it is done.

thevikke commented 3 years ago

I would guess that there is something wrong in the initHiveDB or killHive function. 🤔

stilyng94 commented 3 years ago

Future<void> killHive() async { await Hive.box(BoxConstants.AUTHBOX).close(); await Hive.box(BoxConstants.NOTIFICATIONS_BOX).close(); await Hive.close(); }

Future initHiveDB() async { await Hive.initFlutter(); await Hive.openBox(BoxConstants.AUTHBOX); await Hive.openBox(BoxConstants.User_ACCOUNT_BOX); await Hive.openBox(BoxConstants.WEATHER_BOX); await Hive.openBox(BoxConstants.LANG_BOX); await Hive.openBox(BoxConstants.MACHINES_BOX); await Hive.openBox(BoxConstants.NOTIFICATIONS_BOX); await Hive.openBox(BoxConstants.NOTIFICATION_BADGE_BOX); await Hive.openBox(BoxConstants.PRESETUP_BOX); }

thevikke commented 3 years ago

Not really sure whats wrong. Do you get any errors? Are you sure you are actually saving into the HiveDB? Do you need typeAdapters? I'm also not sure how Firebase works in the background, can you use initFlutter with it or do you need Hive.init?

stilyng94 commented 3 years ago

Am not using TypeAdapters just normal Map<string,dynamic>. According to documentation Firebase in the background creates an Isolate. I use Hive.initFlutter. I don't get errors. Every code gets executed correctly.

magnoleal commented 3 years ago

@stilyng94 You solved the problem?

stilyng94 commented 3 years ago

@stilyng94 You solved the problem?

I switched to Moor and everything is working fine. It has good support for background isolates

priyabratap commented 2 years ago

Hi @stilyng94 , Hope you are doing well. I am facing the same problem, not getting any solution from the "Hive" side. I was looking at the alternate, but I am little bit confused by reading the below document.

Could you please put the sample code of Moor implementation to handle the Firebase Background message? Thanks in advance. :)

https://moor.simonbinder.eu/docs/advanced-features/isolates/

New feature
The api for background isolates only works with moor version 2.1.0 or newer. Due to platform limitations, using moor_ffi is required when using a background isolate. Using moor_flutter is not supported.
stilyng94 commented 2 years ago

@priyabratap , sorry for seeing your message late. I solved this with Moor but the sad part is i never documented the steps down and currently i do not have access to the codes since i have left my company. But the link you posted was what i followed.