evict method

  1. @override
Future<EvictionResult> evict(
  1. EvictionPolicy policy
)
override

Run one eviction pass according to policy.

Backends should remove associated sidecars, provenance, and delivery state for any event they physically delete.

Implementation

@override
Future<EvictionResult> evict(EvictionPolicy policy) async {
  final rawEvents = await _loadEventsInternal(applyVisibilityRules: false);
  final stateRecords = await _loadEventCacheStateRecords();
  final deliveryRecords = await loadEventDeliveryRecords();
  final relayTargets = await loadRelayDeliveryTargets();
  final activeDeliveryEventIds = deliveryRecords
      .where((record) => record.status != EventDeliveryStatus.delivered)
      .map((record) => record.eventId)
      .toSet();
  final lockedEventIds = <String>{
    ...activeDeliveryEventIds,
    ...relayTargets
        .where((target) => target.state != RelayDeliveryState.acked)
        .map((target) => target.eventId),
  };
  final deliveredEventIds = deliveryRecords
      .where((record) => record.status == EventDeliveryStatus.delivered)
      .map((record) => record.eventId)
      .toSet();
  final plan = EventEvictionPlanner.planFromStateRecords(
    stateRecords: stateRecords,
    lockedEventIds: lockedEventIds,
    deliveredEventIds: deliveredEventIds,
    policy: policy,
  );

  if (plan.eventIdsToRemove.isNotEmpty) {
    final removedEvents = rawEvents
        .where((event) => plan.eventIdsToRemove.contains(event.id))
        .toList();
    await _eventsStore
        .records(plan.eventIdsToRemove.toList())
        .delete(_database);
    await _removeEventSidecarsByIds(plan.eventIdsToRemove);
    await _refreshDerivedStateForPubKeys(
      removedEvents.map((event) => event.pubKey).toSet(),
    );
  }

  // Sweep leftover delivery records whose event was kept (or never stored).
  // A terminally failed record swept here unpins its event for the next run.
  final remainingDeliveryRecords = deliveryRecords
      .where((record) => !plan.eventIdsToRemove.contains(record.eventId))
      .toList();
  final deliverySweep = EventEvictionPlanner.planDeliverySweep(
    deliveryRecords: remainingDeliveryRecords,
    policy: policy,
  );
  if (deliverySweep.deliveryEventIdsToRemove.isNotEmpty) {
    final ids = deliverySweep.deliveryEventIdsToRemove.toList();
    await _eventDeliveryStore.records(ids).delete(_database);
    await _relayDeliveryTargetStore.delete(
      _database,
      finder: sembast.Finder(filter: sembast.Filter.inList('eventId', ids)),
    );
  }

  return plan.toResult().copyWith(
    removedCompletedDeliveries: deliverySweep.removedCompletedDeliveries,
    removedTerminalFailedDeliveries:
        deliverySweep.removedTerminalFailedDeliveries,
  );
}