ws_provider.dart 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import 'dart:developer' as developer;
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import '../core/config/app_config.dart';
  4. import '../core/network/ws_client.dart';
  5. import 'node_provider.dart';
  6. export '../core/network/ws_client.dart' show WsConnectionState;
  7. /// 全局 WebSocket 客户端 Provider
  8. /// 仅当 ENABLE_MOCK=true 时使用模拟数据,debug 构建也连真实 WS 以便调试
  9. final wsClientProvider = Provider<WsClient>((ref) {
  10. final nodeState = ref.read(nodeProvider);
  11. // Debug/Profile:合约 WS 固定 env_debug,避免节点缓存里的旧 apitest 覆盖
  12. final wsUrl = AppConfig.isDebug
  13. ? AppConfig.effectiveWsUrl
  14. : (nodeState.currentNode?.normalizedWsHost ?? AppConfig.effectiveWsUrl);
  15. final client = WsClient(
  16. mockMode: AppConfig.enableMock,
  17. wsUrl: wsUrl,
  18. // WS 连续重连失败 → 联动节点 failover;切节点后 listen 自动 reconnectWithUrl
  19. onPersistentFailure: () {
  20. developer.log(
  21. 'WS persistent failure → triggering node failover',
  22. name: 'Node',
  23. );
  24. ref.read(nodeProvider.notifier).reportFailure(immediate: true);
  25. },
  26. );
  27. // Release:切节点时重连 WS;Debug 固定单一地址
  28. if (!AppConfig.isDebug) {
  29. ref.listen(nodeProvider, (prev, next) {
  30. final newWsUrl = next.currentNode?.normalizedWsHost;
  31. if (newWsUrl != null && client.currentWsUrl != newWsUrl) {
  32. developer.log(
  33. 'WS reconnecting: ${client.currentWsUrl} → $newWsUrl',
  34. name: 'Node',
  35. );
  36. client.reconnectWithUrl(newWsUrl);
  37. }
  38. });
  39. }
  40. ref.onDispose(client.dispose);
  41. return client;
  42. });
  43. /// 连接状态 StreamProvider
  44. final wsConnectionStateProvider = StreamProvider<WsConnectionState>((ref) {
  45. final client = ref.watch(wsClientProvider);
  46. return client.connectionStream;
  47. });