felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.77k stars 3.39k forks source link

feat: Make hydrated_storage.dart:Storage.read() method async #4129

Closed iulian0512 closed 4 months ago

iulian0512 commented 6 months ago

Description

I want to provide my own sqlite backed implementation of Storage but i need the read method to be async like the rest of the methods in Storage class, most sqlite libs execute queries async.

Desired Solution

Make the read method Future

/// Interface which is used to persist and retrieve state changes.
abstract class Storage {
  /// Returns value for key async
  Future<dynamic> read(String key);

Alternatives Considered

A workaround of loading an entire table in memory to be accessible to synchronous read method is sub-optimal to say at least.

Additional Context

image The errror above appears randomly on some devices. In the past i have used hive for other purposes and had to eliminate it due to this, hive works but its not reliable, it has issues especially when android apps are paused/resumed.

iulian0512 commented 4 months ago

is see no way i can get rid of hive, read should really be async.

felangel commented 4 months ago

is see no way i can get rid of hive, read should really be async.

If reads were async then it’d be a pretty poor experience imo due to latency and we’d need to reconcile bloc states after async reads (e.g a bloc is instantiated, starts off in the initial state, the async load runs, then we’d need to change the state even though no event was added). That would result in a very unpredictable state (maybe some events were already added and processed before the load finished, etc).

Hydrated bloc is meant to cache your app state and generally if the data you’re working with is so big that it can’t be loaded in ram then you probably shouldn’t be using hydrated bloc. You can still use other storage solutions with async APIs but you’ll just need to load in everything into memory before calling runApp. Hope that helps 👍

iulian0512 commented 4 months ago

@felangel The problem that i'm facing is not that the data is large, the problem is that hive is not reliable and sometimes initialization fails with "Cannot read, unknown typeId: XX. Did you forget to register an adapter?" i cannot reproduce this consistently i get this in production on some devices (android) on and off. so that's why i want to get rid of hive. i am initializing hydrated_bloc the right way as you recommend in the docs. i am not using hive for anything else.

 WidgetsFlutterBinding.ensureInitialized();
  HydratedBloc.storage = await HydratedStorage.build(
    storageDirectory: kIsWeb
        ? HydratedStorage.webStorageDirectory
        : await getApplicationDocumentsDirectory(),
  );
felangel commented 4 months ago

@felangel The problem that i'm facing is not that the data is large, the problem is that hive is not reliable and sometimes initialization fails with "Cannot read, unknown typeId: XX. Did you forget to register an adapter?" i cannot reproduce this consistently i get this in production on some devices (android) on and off. so that's why i want to get rid of hive. i am initializing hydrated_bloc the right way as you recommend in the docs. i am not using hive for anything else.

 WidgetsFlutterBinding.ensureInitialized();
  HydratedBloc.storage = await HydratedStorage.build(
    storageDirectory: kIsWeb
        ? HydratedStorage.webStorageDirectory
        : await getApplicationDocumentsDirectory(),
  );

Are you able to share a minimal reproduction sample and provide the full error logs? I’m happy to take a closer look

iulian0512 commented 4 months ago

no i cannot provide a reproduction sample because i cannot consistently reproduce it, the error occurs randomly on some devices inside the hive package when calling hive.openBox in hydrated_storage.dart:build();

felangel commented 4 months ago

no i cannot provide a reproduction sample because i cannot consistently reproduce it, the error occurs randomly on some devices inside the hive package when calling hive.openBox in hydrated_storage.dart:build();

Can you share the full error and stackTrace? Do you have any error reporting configured in your app?

iulian0512 commented 4 months ago

no i cannot provide a reproduction sample because i cannot consistently reproduce it, the error occurs randomly on some devices inside the hive package when calling hive.openBox in hydrated_storage.dart:build();

Can you share the full error and stackTrace? Do you have any error reporting configured in your app?

i am using sentry for error reporting i had the log but all logs got deleted after a sentry standalone server reinstall. i will post here when i catch it again.

felangel commented 4 months ago

Closing for now since there aren't any actionable next steps. Feel free to post or file a new issue if you're able to reproduce 👍