getNextCrudTransaction method

Future<CrudTransaction?> getNextCrudTransaction()

Get the next recorded transaction to upload.

Returns null if there is no data to upload.

Use this from the PowerSyncBackendConnector.uploadData` callback.

Once the data have been successfully uploaded, call CrudTransaction.complete before requesting the next transaction.

Unlike getCrudBatch, this only returns data from a single transaction at a time. All data for the transaction is loaded into memory.

Implementation

Future<CrudTransaction?> getNextCrudTransaction() async {
  return await readTransaction((tx) async {
    final first = await tx.getOptional(
        'SELECT id, tx_id, data FROM ps_crud ORDER BY id ASC LIMIT 1');
    if (first == null) {
      return null;
    }
    final int? txId = first['tx_id'];
    List<CrudEntry> all;
    if (txId == null) {
      all = [CrudEntry.fromRow(first)];
    } else {
      final rows = await tx.getAll(
          'SELECT id, tx_id, data FROM ps_crud WHERE tx_id = ? ORDER BY id ASC',
          [txId]);
      all = [for (var row in rows) CrudEntry.fromRow(row)];
    }

    final last = all[all.length - 1];

    return CrudTransaction(
        transactionId: txId,
        crud: all,
        complete: ({String? writeCheckpoint}) async {
          await writeTransaction((db) async {
            await db.execute(
                'DELETE FROM ps_crud WHERE id <= ?', [last.clientId]);
            if (writeCheckpoint != null &&
                await db.getOptional('SELECT 1 FROM ps_crud LIMIT 1') ==
                    null) {
              await db.execute(
                  'UPDATE ps_buckets SET target_op = $writeCheckpoint WHERE name=\'\$local\'');
            } else {
              await db.execute(
                  'UPDATE ps_buckets SET target_op = $maxOpId WHERE name=\'\$local\'');
            }
          });
        });
  });
}