0

How would one utilize poison pill to stop message handlers (and message suppliers) with spring-integration?

I have a setup of N producers (subclassed Supplier) and M consumers (subclasses GenericHandler). They are connected via unbounded queue.

Producers should send K messages each, then send poison pill (I think each producer should send M/N poison pills, that is).

I would like then, to stop producers altogether (they are controlled by TaskExecutor)

@Bean(name = "supplierExecutor")
Executor supplierExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

    executor.setCorePoolSize(x);
    executor.setMaxPoolSize(y);
    executor.setKeepAliveSeconds(0);
    executor.setQueueCapacity(z);
    executor.setThreadNamePrefix("supplier-");

    executor.initialize();

    return executor;
}

Also, I would like to stop consumers altogether, but gracefully. (They are controlled by their own TaskScheduler)

@Bean(name = "consumerScheduler")
TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();

    taskScheduler.setPoolSize(a);
    taskScheduler.setThreadNamePrefix("temp-consumer");
    taskScheduler.initialize();
    taskScheduler.setWaitForTasksToCompleteOnShutdown(true);

    return taskScheduler;
}

Right now, in my supplier get() method, I have the following snippet

public Foo get() {
    if (reachedMaxSendLimit()) {
        incrementMsgSentCount();
        return POISON_PILL;
    } else if (surpassedMaxSentLimit()) {
        return null;
    } else {
        return handlePayload(payload);
    }
}

Is there a well-defined way to achieve the behaviour I'm trying to accomplish? I am aware how I'd do it without spring with regular Runnables, but I'm a bit clueless here.

ioreskovic
  • 5,531
  • 5
  • 39
  • 70
  • Why not put your logic in the queue between producers and consumers? If your queue has seen N ProducerFinished messages, it puts M EndOfQueue messages at the end of the queue – Paul Janssens Mar 21 '18 at 13:15
  • @PaulJanssens I'm afraid I'm not sure how I should put that logic in spring's message channel. Could you elaborate, please? – ioreskovic Mar 21 '18 at 13:19

1 Answers1

0

I don't know what is poison pill and it's not clear to me what you are talking about here, but if the story is about stop, then you definitely should consider existing org.springframework.context.Lifecycle control in Spring. In this case all the Spring Integration endpoints are of that type and you simply can use their stop().

For the management purposes Spring Integration provides Control Bus component. For that you can send a command message with the stop() expression to really stop particular endpoint.

Note: it's good practice to stop producers before consumers. This way you won't lose messages for which there is no already consumers to process.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • "Poison pill" is a pattern (I guess you could call it that), which describes a situation where a producer tells a consumer there are no more messages to process from now on. – ioreskovic Mar 21 '18 at 14:22
  • Hm. Doesn't sound for me as reasonable behavior. If there is no more messages, the consumer is just in idle state: nothing to consumer - nothing to do! What am I missing? Maybe there is more information somehwere on the matter and we would introduce such a pattern into the Spring Integration per se ? – Artem Bilan Mar 21 '18 at 14:27
  • Here it is: http://web.mit.edu/6.005/www/fa15/classes/22-queues/ just scroll down to poison pill – ioreskovic Mar 21 '18 at 14:51
  • Cool! Would really mind to raise a JIRA in Spring Integration for future consideration? Meanwhile I suggest you to take a look into the `ChannelInterceptor.postReceive()` implementation which is going go be called before handler. There you can check a received message for the `poison pill` symptoms and stop the consumer endpoint. Although I'm not sure how should that look when we have several producers and when one of them has sent `poison pill`, that doesn't mean that all others are exhausted as well... – Artem Bilan Mar 21 '18 at 15:02
  • Well, that was, I guess, a part of my question :D – ioreskovic Mar 21 '18 at 15:16