gc method

  1. @override
Set<String> gc({
  1. Iterable<String> retain = const [],
})
override

Removes entities not reachable from any operation root nor from one of the retained entity keys (extra roots: SlingClient.gc passes the entities live scopes read). Returns the removed keys. No scope reads a removed entity, so the client rebuilds nothing; onChange still reports the removed entities' fields (a persistence layer drops them).

Implementation

@override
Set<String> gc({Iterable<String> retain = const []}) {
  final live = <String>{};
  void mark(Object? node) {
    if (node is Ref) {
      if (live.add(node.key)) mark(_entities[node.key]);
    } else if (node is Map) {
      node.values.forEach(mark);
    } else if (node is List) {
      node.forEach(mark);
    }
  }

  for (final key in [..._entities.keys.where(isRootKey), ...retain]) {
    final entity = _entities[key];
    if (entity != null && live.add(key)) mark(entity);
  }
  final dead = _entities.keys.where((k) => !live.contains(k)).toSet();
  final touched = <String>{};
  for (final key in dead) {
    final removed = _entities.remove(key)!;
    _depKeys.remove(key);
    // No live reader: the list keys are not reported (see [Cache.gc]).
    _listDepKeys.remove(key);
    _markRemoved(key);
    for (final field in removed.keys) {
      final dep = depKey(key, field);
      _fetchedAt.remove(dep);
      touched.add(dep);
    }
  }
  _emit(touched);
  return dead;
}