manageSyncQueueForSave method

Future<int> manageSyncQueueForSave(
  1. T item,
  2. SyncOperation operation,
  3. String idempotencyKey,
  4. Map<String, String>? headers,
  5. Map<String, dynamic>? extra,
)

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;
}