diff --git a/.ci/validation/test/fixtures/invalid/listen-any-empty-no-until.yaml b/.ci/validation/test/fixtures/invalid/listen-any-empty-no-until.yaml
new file mode 100644
index 00000000..5c9aef15
--- /dev/null
+++ b/.ci/validation/test/fixtures/invalid/listen-any-empty-no-until.yaml
@@ -0,0 +1,10 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-any
+ version: '0.1.0'
+do:
+ - callDoctor:
+ listen:
+ to:
+ any: []
\ No newline at end of file
diff --git a/.ci/validation/test/fixtures/invalid/listen-any-until-any-until.yaml b/.ci/validation/test/fixtures/invalid/listen-any-until-any-until.yaml
new file mode 100644
index 00000000..c9f32f62
--- /dev/null
+++ b/.ci/validation/test/fixtures/invalid/listen-any-until-any-until.yaml
@@ -0,0 +1,14 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-any
+ version: '0.1.0'
+do:
+do:
+ - callDoctor:
+ listen:
+ to:
+ any: []
+ until:
+ any: []
+ until: ${ ($context.events | length) == 3 }
\ No newline at end of file
diff --git a/dsl-reference.md b/dsl-reference.md
index c463d3bb..a16b68dc 100644
--- a/dsl-reference.md
+++ b/dsl-reference.md
@@ -1580,8 +1580,9 @@ Represents the configuration of an event consumption strategy.
| Property | Type | Required | Description |
|----------|:----:|:--------:|-------------|
| all | [`eventFilter[]`](#event-filter) | `no` | Configures the workflow to wait for all defined events before resuming execution.
*Required if `any` and `one` have not been set.* |
-| any | [`eventFilter[]`](#event-filter) | `no` | Configures the workflow to wait for any of the defined events before resuming execution.
*Required if `all` and `one` have not been set.* |
+| any | [`eventFilter[]`](#event-filter) | `no` | Configures the workflow to wait for any of the defined events before resuming execution.
*Required if `all` and `one` have not been set.*
*If empty, listens to all incoming events, and requires `until` to be set.* |
| one | [`eventFilter`](#event-filter) | `no` | Configures the workflow to wait for the defined event before resuming execution.
*Required if `all` and `any` have not been set.* |
+| until | `string`
[`eventConsumptionStrategy`](#event-consumption-strategy) | `no` | Configures the [runtime expression](dsl.md#runtime-expressions) condition or the events that must be consumed to stop listening.
*Only applies if `any` has been set, otherwise ignored.* |
### Event Properties
diff --git a/examples/listen-to-any-until-condition.yaml b/examples/listen-to-any-until-condition.yaml
new file mode 100644
index 00000000..9d611f5b
--- /dev/null
+++ b/examples/listen-to-any-until-condition.yaml
@@ -0,0 +1,11 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-any
+ version: '0.1.0'
+do:
+ - callDoctor:
+ listen:
+ to:
+ any: []
+ until: ( . | length ) > 3 #wait until 3 events have been consumed
\ No newline at end of file
diff --git a/examples/listen-to-any-until-consumed.yaml b/examples/listen-to-any-until-consumed.yaml
new file mode 100644
index 00000000..7c46cc13
--- /dev/null
+++ b/examples/listen-to-any-until-consumed.yaml
@@ -0,0 +1,20 @@
+document:
+ dsl: '1.0.0-alpha1'
+ namespace: test
+ name: listen-to-any
+ version: '0.1.0'
+do:
+ - callDoctor:
+ listen:
+ to:
+ any:
+ - with:
+ type: com.fake-hospital.vitals.measurements.temperature
+ data: ${ .temperature > 38 }
+ - with:
+ type: com.fake-hospital.vitals.measurements.bpm
+ data: ${ .bpm < 60 or .bpm > 100 }
+ until:
+ one:
+ with:
+ type: com.fake-hospital.patient.checked-out
\ No newline at end of file
diff --git a/schema/workflow.yaml b/schema/workflow.yaml
index 2d9b542d..6ca55482 100644
--- a/schema/workflow.yaml
+++ b/schema/workflow.yaml
@@ -1309,14 +1309,47 @@ $defs:
$ref: '#/$defs/eventFilter'
required: [ all ]
- title: AnyEventConsumptionStrategy
- properties:
- any:
- type: array
- title: AnyEventConsumptionStrategyConfiguration
- description: A list containing any of the events to consume.
- items:
- $ref: '#/$defs/eventFilter'
- required: [ any ]
+ oneOf:
+ - properties:
+ any:
+ type: array
+ title: AnyEventConsumptionStrategyConfiguration
+ description: A list containing any of the events to consume.
+ items:
+ $ref: '#/$defs/eventFilter'
+ minItems: 1
+ until:
+ oneOf:
+ - type: string
+ title: AnyEventUntilCondition
+ description: A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening.
+ - allOf:
+ - $ref: '#/$defs/eventConsumptionStrategy'
+ title: AnyEventUntilConsumed
+ description: The strategy that defines the event(s) to consume to stop listening.
+ - properties:
+ until: false
+ required: [ any ]
+ - properties:
+ any:
+ type: array
+ title: AnyEventConsumptionStrategyConfiguration
+ description: A list containing any of the events to consume.
+ items:
+ $ref: '#/$defs/eventFilter'
+ maxItems: 0
+ until:
+ oneOf:
+ - type: string
+ title: AnyEventUntilCondition
+ description: A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening.
+ - allOf:
+ - $ref: '#/$defs/eventConsumptionStrategy'
+ title: AnyEventUntilConsumed
+ description: The strategy that defines the event(s) to consume to stop listening.
+ - properties:
+ until: false
+ required: [ any, until ]
- title: OneEventConsumptionStrategy
properties:
one: