feat: synchronisation mode deconnecte fin chat et stats
This commit is contained in:
139
app/lib/core/data/models/pending_request.dart
Normal file
139
app/lib/core/data/models/pending_request.dart
Normal file
@@ -0,0 +1,139 @@
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
part 'pending_request.g.dart';
|
||||
|
||||
/// Modèle pour stocker les requêtes API en attente quand l'application est hors ligne
|
||||
/// Ces requêtes seront traitées automatiquement au retour de la connexion
|
||||
@HiveType(typeId: 100)
|
||||
class PendingRequest extends HiveObject {
|
||||
/// ID unique de la requête (UUID)
|
||||
@HiveField(0)
|
||||
final String id;
|
||||
|
||||
/// Méthode HTTP (POST, GET, PUT, DELETE)
|
||||
@HiveField(1)
|
||||
final String method;
|
||||
|
||||
/// Path de l'API (ex: /chat/rooms/xxx/messages)
|
||||
@HiveField(2)
|
||||
final String path;
|
||||
|
||||
/// Body de la requête (données JSON)
|
||||
@HiveField(3)
|
||||
final Map<String, dynamic>? data;
|
||||
|
||||
/// Query parameters
|
||||
@HiveField(4)
|
||||
final Map<String, dynamic>? queryParams;
|
||||
|
||||
/// Timestamp de création - UTILISÉ POUR L'ORDRE FIFO
|
||||
@HiveField(5)
|
||||
final DateTime createdAt;
|
||||
|
||||
/// ID temporaire associé (ex: temp_msg_xxx, temp_user_xxx)
|
||||
@HiveField(6)
|
||||
final String? tempId;
|
||||
|
||||
/// Contexte de la requête (chat, user, operation, passage, etc.)
|
||||
@HiveField(7)
|
||||
final String context;
|
||||
|
||||
/// Nombre de tentatives de retry
|
||||
@HiveField(8)
|
||||
final int retryCount;
|
||||
|
||||
/// Message de la dernière erreur
|
||||
@HiveField(9)
|
||||
final String? errorMessage;
|
||||
|
||||
/// Métadonnées additionnelles (userId, amicaleId, etc.)
|
||||
@HiveField(10)
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
/// Priorité de la requête (0 = normale, 1 = haute pour passages)
|
||||
@HiveField(11)
|
||||
final int priority;
|
||||
|
||||
/// Headers spécifiques pour cette requête
|
||||
@HiveField(12)
|
||||
final Map<String, String>? headers;
|
||||
|
||||
PendingRequest({
|
||||
required this.id,
|
||||
required this.method,
|
||||
required this.path,
|
||||
this.data,
|
||||
this.queryParams,
|
||||
required this.createdAt,
|
||||
this.tempId,
|
||||
required this.context,
|
||||
this.retryCount = 0,
|
||||
this.errorMessage,
|
||||
this.metadata,
|
||||
this.priority = 0,
|
||||
this.headers,
|
||||
});
|
||||
|
||||
/// Créer une copie avec des modifications
|
||||
PendingRequest copyWith({
|
||||
String? id,
|
||||
String? method,
|
||||
String? path,
|
||||
Map<String, dynamic>? data,
|
||||
Map<String, dynamic>? queryParams,
|
||||
DateTime? createdAt,
|
||||
String? tempId,
|
||||
String? context,
|
||||
int? retryCount,
|
||||
String? errorMessage,
|
||||
Map<String, dynamic>? metadata,
|
||||
int? priority,
|
||||
Map<String, String>? headers,
|
||||
}) {
|
||||
return PendingRequest(
|
||||
id: id ?? this.id,
|
||||
method: method ?? this.method,
|
||||
path: path ?? this.path,
|
||||
data: data ?? this.data,
|
||||
queryParams: queryParams ?? this.queryParams,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
tempId: tempId ?? this.tempId,
|
||||
context: context ?? this.context,
|
||||
retryCount: retryCount ?? this.retryCount,
|
||||
errorMessage: errorMessage ?? this.errorMessage,
|
||||
metadata: metadata ?? this.metadata,
|
||||
priority: priority ?? this.priority,
|
||||
headers: headers ?? this.headers,
|
||||
);
|
||||
}
|
||||
|
||||
/// Calculer le prochain délai de retry basé sur le nombre de tentatives
|
||||
Duration getNextRetryDelay() {
|
||||
switch (retryCount) {
|
||||
case 0:
|
||||
return Duration.zero; // Immédiat
|
||||
case 1:
|
||||
return const Duration(seconds: 30);
|
||||
case 2:
|
||||
return const Duration(minutes: 2);
|
||||
default:
|
||||
return const Duration(minutes: 5);
|
||||
}
|
||||
}
|
||||
|
||||
/// Vérifier si la requête a expiré (>24h)
|
||||
bool isExpired() {
|
||||
final age = DateTime.now().difference(createdAt);
|
||||
return age.inHours >= 24;
|
||||
}
|
||||
|
||||
/// Obtenir une description lisible pour les logs
|
||||
String toLogString() {
|
||||
return '[$context] $method $path (ID: $id, TempID: $tempId, Priority: $priority, Retry: $retryCount)';
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PendingRequest{id: $id, method: $method, path: $path, context: $context, priority: $priority, retryCount: $retryCount}';
|
||||
}
|
||||
}
|
||||
77
app/lib/core/data/models/pending_request.g.dart
Normal file
77
app/lib/core/data/models/pending_request.g.dart
Normal file
@@ -0,0 +1,77 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'pending_request.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class PendingRequestAdapter extends TypeAdapter<PendingRequest> {
|
||||
@override
|
||||
final int typeId = 100;
|
||||
|
||||
@override
|
||||
PendingRequest read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return PendingRequest(
|
||||
id: fields[0] as String,
|
||||
method: fields[1] as String,
|
||||
path: fields[2] as String,
|
||||
data: (fields[3] as Map?)?.cast<String, dynamic>(),
|
||||
queryParams: (fields[4] as Map?)?.cast<String, dynamic>(),
|
||||
createdAt: fields[5] as DateTime,
|
||||
tempId: fields[6] as String?,
|
||||
context: fields[7] as String,
|
||||
retryCount: fields[8] as int,
|
||||
errorMessage: fields[9] as String?,
|
||||
metadata: (fields[10] as Map?)?.cast<String, dynamic>(),
|
||||
priority: fields[11] as int,
|
||||
headers: (fields[12] as Map?)?.cast<String, String>(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, PendingRequest obj) {
|
||||
writer
|
||||
..writeByte(13)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.method)
|
||||
..writeByte(2)
|
||||
..write(obj.path)
|
||||
..writeByte(3)
|
||||
..write(obj.data)
|
||||
..writeByte(4)
|
||||
..write(obj.queryParams)
|
||||
..writeByte(5)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(6)
|
||||
..write(obj.tempId)
|
||||
..writeByte(7)
|
||||
..write(obj.context)
|
||||
..writeByte(8)
|
||||
..write(obj.retryCount)
|
||||
..writeByte(9)
|
||||
..write(obj.errorMessage)
|
||||
..writeByte(10)
|
||||
..write(obj.metadata)
|
||||
..writeByte(11)
|
||||
..write(obj.priority)
|
||||
..writeByte(12)
|
||||
..write(obj.headers);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is PendingRequestAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
Reference in New Issue
Block a user