The GitHub Actions job "Comment commands" on texera.git/main has succeeded.
Run started by GitHub user kz930 (triggered by kz930).

Head commit for run:
436b37e9b62e6be2ef8ea911ec30387dd7e80415 / Xinyuan Lin <[email protected]>
fix(workflow-operator): disallow multiple links into Loop Start's input port 
(#7154)

### What changes were proposed in this PR?

A Loop Start whose single input port is fed by **two** upstream
operators is accepted by the GUI, then rejected at `StartWorkflow`:

```
requirement failed: Loop Start input port ... expected exactly one reader URI, 
got 2
```

Nothing in the editor hints the plan is invalid until the run fails
([discussion #6966](https://github.com/apache/texera/discussions/6966)).
The restriction itself is intended — fan-in belongs in a `Union` before
the loop — but it should be visible while building the workflow.

`InputPort` already has a `disallowMultiLinks` flag, and the frontend
honors it in two places:

| Guard | Where | Source of the flag |
|---|---|---|
| Editor refuses to draw a second link into the port |
`workflow-editor.component.ts` | operator metadata
(`additionalMetadata.inputPorts[i].disallowMultiLinks`) |
| Workflow validation requires exactly one input |
`validation-workflow.service.ts` | the operator predicate, via
`WorkflowUtilService.inputPortToPortDescription` mapping
`disallowMultiLinks` → `disallowMultiInputs` |

The loop operators simply never set it. This PR sets it on the shared
`LoopOpDesc` input port — **one line**, no frontend change.

It applies to **Loop Start only**. Loop End supports fan-in — a loop
body may branch and converge on it — so this PR also makes that work:
every reader on the input port replays its own branch's copy of the same
iteration's state, so `MainLoop` now consumes it once per iteration and
drops the duplicates (the copies are identical, being one emission from
the matching Loop Start, and a consume emits nothing downstream).
Without that, `update` would run once per branch and the loop would end
early with wrong results.

| | inbound links | why |
|---|---|---|
| Loop Start | exactly 1 | the scheduler resolves the loop's bookkeeping
URIs from that port's single reader — put a `Union` before the loop |
| Loop End | 1 or more | a branching loop body converges here; the loop
state is consumed once per iteration |

The scheduler's `require` (which is Loop-Start-only, under
`filter(_.isLoopStart)`) stays as a defense-in-depth backstop for
programmatically built plans, which bypass the GUI entirely.

**Scope of the guard (corrected).** The two frontend guards read the
flag from different places, so they cover different cases:

| Guard | Reads from | Covers already-saved loop operators? |
|---|---|---|
| Editor refuses to draw a 2nd link
(`workflow-editor.component.ts:1124`) | dynamic **schema** | **yes** |
| Validation requires exactly 1 input
(`validation-workflow.service.ts:328`) | the saved **operator
predicate** | **no** — `updateOperatorVersion` only rebuilds ports from
the schema when the saved port list is empty, so an operator saved
before this change keeps `disallowMultiInputs: false` |

So this stops new second links everywhere (the valuable half), but a
workflow that *already* has two links — including JSON assembled outside
the GUI and then opened — still validates clean and still fails at
`StartWorkflow`. Making validation cover existing content needs
`inputPortToPortDescription` re-applied on load, or a schema fallback in
validation; that is a separate change.

### Any related issues, documentation, discussions?

Closes #7155
Closes #7246

Addresses the GUI half of [discussion
#6966](https://github.com/apache/texera/discussions/6966).

### How was this PR tested?

`LoopStartOpDescSpec` and `LoopEndOpDescSpec` each gain a case pinning
`inputPorts.head.disallowMultiLinks shouldBe true` (both fail before the
change, 29/29 pass after). `scalafmtCheckAll` + `scalafixAll --check`
clean on Java 17.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 5)

---------

Signed-off-by: Xinyuan Lin <[email protected]>

Report URL: https://github.com/apache/texera/actions/runs/30739193936

With regards,
GitHub Actions via GitBox

Reply via email to