manageSyncQueueForSave method
Manages sync queue entries for save operations.
This method handles the complex logic of:
- Checking for existing sync queue entries
- Updating or creating entries as needed
- Managing operation precedence (CREATE vs UPDATE)
- Triggering immediate sync execution
item The model instance to sync.
operation The type of sync operation to manage (create, update).
idempotencyKey A unique key to ensure idempotent task execution.
headers Optional headers to include in the API request.
extra Optional extra data to include in the API request.
Returns the sync queue entry ID for tracking purposes.
Implementation
Future<int> manageSyncQueueForSave(
T item,
SyncOperation operation,
String idempotencyKey,
Map<String, String>? headers,
Map<String, dynamic>? extra,
) async {
final syncQueueDao = SyncQueueDao(SynquillStorage.database);
int syncQueueId;
// First check if there's already a pending CREATE task for this model
// If so, update it with new payload regardless of current operation
final existingCreateTaskId = await syncQueueDao.findPendingSyncTask(
T.toString(),
item.id,
SyncOperation.create.name,
);
if (existingCreateTaskId != null) {
// Update existing CREATE task with new payload
await syncQueueDao.updateItem(
id: existingCreateTaskId,
payload: convert.jsonEncode(item.toJson()),
idempotencyKey: idempotencyKey, // Update idempotency key too
attemptCount: 0, // Reset attempt count for the new payload
clearNextRetryAt: true, // Allow immediate retry
lastError: null, // Clear any previous errors
headers: headers != null ? convert.jsonEncode(headers) : null,
extra: extra != null ? convert.jsonEncode(extra) : null,
);
syncQueueId = existingCreateTaskId;
log.fine(
'Updated existing CREATE sync queue entry $syncQueueId for '
'${item.id} with new data',
);
// Keep it as CREATE operation for the sync task
operation = SyncOperation.create;
} else if (operation == SyncOperation.update) {
// No pending CREATE, check for existing UPDATE task
final existingUpdateTaskId = await syncQueueDao.findPendingSyncTask(
T.toString(),
item.id,
operation.name,
);
if (existingUpdateTaskId != null) {
// Update existing UPDATE task with new payload
await syncQueueDao.updateItem(
id: existingUpdateTaskId,
payload: convert.jsonEncode(item.toJson()),
idempotencyKey: idempotencyKey, // Update idempotency key too
attemptCount: 0, // Reset attempt count for the new payload
clearNextRetryAt: true, // Allow immediate retry
lastError: null, // Clear any previous errors
headers: headers != null ? convert.jsonEncode(headers) : null,
extra: extra != null ? convert.jsonEncode(extra) : null,
);
syncQueueId = existingUpdateTaskId;
log.fine(
'Updated existing UPDATE sync queue entry $syncQueueId for '
'${item.id} with new data',
);
} else {
// No existing UPDATE task, create a new one
syncQueueId = await syncQueueDao.insertItem(
modelId: item.id,
modelType: T.toString(),
payload: convert.jsonEncode(item.toJson()),
operation: operation.name,
idempotencyKey: idempotencyKey,
headers: headers != null ? convert.jsonEncode(headers) : null,
extra: extra != null ? convert.jsonEncode(extra) : null,
);
log.fine('Created sync queue entry $syncQueueId for ${item.id}');
}
} else {
// For CREATE operations, always create a new entry
syncQueueId = await syncQueueDao.insertItem(
modelId: item.id,
modelType: T.toString(),
payload: convert.jsonEncode(item.toJson()),
operation: operation.name,
idempotencyKey: idempotencyKey,
headers: headers != null ? convert.jsonEncode(headers) : null,
extra: extra != null ? convert.jsonEncode(extra) : null,
);
log.fine('Created sync queue entry $syncQueueId for ${item.id}');
}
return syncQueueId;
}