From e7b546c89302066ebd0a54a42fd52c3f484b2d15 Mon Sep 17 00:00:00 2001 From: Dat PHAM HOANG Date: Tue, 16 Jul 2024 16:15:31 +0700 Subject: [PATCH] Close hive boxes in Background (notificaiton) --- lib/features/base/base_controller.dart | 28 +++++++++---------- .../caching/config/hive_cache_client.dart | 27 ++++++++---------- .../data/local/account_cache_manager.dart | 4 ++- .../authentication_info_cache_manager.dart | 2 ++ .../data/local/token_oidc_cache_manager.dart | 4 +++ .../data/local/state_cache_manager.dart | 2 ++ .../controller/fcm_message_controller.dart | 24 ++++++++++++++++ 7 files changed, 61 insertions(+), 30 deletions(-) diff --git a/lib/features/base/base_controller.dart b/lib/features/base/base_controller.dart index e44350eedf..8ec8a7a9c0 100644 --- a/lib/features/base/base_controller.dart +++ b/lib/features/base/base_controller.dart @@ -106,7 +106,7 @@ abstract class BaseController extends GetxController (failure) { if (failure is FeatureFailure) { final exception = _performFilterExceptionInError(failure.exception); - logError('BaseController::onData:exception: $exception'); + logError('$runtimeType::onData:exception: $exception'); if (exception != null) { handleExceptionAction(failure: failure, exception: exception); } else { @@ -120,7 +120,7 @@ abstract class BaseController extends GetxController } void onError(Object error, StackTrace stackTrace) { - logError('BaseController::onError():error: $error | stackTrace: $stackTrace'); + logError('$runtimeType::onError():error: $error | stackTrace: $stackTrace'); final exception = _performFilterExceptionInError(error); if (exception != null) { handleExceptionAction(exception: exception); @@ -132,7 +132,7 @@ abstract class BaseController extends GetxController void onDone() {} Exception? _performFilterExceptionInError(dynamic error) { - logError('BaseController::_performFilterExceptionInError(): $error'); + logError('$runtimeType::_performFilterExceptionInError(): $error'); if (error is NoNetworkError || error is ConnectionTimeout || error is InternalServerError) { if (PlatformInfo.isWeb && currentOverlayContext != null && currentContext != null) { appToast.showToastMessage( @@ -157,7 +157,7 @@ abstract class BaseController extends GetxController void handleErrorViewState(Object error, StackTrace stackTrace) {} void handleExceptionAction({Failure? failure, Exception? exception}) { - logError('BaseController::handleExceptionAction():failure: $failure | exception: $exception'); + logError('$runtimeType::handleExceptionAction():failure: $failure | exception: $exception'); if (exception is ConnectionError) { if (currentOverlayContext != null && currentContext != null) { appToast.showToastErrorMessage( @@ -183,7 +183,7 @@ abstract class BaseController extends GetxController } void handleFailureViewState(Failure failure) async { - logError('BaseController::handleFailureViewState(): ${failure.runtimeType}'); + logError('$runtimeType::handleFailureViewState(): ${failure.runtimeType}'); if (failure is LogoutOidcFailure) { if (_isFcmEnabled) { _getStoredFirebaseRegistrationFromCache(); @@ -197,7 +197,7 @@ abstract class BaseController extends GetxController } void handleSuccessViewState(Success success) async { - log('BaseController::handleSuccessViewState(): ${success.runtimeType}'); + log('$runtimeType::handleSuccessViewState(): ${success.runtimeType}'); if (success is LogoutOidcSuccess) { if (_isFcmEnabled) { _getStoredFirebaseRegistrationFromCache(); @@ -214,7 +214,7 @@ abstract class BaseController extends GetxController void startFpsMeter() { FpsManager().start(); fpsCallback = (fpsInfo) { - log('BaseController::startFpsMeter(): $fpsInfo'); + log('$runtimeType::startFpsMeter(): $fpsInfo'); }; if (fpsCallback != null) { FpsManager().addFpsCallback(fpsCallback!); @@ -234,7 +234,7 @@ abstract class BaseController extends GetxController requireCapability(session!, accountId!, [tmailContactCapabilityIdentifier]); TMailAutoCompleteBindings().dependencies(); } catch (e) { - logError('BaseController::injectAutoCompleteBindings(): exception: $e'); + logError('$runtimeType::injectAutoCompleteBindings(): exception: $e'); } } @@ -243,7 +243,7 @@ abstract class BaseController extends GetxController requireCapability(session!, accountId!, [CapabilityIdentifier.jmapMdn]); MdnInteractorBindings().dependencies(); } catch(e) { - logError('BaseController::injectMdnBindings(): exception: $e'); + logError('$runtimeType::injectMdnBindings(): exception: $e'); } } @@ -252,7 +252,7 @@ abstract class BaseController extends GetxController requireCapability(session!, accountId!, [capabilityForward]); ForwardingInteractorsBindings().dependencies(); } catch(e) { - logError('BaseController::injectForwardBindings(): exception: $e'); + logError('$runtimeType::injectForwardBindings(): exception: $e'); } } @@ -261,14 +261,14 @@ abstract class BaseController extends GetxController requireCapability(session!, accountId!, [capabilityRuleFilter]); EmailRulesInteractorBindings().dependencies(); } catch(e) { - logError('BaseController::injectRuleFilterBindings(): exception: $e'); + logError('$runtimeType::injectRuleFilterBindings(): exception: $e'); } } Future injectFCMBindings(Session? session, AccountId? accountId) async { try { requireCapability(session!, accountId!, [FirebaseCapability.fcmIdentifier]); - log('BaseController::injectFCMBindings: fcmAvailable = ${AppConfig.fcmAvailable}'); + log('$runtimeType::injectFCMBindings: fcmAvailable = ${AppConfig.fcmAvailable}'); if (AppConfig.fcmAvailable) { final mapEnvData = Map.from(dotenv.env); await AppUtils.loadFcmConfigFileToEnv(currentMapEnvData: mapEnvData); @@ -285,7 +285,7 @@ abstract class BaseController extends GetxController throw NotSupportFCMException(); } } catch(e) { - logError('BaseController::injectFCMBindings(): exception: $e'); + logError('$runtimeType::injectFCMBindings(): exception: $e'); } } @@ -348,7 +348,7 @@ abstract class BaseController extends GetxController } Future clearDataAndGoToLoginPage() async { - log('BaseController::clearDataAndGoToLoginPage:'); + log('$runtimeType::clearDataAndGoToLoginPage:'); await clearAllData(); goToLogin(); } diff --git a/lib/features/caching/config/hive_cache_client.dart b/lib/features/caching/config/hive_cache_client.dart index 4700e66848..3da0e9f3ef 100644 --- a/lib/features/caching/config/hive_cache_client.dart +++ b/lib/features/caching/config/hive_cache_client.dart @@ -1,4 +1,3 @@ - import 'dart:typed_data'; import 'package:core/presentation/extensions/map_extensions.dart'; @@ -28,19 +27,16 @@ abstract class HiveCacheClient { if (Hive.isBoxOpen(tableName)) { return Hive.box(tableName); } else { - return Hive.openBox( - tableName, - encryptionCipher: encryptionKey != null - ? HiveAesCipher(encryptionKey) - : null); + return Hive.openBox(tableName, + encryptionCipher: + encryptionKey != null ? HiveAesCipher(encryptionKey) : null); } } Future insertItem(String key, T newObject) { + log('$runtimeType::insertItem:encryption: $encryption - key = $key'); return Future.sync(() async { - final boxItem = encryption - ? await openBoxEncryption() - : await openBox(); + final boxItem = encryption ? await openBoxEncryption() : await openBox(); return boxItem.put(key, newObject); }).catchError((error) { throw error; @@ -49,9 +45,7 @@ abstract class HiveCacheClient { Future insertMultipleItem(Map mapObject) { return Future.sync(() async { - final boxItem = encryption - ? await openBoxEncryption() - : await openBox(); + final boxItem = encryption ? await openBoxEncryption() : await openBox(); return boxItem.putAll(mapObject); }).catchError((error) { throw error; @@ -59,6 +53,7 @@ abstract class HiveCacheClient { } Future getItem(String key, {bool needToReopen = false}) { + log('$runtimeType::getItem() key: $encryption - needToReopen: $needToReopen'); return Future.sync(() async { if (needToReopen) { await closeBox(); @@ -88,7 +83,7 @@ abstract class HiveCacheClient { .where((key, value) => _matchedNestedKey(key, nestedKey)) .values .toList(); - log('HiveCacheClient::getListByNestedKey:listItem: ${listItem.length}'); + log('$runtimeType::getListByNestedKey:listItem: ${listItem.length}'); return listItem; }).catchError((error) { throw error; @@ -180,8 +175,10 @@ abstract class HiveCacheClient { Future clearAllDataContainKey(String nestedKey) { return Future.sync(() async { final boxItem = encryption ? await openBoxEncryption() : await openBox(); - final listKeys = boxItem.toMap().where((key, value) => _matchedNestedKey(key, nestedKey)).keys; - log('HiveCacheClient::clearAllDataContainKey:listKeys: ${listKeys.length}'); + final listKeys = boxItem.toMap() + .where((key, value) => _matchedNestedKey(key, nestedKey)) + .keys; + log('$runtimeType::clearAllDataContainKey:listKeys: ${listKeys.length}'); return boxItem.deleteAll(listKeys); }).catchError((error) { throw error; diff --git a/lib/features/login/data/local/account_cache_manager.dart b/lib/features/login/data/local/account_cache_manager.dart index d7c4839027..4b2403d3d8 100644 --- a/lib/features/login/data/local/account_cache_manager.dart +++ b/lib/features/login/data/local/account_cache_manager.dart @@ -28,7 +28,7 @@ class AccountCacheManager { log('AccountCacheManager::setCurrentAccount(): $newAccount'); final newAccountCache = newAccount.toCache(); final allAccounts = await _accountCacheClient.getAll(); - log('AccountCacheManager::setCurrentAccount::allAccounts(): $allAccounts'); + log('AccountCacheManager::setCurrentAccount::allAccounts(): length: ${allAccounts.length}, $allAccounts'); if (allAccounts.isNotEmpty) { final newAllAccounts = allAccounts .unselected() @@ -47,4 +47,6 @@ class AccountCacheManager { log('AccountCacheManager::deleteCurrentAccount(): $hashId'); return _accountCacheClient.deleteItem(hashId); } + + Future closeAccountHiveCacheBox() => _accountCacheClient.closeBox(); } \ No newline at end of file diff --git a/lib/features/login/data/local/authentication_info_cache_manager.dart b/lib/features/login/data/local/authentication_info_cache_manager.dart index a9089267f9..6b11d8451b 100644 --- a/lib/features/login/data/local/authentication_info_cache_manager.dart +++ b/lib/features/login/data/local/authentication_info_cache_manager.dart @@ -25,4 +25,6 @@ class AuthenticationInfoCacheManager { Future removeAuthenticationInfo() { return _authenticationInfoCacheClient.deleteItem(AuthenticationInfoCache.keyCacheValue); } + + Future closeAuthenticationInfoHiveCacheBox() => _authenticationInfoCacheClient.closeBox(); } \ No newline at end of file diff --git a/lib/features/login/data/local/token_oidc_cache_manager.dart b/lib/features/login/data/local/token_oidc_cache_manager.dart index b65b1523ea..83e015428b 100644 --- a/lib/features/login/data/local/token_oidc_cache_manager.dart +++ b/lib/features/login/data/local/token_oidc_cache_manager.dart @@ -11,6 +11,7 @@ class TokenOidcCacheManager { TokenOidcCacheManager(this._tokenOidcCacheClient); Future getTokenOidc(String tokenIdHash) async { + log('TokenOidcCacheManager::getTokenOidc(): tokenIdHash: $tokenIdHash'); final tokenCache = await _tokenOidcCacheClient.getItem(tokenIdHash); log('TokenOidcCacheManager::getTokenOidc(): tokenCache: $tokenCache'); if (tokenCache == null) { @@ -27,9 +28,12 @@ class TokenOidcCacheManager { log('TokenOidcCacheManager::persistOneTokenOidc(): key\'s hash: ${tokenOIDC.tokenIdHash}'); log('TokenOidcCacheManager::persistOneTokenOidc(): token: ${tokenOIDC.token}'); await _tokenOidcCacheClient.insertItem(tokenOIDC.tokenIdHash, tokenOIDC.toTokenOidcCache()); + log('TokenOidcCacheManager::persistOneTokenOidc(): done'); } Future deleteTokenOidc() async { await _tokenOidcCacheClient.clearAllData(); } + + Future closeTokenOIDCHiveCacheBox() => _tokenOidcCacheClient.closeBox(); } \ No newline at end of file diff --git a/lib/features/mailbox/data/local/state_cache_manager.dart b/lib/features/mailbox/data/local/state_cache_manager.dart index f1dd4c356b..31409a174d 100644 --- a/lib/features/mailbox/data/local/state_cache_manager.dart +++ b/lib/features/mailbox/data/local/state_cache_manager.dart @@ -24,4 +24,6 @@ class StateCacheManager { final stateKey = TupleKey(stateCache.type.name, accountId.asString, userName.value).encodeKey; return await _stateCacheClient.insertItem(stateKey, stateCache); } + + Future closeStateHiveCacheBox() => _stateCacheClient.closeBox(); } \ No newline at end of file diff --git a/lib/features/push_notification/presentation/controller/fcm_message_controller.dart b/lib/features/push_notification/presentation/controller/fcm_message_controller.dart index 9c69a7153d..75588284cb 100644 --- a/lib/features/push_notification/presentation/controller/fcm_message_controller.dart +++ b/lib/features/push_notification/presentation/controller/fcm_message_controller.dart @@ -21,10 +21,14 @@ import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart'; import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interactor.dart'; import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart'; +import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.dart'; +import 'package:tmail_ui_user/features/login/data/local/authentication_info_cache_manager.dart'; +import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_credential_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_stored_token_oidc_state.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_authenticated_account_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox/data/local/state_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/mailbox_dashboard_bindings.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/action/fcm_action.dart'; import 'package:tmail_ui_user/features/push_notification/presentation/bindings/fcm_interactor_bindings.dart'; @@ -49,6 +53,11 @@ class FcmMessageController extends FcmBaseController { AuthorizationInterceptors? _authorizationInterceptors; GetSessionInteractor? _getSessionInteractor; + AccountCacheManager? _accountCacheManager; + TokenOidcCacheManager? _tokenOidcCacheManager; + StateCacheManager? _stateCacheManager; + AuthenticationInfoCacheManager? _authenticationInfoCacheManager; + FcmMessageController._internal(); static final FcmMessageController _instance = FcmMessageController._internal(); @@ -187,6 +196,17 @@ class FcmMessageController extends FcmBaseController { }); _getInteractorBindings(); + + await Future.wait([ + if (_accountCacheManager != null) + _accountCacheManager!.closeAccountHiveCacheBox(), + if (_tokenOidcCacheManager != null) + _tokenOidcCacheManager!.closeTokenOIDCHiveCacheBox(), + if (_stateCacheManager != null) + _stateCacheManager!.closeStateHiveCacheBox(), + if (_authenticationInfoCacheManager != null) + _authenticationInfoCacheManager!.closeAuthenticationInfoHiveCacheBox(), + ]); } void _getInteractorBindings() { @@ -194,6 +214,10 @@ class FcmMessageController extends FcmBaseController { _dynamicUrlInterceptors = getBinding(); _authorizationInterceptors = getBinding(); _getSessionInteractor = getBinding(); + _accountCacheManager = getBinding(); + _tokenOidcCacheManager = getBinding(); + _stateCacheManager = getBinding(); + _authenticationInfoCacheManager = getBinding(); FcmTokenController.instance.initialBindingInteractor(); }