Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/graph processor #41

Merged
merged 8 commits into from
Jan 3, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
import com.milesight.beaveriot.context.security.SecurityUserContext;
import com.milesight.beaveriot.eventbus.api.EventResponse;
import com.milesight.beaveriot.rule.RuleEngineComponentManager;
import com.milesight.beaveriot.rule.RuleEngineExecutor;
import com.milesight.beaveriot.rule.RuleEngineLifecycleManager;
import com.milesight.beaveriot.rule.model.flow.config.RuleFlowConfig;
import com.milesight.beaveriot.rule.model.flow.config.RuleNodeConfig;
import com.milesight.beaveriot.rule.model.trace.FlowTraceInfo;
import com.milesight.beaveriot.rule.model.trace.NodeTraceInfo;
import com.milesight.beaveriot.rule.support.JsonHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.CamelContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;
Expand All @@ -37,6 +39,15 @@ public class DemoRuleEngineController {
ExchangeFlowExecutor exchangeFlowExecutor;
@Autowired
private RuleEngineComponentManager ruleEngineComponentManager;
@Autowired
private RuleEngineExecutor ruleEngineExecutor;

@PostMapping("/public/exec/{directName}")
public String exec(@PathVariable("directName") String name, @RequestBody ExchangePayload exchangePayload) {
ruleEngineExecutor.execute("direct:" + name, exchangePayload);
return "success";
}


@GetMapping("/public/schema/{name}")
public String schema(@PathVariable("name") String name) {
Expand Down Expand Up @@ -77,13 +88,13 @@ public ResponseBody<NodeTraceInfo> testTrackNode(@RequestBody String ruleNodeCon
@PostMapping("/public/test-deploy/{config}")
public String testDeploy(@PathVariable("config") String config) throws IOException {

ClassPathResource classPathResource = new ClassPathResource("config-schema/"+config + ".json");
ClassPathResource classPathResource = new ClassPathResource("config-schema/choice/"+config + ".json");
String flowConfig = classPathResource.getContentAsString(Charset.defaultCharset());

RuleFlowConfig ruleFlowConfig = JsonHelper.fromJSON(flowConfig, RuleFlowConfig.class);
String yaml = ruleEngineLifecycleManager.deployFlow(ruleFlowConfig);
ruleEngineLifecycleManager.deployFlow(ruleFlowConfig);

return yaml;
return "success";
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.milesight.beaveriot.sample.rule.interceptor;

import com.milesight.beaveriot.rule.RuleNodeInterceptor;
import com.milesight.beaveriot.rule.model.flow.route.FromNode;
import com.milesight.beaveriot.rule.model.flow.route.RouteNode;
import com.milesight.beaveriot.rule.model.flow.route.base.OutputNode;
import com.milesight.beaveriot.rule.flow.yaml.RuleNodeInterceptor;
import com.milesight.beaveriot.rule.model.flow.yaml.FromNode;
import com.milesight.beaveriot.rule.model.flow.yaml.RouteNode;
import com.milesight.beaveriot.rule.model.flow.yaml.base.OutputNode;

/**
* @author leon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ camel:
languages:
- code:
- "groovy"
- "javascript"
- "js"
- "python"
- "mvel"
- "choice":
- "groovy"
- "javascript"
- "js"
- "python"
- "mvel"

Expand All @@ -84,7 +84,7 @@ oauth2:
- "/oauth2/token"
- "/user/register"
- "/user/status"
- "/**"
- "/public/**"

logging:
level:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
*/
public interface RuleEngineLifecycleManager {

@Deprecated
String generateRouteFlow(RuleFlowConfig ruleFlowConfig);

String deployFlow(RuleFlowConfig ruleFlowConfig);
void deployFlow(RuleFlowConfig ruleFlowConfig);

void deployFlow(String flowId, String flowRouteYaml);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.milesight.beaveriot.rule;

import com.milesight.beaveriot.rule.model.flow.route.FromNodeDefinition;
import com.milesight.beaveriot.rule.model.flow.route.ToNodeDefinition;
import org.springframework.core.Ordered;

/**
* @author leon
*/
public interface RuleNodeDefinitionInterceptor extends Ordered {

default FromNodeDefinition interceptFromNodeDefinition(String flowId, FromNodeDefinition fromNode) {
return fromNode;
}

default ToNodeDefinition interceptToNodeDefinition(String flowId, ToNodeDefinition toNodeDefinition) {
return toNodeDefinition;
}

@Override
default int getOrder() {
return 0;
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.milesight.beaveriot.rule.api;

import org.apache.camel.Exchange;

/**
* @author leon
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ public interface ExchangeHeaders {
*/
String EXCHANGE_FLOW_ID = "CamelExchangeFlowId";

String GRAPH_CHOICE_MATCH_ID = "CamelGraphChoiceMatchId";

String EXCHANGE_LATEST_TRACE_ID = "CamelExchangeLatestNodeId";

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public String generateUri(String id, Map<String, Object> parameters) {
.findFirst()
.orElse(null);
String path = id;
if (pathOptionDefinition != null ) {
if(ObjectUtils.isEmpty(parameters) || !parameters.containsKey(pathOptionDefinition.generateFullName())) {
if (pathOptionDefinition != null) {
if (ObjectUtils.isEmpty(parameters) || !parameters.containsKey(pathOptionDefinition.generateFullName())) {
//else use id as uri
if (pathOptionDefinition.isAutowired()) {
parameters.put(pathOptionDefinition.generateFullName(), id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* @author leon
*/
@Data
public class ComponentOptionDefinition extends ComponentOptionExtensionDefinition{
public class ComponentOptionDefinition extends ComponentOptionExtensionDefinition {

protected String name;
protected int index;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.milesight.beaveriot.rule.model.flow.route;
package com.milesight.beaveriot.rule.model.flow;

import com.milesight.beaveriot.rule.enums.ExpressionLanguage;
import com.milesight.beaveriot.rule.enums.LogicOperator;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.milesight.beaveriot.rule.model.flow.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.milesight.beaveriot.rule.enums.LogicOperator;
import com.milesight.beaveriot.rule.support.JsonHelper;
import lombok.Data;
import lombok.SneakyThrows;

import java.util.List;
import java.util.Optional;

/**
* @author leon
Expand All @@ -16,22 +16,46 @@ public class RuleChoiceConfig implements RuleConfig {

private String id;
private String componentName;
private String nodeName;
private ChoiceSettingConfig choice;
private RuleChoiceDataConfig data;

@SneakyThrows
public static RuleChoiceConfig create(JsonNode parameters) {
return JsonHelper.fromJSON(JsonHelper.toJSON(parameters), RuleChoiceConfig.class);
public static RuleChoiceConfig create(RuleNodeConfig ruleNodeConfig) {
RuleChoiceConfig ruleChoiceConfig = new RuleChoiceConfig();
RuleChoiceDataConfig dataConfig = JsonHelper.fromJSON(JsonHelper.toJSON(ruleNodeConfig.getParameters()), RuleChoiceDataConfig.class);
ruleChoiceConfig.setData(dataConfig);
ruleChoiceConfig.setId(ruleNodeConfig.getId());
ruleChoiceConfig.setComponentName(ruleNodeConfig.getComponentName());
return ruleChoiceConfig;
}

@Override
public String getName() {
return getConfigDataOptional().orElse(null).getNodeName();
}

private Optional<RuleChoiceDataConfig> getConfigDataOptional() {
RuleChoiceDataConfig dataConfig = getData();
return dataConfig == null ? Optional.empty() : Optional.of(dataConfig);
}

public List<RuleChoiceWhenConfig> getWhen() {
Optional<RuleChoiceDataConfig> dataConfig = getConfigDataOptional();
ChoiceSettingConfig choice = dataConfig.orElse(null).getChoice();
return choice != null ? choice.getWhen() : null;
}

public RuleChoiceOtherwiseConfig getOtherwise() {
Optional<RuleChoiceDataConfig> dataConfig = getConfigDataOptional();
ChoiceSettingConfig choice = dataConfig.orElse(null).getChoice();
return choice != null ? choice.getOtherwise() : null;
}

@Data
public static class RuleChoiceDataConfig {
private String nodeName;
private ChoiceSettingConfig choice;
}

@Data
public static class ChoiceSettingConfig {
private List<RuleChoiceWhenConfig> when;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public interface RuleConfig {

String getId();

default String getName() {
return null;
}

String getComponentName();

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ public class RuleFlowConfig {

private List<RuleEdgeConfig> edges;

private List<RuleConfig> initializedNodes = new ArrayList<>();

public void initialize() {
Assert.notNull(flowId, "flowId must not be empty");

nodes.stream().forEach(node -> {
if (node.getComponentName().equals(RuleConfig.COMPONENT_CHOICE)) {
initializedNodes.add(RuleChoiceConfig.create(node));
} else {
initializedNodes.add(node);
}
});
}

public static RuleFlowConfig create(String flowId) {
RuleFlowConfig flow = new RuleFlowConfig();
flow.setFlowId(flowId);
return flow;
}

public static RuleFlowConfig createSequenceFlow(String flowId, List<RuleNodeConfig> nodes) {

Assert.notEmpty(nodes, "nodes must not be empty");
Expand All @@ -28,9 +48,9 @@ public static RuleFlowConfig createSequenceFlow(String flowId, List<RuleNodeConf

List<RuleEdgeConfig> edgeConfigs = new ArrayList<>();
for (int i = 0; i < nodes.size() - 1; i++) {
RuleNodeConfig source = nodes.get(i);
RuleNodeConfig target = nodes.get(i + 1);
edgeConfigs.add(RuleEdgeConfig.create(source.getId(), target.getId(),null));
RuleConfig source = nodes.get(i);
RuleConfig target = nodes.get(i + 1);
edgeConfigs.add(RuleEdgeConfig.create(source.getId(), target.getId(), null));
}
flow.setEdges(edgeConfigs);
return flow;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public JsonNode getParameters() {
return data != null ? data.getParameters() : null;
}

@Override
public String getName() {
return data != null ? data.getNodeName() : null;
}

@Data
public static class RuleNodeDataConfig {
private String nodeName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.milesight.beaveriot.rule.model.flow.route;

import lombok.Getter;
import lombok.Setter;

/**
* @author leon
*/
@Getter
@Setter
public abstract class AbstractNodeDefinition {

private String id;
private String nameNode;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.milesight.beaveriot.rule.model.flow.route;

import com.milesight.beaveriot.rule.model.flow.ExpressionNode;
import com.milesight.beaveriot.rule.model.flow.config.RuleChoiceConfig;
import lombok.Data;
import org.springframework.util.Assert;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* @author leon
*/
@Data
public class ChoiceNodeDefinition extends AbstractNodeDefinition {

private Map<String, WhenNodeDefinition> whenNodeDefinitions = new LinkedHashMap<>();
private String otherwiseNodeId;

public static ChoiceNodeDefinition create(RuleChoiceConfig ruleChoiceConfig) {
//choice edge and nodes init
Assert.notNull(ruleChoiceConfig, "Invalid choice config, parameters is null");

ChoiceNodeDefinition choiceNodeDefinition = new ChoiceNodeDefinition();

ruleChoiceConfig.getWhen().forEach(when -> {
WhenNodeDefinition whenNodeDefinition = new WhenNodeDefinition(ExpressionNode.create(when));
choiceNodeDefinition.getWhenNodeDefinitions().put(when.getId(), whenNodeDefinition);
});

RuleChoiceConfig.RuleChoiceOtherwiseConfig otherwise = ruleChoiceConfig.getOtherwise();
if (otherwise != null) {
choiceNodeDefinition.setOtherwiseNodeId(otherwise.getId());
}
choiceNodeDefinition.setId(ruleChoiceConfig.getId());
choiceNodeDefinition.setNameNode(ruleChoiceConfig.getName());
return choiceNodeDefinition;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.milesight.beaveriot.rule.model.flow.route;

import com.milesight.beaveriot.rule.model.definition.ComponentDefinition;
import com.milesight.beaveriot.rule.model.flow.config.RuleNodeConfig;
import com.milesight.beaveriot.rule.support.ComponentParameterConverter;
import lombok.Getter;
import lombok.Setter;

import java.util.Map;

/**
* @author leon
*/
@Getter
@Setter
public class FromNodeDefinition extends AbstractNodeDefinition {

private String uri;
private Map<String, Object> parameters;

public static FromNodeDefinition create(String id, String nodeName, String uri, Map<String, Object> parameters) {
FromNodeDefinition fromNodeDefinition = new FromNodeDefinition();
fromNodeDefinition.setId(id);
fromNodeDefinition.setNameNode(nodeName);
fromNodeDefinition.setUri(uri);
fromNodeDefinition.setParameters(parameters);
return fromNodeDefinition;
}

public static FromNodeDefinition create(String flowId, RuleNodeConfig ruleNodeConfig, ComponentDefinition componentDefinition) {
Map<String, Object> parameters = ComponentParameterConverter.convertParameters(ruleNodeConfig.getParameters(), componentDefinition);
String uri = componentDefinition.generateUri(flowId, parameters);

FromNodeDefinition nodeDefinition = new FromNodeDefinition();
nodeDefinition.setId(ruleNodeConfig.getId());
nodeDefinition.setNameNode(ruleNodeConfig.getName());
nodeDefinition.setUri(uri);
nodeDefinition.setParameters(parameters);

return nodeDefinition;
}
}
Loading