-
[OPIK-5659] [BE] fix: delete experiment aggregates when an experiment is deleted (#6428)
发布于
2026-04-22 13:33:05 +00:00 - [OPIK-5659] [BE] fix: delete experiment aggregates when an experiment is deleted
Wire ExperimentAggregateEventListener to ExperimentsDeleted so rows in
experiment_aggregates and experiment_item_aggregates are removed when an
experiment is deleted. Previously the denormalized aggregate rows were
orphaned forever, causing unbounded growth and stale reads via the FINAL
scans used by the hybrid query path.- ExperimentsDeleted now carries the deleted experiment ids; ExperimentService.delete forwards them to the event.
- ExperimentAggregatesDAO.deleteByExperimentIds issues workspace-scoped DELETE FROM against experiment_aggregates (by id) and experiment_item_aggregates (by experiment_id).
- ExperimentAggregatesService exposes the DAO call with logging.
- ExperimentAggregateEventListener.onExperimentsDeleted restores the workspace context from the event and calls the service.
- New integration tests verify direct deletion and end-to-end cleanup via the async event bus.
Implements OPIK-5659: fix experiment aggregation query overload.
- fix(aggregation): clean up item aggregates on experiment item deletion
Wire ExperimentItemsDeleted to also remove orphan rows from
experiment_item_aggregates for each deleted item. Previously the
listener only re-triggered aggregation, leaving stale per-item
aggregate rows that the has_aggregated query branch kept returning.- New ExperimentItemRef(experimentId, itemId) record preserves the
per-item -> experiment association. - ExperimentItemsDeleted now carries Set with
derived experimentIds()/itemIds() accessors. - ExperimentItemService.delete selects refs, buffers them in chunks
of 1000, groups each chunk by experimentId, and for each group
deletes items + publishes the event so listeners receive refs
scoped to a single experiment. - ExperimentItemDAO.delete now scoped by experiment_id and :ids.
- ExperimentAggregatesDAO/Service add deleteItemAggregatesByItemIds
for per-experiment item-aggregate cleanup. - Listener groups event.itemRefs() by experiment, deletes item
aggregates for each, then re-triggers aggregation via the
existing path. - Integration test deleteExperimentItemsCleansUpItemAggregatesViaEvent
covers the partial-delete flow by comparing the aggregated query
against beforeAggregation minus the deleted ids.
- style: remove trailing whitespace (spotless)
下载附件