changesSince method

  1. @override
CacheDelta changesSince(
  1. int version
)
override

The entities changed or removed since version (an earlier value of Cache.version), as JSON copies of those entities only (for the operation roots: of the fields that changed, see CacheDelta.changedFields). Store it, then ask again from CacheDelta.version.

Implementation

@override
CacheDelta changesSince(int version) {
  if (version < _fullSince) {
    return CacheDelta(
      version: _version,
      changed: {
        for (final e in _entities.entries) e.key: _entityJson(e.value),
      },
      removed: {},
      full: true,
    );
  }
  final changed = <String, Map<String, Object?>>{};
  Map<String, Map<String, Object?>>? changedFields;
  Map<String, Set<String>>? removedFields;
  for (final e in _changedAt.entries) {
    if (e.value <= version) continue;
    final key = e.key;
    final entity = _entities[key]!;
    final stamps = _fieldChangedAt[key];
    if (!isRootKey(key) || version < (_fieldsSince[key] ?? 0)) {
      changed[key] = _entityJson(entity);
      continue;
    }
    // A root, field by field: the fields stamped since [version].
    final fields = <String, Object?>{};
    Set<String>? gone;
    if (stamps != null) {
      for (final s in stamps.entries) {
        if (s.value <= version) continue;
        if (entity.containsKey(s.key)) {
          fields[s.key] = _toJson(entity[s.key]);
        } else {
          (gone ??= {}).add(s.key);
        }
      }
    }
    // An empty entry for a root created empty, so it exists in the copy.
    if (fields.isNotEmpty || gone == null) {
      (changedFields ??= {})[key] = fields;
    }
    if (gone != null) (removedFields ??= {})[key] = gone;
  }
  return CacheDelta(
    version: _version,
    changed: changed,
    removed: {
      for (final e in _removedAt.entries)
        if (e.value > version) e.key,
    },
    changedFields: changedFields ?? const {},
    removedFields: removedFields ?? const {},
  );
}