Prepare secure config and reliable workout sync
This commit is contained in:
@@ -31,13 +31,12 @@ class SyncService extends GetxService {
|
||||
static const String _apiKeyKey = 'api_key';
|
||||
static const String _apiSecretKey = 'api_secret';
|
||||
|
||||
@override
|
||||
Future<void> onInit() async {
|
||||
super.onInit();
|
||||
Future<SyncService> init() async {
|
||||
await _checkConnectivity();
|
||||
_startConnectivityMonitor();
|
||||
_startPeriodicSync();
|
||||
await _updatePendingCount();
|
||||
return this;
|
||||
}
|
||||
|
||||
// ─── Connectivity Monitoring ──────────────────────────────────
|
||||
@@ -107,7 +106,7 @@ class SyncService extends GetxService {
|
||||
/// Queue a workout for sync
|
||||
Future<void> queueWorkout(Workout workout) async {
|
||||
final payload = jsonEncode(workout.toApiPayload());
|
||||
await _db.enqueueSync(workout.id, payload);
|
||||
await _db.saveCompletedWorkout(workout, payload);
|
||||
await _updatePendingCount();
|
||||
|
||||
// Try immediate sync if online
|
||||
@@ -116,6 +115,14 @@ class SyncService extends GetxService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> retryWorkout(String workoutId) async {
|
||||
await _db.retryFailedSync(workoutId);
|
||||
await _updatePendingCount();
|
||||
if (_isOnline.value && !_isSyncing.value) {
|
||||
await syncPendingWorkouts();
|
||||
}
|
||||
}
|
||||
|
||||
/// Process all pending sync items
|
||||
Future<void> syncPendingWorkouts() async {
|
||||
if (_isSyncing.value) return;
|
||||
@@ -135,6 +142,7 @@ class SyncService extends GetxService {
|
||||
debugPrint('[SYNC] Processing ${pendingItems.length} pending items');
|
||||
|
||||
for (final item in pendingItems) {
|
||||
if (!_isRetryDue(item)) continue;
|
||||
await _syncSingleItem(
|
||||
id: item['id'] as int,
|
||||
workoutId: item['workout_id'] as String,
|
||||
@@ -177,7 +185,7 @@ class SyncService extends GetxService {
|
||||
)
|
||||
.timeout(const Duration(seconds: 30));
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
await _db.updateSyncQueueItem(id, 'sent');
|
||||
await _db.updateSyncStatus(
|
||||
workoutId,
|
||||
@@ -200,8 +208,20 @@ class SyncService extends GetxService {
|
||||
}
|
||||
|
||||
Future<void> _updatePendingCount() async {
|
||||
final items = await _db.getPendingSyncs();
|
||||
_pendingCount.value = items.length;
|
||||
_pendingCount.value = await _db.getPendingSyncCount();
|
||||
}
|
||||
|
||||
bool _isRetryDue(Map<String, dynamic> item) {
|
||||
if (item['status'] != 'failed') return true;
|
||||
final lastAttempt = item['last_attempt'] as String?;
|
||||
if (lastAttempt == null) return true;
|
||||
|
||||
final retryCount = item['retry_count'] as int? ?? 0;
|
||||
final delaySeconds = (30 * (1 << retryCount)).clamp(30, 3600);
|
||||
final attemptedAt = DateTime.tryParse(lastAttempt);
|
||||
if (attemptedAt == null) return true;
|
||||
return DateTime.now().toUtc().difference(attemptedAt.toUtc()).inSeconds >=
|
||||
delaySeconds;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user