Skip to content

Commit 9dc962d

Browse files
ipatiniatsag
andauthored
Nochanges2 (#69)
* Merge latest improvements (#53) * Rebuilding images (#51) * Rebuilding images (#52) --------- Co-authored-by: ipatini <3739531+ipatini@users.noreply.github.com> * Updating R1 with latest changes (#63) * Rebuilding images (#51) * Rebuilding images (#52) * Rebuilding images (#54) * Rebuilding images (#55) * Rebuilding images (#57) * Rebuild/2025 02 26 a (#58) * Rebuilding images * Rebuilding images * Rebuilding images (#59) * Rebuilding images (#60) * Rebuilding images (#61) * Sync to source (#62) * Upgraded to SB version 3.4.2, as well as the versions of other dependencies to their latest versions. Fixed scripts for running on ARM64. Improved broker-client tool. Added persistence to Broker-CEP. Few other minor improvements and bugfixes. * Extended ems-core to allow get/set constants through WebAdmin * Extended EMS-Nebulous plugin to (a) cache optimiser and solver solutions (at platform side), (b) parse and cache composite constant bindings, (c) use the cached solutions at application side (and evaluate composite constants) --------- Co-authored-by: atsag <andreastsagkaropoulos@hotmail.com>
1 parent 2de4a51 commit 9dc962d

File tree

6 files changed

+188
-178
lines changed

6 files changed

+188
-178
lines changed

nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/boot/BootService.java

+15-40
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package eu.nebulous.ems.boot;
1010

1111
import com.fasterxml.jackson.databind.ObjectMapper;
12+
import eu.nebulouscloud.exn.core.Publisher;
1213
import lombok.RequiredArgsConstructor;
1314
import lombok.extern.slf4j.Slf4j;
1415
import org.apache.commons.lang3.StringUtils;
@@ -17,11 +18,9 @@
1718

1819
import java.io.IOException;
1920
import java.nio.file.Files;
20-
import java.nio.file.Path;
2121
import java.nio.file.Paths;
2222
import java.util.List;
2323
import java.util.Map;
24-
import java.util.function.BiConsumer;
2524

2625
@Slf4j
2726
@Service
@@ -36,21 +35,20 @@ public void afterPropertiesSet() throws Exception {
3635
log.info("EMS Boot Service: {}", properties.isEnabled() ? "enabled" : "disabled");
3736
}
3837

39-
String processEmsBootMessage(Command command, String appId, BiConsumer<Map,String> emsBootResponsePublisher) throws IOException {
38+
void processEmsBootMessage(Command command, String appId, Publisher emsBootResponsePublisher) throws IOException {
4039
// Process EMS Boot message
4140
log.info("Received a new EMS Boot message from external broker: {}", command.body());
4241

4342
// Load info from models store
4443
Map<String, String> entry = indexService.getFromIndex(appId);
4544
log.debug("Index entry for app-id: {}, entry: {}", appId, entry);
4645
if (entry==null) {
47-
String msg = "No EMS Boot entry found for app-id: " + appId;
48-
log.warn(msg);
49-
return "ERROR "+msg;
46+
log.warn("No EMS Boot entry found for app-id: {}", appId);
47+
return;
5048
}
5149
String modelFile = entry.get(ModelsService.MODEL_FILE_KEY);
5250
String bindingsFile = entry.get(ModelsService.BINDINGS_FILE_KEY);
53-
String solutionFile = entry.get(ModelsService.SOLUTION_FILE_KEY);
51+
String solutionFile = entry.get(ModelsService.SOLUTIONS_FILE_KEY);
5452
String optimiserMetricsFile = entry.get(ModelsService.OPTIMISER_METRICS_FILE_KEY);
5553
log.info("""
5654
Received EMS Boot request:
@@ -62,24 +60,20 @@ String processEmsBootMessage(Command command, String appId, BiConsumer<Map,Strin
6260
""", appId, modelFile, bindingsFile, solutionFile, optimiserMetricsFile);
6361

6462
if (StringUtils.isAnyBlank(appId, modelFile, bindingsFile, optimiserMetricsFile)) {
65-
String msg = "Missing info in EMS Boot entry for app-id: " + appId;
66-
log.warn(msg);
67-
return "ERROR "+msg;
63+
log.warn("Missing info in EMS Boot entry for app-id: {}", appId);
64+
return;
6865
}
6966

70-
String modelStr = readFileContentsSafe(modelFile);
67+
String modelStr = Files.readString(Paths.get(properties.getModelsDir(), modelFile));
7168
log.debug("Model file contents:\n{}", modelStr);
72-
73-
String bindingsStr = readFileContentsSafe(bindingsFile);
74-
Map bindingsMap = bindingsStr!=null ? objectMapper.readValue(bindingsStr, Map.class) : Map.of();
69+
String bindingsStr = Files.readString(Paths.get(properties.getModelsDir(), bindingsFile));
70+
Map bindingsMap = objectMapper.readValue(bindingsStr, Map.class);
7571
log.debug("Bindings file contents:\n{}", bindingsMap);
76-
77-
String solutionStr = readFileContentsSafe(solutionFile);
78-
Map solutionMap = solutionStr!=null ? objectMapper.readValue(solutionStr, Map.class) : Map.of();
72+
String solutionStr = Files.readString(Paths.get(properties.getModelsDir(), solutionFile));
73+
Map solutionMap = objectMapper.readValue(solutionStr, Map.class);
7974
log.debug("Solution file contents:\n{}", solutionMap);
80-
81-
String metricsStr = readFileContentsSafe(optimiserMetricsFile);
82-
List metricsList = metricsStr!=null ? objectMapper.readValue(metricsStr, List.class) : List.of();
75+
String metricsStr = Files.readString(Paths.get(properties.getModelsDir(), optimiserMetricsFile));
76+
List metricsList = objectMapper.readValue(metricsStr, List.class);
8377
log.debug("Optimiser Metrics file contents:\n{}", metricsList);
8478

8579
// Send EMS Boot response message
@@ -90,26 +84,7 @@ String processEmsBootMessage(Command command, String appId, BiConsumer<Map,Strin
9084
"solution", solutionMap,
9185
"optimiser-metrics", metricsList
9286
);
93-
log.debug("EMS Boot response message: {}", message);
94-
emsBootResponsePublisher.accept(message, appId);
87+
emsBootResponsePublisher.send(message, appId);
9588
log.info("EMS Boot response sent");
96-
return "OK";
97-
}
98-
99-
protected String readFileContentsSafe(String file) {
100-
if (StringUtils.isBlank(file)) return null;
101-
Path path = Paths.get(properties.getModelsDir(), file);
102-
if (! path.toFile().exists()) {
103-
log.warn("File not found in models dir.: {}", file);
104-
return null;
105-
}
106-
107-
try {
108-
String contents = Files.readString(path);
109-
return contents;
110-
} catch (Exception e) {
111-
log.warn("Error while reading file: {}\n", file, e);
112-
return null;
113-
}
11489
}
11590
}

nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/boot/IndexService.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public Map<String,String> getAppBindings(@NonNull String appId) throws IOExcepti
155155
}
156156

157157
public Map<String,Double> getAppSolution(@NonNull String appId) throws IOException {
158-
String fileName = getAppData(appId).get(ModelsService.SOLUTION_FILE_KEY);
158+
String fileName = getAppData(appId).get(ModelsService.SOLUTIONS_FILE_KEY);
159159
String solutionStr = applicationContext.getBean(ModelsService.class).readFromFile(fileName);
160160
return objectMapper.readValue(solutionStr, Map.class);
161161
}
@@ -268,16 +268,14 @@ public synchronized boolean deleteAppsBefore(Instant before, boolean deleteFiles
268268

269269
public synchronized void addAppData(String appId) throws IOException {
270270
long ts = Instant.now().toEpochMilli();
271-
String modelStr, bindingsStr, solutionStr, metricsStr;
271+
String modelStr, bindingsStr, metricsStr;
272272
Map<String, String> data = Map.of(
273-
ModelsService.MODEL_FILE_KEY, modelStr = appId + "--model--" + ts + ".yml",
274-
ModelsService.BINDINGS_FILE_KEY, bindingsStr = appId + "--bindings--" + ts + ".json",
275-
ModelsService.SOLUTION_FILE_KEY, solutionStr = appId + "--solution--" + ts + ".json",
276-
ModelsService.OPTIMISER_METRICS_FILE_KEY, metricsStr = appId + "--metrics--" + ts + ".json"
273+
"model-file", modelStr = appId + "--model--" + ts + ".yml",
274+
"bindings-file", bindingsStr = appId + "--bindings--" + ts + ".json",
275+
"optimiser-metrics-file", metricsStr = appId + "--metrics--" + ts + ".json"
277276
);
278277
Files.writeString(Paths.get(properties.getModelsDir(), modelStr), "{}");
279278
Files.writeString(Paths.get(properties.getModelsDir(), bindingsStr), "{}");
280-
Files.writeString(Paths.get(properties.getModelsDir(), solutionStr), "{}");
281279
Files.writeString(Paths.get(properties.getModelsDir(), metricsStr), "[]");
282280
storeToIndex(appId, data);
283281
}

nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/boot/ModelsService.java

+4-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.HashMap;
2727
import java.util.List;
2828
import java.util.Map;
29+
import java.util.Set;
2930
import java.util.stream.Collectors;
3031

3132
@Slf4j
@@ -34,7 +35,7 @@
3435
public class ModelsService implements InitializingBean {
3536
final static String MODEL_FILE_KEY = "model-file";
3637
final static String BINDINGS_FILE_KEY = "bindings-file";
37-
final static String SOLUTION_FILE_KEY = "solution-file";
38+
final static String SOLUTIONS_FILE_KEY = "solutions-file";
3839
final static String OPTIMISER_METRICS_FILE_KEY = "optimiser-metrics-file";
3940

4041
public final static String SIMPLE_BINDING_KEY = "simple-bindings";
@@ -139,12 +140,7 @@ String extractBindings(Command command, String appId) throws IOException {
139140

140141
// Store bindings in models store
141142
String bindingsFile = getFileName("bindings", appId, "json");
142-
if (bindingsMap==null) {
143-
bindingsMap = Map.of(
144-
SIMPLE_BINDING_KEY, Map.of(),
145-
COMPOSITE_BINDING_KEY, Map.of()
146-
);
147-
}
143+
if (bindingsMap==null) bindingsMap = Map.of();
148144
storeToFile(bindingsFile, objectMapper.writeValueAsString(bindingsMap));
149145
log.info("Stored bindings in file: app-id={}, file={}", appId, bindingsFile);
150146

@@ -236,7 +232,7 @@ String extractSolution(Command command, String appId) throws IOException {
236232
log.info("Stored solution in file: app-id={}, file={}", appId, solutionFile);
237233

238234
// Add appId-solutionFile entry in the stored Index
239-
indexService.storeToIndex(appId, Map.of(SOLUTION_FILE_KEY, solutionFile));
235+
indexService.storeToIndex(appId, Map.of(SOLUTIONS_FILE_KEY, solutionFile));
240236

241237
return "OK";
242238
}

nebulous/ems-nebulous/src/main/java/eu/nebulous/ems/service/MvvService.java

+43-57
Original file line numberDiff line numberDiff line change
@@ -70,66 +70,52 @@ public boolean isEmpty() {
7070
}
7171

7272
public void translateAndSetValues(Map<String,Object> varValues) {
73-
// Check if bindings are available
74-
if (bindings == null || bindings.isEmpty()) {
75-
log.error("MvvService.translateAndSetValues: No bindings provided: {}", bindings);
76-
return;
77-
}
78-
Map<String, String> simpleBindings = bindings.get(ModelsService.SIMPLE_BINDING_KEY);
79-
Map<String, String> compositeBindings = bindings.get(ModelsService.COMPOSITE_BINDING_KEY);
80-
if (simpleBindings==null || simpleBindings.isEmpty()) {
81-
log.error("MvvService.translateAndSetValues: No simple bindings provided: {}", bindings);
82-
return;
83-
}
84-
85-
// Log new values
86-
log.info("MvvService.translateAndSetValues: New Variable Values: {}", varValues);
87-
Map<String, Double> newValues = new HashMap<>();
88-
89-
// Process simple constants
90-
varValues.forEach((k, v) -> {
91-
String constName = simpleBindings.get(k);
92-
if (StringUtils.isNotBlank(constName)) {
93-
if (v instanceof Number n)
94-
newValues.put(constName, n.doubleValue());
95-
else
96-
throw new IllegalArgumentException("Solution variable value is not a number: " + v);
97-
log.trace("MvvService.translateAndSetValues: Added Simple Constant value: {} = {}", constName, n);
98-
} else
99-
log.warn("MvvService.translateAndSetValues: No Constant found for Solution variable: {}", k);
100-
});
101-
log.debug("MvvService.translateAndSetValues: Simple Constant values: {}", newValues);
102-
103-
// Process composite constants
104-
if (compositeBindings!=null && ! compositeBindings.isEmpty()) {
105-
Map<String, String> pending = new HashMap<>(bindings.get(ModelsService.COMPOSITE_BINDING_KEY));
106-
@NotNull final Map<String, Double> varValues1 = varValues.entrySet().stream().collect(Collectors.toMap(
107-
Map.Entry::getKey, e -> ((Number) e.getValue()).doubleValue()
108-
));
109-
while (!pending.isEmpty()) {
110-
Map<String, String> newPending = new HashMap<>();
111-
pending.forEach((formula, constName) -> {
112-
if (StringUtils.isNotBlank(formula) && StringUtils.isNotBlank(constName)) {
113-
try {
114-
log.trace("MvvService.translateAndSetValues: Calculating Composite Constant value: {} ::= {} -- Values: {}", constName, formula, newValues);
115-
Double formulaValue = MathUtil.eval(formula, varValues1);
116-
newValues.put(constName, formulaValue);
117-
log.trace("MvvService.translateAndSetValues: Added Composite Constant value: {} = {}", constName, formulaValue);
118-
} catch (Exception e) {
119-
log.trace("MvvService.translateAndSetValues: Could not calculate Composite Constant value: {} ::= {} -- Values: {} -- Reason: {}", constName, formula, newValues, e.getMessage());
120-
newPending.put(formula, constName);
121-
}
73+
log.info("MvvService.translateAndSetValues: New Variable Values: {}", varValues);
74+
Map<String, Double> newValues = new HashMap<>();
75+
76+
// Process simple constants
77+
final Map<String, String> simpleBindings = bindings.get(ModelsService.SIMPLE_BINDING_KEY);
78+
varValues.forEach((k,v) -> {
79+
String constName = simpleBindings.get(k);
80+
if (StringUtils.isNotBlank(constName)) {
81+
if (v instanceof Number n)
82+
newValues.put(constName, n.doubleValue());
83+
else
84+
throw new IllegalArgumentException("Solution variable value is not a number: "+v);
85+
log.trace("MvvService.translateAndSetValues: Added Simple Constant value: {} = {}", constName, n);
86+
} else
87+
log.warn("MvvService.translateAndSetValues: No Constant found for Solution variable: {}", k);
88+
});
89+
log.debug("MvvService.translateAndSetValues: Simple Constant values: {}", newValues);
90+
91+
// Process composite constants
92+
Map<String, String> pending = new HashMap<>(bindings.get(ModelsService.COMPOSITE_BINDING_KEY));
93+
@NotNull final Map<String, Double> varValues1 = varValues.entrySet().stream().collect(Collectors.toMap(
94+
Map.Entry::getKey, e -> ((Number) e.getValue()).doubleValue()
95+
));
96+
while (! pending.isEmpty()) {
97+
Map<String, String> newPending = new HashMap<>();
98+
pending.forEach((formula, constName) -> {
99+
if (StringUtils.isNotBlank(formula) && StringUtils.isNotBlank(constName)) {
100+
try {
101+
log.trace("MvvService.translateAndSetValues: Calculating Composite Constant value: {} ::= {} -- Values: {}", constName, formula, newValues);
102+
Double formulaValue = MathUtil.eval(formula, varValues1);
103+
newValues.put(constName, formulaValue);
104+
log.trace("MvvService.translateAndSetValues: Added Composite Constant value: {} = {}", constName, formulaValue);
105+
} catch (Exception e) {
106+
log.trace("MvvService.translateAndSetValues: Could not calculate Composite Constant value: {} ::= {} -- Values: {} -- Reason: {}", constName, formula, newValues, e.getMessage());
107+
newPending.put(formula, constName);
122108
}
123-
});
124-
if (pending.size() == newPending.size())
125-
throw new IllegalArgumentException("Composite Constants cannot be calculated. Check for missing terms or circles in formulas: " + pending);
126-
pending = newPending;
127-
}
109+
}
110+
});
111+
if (pending.size()==newPending.size())
112+
throw new IllegalArgumentException("Composite Constants cannot be calculated. Check for missing terms or circles in formulas: "+pending);
113+
pending = newPending;
128114
}
129-
log.info("MvvService.translateAndSetValues: New Constant values: {}", newValues);
115+
log.info("MvvService.translateAndSetValues: New Constant values: {}", newValues);
130116

131-
setControlServiceConstants(newValues);
132-
}
117+
setControlServiceConstants(newValues);
118+
}
133119

134120
private void setControlServiceConstants(@NonNull Map<String, Double> newValues) {
135121
this.values = newValues;

0 commit comments

Comments
 (0)