transaction<R> method

  1. @override
Future<R> transaction<R>(
  1. Future<R> body(
    1. KeyStoreTxn<String, AtData, dynamic> txn
    )
)
override

Run body as a transaction. Mutations performed via the supplied handle are buffered in memory and applied in body order on successful completion; if the body throws, the buffer is dropped and the exception propagates.

Hive impls provide best-effort atomicity; a future SQL impl will provide true atomicity.

Implementation

@override
Future<R> transaction<R>(
    Future<R> Function(KeyStoreTxn<String, AtData, dynamic> txn) body) async {
  final txn = _SqliteKeyStoreTxn(this);
  final result = await body(txn);
  // Apply buffered ops atomically, in body order.
  final fired = <KeyStoreChange>[];
  _db.runInTransaction(() {
    for (final op in txn._ops) {
      if (op.isRemove) {
        if (_existsSync(op.key)) {
          _db.raw.execute('DELETE FROM at_data WHERE atkey = ?;', [op.key]);
          _commitOrNull(op.key, CommitOp.DELETE);
          fired.add(KeyRemoved(op.key));
        }
      } else {
        final existed = _existsSync(op.key);
        final toStore = AtData()
          ..data = op.value!.data
          ..metaData = AtMetadataBuilder(
            atSign: atSign,
            newAtMetaData: op.metadata,
            existingMetaData: existed ? _getSync(op.key)?.metaData : null,
          ).build();
        _upsertAtData(op.key, toStore);
        _commitOrNull(op.key, CommitOp.UPDATE_ALL);
        fired.add(existed ? KeyUpdated(op.key) : KeyAdded(op.key));
      }
    }
  });
  for (final change in fired) {
    _changes.add(change);
  }
  return result;
}