initial commit
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../../core/models/models.dart';
|
||||
import '../../core/network/api_client_provider.dart';
|
||||
import '../../core/network/node_master_api_client.dart';
|
||||
import '../../core/polling/polling_async_notifier.dart';
|
||||
|
||||
part 'nodes_repository.g.dart';
|
||||
|
||||
/// Wraps the `/nodes/*` endpoints — the registry of sibling NodeMaster
|
||||
/// hosts and the server-side fan-out status view.
|
||||
class NodesRepository {
|
||||
const NodesRepository(this._client);
|
||||
|
||||
final NodeMasterApiClient _client;
|
||||
|
||||
Future<List<RemoteNode>> getAll() => _client.getAllRemoteNodes();
|
||||
Future<RemoteNode> get(String id) => _client.getRemoteNode(id);
|
||||
Future<RemoteNode> add(RemoteNode node) => _client.addRemoteNode(node);
|
||||
Future<RemoteNode> update(String id, RemoteNode node) => _client.updateRemoteNode(id, node);
|
||||
Future<void> delete(String id) => _client.deleteRemoteNode(id);
|
||||
Future<List<AggregatedNodeStatus>> getAggregated() => _client.getAggregated();
|
||||
}
|
||||
|
||||
/// Null when no connection is active, mirroring [apiClientProvider].
|
||||
@riverpod
|
||||
NodesRepository? nodesRepository(Ref ref) {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
if (client == null) return null;
|
||||
return NodesRepository(client);
|
||||
}
|
||||
|
||||
/// The registered-nodes list. Manual-refresh only, same reasoning as
|
||||
/// `servicesListProvider` — this backs Fleet's registry table (M6).
|
||||
@riverpod
|
||||
Future<List<RemoteNode>> remoteNodesList(Ref ref) async {
|
||||
final repo = ref.watch(nodesRepositoryProvider);
|
||||
if (repo == null) return [];
|
||||
return repo.getAll();
|
||||
}
|
||||
|
||||
/// The live `/nodes/aggregated` fan-out result, polled every 25s. Shared
|
||||
/// by the Dashboard's "Fleet" stat tile and the Fleet screen's card grid
|
||||
/// (M6) — one poll, cached by Riverpod, rather than each screen running
|
||||
/// its own duplicate timer against the same endpoint.
|
||||
@riverpod
|
||||
class AggregatedNodes extends _$AggregatedNodes with PollingMixin<List<AggregatedNodeStatus>> {
|
||||
@override
|
||||
Duration get interval => const Duration(seconds: 25);
|
||||
|
||||
@override
|
||||
Future<List<AggregatedNodeStatus>> fetch() async {
|
||||
final repo = ref.watch(nodesRepositoryProvider);
|
||||
if (repo == null) return [];
|
||||
return repo.getAggregated();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<AggregatedNodeStatus>> build() => startPolling();
|
||||
}
|
||||
Reference in New Issue
Block a user