Skip to content

Commit b7648f8

Browse files
Add gaps ListenToConfigurerBuilder and enhance DSL for event filtering and data expressions (#1471)
Signed-off-by: Matheus André <matheusandr2@gmail.com>
1 parent a165007 commit b7648f8

5 files changed

Lines changed: 170 additions & 0 deletions

File tree

‎fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/AbstractListenTaskBuilder.java‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import io.serverlessworkflow.api.types.ListenTask;
2020
import io.serverlessworkflow.api.types.ListenTaskConfiguration;
2121
import io.serverlessworkflow.api.types.ListenTo;
22+
import io.serverlessworkflow.api.types.TaskTimeout;
23+
import io.serverlessworkflow.api.types.Timeout;
24+
import io.serverlessworkflow.api.types.TimeoutAfter;
2225
import java.util.function.Consumer;
2326

2427
public abstract class AbstractListenTaskBuilder<
@@ -63,6 +66,27 @@ public AbstractListenTaskBuilder<T, F> to(Consumer<F> c) {
6366
return this;
6467
}
6568

69+
public ListenToConfigurerBuilder<T> to() {
70+
return new ListenToConfigurerBuilder<>(this, taskItemListBuilder);
71+
}
72+
73+
void applyTo(ListenTo listenTo) {
74+
this.config.setTo(listenTo);
75+
}
76+
77+
public AbstractListenTaskBuilder<T, F> timeout(String durationExpression) {
78+
this.listenTask.setTimeout(
79+
new TaskTimeout()
80+
.withTaskTimeoutDefinition(
81+
new Timeout()
82+
.withAfter(new TimeoutAfter().withDurationExpression(durationExpression))));
83+
return this;
84+
}
85+
86+
protected ListenTask getListenTask() {
87+
return listenTask;
88+
}
89+
6690
public ListenTask build() {
6791
return listenTask;
6892
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.fluent.spec;
17+
18+
import java.util.function.Consumer;
19+
20+
public class ListenToConfigurerBuilder<T extends BaseTaskItemListBuilder<T>> {
21+
22+
private final AbstractListenTaskBuilder<T, ?> listenTaskBuilder;
23+
private final T taskItemListBuilder;
24+
private final ListenToBuilder listenToBuilder;
25+
private boolean strategySet;
26+
27+
public ListenToConfigurerBuilder(
28+
AbstractListenTaskBuilder<T, ?> listenTaskBuilder, T taskItemListBuilder) {
29+
this.listenTaskBuilder = listenTaskBuilder;
30+
this.taskItemListBuilder = taskItemListBuilder;
31+
this.listenToBuilder = new ListenToBuilder();
32+
}
33+
34+
public ListenToConfigurerBuilder<T> one(Consumer<EventFilterBuilder> filter) {
35+
listenToBuilder.one(filter);
36+
strategySet = true;
37+
return this;
38+
}
39+
40+
public ListenToConfigurerBuilder<T> all(Consumer<EventFilterBuilder>... filters) {
41+
listenToBuilder.all(filters);
42+
strategySet = true;
43+
return this;
44+
}
45+
46+
public ListenToConfigurerBuilder<T> any(Consumer<EventFilterBuilder>... filters) {
47+
listenToBuilder.any(filters);
48+
strategySet = true;
49+
return this;
50+
}
51+
52+
public ListenToConfigurerBuilder<T> until(String expression) {
53+
listenToBuilder.until(expression);
54+
return this;
55+
}
56+
57+
public ListenToConfigurerBuilder<T> forEach(
58+
String item, Consumer<SubscriptionIteratorBuilder<T>> tasksConsumer) {
59+
final SubscriptionIteratorBuilder<T> iteratorBuilder =
60+
new SubscriptionIteratorBuilder<>(this.taskItemListBuilder);
61+
tasksConsumer.accept(iteratorBuilder);
62+
listenTaskBuilder.getListenTask().setForeach(iteratorBuilder.build());
63+
return this;
64+
}
65+
66+
public AbstractListenTaskBuilder<T, ?> apply() {
67+
listenTaskBuilder.applyTo(listenToBuilder.build());
68+
return listenTaskBuilder;
69+
}
70+
71+
public boolean isStrategySet() {
72+
return strategySet;
73+
}
74+
}

‎fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/ExprEventEmitPropertiesSpec.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,15 @@ public SELF jsonData(Map<String, Object> data) {
3333
addPropertyStep(e -> e.data(data));
3434
return JSON();
3535
}
36+
37+
/**
38+
* Sets the event data as an expression without setting content type.
39+
*
40+
* @param expr the data expression (e.g., "${.temperature}")
41+
* @return self
42+
*/
43+
public SELF data(String expr) {
44+
addPropertyStep(e -> e.data(expr));
45+
return self();
46+
}
3647
}

‎fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/ExprEventFilterSpec.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,15 @@ public SELF jsonData(String expr) {
2626
addPropertyStep(e -> e.data(expr));
2727
return JSON();
2828
}
29+
30+
/**
31+
* Sets the event data filter expression without setting content type.
32+
*
33+
* @param expr the data filter expression (e.g., "${ .temperature > 38 }")
34+
* @return self
35+
*/
36+
public SELF data(String expr) {
37+
addPropertyStep(e -> e.data(expr));
38+
return self();
39+
}
2940
}

