Files
iiEsaywebUIapp/lib/core/models/socket_health.dart

120 lines
3.4 KiB
Dart
Raw Normal View History

import 'package:flutter/foundation.dart';
/// Represents the current health status of the socket connection.
@immutable
class SocketHealth {
const SocketHealth({
required this.latencyMs,
required this.isConnected,
required this.transport,
required this.reconnectCount,
this.lastHeartbeat,
});
/// Round-trip latency in milliseconds from last heartbeat (-1 if unknown).
final int latencyMs;
/// Whether the socket is currently connected.
final bool isConnected;
/// Current transport type: 'websocket', 'polling', or 'unknown'.
final String transport;
/// Number of reconnections since service creation.
final int reconnectCount;
/// Timestamp of the last successful heartbeat response.
final DateTime? lastHeartbeat;
/// Whether the connection is using WebSocket transport.
bool get isWebSocket => transport == 'websocket';
/// Whether the connection is using HTTP polling transport.
bool get isPolling => transport == 'polling';
/// Whether latency information is available.
bool get hasLatencyInfo => latencyMs >= 0;
/// Connection quality based on latency.
/// Thresholds account for the ~100ms measurement floor in heartbeat timing.
/// Returns 'excellent' (<150ms), 'good' (<300ms), 'fair' (<1000ms),
/// 'poor' (>=1000ms), or 'unknown' if no latency data.
String get quality {
if (latencyMs < 0) return 'unknown';
if (latencyMs < 150) return 'excellent';
if (latencyMs < 300) return 'good';
if (latencyMs < 1000) return 'fair';
return 'poor';
}
SocketHealth copyWith({
int? latencyMs,
bool? isConnected,
String? transport,
int? reconnectCount,
DateTime? lastHeartbeat,
}) {
return SocketHealth(
latencyMs: latencyMs ?? this.latencyMs,
isConnected: isConnected ?? this.isConnected,
transport: transport ?? this.transport,
reconnectCount: reconnectCount ?? this.reconnectCount,
lastHeartbeat: lastHeartbeat ?? this.lastHeartbeat,
);
}
Map<String, dynamic> toJson() {
return {
'latencyMs': latencyMs,
'isConnected': isConnected,
'transport': transport,
'reconnectCount': reconnectCount,
'lastHeartbeat': lastHeartbeat?.toIso8601String(),
};
}
factory SocketHealth.fromJson(Map<String, dynamic> json) {
return SocketHealth(
latencyMs: json['latencyMs'] as int? ?? -1,
isConnected: json['isConnected'] as bool? ?? false,
transport: json['transport'] as String? ?? 'unknown',
reconnectCount: json['reconnectCount'] as int? ?? 0,
lastHeartbeat: json['lastHeartbeat'] != null
? DateTime.tryParse(json['lastHeartbeat'] as String)
: null,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is SocketHealth &&
other.latencyMs == latencyMs &&
other.isConnected == isConnected &&
other.transport == transport &&
other.reconnectCount == reconnectCount &&
other.lastHeartbeat == lastHeartbeat;
}
@override
int get hashCode {
return Object.hash(
latencyMs,
isConnected,
transport,
reconnectCount,
lastHeartbeat,
);
}
@override
String toString() {
return 'SocketHealth('
'latencyMs: $latencyMs, '
'isConnected: $isConnected, '
'transport: $transport, '
'reconnectCount: $reconnectCount, '
'lastHeartbeat: $lastHeartbeat)';
}
}