sync method
Synchronizes the local and remote data.
Implementation
Future<void> sync() async {
if (_isSyncing) {
_logger.d('SyncService: Sync already in progress, skipping...');
return; // Exit if another sync is running
}
_isSyncing = true; // Set the flag to indicate sync is starting
try {
_logger.d('SyncService: Starting sync process...');
// 1. Ensure all media files are uploaded
_logger.d('SyncService: Uploading local files...');
await _uploadLocalFiles();
_logger.d('SyncService: Local files uploaded successfully.');
// 2. Get sync timestamps
_logger.d('SyncService: Getting last sync time...');
final lastSyncTime = await localRepository.getLastSyncServerTime();
_logger.d('SyncService: Last sync time: $lastSyncTime');
_logger.d('SyncService: Getting latest server sync time...');
final serverTime = await remoteRepository.getLatestServerSyncTime();
_logger.d('SyncService: Latest server sync time: $serverTime');
// 3. Fetch items from remote (if needed)
var itemsToFetch = <T>[];
if (serverTime != null) {
_logger.d('SyncService: Fetching items from remote...');
itemsToFetch =
await remoteRepository.fetchItemsByServerWrittenTimeRange(
from: lastSyncTime,
to: serverTime,
);
_logger.d(
'SyncService: Fetched ${itemsToFetch.length} items from remote.',
);
}
// 4. Filter fetched items (LWW conflict resolution)
_logger.d('SyncService: Filtering fetched items...');
final filteredFetchedItems = await _filterFetchedItems(itemsToFetch);
_logger.d(
'SyncService: ${filteredFetchedItems.length} items remain after LWW',
);
// 5. Update local repository
_logger.d('SyncService: Updating local repository...');
await localRepository.addOrUpdate(filteredFetchedItems, fromCloud: true);
_logger.d('SyncService: Local repository updated.');
// 6. Download missing files (NEW - Add this step)
_logger.d('SyncService: Downloading missing files...');
await _downloadMissingFiles();
_logger.d('SyncService: Missing files downloaded successfully.');
// 7. Get unsynced items after conflict resolution
_logger.d('SyncService: Getting unsynced items...');
final itemsToPush = await localRepository.getUnsyncedItems();
_logger.d('SyncService: Found ${itemsToPush.length} unsynced items.');
// 8. Push to remote
if (itemsToPush.isNotEmpty) {
_logger.d('SyncService: Pushing unsynced items to remote...');
await remoteRepository.pushUnsyncedItems(itemsToPush);
_logger.d('SyncService: Unsynced items pushed successfully.');
} else {
_logger.d('SyncService: No unsynced items to push.');
}
// 9. Manually mark pushed items as synced (without triggering updatedAt)
for (final item in itemsToPush) {
final updatedItem = item.copyWith(
serverTimeSyncedAt: serverTime,
localTimeSyncedAt: DateTime.now(),
) as T;
_logger.d('SyncService: Marking item ${item.id} as synced...');
await localRepository.update(updatedItem);
_logger.d('SyncService: Item ${item.id} marked as synced.');
}
_logger.d('SyncService: Sync process completed.');
} catch (e) {
_logger.e('SyncService: Error during sync: $e');
rethrow;
} finally {
_isSyncing = false; // Reset the flag after sync is done
}
}