Skip to content

intent: a wait step's when never resolves a status name - the guard compares a String to an integer FK and the wait never resumes #6907

Description

@delchev

Summary

A wait step's when guard is the last place in the DSL where a status NAME survives unresolved into generated code. StatusSymbolResolver rewrites a status symbol to its seed id for abortOn, process steps' setRelationField, postings, generates, resolves, reports, entity immutableWhen - and, as of #6906, a process trigger's when - but not a wait step's.

The result is a guard that can never hold:

processes:
  - name: Dunning
    trigger: { onTransition: Fine, when: "Status == IDENTIFIED" }
    steps:
      - { name: hold, kind: wait, args: { onTransition: Fine, when: "Status == NEW", next: remind } }
      - { name: remind, kind: end }

renders (probed through GlueIntentGenerator.buildWaitsForTest on origin/master + #6906):

PROBE trigger=Dunning topic=-transitioned guard=[java.util.Objects.equals(entity.Status, 2)]
PROBE wait=Dunning    topic=-transitioned guard=[java.util.Objects.equals(entity.Status, "NEW")]

The trigger's guard resolves; the wait's does not. Wait.java.template emits it verbatim, so the generated listener compares the integer status FK against the string "NEW" - always false, so Process.correlateMessageEvent is never reached and the parked instance sits there forever.

Why it hides

Every failure on this path is fail-soft by design ("no matching parked instance is a no-op, never an error"), so a guard that never holds is indistinguishable from an event that was not for this wait. Nothing is logged. The onTransition axis (#6810) makes this the normal thing to write - a wait that resumes when the record reaches a status - so the symbol form is exactly what an author reaches for.

The numeric form works today (when: "Status == 1"), which is presumably why it has not been noticed.

Fix candidate

StatusSymbolResolver.rewriteProcesses already walks each process's steps (for setRelationField + value). Resolve args.when for a kind: wait step in the same loop, against the status nomenclature of the step's OWN event entity (args.onCreate/onUpdate/onTransition), which is not necessarily the trigger entity - the via: case is exactly when they differ.

A test belongs next to the trigger one added in #6906 (GlueTransitionAxisTest), asserting the wait's guardExpression resolves to the seed id rather than the name.

Found while fixing #6862 (see #6906, which fixes the trigger half).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions