Uploaded image for project: 'Red Hat Process Automation Manager'
  1. Red Hat Process Automation Manager
  2. RHPAM-2877

Drools Canonical Model causes infinite loop firing of rules

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Blocker Blocker
    • 7.7.1.GA
    • 7.7.0.GA
    • BRE
    • None
    • macOS 10.15.4, openjdk version "11.0.6" 2020-01-14, Drools 7.35.0.Final

    • 2
    • Release Notes
    • CR1
    • +
    • Hide

      1) Clone this repository: https://github.com/DuncanDoyle/drools-canonical-model-loop-issue

      2) Run:

      mvn clean test -DgenerateModel=NO

      Test completes successfully.

      3) Run:

      mvn clean test

      Rule firing goes into an infinite loop.

      Show
      1) Clone this repository: https://github.com/DuncanDoyle/drools-canonical-model-loop-issue 2) Run: mvn clean test -DgenerateModel=NO Test completes successfully. 3) Run: mvn clean test Rule firing goes into an infinite loop.
    • 2020 Week 16-18 (from Apr 13)

      This happens both in RHPAM 7.7.0.GA, Drools 7.35.0.Final and Kogito 0.9.1-SNAPSHOT (and master).

      Reproducer here: https://github.com/DuncanDoyle/drools-canonical-model-loop-issue

      When running the unit-test with the Canonical Model enabled (which is the default in RHPAM 7.7.0.GA), this rule goes into an infinite loop. This does not happen with the Canonical Model disabled (-DgenerateModel=NO).

      The problem seems to be with incorrect application of property reactivity. It seems that this line https://github.com/DuncanDoyle/drools-canonical-model-loop-issue/blob/master/src/main/resources/persons.drl#L9 is the problem (when you remove that System.out, looping is gone).

      The generated rule with that line enabled:

      public static org.drools.model.Rule rule_Set_32Duncan_39s_32age() {
              final org.drools.model.Variable<com.redhat.Person> var_$p = D.declarationOf(com.redhat.Person.class,
                                                                                          DomainClassesMetadatae5c379871a3c48e99da0b6663f475772.com_redhat_Person_Metadata_INSTANCE,
                                                                                          "$p");
              final org.drools.model.BitMask mask_$p = org.drools.model.BitMask.getPatternMask(DomainClassesMetadatae5c379871a3c48e99da0b6663f475772.com_redhat_Person_Metadata_INSTANCE,
                                                                                               "name",
                                                                                               "age");
              org.drools.model.Rule rule = D.rule("com.redhat",
                                                  "Set Duncan's age").build(D.pattern(var_$p).expr("C1EB57BF17B7A3967DB15FAF80D69BBB",
                                                                                                   (com.redhat.Person _this) -> org.drools.modelcompiler.util.EvaluationUtil.areNullSafeEquals(_this.getName(),
                                                                                                                                                                                               "Duncan"),
                                                                                                   D.alphaIndexedBy(java.lang.String.class,
                                                                                                                    org.drools.model.Index.ConstraintType.EQUAL,
                                                                                                                    DomainClassesMetadatae5c379871a3c48e99da0b6663f475772.com_redhat_Person_Metadata_INSTANCE.getPropertyIndex("name"),
                                                                                                                    (com.redhat.Person _this) -> _this.getName(),
                                                                                                                    "Duncan"),
                                                                                                   D.reactOn("name")),
                                                                            D.on(var_$p).execute((org.drools.model.Drools drools, com.redhat.Person $p) -> {
                                                                                {
                                                                                    {
                                                                                        System.out.println("Found: " + $p.getName());
                                                                                        ($p).setAge(41);
                                                                                        drools.update($p,
                                                                                                      mask_$p);
                                                                                    }
                                                                                }
                                                                            }));
              return rule;
          }
      

      And with that line commented out:

      public static org.drools.model.Rule rule_Set_32Duncan_39s_32age() {
              final org.drools.model.Variable<com.redhat.Person> var_$p = D.declarationOf(com.redhat.Person.class,
                                                                                          DomainClassesMetadata9e133d566da042288db1930397a53ae8.com_redhat_Person_Metadata_INSTANCE,
                                                                                          "$p");
              final org.drools.model.BitMask mask_$p = org.drools.model.BitMask.getPatternMask(DomainClassesMetadata9e133d566da042288db1930397a53ae8.com_redhat_Person_Metadata_INSTANCE,
                                                                                               "age");
              org.drools.model.Rule rule = D.rule("com.redhat",
                                                  "Set Duncan's age").build(D.pattern(var_$p).expr("C1EB57BF17B7A3967DB15FAF80D69BBB",
                                                                                                   (com.redhat.Person _this) -> org.drools.modelcompiler.util.EvaluationUtil.areNullSafeEquals(_this.getName(),
                                                                                                                                                                                               "Duncan"),
                                                                                                   D.alphaIndexedBy(java.lang.String.class,
                                                                                                                    org.drools.model.Index.ConstraintType.EQUAL,
                                                                                                                    DomainClassesMetadata9e133d566da042288db1930397a53ae8.com_redhat_Person_Metadata_INSTANCE.getPropertyIndex("name"),
                                                                                                                    (com.redhat.Person _this) -> _this.getName(),
                                                                                                                    "Duncan"),
                                                                                                   D.reactOn("name")),
                                                                            D.on(var_$p).execute((org.drools.model.Drools drools, com.redhat.Person $p) -> {
                                                                                {
                                                                                    {
                                                                                        ($p).setAge(41);
                                                                                        drools.update($p,
                                                                                                      mask_$p);
                                                                                    }
                                                                                }
                                                                            }));
              return rule;
          }
      

      The main difference (from a glance) is that in the first code-snippet, the bit-mask includes the age AND name, where in the second snippet, the bit-mask only includes the age. And this difference seems to be causing the loop.

      Since the Canonical Model has been set as the default mode in version 7.7.0.GA, I find this a pretty serious issue, and therefore have marked this as a blocker.

              rhn-support-tkobayas Toshiya Kobayashi
              rhn-gps-ddoyle Duncan Doyle (Inactive)
              Daniel Rosa Daniel Rosa
              Daniel Rosa Daniel Rosa
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: