Files
umbrix/lib/features/profile/notifier/profiles_update_notifier.dart
problematicconsumer 829d58a1a2 Refactor profiles
2023-11-26 21:20:58 +03:30

93 lines
2.9 KiB
Dart

import 'package:dartx/dartx.dart';
import 'package:hiddify/data/data_providers.dart';
import 'package:hiddify/features/profile/data/profile_data_providers.dart';
import 'package:hiddify/features/profile/model/profile_entity.dart';
import 'package:hiddify/utils/custom_loggers.dart';
import 'package:meta/meta.dart';
import 'package:neat_periodic_task/neat_periodic_task.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'profiles_update_notifier.g.dart';
@Riverpod(keepAlive: true)
class ForegroundProfilesUpdateNotifier
extends _$ForegroundProfilesUpdateNotifier with AppLogger {
static const prefKey = "profiles_update_check";
static const interval = Duration(minutes: 15);
@override
Future<void> build() async {
loggy.debug("initializing");
var cycleCount = 0;
final scheduler = NeatPeriodicTaskScheduler(
name: 'profiles update worker',
interval: interval,
timeout: const Duration(minutes: 5),
task: () async {
loggy.debug("cycle [${cycleCount++}]");
await updateProfiles();
},
);
ref.onDispose(() async {
await scheduler.stop();
});
return scheduler.start();
}
@visibleForTesting
Future<void> updateProfiles() async {
try {
final previousRun = DateTime.tryParse(
ref.read(sharedPreferencesProvider).getString(prefKey) ?? "",
);
if (previousRun != null && previousRun.add(interval) > DateTime.now()) {
loggy.debug("too soon! previous run: [$previousRun]");
return;
}
loggy.debug("running, previous run: [$previousRun]");
final remoteProfiles = await ref
.read(profileRepositoryProvider)
.requireValue
.watchAll()
.map(
(event) => event.getOrElse((f) {
loggy.error("error getting profiles");
throw f;
}).whereType<RemoteProfileEntity>(),
)
.first;
await for (final profile in Stream.fromIterable(remoteProfiles)) {
final updateInterval = profile.options?.updateInterval;
if (updateInterval != null &&
updateInterval <= DateTime.now().difference(profile.lastUpdate)) {
await ref
.read(profileRepositoryProvider)
.requireValue
.updateSubscription(profile)
.mapLeft(
(l) => loggy.debug("error updating profile [${profile.id}]", l),
)
.map(
(_) =>
loggy.debug("profile [${profile.id}] updated successfully"),
)
.run();
} else {
loggy.debug(
"skipping profile [${profile.id}] update. last successful update: [${profile.lastUpdate}] - interval: [${profile.options?.updateInterval}]",
);
}
}
} finally {
await ref
.read(sharedPreferencesProvider)
.setString(prefKey, DateTime.now().toIso8601String());
}
}
}