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 {
  await dbRdy;
  final eventBox = _objectBox.store.box<DbNip01Event>();
  final rawEvents = eventBox.getAll().map((event) => event.toNdk()).toList();
  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.plan(
    rawEvents: rawEvents,
    lockedEventIds: lockedEventIds,
    deliveredEventIds: deliveredEventIds,
    policy: policy,
  );

  // 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 (plan.eventIdsToRemove.isEmpty &&
      deliverySweep.deliveryEventIdsToRemove.isEmpty) {
    return plan.toResult();
  }

  if (plan.eventIdsToRemove.isNotEmpty) {
    final query = eventBox
        .query(DbNip01Event_.nostrId.oneOf(plan.eventIdsToRemove.toList()))
        .build();
    final results = query.find();
    query.close();
    eventBox.removeMany(results.map((event) => event.dbId).toList());
    _removeEventSidecarsByIds(plan.eventIdsToRemove);
  }

  if (deliverySweep.deliveryEventIdsToRemove.isNotEmpty) {
    _removeDeliveryRecordsByIds(deliverySweep.deliveryEventIdsToRemove);
  }

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