Skip to content

Commit ecc28bb

Browse files
committed
[Fix #463] Supporting runtime expressions
Signed-off-by: Francisco Javier Tirado Sarti <[email protected]>
1 parent 4bfa0d9 commit ecc28bb

20 files changed

+497
-114
lines changed

impl/core/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
<artifactId>serverlessworkflow-api</artifactId>
1616
<version>7.0.0-SNAPSHOT</version>
1717
</dependency>
18+
<dependency>
19+
<groupId>com.github.f4b6a3</groupId>
20+
<artifactId>ulid-creator</artifactId>
21+
<version>5.2.3</version>
22+
</dependency>
1823
<dependency>
1924
<groupId>com.networknt</groupId>
2025
<artifactId>json-schema-validator</artifactId>

impl/core/src/main/java/io/serverlessworkflow/impl/DefaultWorkflowPositionFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ private DefaultWorkflowPositionFactory() {}
2727

2828
@Override
2929
public WorkflowPosition buildPosition() {
30-
return new DefaultWorkflowPosition();
30+
return new ListWorkflowPosition();
3131
}
3232
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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.impl;
17+
18+
import java.util.Deque;
19+
import java.util.LinkedList;
20+
import java.util.stream.Collectors;
21+
22+
public class ListWorkflowPosition implements WorkflowPosition {
23+
24+
private Deque<Object> list;
25+
26+
ListWorkflowPosition() {
27+
this(new LinkedList<>());
28+
}
29+
30+
private ListWorkflowPosition(Deque<Object> list) {
31+
this.list = list;
32+
}
33+
34+
public ListWorkflowPosition copy() {
35+
return new ListWorkflowPosition(this.list);
36+
}
37+
38+
@Override
39+
public WorkflowPosition addIndex(int index) {
40+
list.add(index);
41+
return this;
42+
}
43+
44+
@Override
45+
public WorkflowPosition addProperty(String prop) {
46+
list.add(prop);
47+
return this;
48+
}
49+
50+
@Override
51+
public String jsonPointer() {
52+
return list.stream().map(Object::toString).collect(Collectors.joining("/"));
53+
}
54+
55+
@Override
56+
public String toString() {
57+
return "ListWorkflowPosition [list=" + list + "]";
58+
}
59+
60+
@Override
61+
public WorkflowPosition back() {
62+
list.removeLast();
63+
return this;
64+
}
65+
66+
@Override
67+
public Object last() {
68+
return list.pollLast();
69+
}
70+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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.impl;
17+
18+
import io.serverlessworkflow.impl.expressions.RuntimeDescriptor;
19+
import java.util.function.Supplier;
20+
21+
@FunctionalInterface
22+
public interface RuntimeDescriptorFactory extends Supplier<RuntimeDescriptor> {}

impl/core/src/main/java/io/serverlessworkflow/impl/DefaultWorkflowPosition.java renamed to impl/core/src/main/java/io/serverlessworkflow/impl/StringBufferWorkflowPosition.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@
1515
*/
1616
package io.serverlessworkflow.impl;
1717

18-
public class DefaultWorkflowPosition implements WorkflowPosition {
18+
public class StringBufferWorkflowPosition implements WorkflowPosition {
1919

2020
private StringBuilder sb;
2121

22-
DefaultWorkflowPosition() {
23-
this.sb = new StringBuilder("");
22+
StringBufferWorkflowPosition() {
23+
this("");
2424
}
2525

26-
private DefaultWorkflowPosition(WorkflowPosition position) {
27-
this.sb = new StringBuilder(position.toString());
26+
private StringBufferWorkflowPosition(String str) {
27+
this.sb = new StringBuilder(str);
2828
}
2929

30-
public DefaultWorkflowPosition copy() {
31-
return new DefaultWorkflowPosition(this);
30+
public StringBufferWorkflowPosition copy() {
31+
return new StringBufferWorkflowPosition(this.jsonPointer());
3232
}
3333

3434
@Override
@@ -50,7 +50,7 @@ public String jsonPointer() {
5050

5151
@Override
5252
public String toString() {
53-
return "DefaultWorkflowPosition [sb=" + sb + "]";
53+
return "StringBufferWorkflowPosition [sb=" + sb + "]";
5454
}
5555

5656
@Override
@@ -61,4 +61,10 @@ public WorkflowPosition back() {
6161
}
6262
return this;
6363
}
64+
65+
@Override
66+
public Object last() {
67+
int indexOf = sb.lastIndexOf("/");
68+
return indexOf != -1 ? jsonPointer().substring(indexOf + 1) : "";
69+
}
6470
}

impl/core/src/main/java/io/serverlessworkflow/impl/TaskContext.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.serverlessworkflow.api.types.FlowDirective;
2020
import io.serverlessworkflow.api.types.FlowDirectiveEnum;
2121
import io.serverlessworkflow.api.types.TaskBase;
22+
import java.time.Instant;
2223
import java.util.HashMap;
2324
import java.util.Map;
2425

@@ -27,6 +28,7 @@ public class TaskContext<T extends TaskBase> {
2728
private final JsonNode rawInput;
2829
private final T task;
2930
private final WorkflowPosition position;
31+
private final Instant startedAt = Instant.now();
3032

3133
private JsonNode input;
3234
private JsonNode output;
@@ -109,4 +111,8 @@ public Map<String, Object> variables() {
109111
public WorkflowPosition position() {
110112
return position;
111113
}
114+
115+
public Instant startedAt() {
116+
return startedAt;
117+
}
112118
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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.impl;
17+
18+
import com.github.f4b6a3.ulid.UlidCreator;
19+
20+
public class ULIDFactory implements WorkflowIdFactory {
21+
22+
private static ULIDFactory instance = new ULIDFactory();
23+
24+
public static WorkflowIdFactory get() {
25+
return instance;
26+
}
27+
28+
private ULIDFactory() {}
29+
30+
@Override
31+
public String id() {
32+
return UlidCreator.getMonotonicUlid().toString();
33+
}
34+
}

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowApplication.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.serverlessworkflow.impl.executors.TaskExecutorFactory;
2222
import io.serverlessworkflow.impl.expressions.ExpressionFactory;
2323
import io.serverlessworkflow.impl.expressions.JQExpressionFactory;
24+
import io.serverlessworkflow.impl.expressions.RuntimeDescriptor;
2425
import io.serverlessworkflow.impl.jsonschema.DefaultSchemaValidatorFactory;
2526
import io.serverlessworkflow.impl.jsonschema.SchemaValidatorFactory;
2627
import io.serverlessworkflow.impl.resources.DefaultResourceLoaderFactory;
@@ -37,22 +38,28 @@ public class WorkflowApplication implements AutoCloseable {
3738
private final ExpressionFactory exprFactory;
3839
private final ResourceLoaderFactory resourceLoaderFactory;
3940
private final SchemaValidatorFactory schemaValidatorFactory;
41+
private final WorkflowIdFactory idFactory;
4042
private final Collection<WorkflowExecutionListener> listeners;
4143
private final Map<WorkflowId, WorkflowDefinition> definitions;
4244
private final WorkflowPositionFactory positionFactory;
45+
private final RuntimeDescriptorFactory runtimeDescriptorFactory;
4346

4447
public WorkflowApplication(
4548
TaskExecutorFactory taskFactory,
4649
ExpressionFactory exprFactory,
4750
ResourceLoaderFactory resourceLoaderFactory,
4851
SchemaValidatorFactory schemaValidatorFactory,
4952
WorkflowPositionFactory positionFactory,
53+
WorkflowIdFactory idFactory,
54+
RuntimeDescriptorFactory runtimeDescriptorFactory,
5055
Collection<WorkflowExecutionListener> listeners) {
5156
this.taskFactory = taskFactory;
5257
this.exprFactory = exprFactory;
5358
this.resourceLoaderFactory = resourceLoaderFactory;
5459
this.schemaValidatorFactory = schemaValidatorFactory;
5560
this.positionFactory = positionFactory;
61+
this.idFactory = idFactory;
62+
this.runtimeDescriptorFactory = runtimeDescriptorFactory;
5663
this.listeners = listeners;
5764
this.definitions = new ConcurrentHashMap<>();
5865
}
@@ -81,13 +88,20 @@ public Collection<WorkflowExecutionListener> listeners() {
8188
return listeners;
8289
}
8390

91+
public WorkflowIdFactory idFactory() {
92+
return idFactory;
93+
}
94+
8495
public static class Builder {
8596
private TaskExecutorFactory taskFactory = DefaultTaskExecutorFactory.get();
8697
private ExpressionFactory exprFactory = JQExpressionFactory.get();
8798
private Collection<WorkflowExecutionListener> listeners;
8899
private ResourceLoaderFactory resourceLoaderFactory = DefaultResourceLoaderFactory.get();
89100
private SchemaValidatorFactory schemaValidatorFactory = DefaultSchemaValidatorFactory.get();
90101
private WorkflowPositionFactory positionFactory = DefaultWorkflowPositionFactory.get();
102+
private WorkflowIdFactory idFactory = ULIDFactory.get();
103+
private RuntimeDescriptorFactory descriptorFactory =
104+
() -> new RuntimeDescriptor("reference impl", "1.0.0_alpha", Collections.emptyMap());
91105

92106
private Builder() {}
93107

@@ -124,13 +138,25 @@ public Builder withSchemaValidatorFactory(SchemaValidatorFactory factory) {
124138
return this;
125139
}
126140

141+
public Builder withIdFactory(WorkflowIdFactory factory) {
142+
this.idFactory = factory;
143+
return this;
144+
}
145+
146+
public Builder withDescriptorFactory(RuntimeDescriptorFactory factory) {
147+
this.descriptorFactory = factory;
148+
return this;
149+
}
150+
127151
public WorkflowApplication build() {
128152
return new WorkflowApplication(
129153
taskFactory,
130154
exprFactory,
131155
resourceLoaderFactory,
132156
schemaValidatorFactory,
133157
positionFactory,
158+
idFactory,
159+
descriptorFactory,
134160
listeners == null
135161
? Collections.emptySet()
136162
: Collections.unmodifiableCollection(listeners));
@@ -159,4 +185,8 @@ public void close() throws Exception {
159185
public WorkflowPositionFactory positionFactory() {
160186
return positionFactory;
161187
}
188+
189+
public RuntimeDescriptorFactory runtimeDescriptorFactory() {
190+
return runtimeDescriptorFactory;
191+
}
162192
}

impl/core/src/main/java/io/serverlessworkflow/impl/WorkflowContext.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,26 @@
1616
package io.serverlessworkflow.impl;
1717

1818
import com.fasterxml.jackson.databind.JsonNode;
19-
import io.serverlessworkflow.impl.json.JsonUtils;
2019

2120
public class WorkflowContext {
2221
private final WorkflowDefinition definition;
23-
private final JsonNode input;
24-
private JsonNode context;
22+
private final WorkflowInstance instance;
2523

26-
WorkflowContext(WorkflowDefinition definition, JsonNode input) {
24+
WorkflowContext(WorkflowDefinition definition, WorkflowInstance instance) {
2725
this.definition = definition;
28-
this.input = input;
29-
this.context = JsonUtils.mapper().createObjectNode();
26+
this.instance = instance;
3027
}
3128

32-
public JsonNode context() {
33-
return context;
29+
public WorkflowInstance instance() {
30+
return instance;
3431
}
3532

36-
public void context(JsonNode context) {
37-
this.context = context;
33+
public JsonNode context() {
34+
return instance.context();
3835
}
3936

40-
public JsonNode rawInput() {
41-
return input;
37+
public void context(JsonNode context) {
38+
this.instance.context(context);
4239
}
4340

4441
public WorkflowDefinition definition() {

0 commit comments

Comments
 (0)