class ProcessorEventPublisher {

    public void mergeSegment(String context, List<String> clientIds, String processorName) {
        Map<ClientSegmentPair, SegmentStatus> clientToTracker =
                buildClientToTrackerMap(clientIds, processorName, REVERSE_ORDER);

        SegmentStatus smallestSegment =
                clientToTracker.values().stream()
                               .max(Comparator.comparingInt(SegmentStatus::getOnePartOf))
                               .orElseThrow(() -> new IllegalArgumentException(
                                       "No segments found for processor name [" + processorName + "]"
                               ));

        int segmentToMerge = deduceSegmentToMerge(smallestSegment);
        Optional<String> clientIdOwningSegmentToMerge = getClientIdForSegment(clientToTracker, segmentToMerge);

        clientIdOwningSegmentToMerge.ifPresent(
                clientId -> {
                    clientIds.stream()
                               .filter(client -> !client.equals(clientId))
                               .forEach(client -> releaseSegment(context, client, processorName, smallestSegment.getSegmentId()));

                }
        );

        if (clientIdOwningSegmentToMerge.isPresent()) {
            applicationEventPublisher.publishEvent(new MergeSegmentRequest(
                    NOT_PROXIED, context, clientIdOwningSegmentToMerge.get(), processorName, segmentToMerge
            ));
        } else {
            // the segment to merge with is unclaimed. We need to merge the known part
            String clientOwningSmallestSegment = getClientIdForSegment(clientToTracker, smallestSegment.getSegmentId())
                    .orElseThrow(() -> new IllegalArgumentException(
                            "Attempt to merge segments [" + segmentToMerge + "] and [" + smallestSegment.getSegmentId()
                                    + "] failed")
                    );

            applicationEventPublisher.publishEvent(new MergeSegmentRequest(
                    NOT_PROXIED, context, clientOwningSmallestSegment, processorName, smallestSegment.getSegmentId()
            ));
        }
    }

    public  ProcessorEventPublisher(PlatformService platformService,
                                   ApplicationEventPublisher applicationEventPublisher,
                                   ClientProcessors clientProcessors);

}