import 'dart:async'; import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:stack_trace/stack_trace.dart'; import '../models/auth/profile.dart'; import 'account_services.dart'; import 'connection_manager_services.dart'; import 'persistent_info_services.dart'; import 'settings_services.dart'; part 'background_updater_services.g.dart'; const _connectionsRefreshInterval = Duration(hours: 12); const _timerRefresh = Duration(minutes: 5); final _logger = Logger('BackgroundUpdatersProvider'); // TODO should this stop and be deleted if a profile is switched? // TODO Confirm this is being bootstrapped correctly and running consistently @Riverpod(keepAlive: true) class BackgroundUpdaters extends _$BackgroundUpdaters { bool _executingUpdate = false; @override Timer build(Profile profile) { _logger.info('Building BackgroundUpdater for $profile'); ref.onDispose(() { _logger.info('Disposing of Background updater for $profile'); state.cancel(); }); return Timer.periodic(_timerRefresh, (_) async { await _executeUpdatesForProfile(); }); } Timer stop() { _logger.info('Stopping background updates for $profile'); state.cancel(); return state; } Timer reset() { _logger.info('Resetting background updates for $profile'); state.cancel(); state = Timer.periodic(_timerRefresh, (_) async { await _executeUpdatesForProfile(); }); return state; } Future _executeUpdatesForProfile() async { _logger.fine('_executeUpdatesForProfile for $profile'); if (_executingUpdate) { _logger.fine('Already executing updating so skipping for $profile'); return; } final lowBandwidthMode = ref.watch(lowBandwidthModeSettingProvider); if (lowBandwidthMode) { _logger.fine('low bandwidth mode so skipping for $profile'); return; } if (ref.read(activeProfileProvider) != profile) { _logger.fine('Skipping update since no longer active profile: $profile'); state.cancel(); return; } _logger.fine('Executing background update for $profile'); final dt = DateTime.now().difference(ref.watch(persistentInfoProvider(profile))); _logger.fine('Time since last update for ${profile.id}: $dt'); if (dt >= _connectionsRefreshInterval) { if (_executingUpdate) { _logger.fine('Already executing updating so skipping for $profile'); return; } _executingUpdate = true; try { await ref .read(allContactsUpdaterProvider(profile).notifier) .updateAllContacts(true); } catch (e) { _logger.severe( 'Exception thrown while executing update: $e', Trace.current()); } _executingUpdate = false; } } }