chore(project): 添加项目配置文件和忽略规则
- 添加 Babel 配置文件支持 ES6+ 语法转换 - 添加 ESLint 忽略规则和配置文件 - 添加 Git 忽略规则文件 - 添加 Travis CI 配置文件 - 添加 1.4.2 版本变更日志文件 - 添加 Helm 图表辅助模板文件 - 添加 Helm 忽略规则文件
This commit is contained in:
31
saga/seata-saga-processctrl/pom.xml
Normal file
31
saga/seata-saga-processctrl/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2019 Seata.io Group.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>seata-saga</artifactId>
|
||||
<groupId>io.seata</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<name>seata-saga-processctrl ${project.version}</name>
|
||||
<artifactId>seata-saga-processctrl</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Hierarchical process context
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface HierarchicalProcessContext extends ProcessContext {
|
||||
|
||||
/**
|
||||
* Gets get variable locally.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the get variable locally
|
||||
*/
|
||||
Object getVariableLocally(String name);
|
||||
|
||||
/**
|
||||
* Sets set variable locally.
|
||||
*
|
||||
* @param name the name
|
||||
* @param value the value
|
||||
*/
|
||||
void setVariableLocally(String name, Object value);
|
||||
|
||||
/**
|
||||
* Gets get variables locally.
|
||||
*
|
||||
* @return the get variables locally
|
||||
*/
|
||||
Map<String, Object> getVariablesLocally();
|
||||
|
||||
/**
|
||||
* Sets set variables locally.
|
||||
*
|
||||
* @param variables the variables
|
||||
*/
|
||||
void setVariablesLocally(Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* Has variable local boolean.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the boolean
|
||||
*/
|
||||
boolean hasVariableLocal(String name);
|
||||
|
||||
/**
|
||||
* Remove variable locally.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the removed variable or null
|
||||
*/
|
||||
Object removeVariableLocally(String name);
|
||||
|
||||
/**
|
||||
* Clear locally.
|
||||
*/
|
||||
void clearLocally();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
/**
|
||||
* Instruction
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author xi.chen
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface Instruction {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Process Context
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface ProcessContext {
|
||||
|
||||
String VAR_NAME_PROCESS_TYPE = "_ProcessType_";
|
||||
|
||||
/**
|
||||
* Gets get variable.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the get variable
|
||||
*/
|
||||
Object getVariable(String name);
|
||||
|
||||
/**
|
||||
* Sets set variable.
|
||||
*
|
||||
* @param name the name
|
||||
* @param value the value
|
||||
*/
|
||||
void setVariable(String name, Object value);
|
||||
|
||||
/**
|
||||
* Gets get variables.
|
||||
*
|
||||
* @return the get variables
|
||||
*/
|
||||
Map<String, Object> getVariables();
|
||||
|
||||
/**
|
||||
* Sets set variables.
|
||||
*
|
||||
* @param variables the variables
|
||||
*/
|
||||
void setVariables(Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* Remove variable.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the removed variable or null
|
||||
*/
|
||||
Object removeVariable(String name);
|
||||
|
||||
/**
|
||||
* Has variable boolean.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the boolean
|
||||
*/
|
||||
boolean hasVariable(String name);
|
||||
|
||||
/**
|
||||
* Gets get instruction.
|
||||
*
|
||||
* @return the get instruction
|
||||
*/
|
||||
Instruction getInstruction();
|
||||
|
||||
/**
|
||||
* Sets set instruction.
|
||||
*
|
||||
* @param instruction the instruction
|
||||
*/
|
||||
void setInstruction(Instruction instruction);
|
||||
|
||||
/**
|
||||
* Gets get instruction.
|
||||
*
|
||||
* @param <T> the type parameter
|
||||
* @param clazz the clazz
|
||||
* @return the get instruction
|
||||
*/
|
||||
<T extends Instruction> T getInstruction(Class<T> clazz);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
|
||||
/**
|
||||
* Process Controller
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface ProcessController {
|
||||
|
||||
/**
|
||||
* process business logic
|
||||
*
|
||||
* @param context
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
void process(ProcessContext context) throws FrameworkException;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
|
||||
/**
|
||||
* Process Router
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface ProcessRouter {
|
||||
|
||||
/**
|
||||
* route
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
Instruction route(ProcessContext context) throws FrameworkException;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
/**
|
||||
* Process type
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public enum ProcessType {
|
||||
|
||||
/**
|
||||
* SEATA State Language
|
||||
*/
|
||||
STATE_LANG("STATE_LANG", "SEATA State Language");
|
||||
|
||||
private String code;
|
||||
|
||||
private String message;
|
||||
|
||||
ProcessType(String code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* get enum by code
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public static ProcessType getEnumByCode(String code) {
|
||||
for (ProcessType codetmp : ProcessType.values()) {
|
||||
if (codetmp.getCode().equalsIgnoreCase(code)) {
|
||||
return codetmp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get code
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* get message
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
|
||||
/**
|
||||
* Event bus
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface EventBus<E> {
|
||||
|
||||
/**
|
||||
* insert add element into bus
|
||||
*
|
||||
* @param e
|
||||
* @return
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
boolean offer(E e) throws FrameworkException;
|
||||
|
||||
/**
|
||||
* get event consumers
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
List<EventConsumer> getEventConsumers(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* register event consumer
|
||||
*
|
||||
* @param eventConsumer
|
||||
*/
|
||||
void registerEventConsumer(EventConsumer eventConsumer);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
|
||||
/**
|
||||
* Event Consumer
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface EventConsumer<E> {
|
||||
|
||||
/**
|
||||
* process
|
||||
*
|
||||
* @param event
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
void process(E event) throws FrameworkException;
|
||||
|
||||
/**
|
||||
* if thd handler can handle this class return true otherwise return false
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
boolean accept(Class<E> clazz);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
|
||||
/**
|
||||
* Event publisher
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface EventPublisher<E> {
|
||||
|
||||
boolean publish(E event) throws FrameworkException;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.seata.saga.proctrl.eventing.EventBus;
|
||||
import io.seata.saga.proctrl.eventing.EventConsumer;
|
||||
|
||||
/**
|
||||
* Abstract Event Bus
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public abstract class AbstractEventBus<E> implements EventBus<E> {
|
||||
|
||||
private List<EventConsumer> eventConsumerList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public List<EventConsumer> getEventConsumers(Class clazz) {
|
||||
|
||||
List<EventConsumer> acceptedConsumers = new ArrayList<>();
|
||||
for (EventConsumer eventConsumer : eventConsumerList) {
|
||||
if (eventConsumer.accept(clazz)) {
|
||||
acceptedConsumers.add(eventConsumer);
|
||||
}
|
||||
}
|
||||
return acceptedConsumers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEventConsumer(EventConsumer eventConsumer) {
|
||||
eventConsumerList.add(eventConsumer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.eventing.EventConsumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Asynchronized EventBus
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class AsyncEventBus extends AbstractEventBus<ProcessContext> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AsyncEventBus.class);
|
||||
|
||||
private ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
@Override
|
||||
public boolean offer(ProcessContext context) throws FrameworkException {
|
||||
List<EventConsumer> eventConsumers = getEventConsumers(context.getClass());
|
||||
if (CollectionUtils.isEmpty(eventConsumers)) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn("cannot find event handler by class: " + context.getClass());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for (EventConsumer eventConsumer : eventConsumers) {
|
||||
threadPoolExecutor.execute(() -> eventConsumer.process(context));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor) {
|
||||
this.threadPoolExecutor = threadPoolExecutor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.eventing.EventConsumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Deliver event to event consumer directly
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class DirectEventBus extends AbstractEventBus<ProcessContext> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DirectEventBus.class);
|
||||
|
||||
private static final String VAR_NAME_SYNC_EXE_STACK = "_sync_execution_stack_";
|
||||
|
||||
@Override
|
||||
public boolean offer(ProcessContext context) throws FrameworkException {
|
||||
List<EventConsumer> eventHandlers = getEventConsumers(context.getClass());
|
||||
if (CollectionUtils.isEmpty(eventHandlers)) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn("cannot find event handler by class: " + context.getClass());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isFirstEvent = false;
|
||||
Stack<ProcessContext> currentStack = (Stack<ProcessContext>)context.getVariable(VAR_NAME_SYNC_EXE_STACK);
|
||||
if (currentStack == null) {
|
||||
synchronized (context) {
|
||||
currentStack = (Stack<ProcessContext>)context.getVariable(VAR_NAME_SYNC_EXE_STACK);
|
||||
if (currentStack == null) {
|
||||
currentStack = new Stack<>();
|
||||
context.setVariable(VAR_NAME_SYNC_EXE_STACK, currentStack);
|
||||
isFirstEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentStack.push(context);
|
||||
|
||||
if (isFirstEvent) {
|
||||
try {
|
||||
while (currentStack.size() > 0) {
|
||||
ProcessContext currentContext = currentStack.pop();
|
||||
for (EventConsumer eventHandler : eventHandlers) {
|
||||
eventHandler.process(currentContext);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
context.removeVariable(VAR_NAME_SYNC_EXE_STACK);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing.impl;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.ProcessController;
|
||||
import io.seata.saga.proctrl.eventing.EventConsumer;
|
||||
|
||||
/**
|
||||
* ProcessCtrl Event Consumer
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class ProcessCtrlEventConsumer implements EventConsumer<ProcessContext> {
|
||||
|
||||
private ProcessController processController;
|
||||
|
||||
@Override
|
||||
public void process(ProcessContext event) throws FrameworkException {
|
||||
|
||||
processController.process(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Class<ProcessContext> clazz) {
|
||||
return ProcessContext.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
public void setProcessController(ProcessController processController) {
|
||||
this.processController = processController;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.eventing.impl;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.eventing.EventBus;
|
||||
import io.seata.saga.proctrl.eventing.EventPublisher;
|
||||
|
||||
/**
|
||||
* ProcessCtrl Event Pulisher
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class ProcessCtrlEventPublisher implements EventPublisher<ProcessContext> {
|
||||
|
||||
private EventBus<ProcessContext> eventBus;
|
||||
|
||||
@Override
|
||||
public boolean publish(ProcessContext event) throws FrameworkException {
|
||||
return eventBus.offer(event);
|
||||
}
|
||||
|
||||
public void setEventBus(EventBus<ProcessContext> eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.seata.common.exception.FrameworkErrorCode;
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.Instruction;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.ProcessRouter;
|
||||
import io.seata.saga.proctrl.ProcessType;
|
||||
import io.seata.saga.proctrl.eventing.EventPublisher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Default Router handler
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class DefaultRouterHandler implements RouterHandler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRouterHandler.class);
|
||||
|
||||
private EventPublisher<ProcessContext> eventPublisher;
|
||||
private Map<String, ProcessRouter> processRouters;
|
||||
|
||||
public static ProcessType matchProcessType(ProcessContext context) {
|
||||
ProcessType processType = (ProcessType)context.getVariable(ProcessContext.VAR_NAME_PROCESS_TYPE);
|
||||
if (processType == null) {
|
||||
processType = ProcessType.STATE_LANG;
|
||||
}
|
||||
return processType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(ProcessContext context) throws FrameworkException {
|
||||
|
||||
try {
|
||||
ProcessType processType = matchProcessType(context);
|
||||
if (processType == null) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn("Process type not found, context= {}", context);
|
||||
}
|
||||
throw new FrameworkException(FrameworkErrorCode.ProcessTypeNotFound);
|
||||
}
|
||||
|
||||
ProcessRouter processRouter = processRouters.get(processType.getCode());
|
||||
if (processRouter == null) {
|
||||
LOGGER.error("Cannot find process router by type {}, context = {}", processType.getCode(), context);
|
||||
throw new FrameworkException(FrameworkErrorCode.ProcessRouterNotFound);
|
||||
}
|
||||
|
||||
Instruction instruction = processRouter.route(context);
|
||||
if (instruction == null) {
|
||||
LOGGER.info("route instruction is null, process end");
|
||||
} else {
|
||||
context.setInstruction(instruction);
|
||||
|
||||
eventPublisher.publish(context);
|
||||
}
|
||||
} catch (FrameworkException e) {
|
||||
throw e;
|
||||
} catch (Exception ex) {
|
||||
throw new FrameworkException(ex, ex.getMessage(), FrameworkErrorCode.UnknownAppError);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEventPublisher(EventPublisher<ProcessContext> eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
public void setProcessRouters(Map<String, ProcessRouter> processRouters) {
|
||||
this.processRouters = processRouters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.handler;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
|
||||
/**
|
||||
* Process Handler
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface ProcessHandler {
|
||||
|
||||
/**
|
||||
* process
|
||||
*
|
||||
* @param context
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
void process(ProcessContext context) throws FrameworkException;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.handler;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
|
||||
/**
|
||||
* Router Handler
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface RouterHandler {
|
||||
|
||||
/**
|
||||
* route
|
||||
*
|
||||
* @param context
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
void route(ProcessContext context) throws FrameworkException;
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import io.seata.saga.proctrl.HierarchicalProcessContext;
|
||||
import io.seata.saga.proctrl.Instruction;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
|
||||
/**
|
||||
* The default process context implementation
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class ProcessContextImpl implements HierarchicalProcessContext, ProcessContext {
|
||||
|
||||
private Map<String, Object> variables = new ConcurrentHashMap<>();
|
||||
private Instruction instruction;
|
||||
private ProcessContext parent;
|
||||
|
||||
@Override
|
||||
public Object getVariable(String name) {
|
||||
if (variables.containsKey(name)) {
|
||||
return variables.get(name);
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
return parent.getVariable(name);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVariable(String name, Object value) {
|
||||
if (variables.containsKey(name)) {
|
||||
setVariableLocally(name, value);
|
||||
} else {
|
||||
if (parent != null) {
|
||||
parent.setVariable(name, value);
|
||||
} else {
|
||||
setVariableLocally(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getVariables() {
|
||||
final Map<String, Object> collectedVariables = new HashMap<>();
|
||||
|
||||
if (parent != null) {
|
||||
collectedVariables.putAll(parent.getVariables());
|
||||
}
|
||||
variables.forEach(collectedVariables::put);
|
||||
return collectedVariables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVariables(final Map<String, Object> variables) {
|
||||
if (variables != null) {
|
||||
variables.forEach(this::setVariable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getVariableLocally(String name) {
|
||||
return variables.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVariableLocally(String name, Object value) {
|
||||
variables.put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getVariablesLocally() {
|
||||
return Collections.unmodifiableMap(variables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVariablesLocally(Map<String, Object> variables) {
|
||||
this.variables.putAll(variables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVariable(String name) {
|
||||
if (variables.containsKey(name)) {
|
||||
return true;
|
||||
}
|
||||
if (parent != null) {
|
||||
return parent.hasVariable(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instruction getInstruction() {
|
||||
return instruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInstruction(Instruction instruction) {
|
||||
this.instruction = instruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Instruction> T getInstruction(Class<T> clazz) {
|
||||
return (T)instruction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVariableLocal(String name) {
|
||||
return variables.containsKey(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object removeVariable(String name) {
|
||||
if (variables.containsKey(name)) {
|
||||
return variables.remove(name);
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
return parent.removeVariable(name);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object removeVariableLocally(String name) {
|
||||
return variables.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLocally() {
|
||||
variables.clear();
|
||||
}
|
||||
|
||||
public ProcessContext getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(ProcessContext parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + "variables=" + variables + ", instruction=" + instruction + ", parent=" + parent + '}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.impl;
|
||||
|
||||
import io.seata.common.exception.FrameworkErrorCode;
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.ProcessController;
|
||||
import io.seata.saga.proctrl.process.BusinessProcessor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Default implementation of Process controller
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class ProcessControllerImpl implements ProcessController {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ProcessControllerImpl.class);
|
||||
|
||||
private BusinessProcessor businessProcessor;
|
||||
|
||||
@Override
|
||||
public void process(ProcessContext context) throws FrameworkException {
|
||||
|
||||
try {
|
||||
|
||||
businessProcessor.process(context);
|
||||
|
||||
businessProcessor.route(context);
|
||||
|
||||
} catch (FrameworkException fex) {
|
||||
throw fex;
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Unknown exception occurred, context = {}", context, ex);
|
||||
throw new FrameworkException(ex, "Unknown exception occurred", FrameworkErrorCode.UnknownAppError);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBusinessProcessor(BusinessProcessor businessProcessor) {
|
||||
this.businessProcessor = businessProcessor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.process;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
|
||||
/**
|
||||
* Business logic processor
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public interface BusinessProcessor {
|
||||
|
||||
/**
|
||||
* process business logic
|
||||
*
|
||||
* @param context
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
void process(ProcessContext context) throws FrameworkException;
|
||||
|
||||
/**
|
||||
* route
|
||||
*
|
||||
* @param context
|
||||
* @throws FrameworkException
|
||||
*/
|
||||
void route(ProcessContext context) throws FrameworkException;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.process.impl;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.seata.common.exception.FrameworkErrorCode;
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.ProcessType;
|
||||
import io.seata.saga.proctrl.handler.ProcessHandler;
|
||||
import io.seata.saga.proctrl.handler.RouterHandler;
|
||||
import io.seata.saga.proctrl.process.BusinessProcessor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Customizable Business Processor
|
||||
*
|
||||
* @author jin.xie
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class CustomizeBusinessProcessor implements BusinessProcessor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CustomizeBusinessProcessor.class);
|
||||
|
||||
private Map<String, ProcessHandler> processHandlers;
|
||||
|
||||
private Map<String, RouterHandler> routerHandlers;
|
||||
|
||||
public static ProcessType matchProcessType(ProcessContext context) {
|
||||
ProcessType processType = (ProcessType)context.getVariable(ProcessContext.VAR_NAME_PROCESS_TYPE);
|
||||
if (processType == null) {
|
||||
processType = ProcessType.STATE_LANG;
|
||||
}
|
||||
return processType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ProcessContext context) throws FrameworkException {
|
||||
|
||||
ProcessType processType = matchProcessType(context);
|
||||
if (processType == null) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn("Process type not found, context= {}", context);
|
||||
}
|
||||
throw new FrameworkException(FrameworkErrorCode.ProcessTypeNotFound);
|
||||
}
|
||||
|
||||
ProcessHandler processor = processHandlers.get(processType.getCode());
|
||||
if (processor == null) {
|
||||
LOGGER.error("Cannot find process handler by type {}, context= {}", processType.getCode(), context);
|
||||
throw new FrameworkException(FrameworkErrorCode.ProcessHandlerNotFound);
|
||||
}
|
||||
|
||||
processor.process(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void route(ProcessContext context) throws FrameworkException {
|
||||
|
||||
ProcessType processType = matchProcessType(context);
|
||||
if (processType == null) {
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
LOGGER.warn("Process type not found, the process is no longer advanced, context= {}", context);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
RouterHandler router = routerHandlers.get(processType.getCode());
|
||||
if (router == null) {
|
||||
LOGGER.error("Cannot find router handler by type {}, context= {}", processType.getCode(), context);
|
||||
return;
|
||||
}
|
||||
|
||||
router.route(context);
|
||||
}
|
||||
|
||||
public void setProcessHandlers(Map<String, ProcessHandler> processHandlers) {
|
||||
this.processHandlers = processHandlers;
|
||||
}
|
||||
|
||||
public void setRouterHandlers(Map<String, RouterHandler> routerHandlers) {
|
||||
this.routerHandlers = routerHandlers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.seata.saga.proctrl.eventing.impl.AsyncEventBus;
|
||||
import io.seata.saga.proctrl.eventing.impl.DirectEventBus;
|
||||
import io.seata.saga.proctrl.eventing.impl.ProcessCtrlEventConsumer;
|
||||
import io.seata.saga.proctrl.eventing.impl.ProcessCtrlEventPublisher;
|
||||
import io.seata.saga.proctrl.handler.DefaultRouterHandler;
|
||||
import io.seata.saga.proctrl.handler.ProcessHandler;
|
||||
import io.seata.saga.proctrl.handler.RouterHandler;
|
||||
import io.seata.saga.proctrl.impl.ProcessContextImpl;
|
||||
import io.seata.saga.proctrl.impl.ProcessControllerImpl;
|
||||
import io.seata.saga.proctrl.mock.MockInstruction;
|
||||
import io.seata.saga.proctrl.mock.MockProcessHandler;
|
||||
import io.seata.saga.proctrl.mock.MockProcessRouter;
|
||||
import io.seata.saga.proctrl.process.impl.CustomizeBusinessProcessor;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* ProcessController Tests
|
||||
*
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class ProcessControllerTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleProcessCtrl() {
|
||||
|
||||
try {
|
||||
ProcessCtrlEventPublisher processCtrlEventPublisher = buildEventPublisher();
|
||||
|
||||
ProcessContext context = new ProcessContextImpl();
|
||||
MockInstruction instruction = new MockInstruction();
|
||||
instruction.setTestString("one");
|
||||
context.setInstruction(instruction);
|
||||
context.setVariable("TEST", "test");
|
||||
|
||||
processCtrlEventPublisher.publish(context);
|
||||
} catch (Exception e) {
|
||||
Assertions.fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleProcessCtrlAsync() {
|
||||
|
||||
try {
|
||||
ProcessCtrlEventPublisher processCtrlEventPublisher = buildAsyncEventPublisher();
|
||||
|
||||
ProcessContext context = new ProcessContextImpl();
|
||||
MockInstruction instruction = new MockInstruction();
|
||||
instruction.setTestString("one");
|
||||
context.setInstruction(instruction);
|
||||
context.setVariable("TEST", "test");
|
||||
|
||||
processCtrlEventPublisher.publish(context);
|
||||
} catch (Exception e) {
|
||||
Assertions.fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
private ProcessCtrlEventPublisher buildEventPublisher() throws Exception {
|
||||
ProcessCtrlEventPublisher syncEventPublisher = new ProcessCtrlEventPublisher();
|
||||
|
||||
ProcessControllerImpl processorController = createProcessorController(syncEventPublisher);
|
||||
|
||||
ProcessCtrlEventConsumer processCtrlEventConsumer = new ProcessCtrlEventConsumer();
|
||||
processCtrlEventConsumer.setProcessController(processorController);
|
||||
|
||||
DirectEventBus directEventBus = new DirectEventBus();
|
||||
syncEventPublisher.setEventBus(directEventBus);
|
||||
|
||||
directEventBus.registerEventConsumer(processCtrlEventConsumer);
|
||||
|
||||
return syncEventPublisher;
|
||||
}
|
||||
|
||||
private ProcessCtrlEventPublisher buildAsyncEventPublisher() throws Exception {
|
||||
ProcessCtrlEventPublisher asyncEventPublisher = new ProcessCtrlEventPublisher();
|
||||
|
||||
ProcessControllerImpl processorController = createProcessorController(asyncEventPublisher);
|
||||
|
||||
ProcessCtrlEventConsumer processCtrlEventConsumer = new ProcessCtrlEventConsumer();
|
||||
processCtrlEventConsumer.setProcessController(processorController);
|
||||
|
||||
AsyncEventBus asyncEventBus = new AsyncEventBus();
|
||||
asyncEventBus.setThreadPoolExecutor(
|
||||
new ThreadPoolExecutor(1, 5, 5000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()));
|
||||
|
||||
asyncEventPublisher.setEventBus(asyncEventBus);
|
||||
|
||||
asyncEventBus.registerEventConsumer(processCtrlEventConsumer);
|
||||
|
||||
return asyncEventPublisher;
|
||||
}
|
||||
|
||||
private ProcessControllerImpl createProcessorController(ProcessCtrlEventPublisher eventPublisher) throws Exception {
|
||||
|
||||
DefaultRouterHandler defaultRouterHandler = new DefaultRouterHandler();
|
||||
defaultRouterHandler.setEventPublisher(eventPublisher);
|
||||
|
||||
Map<String, ProcessRouter> processRouterMap = new HashMap<>(1);
|
||||
processRouterMap.put(ProcessType.STATE_LANG.getCode(), new MockProcessRouter());
|
||||
defaultRouterHandler.setProcessRouters(processRouterMap);
|
||||
|
||||
CustomizeBusinessProcessor customizeBusinessProcessor = new CustomizeBusinessProcessor();
|
||||
|
||||
Map<String, ProcessHandler> processHandlerMap = new HashMap<>(1);
|
||||
processHandlerMap.put(ProcessType.STATE_LANG.getCode(), new MockProcessHandler());
|
||||
customizeBusinessProcessor.setProcessHandlers(processHandlerMap);
|
||||
|
||||
Map<String, RouterHandler> routerHandlerMap = new HashMap<>(1);
|
||||
routerHandlerMap.put(ProcessType.STATE_LANG.getCode(), defaultRouterHandler);
|
||||
customizeBusinessProcessor.setRouterHandlers(routerHandlerMap);
|
||||
|
||||
ProcessControllerImpl processorController = new ProcessControllerImpl();
|
||||
processorController.setBusinessProcessor(customizeBusinessProcessor);
|
||||
|
||||
return processorController;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.mock;
|
||||
|
||||
import io.seata.saga.proctrl.Instruction;
|
||||
|
||||
/**
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class MockInstruction implements Instruction {
|
||||
|
||||
private String testString;
|
||||
|
||||
public String getTestString() {
|
||||
return testString;
|
||||
}
|
||||
|
||||
public void setTestString(String testString) {
|
||||
this.testString = testString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MockInstruction{" + "testString='" + testString + '\'' + '}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.mock;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.handler.ProcessHandler;
|
||||
|
||||
/**
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class MockProcessHandler implements ProcessHandler {
|
||||
|
||||
@Override
|
||||
public void process(ProcessContext context) throws FrameworkException {
|
||||
System.out.println("MockProcessHandler.process executed. context: " + context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.saga.proctrl.mock;
|
||||
|
||||
import io.seata.common.exception.FrameworkException;
|
||||
import io.seata.saga.proctrl.Instruction;
|
||||
import io.seata.saga.proctrl.ProcessContext;
|
||||
import io.seata.saga.proctrl.ProcessRouter;
|
||||
|
||||
/**
|
||||
* @author lorne.cl
|
||||
*/
|
||||
public class MockProcessRouter implements ProcessRouter {
|
||||
|
||||
@Override
|
||||
public Instruction route(ProcessContext context) throws FrameworkException {
|
||||
System.out.println("MockProcessRouter.route executed. context: " + context);
|
||||
MockInstruction instruction = context.getInstruction(MockInstruction.class);
|
||||
if (instruction != null) {
|
||||
if ("one".equals(instruction.getTestString())) {
|
||||
instruction.setTestString("two");
|
||||
} else if ("two".equals(instruction.getTestString())) {
|
||||
instruction.setTestString("three");
|
||||
} else {
|
||||
instruction.setTestString(null);
|
||||
return null;//end process
|
||||
}
|
||||
}
|
||||
return instruction;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user