disruptor icon indicating copy to clipboard operation
disruptor copied to clipboard

Sequence barrier design questions

Open ocoanet opened this issue 2 years ago • 0 comments

I have a few questions related to sequence barriers which I decided to group in a single issue. I can split them in multiple issues if needed.

1. Why is the sequence barrier alerted when the exception handler is configured?

ExceptionHandlerSetting is invoking SequenceBarrier.alert() when the exception handler is configured:

    public void with(final ExceptionHandler<? super T> exceptionHandler)
    {
        final EventProcessor eventProcessor = consumerRepository.getEventProcessorFor(eventHandler);
        if (eventProcessor instanceof BatchEventProcessor)
        {
            ((BatchEventProcessor<T>) eventProcessor).setExceptionHandler(exceptionHandler);
            consumerRepository.getBarrierFor(eventHandler).alert();
        }

If see two possible states when this code is run:

  • Either the disruptor is not started and alerting the sequence barrier is useless because the sequence barrier is cleared on start by the event processor.
  • Or the disruptor is started, and alerting the sequence barrier will stop the event processors. Worse, the event processors will not be properly stopped, they will enter an infinite loop where AlertException is thrown and caught.

I wrote a small test to show that it is not possible to configure the exception handler after start:

    @Test
    public void shouldBeAbleToOverrideTheExceptionHandlerForAEventProcessorAfterStart()
            throws Exception
    {
        CountDownLatch onStartCountDown = new CountDownLatch(1);

        EventHandler<TestEvent> eventHandler = new EventHandler<TestEvent>()
        {
            @Override
            public void onStart()
            {
                onStartCountDown.countDown();
            }

            @Override
            public void onEvent(final TestEvent event, final long sequence, final boolean endOfBatch) throws Exception
            {
                throw new Exception();
            }
        };
        disruptor.handleEventsWith(eventHandler);
        disruptor.start();

        onStartCountDown.await();

        AtomicReference<Throwable> reference = new AtomicReference<>();
        StubExceptionHandler exceptionHandler = new StubExceptionHandler(reference);
        disruptor.handleExceptionsFor(eventHandler).with(exceptionHandler);
        disruptor.publishEvent((event, sequence) -> { });

        waitFor(reference);
    }

2. Is there an important design reason to share the sequence barriers with multiple event processors?

The event processors that share the same gating sequences are created with the same sequence barrier instance. This is clearly sensible, but because the sequence barriers are stateless, it would also be possible to create unique sequence barriers for each event processor. Is there a design reason other than convenience to share the sequence barriers?

3. Why are the sequence barrier exposed in the disruptor API?

Sequence barriers are exposed in the public API with Disruptor.getBarrierFor. This method is never used in tests or examples, so I wonder if it is really useful. Also, exposing alert() or clearAlert() seems quite dangerous (see question 1) because these methods are not supposed to be used. I see some value in exposing the sequences of the event processors (Disruptor.getSequenceValueFor), for example for disruptor state monitoring, but I do not understand the expected usage of Disruptor.getBarrierFor.

ocoanet avatar Mar 12 '22 15:03 ocoanet