Опрос бизнес-процессов Hybris

#hybris

Вопрос:

Мне нужно создать действие в своем пользовательском бизнес-процессе, которое должно выполняться каждые 10 минут до тех пор, пока не будет возвращено определенное действие. Есть ли способ настроить интервал опроса действия в бизнес-процессе hybris order? Я знаю, что вы можете настроить тайм-аут, но не интервал опроса:

 <wait id='waitForOrderConfirmation' then='checkOrder' prependProcessCode='true'>
<event>confirm</event>
<timeout delay='PT12H' then='asmCancelOrder'/>
 

Комментарии:

1. вы могли бы завершить это действие в состоянии ожидания и создать cronjob, который запускается каждые 10 минут для проверки/перезапуска процесса на определенном шаге

Ответ №1:

Для этого нужна пользовательская реализация, и необходимо использовать модель BusinessProcessParameterModel.

Ниже приведены шаги, чтобы повторить попытку на основе Dealy.

Создайте повторяющееся действие.

 import de.hybris.platform.processengine.model.BusinessProcessModel;
import de.hybris.platform.processengine.model.BusinessProcessParameterModel;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.warehousing.process.BusinessProcessException;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;


public interface RepeatableAction<T extends BusinessProcessModel>
{
    int COUNTER_STARTER = 1;

    ModelService getModelService();

    Optional<Integer> extractThreshold(T process);

    String getParamName();

    default void increaseRetriesCounter(final T process)
    {
        final Collection<BusinessProcessParameterModel> contextParameters = process.getContextParameters();

        final Optional<BusinessProcessParameterModel> paramOptional = extractCounter(contextParameters);

        paramOptional.ifPresent(this::incrementParameter);

        if (!paramOptional.isPresent())
        {
            final Collection<BusinessProcessParameterModel> newContextParameters = new ArrayList<>(contextParameters);

            final BusinessProcessParameterModel counter = getModelService().create(BusinessProcessParameterModel.class);
            counter.setName(getParamName());
            counter.setValue(COUNTER_STARTER);
            counter.setProcess(process);

            newContextParameters.add(counter);

            process.setContextParameters(newContextParameters);
            getModelService().save(process);
        }
    }

    default Optional<BusinessProcessParameterModel> extractCounter(
            final Collection<BusinessProcessParameterModel> contextParameters)
    {
        //@formatter:off
        return contextParameters.stream().filter(p -> getParamName().equals(p.getName())).findFirst();
        //@formatter:on
    }

    default void incrementParameter(final BusinessProcessParameterModel parameter)
    {
        final Object value = parameter.getValue();
        if (value instanceof Integer)
        {
            parameter.setValue((Integer) value   1);

            getModelService().save(parameter);
        }
        else
        {
            //@formatter:off
            final String message = MessageFormat.format("Wrong process parameter '{}' type. {} expected, {} actual.", getParamName(),
                    Integer.class.getSimpleName(), value.getClass().getSimpleName());
            //@formatter:on

            throw new BusinessProcessException(message);
        }
    }

    default boolean retriesCountThresholdExceeded(final T process)
    {
        //@formatter:off
        final Optional<Integer> counterOptional = extractCounter(process.getContextParameters())
                .map(BusinessProcessParameterModel::getValue).filter(Integer.class::isInstance).map(Integer.class::cast);
        //@formatter:on

        final Optional<Integer> thresholdOptional = extractThreshold(process);

        final boolean counterSet = counterOptional.isPresent();
        final boolean thresholdSet = thresholdOptional.isPresent();

        boolean thresholdExceeded = false;

        if (counterSet amp;amp; thresholdSet)
        {
            final int counter = counterOptional.get();
            final int threshold = thresholdOptional.get();
            thresholdExceeded = counter > threshold;
        }

        return counterSet amp;amp; thresholdSet amp;amp; thresholdExceeded;
    }
}
 

Затем перейдите к Пользовательскому действию и Реализуйте этот интерфейс, и на основе некоторого условия сделайте пользовательский переход как ПОВТОРНУЮ попытку, что-то вроде этого.

 public class CustomAction extends AbstractAction<OrderProcessModel>
        implements RepeatableAction<OrderProcessModel>
        {
        
        private static final int MAX_RETRIES = 3;//make it configurable it's your choice
        @Override
    public Transition prepare(OrderModel order, OrderProcessModel process)
    {
        if (!retriesCountThresholdExceeded(process))
        {
            if (custom condition)
            {
                return Transition.OK;
            }
            getModelService().refresh(order);
            increaseRetriesCounter(process);
            return Transition.RETRY;
        }
        return Transition.NOK;
    }
        
        }
        
        @Override
    public Optional<Integer> extractThreshold(OrderProcessModel process)
    {
        return Optional.of(MAX_RETRIES);
    }
 

Затем в process.xml Записи действий должны быть такими.

 <action id="customAction" bean="customAction">
        <transition name="OK" to="nextStep"/>
        <transition name="RETRY" to="waitForOrderConfirmation"/>
        <transition name="NOK" to="cancelOrderAction"/>
    </action>

<wait id='waitForOrderConfirmation' then='checkOrder' prependProcessCode='true'>
<event>confirm</event>
<timeout delay='PT12H' then='asmCancelOrder'/>
<wait>
 

ПРИМЕЧАНИЕ: Пожалуйста, установите dealy в соответствии с требованиями, начиная с новых 12 часов, кажется, слишком много