Refactor ForexRateApiService to remove API key dependency and update README and launch configurations
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -41,35 +41,17 @@ class RentController extends ChangeNotifier {
|
||||
|
||||
RentController({
|
||||
StorageService? storageService,
|
||||
ForexRateApiService? exchangeService,
|
||||
FrankfurterApiService? exchangeService,
|
||||
NotificationService? notificationService,
|
||||
}) : _storageService = storageService ?? StorageService(),
|
||||
_exchangeService =
|
||||
exchangeService ??
|
||||
ForexRateApiService(
|
||||
httpClient: http.Client(),
|
||||
apiKey: _exchangeRateApiKeyFromEnv(),
|
||||
) {
|
||||
exchangeService ?? FrankfurterApiService(httpClient: http.Client()) {
|
||||
_notificationService =
|
||||
notificationService ?? NotificationService(_onNotificationAction);
|
||||
}
|
||||
|
||||
static String _exchangeRateApiKeyFromEnv() {
|
||||
const key = String.fromEnvironment('FOREX_RATE_API_KEY');
|
||||
final trimmed = key.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
if (kDebugMode) {
|
||||
debugPrint(
|
||||
'[RentController] FOREX_RATE_API_KEY missing from dart defines. Pass --dart-define-from-file=.env (or --dart-define) when building/running.',
|
||||
);
|
||||
}
|
||||
return 'REPLACE_WITH_YOUR_FOREXRATE_API_KEY';
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
final StorageService _storageService;
|
||||
final ForexRateApiService _exchangeService;
|
||||
final FrankfurterApiService _exchangeService;
|
||||
late NotificationService _notificationService;
|
||||
|
||||
AppSettings _settings = AppSettings.defaults();
|
||||
@@ -79,6 +61,33 @@ class RentController extends ChangeNotifier {
|
||||
String? _errorMessage;
|
||||
int _selectedYear = DateTime.now().year;
|
||||
|
||||
double? _lookupRateOnOrBefore(
|
||||
Map<String, double> rates,
|
||||
DateTime targetDate,
|
||||
) {
|
||||
final target = DateTime(targetDate.year, targetDate.month, targetDate.day);
|
||||
DateTime? nearestDate;
|
||||
double? nearestRate;
|
||||
|
||||
for (final entry in rates.entries) {
|
||||
final parsed = DateTime.tryParse(entry.key);
|
||||
if (parsed == null) {
|
||||
continue;
|
||||
}
|
||||
final day = DateTime(parsed.year, parsed.month, parsed.day);
|
||||
if (day.isAfter(target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nearestDate == null || day.isAfter(nearestDate)) {
|
||||
nearestDate = day;
|
||||
nearestRate = entry.value;
|
||||
}
|
||||
}
|
||||
|
||||
return nearestRate;
|
||||
}
|
||||
|
||||
AppSettings get settings => _settings;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get errorMessage => _errorMessage;
|
||||
@@ -334,27 +343,25 @@ class RentController extends ChangeNotifier {
|
||||
final usd = _settings.rentUsd;
|
||||
final estDate = DateTime(year, month, 1);
|
||||
|
||||
final ForexConversionResult conversion;
|
||||
final ConversionResult conversion;
|
||||
if (batchRates != null) {
|
||||
final dateStr = DateFormat('yyyy-MM-dd').format(estDate);
|
||||
final quote = batchRates[dateStr];
|
||||
final quote = _lookupRateOnOrBefore(batchRates, estDate);
|
||||
if (quote == null) {
|
||||
throw StateError('Batch rates missing entry for $dateStr.');
|
||||
throw StateError(
|
||||
'Batch rates missing entry on or before ${DateFormat('yyyy-MM-dd').format(estDate)}.',
|
||||
);
|
||||
}
|
||||
conversion = ForexConversionResult(
|
||||
quote: quote,
|
||||
result: quote * usd,
|
||||
);
|
||||
conversion = ConversionResult(quote: quote, result: quote * usd);
|
||||
} else {
|
||||
// Pace individual requests to avoid triggering the rate limit.
|
||||
if (!isFirstIndividualFetch) {
|
||||
await Future.delayed(const Duration(milliseconds: 700));
|
||||
}
|
||||
isFirstIndividualFetch = false;
|
||||
conversion = await _exchangeService.convertUsdToSek(
|
||||
final quote = await _exchangeService.fetchUsdToSekRate(
|
||||
estDate: estDate,
|
||||
amount: usd,
|
||||
);
|
||||
conversion = ConversionResult(quote: quote, result: quote * usd);
|
||||
}
|
||||
|
||||
if (kDebugMode) {
|
||||
@@ -385,9 +392,7 @@ class RentController extends ChangeNotifier {
|
||||
savedMonths++;
|
||||
} catch (err) {
|
||||
final errorText = err.toString();
|
||||
if (errorText.contains('429') ||
|
||||
errorText.contains('104') ||
|
||||
errorText.toLowerCase().contains('rate_limit_reached')) {
|
||||
if (errorText.contains('429')) {
|
||||
pausedByRateLimit = true;
|
||||
_errorMessage =
|
||||
'Backfill paused by API rate limits after $savedMonths new month(s). Run backfill again in a minute to continue.';
|
||||
|
||||
Reference in New Issue
Block a user