TF-4268 Cache Sentry config and user for FCM background re-initialization

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2026-04-09 16:22:37 +07:00
committed by Dat H. Pham
parent cb5d43630a
commit eeaab49e93
20 changed files with 755 additions and 183 deletions
+7 -2
View File
@@ -3,6 +3,7 @@ import 'package:core/utils/file_utils.dart';
import 'package:core/utils/platform_info.dart';
import 'package:tmail_ui_user/features/caching/clients/hive_cache_version_client.dart';
import 'package:tmail_ui_user/features/caching/config/hive_cache_config.dart';
import 'package:tmail_ui_user/features/caching/manager/sentry_configuration_cache_manager.dart';
import 'package:tmail_ui_user/features/caching/manager/session_cache_manger.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
import 'package:tmail_ui_user/features/cleanup/data/local/recent_login_url_cache_manager.dart';
@@ -42,6 +43,7 @@ class CachingManager {
final OidcConfigurationCacheManager _oidcConfigurationCacheManager;
final EncryptionKeyCacheManager _encryptionKeyCacheManager;
final AuthenticationInfoCacheManager _authenticationInfoCacheManager;
final SentryConfigurationCacheManager? _sentryConfigurationCacheManager;
CachingManager(
this._mailboxCacheManager,
@@ -62,8 +64,9 @@ class CachingManager {
this._tokenOidcCacheManager,
this._oidcConfigurationCacheManager,
this._encryptionKeyCacheManager,
this._authenticationInfoCacheManager,
);
this._authenticationInfoCacheManager, {
SentryConfigurationCacheManager? sentryConfigurationCacheManager,
}) : _sentryConfigurationCacheManager = sentryConfigurationCacheManager;
Future<void> clearAll() async {
try {
@@ -104,6 +107,8 @@ class CachingManager {
_oidcConfigurationCacheManager.clear(),
_tokenOidcCacheManager.clear(),
_authenticationInfoCacheManager.clear(),
if (PlatformInfo.isMobile && _sentryConfigurationCacheManager != null)
_sentryConfigurationCacheManager!.clearSentryConfiguration(),
], eagerError: true);
} catch (e) {
logWarning('CachingManager::clearAccountDataCached: Cannot clear account data cache: $e');
@@ -0,0 +1,12 @@
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_configuration_cache.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
class SentryConfigurationCacheClient
extends HiveCacheClient<SentryConfigurationCache> {
@override
String get tableName => CachingConstants.sentryConfigurationCacheBoxName;
@override
bool get encryption => true;
}
@@ -0,0 +1,12 @@
import 'package:tmail_ui_user/features/caching/config/hive_cache_client.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_user_cache.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
class SentryUserCacheClient
extends HiveCacheClient<SentryUserCache> {
@override
String get tableName => CachingConstants.sentryUserCacheBoxName;
@override
bool get encryption => true;
}
@@ -22,6 +22,8 @@ import 'package:tmail_ui_user/features/base/upgradeable/upgrade_hive_database_st
import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/caching/config/cache_version.dart';
import 'package:tmail_ui_user/features/caching/config/fcm_isolate_name_server.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_configuration_cache.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_user_cache.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
import 'package:tmail_ui_user/features/home/data/model/session_hive_obj.dart';
import 'package:tmail_ui_user/features/login/data/local/encryption_key_cache_manager.dart';
@@ -239,6 +241,16 @@ class HiveCacheConfig {
CachingConstants.OIDC_CONFIGURATION_CACHE_ID,
isolated: isolated,
);
registerCacheAdapter<SentryConfigurationCache>(
SentryConfigurationCacheAdapter(),
CachingConstants.SENTRY_CONFIGURATION_CACHE_ID,
isolated: isolated,
);
registerCacheAdapter<SentryUserCache>(
SentryUserCacheAdapter(),
CachingConstants.SENTRY_USER_CACHE_ID,
isolated: isolated,
);
}
void registerCacheAdapter<T>(
@@ -0,0 +1,80 @@
import 'package:equatable/equatable.dart';
import 'package:hive_ce/hive.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
part 'sentry_configuration_cache.g.dart';
@HiveType(typeId: CachingConstants.SENTRY_CONFIGURATION_CACHE_ID)
class SentryConfigurationCache extends HiveObject with EquatableMixin {
@HiveField(0)
final String dsn;
@HiveField(1)
final String environment;
@HiveField(2)
final String release;
@HiveField(3)
final double tracesSampleRate;
@HiveField(4)
final double profilesSampleRate;
@HiveField(5)
final bool enableLogs;
@HiveField(6)
final bool isDebug;
@HiveField(7)
final bool attachScreenshot;
@HiveField(8)
final bool isAvailable;
@HiveField(9)
final double sessionSampleRate;
@HiveField(10)
final double onErrorSampleRate;
@HiveField(11)
final bool enableFramesTracking;
@HiveField(12)
final String? dist;
SentryConfigurationCache({
required this.dsn,
required this.environment,
required this.release,
required this.tracesSampleRate,
required this.profilesSampleRate,
required this.enableLogs,
required this.isDebug,
required this.attachScreenshot,
required this.isAvailable,
required this.sessionSampleRate,
required this.onErrorSampleRate,
required this.enableFramesTracking,
required this.dist,
});
@override
List<Object?> get props => [
dsn,
environment,
release,
tracesSampleRate,
profilesSampleRate,
enableLogs,
isDebug,
attachScreenshot,
isAvailable,
sessionSampleRate,
onErrorSampleRate,
enableFramesTracking,
dist,
];
}
@@ -0,0 +1,35 @@
import 'package:equatable/equatable.dart';
import 'package:hive_ce/hive.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
part 'sentry_user_cache.g.dart';
@HiveType(typeId: CachingConstants.SENTRY_USER_CACHE_ID)
class SentryUserCache extends HiveObject with EquatableMixin {
@HiveField(0)
final String id;
@HiveField(1)
final String name;
@HiveField(2)
final String username;
@HiveField(3)
final String email;
SentryUserCache({
required this.id,
required this.name,
required this.username,
required this.email,
});
@override
List<Object?> get props => [
id,
name,
username,
email,
];
}
@@ -6,3 +6,17 @@ class NotFoundDataWithThisKeyException extends AppBaseException {
@override
String get exceptionName => 'NotFoundDataWithThisKeyException';
}
class NotFoundSentryConfigurationException extends AppBaseException {
const NotFoundSentryConfigurationException([super.message]);
@override
String get exceptionName => 'NotFoundSentryConfigurationException';
}
class NotFoundSentryUserException extends AppBaseException {
const NotFoundSentryUserException([super.message]);
@override
String get exceptionName => 'NotFoundSentryUserException';
}
@@ -0,0 +1,66 @@
import 'package:core/utils/sentry/sentry_config.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_configuration_cache.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_user_cache.dart';
extension SentryConfigExtension on SentryConfig {
SentryConfigurationCache toSentryConfigurationCache() {
return SentryConfigurationCache(
dsn: dsn,
environment: environment,
release: release,
isAvailable: isAvailable,
tracesSampleRate: tracesSampleRate,
profilesSampleRate: profilesSampleRate,
sessionSampleRate: sessionSampleRate,
onErrorSampleRate: onErrorSampleRate,
enableLogs: enableLogs,
enableFramesTracking: enableFramesTracking,
isDebug: isDebug,
attachScreenshot: attachScreenshot,
dist: dist,
);
}
}
extension SentryConfigurationCacheExtension on SentryConfigurationCache {
SentryConfig toSentryConfig() {
return SentryConfig(
dsn: dsn,
environment: environment,
release: release,
isAvailable: isAvailable,
tracesSampleRate: tracesSampleRate,
profilesSampleRate: profilesSampleRate,
sessionSampleRate: sessionSampleRate,
onErrorSampleRate: onErrorSampleRate,
enableLogs: enableLogs,
enableFramesTracking: enableFramesTracking,
isDebug: isDebug,
attachScreenshot: attachScreenshot,
dist: dist,
);
}
}
extension SentryUserExtension on SentryUser {
SentryUserCache toSentryUserCache() {
return SentryUserCache(
id: id ?? '',
name: name ?? '',
username: username ?? '',
email: email ?? '',
);
}
}
extension SentryUserCacheExtension on SentryUserCache {
SentryUser toSentryUser() {
return SentryUser(
id: id.isEmpty ? null : id,
name: name.isEmpty ? null : name,
username: username.isEmpty ? null : username,
email: email.isEmpty ? null : email,
);
}
}
@@ -0,0 +1,68 @@
import 'package:core/utils/app_logger.dart';
import 'package:tmail_ui_user/features/caching/clients/sentry_configuration_cache_client.dart';
import 'package:tmail_ui_user/features/caching/clients/sentry_user_cache_client.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_configuration_cache.dart';
import 'package:tmail_ui_user/features/caching/entries/sentry_user_cache.dart';
import 'package:tmail_ui_user/features/caching/exceptions/local_storage_exception.dart';
import 'package:tmail_ui_user/features/caching/utils/caching_constants.dart';
class SentryConfigurationCacheManager {
final SentryConfigurationCacheClient _configurationCacheClient;
final SentryUserCacheClient _userCacheClient;
final String _configurationCacheKey =
CachingConstants.sentryConfigurationCacheKeyName;
final String _userCacheKey = CachingConstants.sentryUserCacheKeyName;
SentryConfigurationCacheManager(
this._configurationCacheClient,
this._userCacheClient,
);
Future<SentryConfigurationCache> getSentryConfiguration() async {
final cache = await _configurationCacheClient.getItem(_configurationCacheKey);
if (cache == null) throw const NotFoundSentryConfigurationException();
return cache;
}
Future<void> saveSentryConfiguration(
SentryConfigurationCache sentryConfigurationCache,
) async {
await _configurationCacheClient.insertItem(
_configurationCacheKey,
sentryConfigurationCache,
);
}
Future<SentryUserCache> getSentryUser() async {
final cache = await _userCacheClient.getItem(_userCacheKey);
if (cache == null) throw const NotFoundSentryUserException();
return cache;
}
Future<void> saveSentryUser(
SentryUserCache sentryUserCache,
) async {
await _userCacheClient.insertItem(_userCacheKey, sentryUserCache);
}
Future<void> clearSentryConfiguration() async {
try {
await _configurationCacheClient.clearAllData();
} catch (e, st) {
logError(
'SentryConfigurationCacheManager::clearSentryConfiguration: Failed to clear config cache',
exception: e,
stackTrace: st,
);
}
try {
await _userCacheClient.clearAllData();
} catch (e, st) {
logError(
'SentryConfigurationCacheManager::clearSentryConfiguration: Failed to clear user cache',
exception: e,
stackTrace: st,
);
}
}
}
@@ -20,6 +20,8 @@ class CachingConstants {
static const int SENDING_EMAIL_HIVE_CACHE_ID = 18;
static const int SESSION_HIVE_CACHE_ID = 19;
static const int OIDC_CONFIGURATION_CACHE_ID = 20;
static const int SENTRY_CONFIGURATION_CACHE_ID = 21;
static const int SENTRY_USER_CACHE_ID = 22;
static const String fcmCacheBoxName = 'fcm_cache_box';
static const String newEmailCacheBoxName = 'new_email_cache_box';
@@ -28,8 +30,12 @@ class CachingConstants {
static const String sessionCacheBoxName = 'session_cache_box';
static const String firebaseRegistrationCacheBoxName = 'firebase_registration_cache_box';
static const String oidcConfigurationCacheBoxName = 'oidc_configuration_cache_box';
static const String sentryConfigurationCacheBoxName = 'sentry_configuration_cache_box';
static const String sentryUserCacheBoxName = 'sentry_user_cache_box';
static const String oidcConfigurationCacheKeyName = 'oidc_configuration_cache_key';
static const String sentryConfigurationCacheKeyName = 'sentry_configuration_cache_key';
static const String sentryUserCacheKeyName = 'sentry_user_cache_key';
static const String newEmailsContentFolderName = 'new_emails';
static const String openedEmailContentFolderName = 'opened_email';