Boundary timer events on service tasks

В документации по Flowable указано:

When an execution arrives at the activity where the boundary event is attached, a timer is started.

Но если boundary timer event прикручивается к любому Activity кроме UserTask, то он срабатывает только ПОСЛЕ того как Activity завершает свою работу, что не позволяет реализовать функционал прерывания “зависших” task’ов.
image
Как, например сделать так, чтобы в данной ситуации сработал таймер?

Аналогичная ситуация и в случае параллельной обработки:
таймер даже не попадает в стек обработки пока не завершится Activity
image

Есть ли решение, как обходить такую ситуацию и сделать возможным прерывание зависших или сильно долго работающих Activity?

Добрый день.

Разработчики flowable говорят:

Boundary events on automatic service tasks won’t work - they only work on wait states.
Once a service task is started, it cannot be stopped - checking continuously for boundary events firing would be bad for performance.

В то же время Error boundary event на сервис тасках вроде бы работают. Т.е. можно попробовать следующий подход - контроль над тем, не превышен ли таймаут реализовать внутри сервис таски:

@Component
public class MyBpmService {

    private static final Logger log = LoggerFactory.getLogger(MyBpmService.class);

    public void testMethod() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Callable<String> task = this::longRunningMethod;
        Future<String> future = executorService.submit(task);
        try {
            future.get(10, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            log.info("longRunningMethod execution interrupted by timeout");
            throw new BpmnError("longTaskError", e.getMessage());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } finally {
            future.cancel(true);
        }
        log.info("longRunningMethod execution completed");
    }

    private String longRunningMethod() {
        try {
            log.info("longRunningMethod execution started");
            TimeUnit.SECONDS.sleep(30);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return "result";
    }
}

Если таймаут превышен, то сервис-таска будет кидать специальный эксепшн BpmnError.

throw new BpmnError("longTaskError", e.getMessage());

По этому эксепшну будет сработывать error boundary event.

image

Вот сэмпл-проект, в котором этот подход реализован:
bpmn-error.zip (120.2 КБ)