‎fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/WorkflowBuilderTest.java‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static io.serverlessworkflow.fluent.spec.dsl.DSL.cases;
2121
import static io.serverlessworkflow.fluent.spec.dsl.DSL.doTasks;
2222
import static io.serverlessworkflow.fluent.spec.dsl.DSL.emit;
23+
import static io.serverlessworkflow.fluent.spec.dsl.DSL.event;
2324
import static io.serverlessworkflow.fluent.spec.dsl.DSL.forEach;
2425
import static io.serverlessworkflow.fluent.spec.dsl.DSL.fork;
2526
import static io.serverlessworkflow.fluent.spec.dsl.DSL.http;
@@ -703,4 +704,53 @@ void testDoTaskRunWorkflow() {
703704
RunTaskConfiguration.ProcessReturnType.NONE, runTask.getRun().getRunWorkflow().getReturn());
704705
assertEquals(false, runTask.getRun().getRunWorkflow().isAwait());
705706
}
707+
708+
@Test
709+
void testListenWithConfigurerBuilder() {
710+
Workflow wf =
711+
WorkflowBuilder.workflow("listen-with-configurer", "test", "0.1.0")
712+
.tasks(
713+
doTasks(
714+
listen(
715+
"waitForEvent",
716+
l ->
717+
l.to()
718+
.any(
719+
event().type("com.example.event.A"),
720+
event().type("com.example.event.B"))
721+
.until("$.count > 0")
722+
.forEach(
723+
"item",
724+
f ->
725+
f.tasks(
726+
set("processed", s -> s.put("eventType", "processed"))))
727+
.apply())))
728+
.build();
729+
730+
List<TaskItem> items = wf.getDo();
731+
assertNotNull(items, "Do list must not be null");
732+
assertEquals(1, items.size(), "There should be one listen task");
733+
734+
TaskItem item = items.get(0);
735+
assertEquals("waitForEvent", item.getName(), "TaskItem name should match");
736+
ListenTask lt = item.getTask().getListenTask();
737+
assertNotNull(lt, "ListenTask should be present");
738+
739+
// Verify strategy
740+
var strategy = lt.getListen().getTo().getAnyEventConsumptionStrategy();
741+
assertNotNull(strategy, "Any strategy should be set");
742+
assertEquals(2, strategy.getAny().size(), "Should have 2 event filters");
743+
744+
// Verify until condition
745+
var until = strategy.getUntil();
746+
assertNotNull(until, "Until should be set");
747+
assertEquals("$.count > 0", until.getAnyEventUntilCondition(), "Until expression should match");
748+
749+
// Verify foreach
750+
var foreach = lt.getForeach();
751+
assertNotNull(foreach, "Foreach should be set");
752+
assertNotNull(foreach.getDo(), "Foreach do tasks should be set");
753+
assertEquals(1, foreach.getDo().size(), "Foreach do should have 1 task");
754+
assertEquals("processed", foreach.getDo().get(0).getName(), "Foreach task name should match");
755+
}
706756
}

0 commit comments

Comments
 (0)