From 8b9436a9e527a274747e03ef4e9e5be7bfd5e694 Mon Sep 17 00:00:00 2001 From: fulleni Date: Wed, 20 Aug 2025 08:27:55 +0100 Subject: [PATCH] refactor(country): improve country fetching logic - Introduce helper methods for fetching and caching event and headquarter countries - Use atomic assignment for _eventCountriesFuture and _headquarterCountriesFuture - Remove duplicate code and improve readability --- lib/src/services/country_service.dart | 66 ++++++++++++--------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/lib/src/services/country_service.dart b/lib/src/services/country_service.dart index 9b318d4..b24d5a4 100644 --- a/lib/src/services/country_service.dart +++ b/lib/src/services/country_service.dart @@ -117,22 +117,35 @@ class CountryService { _log.finer('Returning cached event countries.'); return _cachedEventCountries!.data; } + // Atomically assign the future if no fetch is in progress. + _eventCountriesFuture ??= _fetchAndCacheEventCountries(); + return _eventCountriesFuture!; + } - // If a fetch is already in progress, await it to prevent cache stampede. - if (_eventCountriesFuture != null) { - _log.finer('Awaiting in-flight event countries fetch.'); - return _eventCountriesFuture!; + /// Fetches a distinct list of countries that are referenced as + /// `headquarters` in sources. + /// + /// Uses MongoDB aggregation to efficiently get distinct country IDs + /// and then fetches the full Country objects. Results are cached. + Future> _getHeadquarterCountries() async { + if (_cachedHeadquarterCountries != null && + _cachedHeadquarterCountries!.isValid()) { + _log.finer('Returning cached headquarter countries.'); + return _cachedHeadquarterCountries!.data; } + // Atomically assign the future if no fetch is in progress. + _headquarterCountriesFuture ??= _fetchAndCacheHeadquarterCountries(); + return _headquarterCountriesFuture!; + } + /// Helper method to fetch and cache distinct event countries. + Future> _fetchAndCacheEventCountries() async { _log.finer('Fetching distinct event countries via aggregation.'); - // Start a new fetch and store the future. - _eventCountriesFuture = _getDistinctCountriesFromAggregation( - repository: _headlineRepository, - fieldName: 'eventCountry', - ); - try { - final distinctCountries = await _eventCountriesFuture!; + final distinctCountries = await _getDistinctCountriesFromAggregation( + repository: _headlineRepository, + fieldName: 'eventCountry', + ); _cachedEventCountries = _CacheEntry( distinctCountries, DateTime.now().add(_cacheDuration), @@ -148,33 +161,14 @@ class CountryService { } } - /// Fetches a distinct list of countries that are referenced as - /// `headquarters` in sources. - /// - /// Uses MongoDB aggregation to efficiently get distinct country IDs - /// and then fetches the full Country objects. Results are cached. - Future> _getHeadquarterCountries() async { - if (_cachedHeadquarterCountries != null && - _cachedHeadquarterCountries!.isValid()) { - _log.finer('Returning cached headquarter countries.'); - return _cachedHeadquarterCountries!.data; - } - - // If a fetch is already in progress, await it to prevent cache stampede. - if (_headquarterCountriesFuture != null) { - _log.finer('Awaiting in-flight headquarter countries fetch.'); - return _headquarterCountriesFuture!; - } - + /// Helper method to fetch and cache distinct headquarter countries. + Future> _fetchAndCacheHeadquarterCountries() async { _log.finer('Fetching distinct headquarter countries via aggregation.'); - // Start a new fetch and store the future. - _headquarterCountriesFuture = _getDistinctCountriesFromAggregation( - repository: _sourceRepository, - fieldName: 'headquarters', - ); - try { - final distinctCountries = await _headquarterCountriesFuture!; + final distinctCountries = await _getDistinctCountriesFromAggregation( + repository: _sourceRepository, + fieldName: 'headquarters', + ); _cachedHeadquarterCountries = _CacheEntry( distinctCountries, DateTime.now().add(_cacheDuration),