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
@@ -154,7 +154,9 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_current_emails_flags_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/update_text_formatting_menu_state_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/web_auth_redirect_processor_extension.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/sentry_ecosystem_mixin.dart';
import 'package:tmail_ui_user/features/caching/manager/sentry_configuration_cache_manager.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/sentry_config_linagora_ecosystem.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/sentry_ecosystem.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/dashboard_routes.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/download/download_task_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/draggable_app_state.dart';
@@ -242,8 +244,9 @@ class MailboxDashBoardController extends ReloadableController
AiScribeMixin,
SearchLabelFilterModalMixin,
AddLabelToEmailMixin,
HandleTeamMailboxMixin,
SentryEcosystemMixin {
HandleTeamMailboxMixin {
SentryEcosystem? _sentryEcosystem;
final RemoveEmailDraftsInteractor _removeEmailDraftsInteractor = Get.find<RemoveEmailDraftsInteractor>();
final EmailReceiveManager _emailReceiveManager = Get.find<EmailReceiveManager>();
@@ -403,6 +406,7 @@ class MailboxDashBoardController extends ReloadableController
@override
void onInit() {
if (PlatformInfo.isMobile) {
_sentryEcosystem = SentryEcosystem(getBinding<SentryConfigurationCacheManager>());
_registerReceivingFileSharingStream();
_registerDeepLinks();
}
@@ -415,6 +419,11 @@ class MailboxDashBoardController extends ReloadableController
super.onInit();
}
void initSentryUser(SentryUser? user) => _sentryEcosystem?.initUser(user);
Future<void> setUpSentry(SentryConfigLinagoraEcosystem ecosystemConfig) async =>
_sentryEcosystem?.setUp(ecosystemConfig);
@override
void onReady() {
if (PlatformInfo.isWeb) {
@@ -3477,6 +3486,7 @@ class MailboxDashBoardController extends ReloadableController
paywallController?.onClose();
paywallController = null;
cachedLinagoraEcosystem = null;
_sentryEcosystem = null;
_disposeWorkerObxVariables();
super.onClose();
}
@@ -1,4 +1,5 @@
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart';
import 'package:scribe/scribe/ai/data/service/prompt_service.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/linagora_ecosystem.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_linagora_ecosystem_state.dart';
@@ -51,6 +52,7 @@ extension SetupScribePromptUrlExtension on MailboxDashBoardController {
}
void _setUpSentry(LinagoraEcosystem ecosystem) {
if (PlatformInfo.isWeb) return;
final sentryConfigEcosystem = ecosystem.sentryConfigEcosystem;
if (sentryConfigEcosystem != null) {
setUpSentry(sentryConfigEcosystem);
@@ -1,43 +0,0 @@
import 'package:core/presentation/extensions/string_extension.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/sentry/sentry_manager.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/sentry_config_linagora_ecosystem.dart';
mixin SentryEcosystemMixin {
SentryUser? _sentryUser;
void initSentryUser(SentryUser? newSentryUser) {
_sentryUser = newSentryUser;
}
Future<void> setUpSentry(
SentryConfigLinagoraEcosystem ecosystemConfig,
) async {
final dsn = ecosystemConfig.dsn?.trimmed;
final env = ecosystemConfig.environment?.trimmed;
final isValid = ecosystemConfig.enabled == true
&& (dsn?.isNotEmpty ?? false)
&& (env?.isNotEmpty ?? false);
if (!isValid) {
logWarning(
'SentryEcosystemMixin::setUpSentry: config invalid '
'(enabled=${ecosystemConfig.enabled}, dsn=${dsn?.isNotEmpty}, env=${env?.isNotEmpty})',
);
return;
}
final sentryConfig = await ecosystemConfig.toSentryConfig();
await SentryManager.instance.initializeWithSentryConfig(sentryConfig);
_setupSentryUser();
}
void _setupSentryUser() {
if (_sentryUser == null) return;
SentryManager.instance.setUser(_sentryUser!);
}
}
@@ -0,0 +1,67 @@
import 'package:core/presentation/extensions/string_extension.dart';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/sentry/sentry_config.dart';
import 'package:core/utils/sentry/sentry_manager.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tmail_ui_user/features/caching/extensions/sentry_cache_extensions.dart';
import 'package:tmail_ui_user/features/caching/manager/sentry_configuration_cache_manager.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/linagora_ecosystem/sentry_config_linagora_ecosystem.dart';
class SentryEcosystem {
final SentryConfigurationCacheManager? _cacheManager;
SentryUser? _sentryUser;
SentryEcosystem(this._cacheManager);
void initUser(SentryUser? user) {
_sentryUser = user;
}
Future<void> setUp(SentryConfigLinagoraEcosystem ecosystemConfig) async {
final dsn = ecosystemConfig.dsn?.trimmed;
final env = ecosystemConfig.environment?.trimmed;
final isValid = ecosystemConfig.enabled == true
&& (dsn?.isNotEmpty ?? false)
&& (env?.isNotEmpty ?? false);
if (!isValid) {
logWarning(
'SentryEcosystem::setUp: config invalid '
'(enabled=${ecosystemConfig.enabled}, dsn=${dsn?.isNotEmpty}, env=${env?.isNotEmpty})',
);
return;
}
final sentryConfig = await ecosystemConfig.toSentryConfig();
await SentryManager.instance.initializeWithSentryConfig(sentryConfig);
_applyUser();
await _cacheData(sentryConfig, _sentryUser);
}
void _applyUser() {
if (_sentryUser == null) return;
SentryManager.instance.setUser(_sentryUser!);
}
Future<void> _cacheData(SentryConfig sentryConfig, SentryUser? sentryUser) async {
if (_cacheManager == null) return;
try {
await _cacheManager!.saveSentryConfiguration(sentryConfig.toSentryConfigurationCache());
if (sentryUser != null) {
await _cacheManager!.saveSentryUser(sentryUser.toSentryUserCache());
}
} catch (e, st) {
logError(
'SentryEcosystem::_cacheData: Cannot cache Sentry data',
exception: e,
stackTrace: st,
);
// Clear both caches to avoid stale/inconsistent state (e.g. new config + old user PII)
await _cacheManager!.clearSentryConfiguration().catchError((_) {});
}
}
}