@Override
    public Set<String> physicalDeleteOldProcessorFilters(final Instant deleteThreshold) {
        final List<PipeFilterKeys> result =
                JooqUtil.contextResult(processorDbConnProvider, context -> context
                        .select(PROCESSOR_FILTER.ID,
                                PROCESSOR_FILTER.UUID,
                                PROCESSOR_FILTER.FK_PROCESSOR_FILTER_TRACKER_ID)
                        .from(PROCESSOR_FILTER)
                        .where(PROCESSOR_FILTER.DELETED.eq(true))
                        .and(PROCESSOR_FILTER.UPDATE_TIME_MS.lessThan(deleteThreshold.toEpochMilli()))
                        .fetch()
                        .map(rec -> new PipeFilterKeys(
                                rec.get(PROCESSOR_FILTER.ID),
                                rec.get(PROCESSOR_FILTER.UUID),
                                rec.get(PROCESSOR_FILTER_TRACKER.ID))));

        LAMBDA_LOGGER.debug(() ->
                LogUtil.message("Found {} logically deleted filters with an update time older than {}",
                        result.size(), deleteThreshold));

        final Set<String> processorFilterUuids = new HashSet<>();
        // Delete one by one as we expect some constraint errors.
        result.forEach(dbKeys -> {
            try {
                final int count = JooqUtil.transactionResult(processorDbConnProvider, context -> {
                    final int filterCount = context
                            .deleteFrom(PROCESSOR_FILTER)
                            .where(PROCESSOR_FILTER.ID.eq(dbKeys.processorFilterId))
                            .execute();
                    LOGGER.debug("Physically deleted {} processor filters with id {}",
                            filterCount,
                            dbKeys.processorFilterId);

                    final int trackerCount = context
                            .deleteFrom(PROCESSOR_FILTER_TRACKER)
                            .where(PROCESSOR_FILTER_TRACKER.ID.eq(dbKeys.processorFilterTrackerId))
                            .execute();
                    LOGGER.debug("Physically deleted {} processor filter trackers with id {}",
                            trackerCount, dbKeys.processorFilterTrackerId);

                    return filterCount;
                });

                if (count > 0) {
                    // Make a note of the uuid, so we can delete any doc perms associated with it
                    // The tracker is 1:1 with filter, so don't need to return tracker delete count
                    processorFilterUuids.add(dbKeys.processorFilterUuid);
                }
            } catch (final DataAccessException e) {
                if (e.getCause() instanceof final SQLIntegrityConstraintViolationException sqlEx) {
                    LOGGER.debug("Expected constraint violation exception: " + sqlEx.getMessage(), e);
                } else {
                    throw e;
                }
            }
        });
        LAMBDA_LOGGER.debug(() -> "physicalDeleteOldProcessorFilters returning: "
                                  + processorFilterUuids.size() + " UUIDs");
        return processorFilterUuids;
    }
Physically delete old processor filters that are logically deleted with an update time older than the threshold.

@param deleteThreshold Only physically delete filters with an update time older than the threshold.
@return The processor filter UUIDs of all the processor filters deleted.
stroom-processor/stroom-processor-impl-db/src/main/java/stroom/processor/impl/db/ProcessorFilterDaoImpl.java