如何使规则只触发一次?

时间:2018-07-23 09:38:30

标签: drools rules rule-engine kie

假定以下规则侦听具有特定标识符的事件。每个标识符只能处理一个事件。

rule "SampleRule"
dialect "mvel"
no-loop true
when
    Event( $identifier : identifier)
    not(EventHandler( identifier == $identifier )) 
then
    EventHandler $h = new EventHandler();
    $h.setIdentifier( $identifier );
    insert( $h );
end

事件类:

...

@javax.persistence.Entity
@org.kie.api.definition.type.Role(org.kie.api.definition.type.
                         Role.Type.EVENT) // line break just for SO
public class Event implements java.io.Serializable {

  static final long serialVersionUID = 1L;

  @javax.persistence.GeneratedValue(generator = "STATUSNOTIFICATION_ID_GENERATOR", strategy = javax.persistence.GenerationType.AUTO)
  @javax.persistence.SequenceGenerator(name = "STATUSNOTIFICATION_ID_GENERATOR", sequenceName = "STATUSNOTIFICATION_ID_SEQ")
  private java.lang.Long id;

  private java.lang.String identifier;

  public Event() {
  }

  public java.lang.String getIdentifier() {
    return this.identifier;
  }

  public void setIdentifier(java.lang.String identifier) {
    this.identifier = identifier;
  }
}

事件类是通过Drools Workbench配置的。除了将课程声明为“ EVENT”外,我没有做任何其他更改。

将事件插入规则引擎的方式:

KieServicesConfiguration conf = KieServicesFactory.newRestConfiguration(
            url, user, pass);
conf.setMarshallingFormat(FORMAT);   
KieServicesClient kieServicesClient = KieServicesFactory.newKieServicesClient(conf);
RuleServicesClient rulesClient = kieServicesClient.getServicesClient(RuleServicesClient.class); 
KieCommands commandsFactory = KieServices.Factory.get().getCommands();

while (hasEvent) {
  String identifier = ... // get the identifier of the event, events with same identifier possible, sometimes within same seconds, sometimes several minutes/hours in between

  Event event = new Event();
  event.setIdentifier(identifier);

  Command<?> insert = commandsFactory.newInsert(event, "notificationIdentifier");
  Command<?> fireAllRules = commandsFactory.newFireAllRules();
  Command<?> batchCommand = commandsFactory.newBatchExecution(Arrays.asList(insert, fireAllRules));

  ServiceResponse<ExecutionResults> executeResponse = rulesClient.executeCommandsWithResults("name_of_rules_package_incl_version", batchCommand);
  if (executeResponse.getType() == ResponseType.SUCCESS) {
    ...
  } else {
    ...
  }  
}                                                   

除了上面的“ SampleRule”规则外,我还启用了另一个规则,如果每个标识符存在一个EventHandler,该规则将从工作内存中撤回事件:

rule "SampleRuleClear"
dialect "mvel"
no-loop true
when
    $E : Event( $identifier : identifier)
    EventHandler( identifier == $identifier )
then
    retract( $E ); 
end

实际上,不需要“ SampleRuleClear”规则来防止重复。出于完整性考虑,我在这里只提到它。

我希望每个标识符每个事件仅触发一次“ SampleRule”规则。不幸的是,即使事件间隔很大,它也会触发多次。

0 个答案:

没有答案