fetchSince method

  1. @override
Future<Delta<T, Id>> fetchSince(
  1. SyncScope scope,
  2. DateTime? since
)
override

Implementation

@override
Future<Delta<T, Id>> fetchSince(SyncScope scope, DateTime? since) async {
  var upsertQuery = _table()
      .select()
      .eq(config.scopeNameColumn, scope.name)
      .contains(config.scopeKeysColumn, scope.keys);
  if (since != null) {
    upsertQuery = upsertQuery.gt(
      config.updatedAtColumn,
      since.toUtc().toIso8601String(),
    );
  }
  if (config.deletedAtColumn != null) {
    // `is` operator to check for NULL
    upsertQuery = upsertQuery.filter(config.deletedAtColumn!, 'is', null);
  }
  final upsertsRaw = await upsertQuery;
  final upserts = (upsertsRaw as List)
      .map((e) => config.fromJson(Map<String, dynamic>.from(e)))
      .toList(growable: false);

  // Deletes: updated_at > since and soft-deleted (if supported). For hard delete, server must provide tombstones.
  List<Id> deletes = const [];
  if (config.deletedAtColumn != null) {
    var delQ = _table()
        .select(config.idColumn)
        .eq(config.scopeNameColumn, scope.name)
        .contains(config.scopeKeysColumn, scope.keys);
    if (since != null) {
      delQ = delQ.gt(config.updatedAtColumn, since.toUtc().toIso8601String());
    }
    delQ = delQ.not(config.deletedAtColumn!, 'is', null);
    final delsRaw = await delQ;
    deletes = (delsRaw as List)
        .map((e) => config.idFromString('${(e as Map)[config.idColumn]}'))
        .toList(growable: false);
  }

  final serverTs = await getServerTime();
  return Delta<T, Id>(
    upserts: upserts,
    deletes: deletes,
    serverTimestamp: serverTs,
  );
}