|
20 | 20 | import io.serverlessworkflow.impl.WorkflowInstance; |
21 | 21 | import io.serverlessworkflow.impl.WorkflowModel; |
22 | 22 | import io.serverlessworkflow.impl.WorkflowModelCollection; |
23 | | -import java.util.concurrent.CompletableFuture; |
| 23 | +import io.serverlessworkflow.impl.events.EventConsumer; |
| 24 | +import io.serverlessworkflow.impl.events.EventRegistration; |
| 25 | +import io.serverlessworkflow.impl.events.EventRegistrationBuilder; |
| 26 | +import io.serverlessworkflow.impl.events.EventRegistrationBuilderInfo; |
| 27 | +import java.util.ArrayList; |
| 28 | +import java.util.Collection; |
| 29 | +import java.util.HashMap; |
| 30 | +import java.util.List; |
| 31 | +import java.util.Map; |
24 | 32 | import java.util.function.Function; |
25 | 33 |
|
26 | | -public abstract class ScheduledEventConsumer { |
| 34 | +public abstract class ScheduledEventConsumer implements AutoCloseable { |
27 | 35 |
|
28 | 36 | private final Function<CloudEvent, WorkflowModel> converter; |
29 | 37 | private final WorkflowDefinition definition; |
| 38 | + private final EventRegistrationBuilderInfo builderInfo; |
| 39 | + private final EventConsumer eventConsumer; |
| 40 | + private Map<EventRegistrationBuilder, List<CloudEvent>> correlatedEvents; |
| 41 | + private Collection<EventRegistration> registrations = new ArrayList<>(); |
30 | 42 |
|
31 | 43 | protected ScheduledEventConsumer( |
32 | | - WorkflowDefinition definition, Function<CloudEvent, WorkflowModel> converter) { |
| 44 | + WorkflowDefinition definition, |
| 45 | + Function<CloudEvent, WorkflowModel> converter, |
| 46 | + EventRegistrationBuilderInfo builderInfo) { |
33 | 47 | this.definition = definition; |
34 | 48 | this.converter = converter; |
| 49 | + this.builderInfo = builderInfo; |
| 50 | + this.eventConsumer = definition.application().eventConsumer(); |
| 51 | + if (builderInfo.registrations().isAnd() |
| 52 | + && builderInfo.registrations().registrations().size() > 1) { |
| 53 | + this.correlatedEvents = new HashMap<>(); |
| 54 | + builderInfo |
| 55 | + .registrations() |
| 56 | + .registrations() |
| 57 | + .forEach( |
| 58 | + reg -> { |
| 59 | + correlatedEvents.put(reg, new ArrayList<>()); |
| 60 | + registrations.add( |
| 61 | + eventConsumer.register(reg, ce -> consumeEvent(reg, (CloudEvent) ce))); |
| 62 | + }); |
| 63 | + } else { |
| 64 | + builderInfo |
| 65 | + .registrations() |
| 66 | + .registrations() |
| 67 | + .forEach( |
| 68 | + reg -> registrations.add(eventConsumer.register(reg, ce -> start((CloudEvent) ce)))); |
| 69 | + } |
35 | 70 | } |
36 | 71 |
|
37 | | - public void accept( |
38 | | - CloudEvent t, CompletableFuture<WorkflowModel> u, WorkflowModelCollection col) { |
39 | | - WorkflowModel model = converter.apply(t); |
40 | | - col.add(model); |
41 | | - u.complete(model); |
| 72 | + private void consumeEvent(EventRegistrationBuilder reg, CloudEvent ce) { |
| 73 | + Collection<Collection<CloudEvent>> collections = new ArrayList<>(); |
| 74 | + // to minimize the critical section, conversion is done later, here we are |
| 75 | + // performing |
| 76 | + // just collection, if any |
| 77 | + synchronized (correlatedEvents) { |
| 78 | + correlatedEvents.get(reg).add((CloudEvent) ce); |
| 79 | + while (satisfyCondition()) { |
| 80 | + Collection<CloudEvent> collection = new ArrayList<>(); |
| 81 | + for (List<CloudEvent> values : correlatedEvents.values()) { |
| 82 | + collection.add(values.remove(0)); |
| 83 | + } |
| 84 | + collections.add(collection); |
| 85 | + } |
| 86 | + } |
| 87 | + // convert and start outside synchronized |
| 88 | + collections.forEach(this::start); |
42 | 89 | } |
43 | 90 |
|
44 | | - public void start(Object model) { |
| 91 | + private boolean satisfyCondition() { |
| 92 | + for (List<CloudEvent> values : correlatedEvents.values()) { |
| 93 | + if (values.isEmpty()) { |
| 94 | + return false; |
| 95 | + } |
| 96 | + } |
| 97 | + return true; |
| 98 | + } |
| 99 | + |
| 100 | + protected void start(CloudEvent ce) { |
| 101 | + WorkflowModelCollection model = definition.application().modelFactory().createCollection(); |
| 102 | + model.add(converter.apply(ce)); |
| 103 | + start(model); |
| 104 | + } |
| 105 | + |
| 106 | + protected void start(Collection<CloudEvent> ces) { |
| 107 | + WorkflowModelCollection model = definition.application().modelFactory().createCollection(); |
| 108 | + ces.forEach(ce -> model.add(converter.apply(ce))); |
| 109 | + start(model); |
| 110 | + } |
| 111 | + |
| 112 | + private void start(WorkflowModel model) { |
45 | 113 | WorkflowInstance instance = definition.instance(model); |
46 | 114 | addScheduledInstance(instance); |
47 | 115 | instance.start(); |
48 | 116 | } |
49 | 117 |
|
| 118 | + public void close() { |
| 119 | + if (correlatedEvents != null) { |
| 120 | + correlatedEvents.clear(); |
| 121 | + } |
| 122 | + registrations.forEach(eventConsumer::unregister); |
| 123 | + } |
| 124 | + |
50 | 125 | protected abstract void addScheduledInstance(WorkflowInstance instace); |
51 | 126 | } |
0 commit comments