Skip to content
Merged

Dev #175

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flow-engine-example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.codingapi.flow</groupId>
<artifactId>flow-engine-parent</artifactId>
<version>0.0.65</version>
<version>0.0.66</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion flow-engine-framework/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.codingapi.flow</groupId>
<artifactId>flow-engine-parent</artifactId>
<version>0.0.65</version>
<version>0.0.66</version>
</parent>

<name>flow-engine-framework</name>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.codingapi.flow.cache;

import java.util.HashMap;
import java.util.Map;

/**
* 流程运行时脚本线程级缓存。
* <p>
* 在一次流程操作内缓存当前运行时的脚本快照(脚本key -&gt; 脚本内容),
* 供脚本代理({@code FlowScriptRuntimeContext})优先读取,从而隔离流程设计阶段
* 对脚本内容的修改对已经在运行的流程造成的影响。
* <p>
* 使用约定与 {@link FlowOperatorLocalThreadCache} 一致:
* 在 {@code FlowService} 各入口及延迟任务执行前调用 {@link #clear()} 清理,
* 各 {@code FlowXxxService} 加载运行时快照后调用 {@link #set(Map)} 装载。
*/
public class FlowRuntimeScriptLocalCache {

private final ThreadLocal<Map<String, String>> cache;

private FlowRuntimeScriptLocalCache() {
this.cache = new ThreadLocal<>();
}

private final static FlowRuntimeScriptLocalCache instance = new FlowRuntimeScriptLocalCache();

public static FlowRuntimeScriptLocalCache getInstance() {
return instance;
}

/**
* 清理当前线程的脚本快照缓存
*/
public void clear() {
this.cache.remove();
}

/**
* 装载当前运行时的脚本快照
*
* @param scripts 脚本key到脚本内容的映射,为 null 时清理缓存
*/
public void set(Map<String, String> scripts) {
if (scripts == null) {
this.cache.remove();
return;
}
this.cache.set(new HashMap<>(scripts));
}

/**
* 获取运行时快照中的脚本内容
*
* @param key 脚本key
* @return 快照中的脚本内容,无运行时快照或无该key时返回 null
*/
public String get(String key) {
Map<String, String> scripts = this.cache.get();
if (scripts == null) {
return null;
}
return scripts.get(key);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.codingapi.flow.domain;

import com.codingapi.flow.cache.FlowOperatorLocalThreadCache;
import com.codingapi.flow.cache.FlowRuntimeScriptLocalCache;
import com.codingapi.flow.service.impl.FlowDelayTriggerService;
import com.codingapi.flow.session.IRepositoryHolder;
import lombok.Getter;
Expand Down Expand Up @@ -80,6 +81,7 @@ private void start(IRepositoryHolder repositoryHolder) {
@Override
public void run() {
FlowOperatorLocalThreadCache.getInstance().clear();
FlowRuntimeScriptLocalCache.getInstance().clear();
FlowDelayTriggerService flowDelayTriggerService = repositoryHolder.createDelayTriggerService(task);
flowDelayTriggerService.trigger();
repositoryHolder.deleteDelayTask(task);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.codingapi.flow.script.utils.GroovyScriptUtils;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.util.StringUtils;
Expand All @@ -30,7 +30,7 @@ public class ActionCustomScript {
*/
public String getTriggerType(){
if(script!=null){
String scriptData = GroovyScriptCacheContext.getInstance()
String scriptData = FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.getScript();

Expand All @@ -47,7 +47,7 @@ public String getTriggerType(){
*/
public String execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
return GroovyScriptCacheContext.getInstance()
return FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -25,7 +25,7 @@ public class ActionDisplayScript {
*/
public boolean execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
return GroovyScriptCacheContext.getInstance()
return FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -27,7 +27,7 @@ public class ActionRejectScript {

public RejectResult execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
String result = GroovyScriptCacheContext.getInstance()
String result = FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
return new RejectResult(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -21,7 +21,7 @@ public class ConditionScript {

public boolean execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
return GroovyScriptCacheContext.getInstance()
return FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -29,7 +29,7 @@ public class ErrorTriggerScript {

public ErrorThrow execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
Object value = GroovyScriptCacheContext.getInstance()
Object value = FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
if(value instanceof String){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -25,7 +25,7 @@ public class NodeTitleScript {

public String execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
return GroovyScriptCacheContext.getInstance()
return FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -28,7 +28,7 @@ public class OperatorLoadScript {

public List<IFlowOperator> execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
List<Object> userIds = GroovyScriptCacheContext.getInstance()
List<Object> userIds = FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
List<Long> operatorIds = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.codingapi.flow.script.request.GroovyWorkflowRequest;
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -22,7 +22,7 @@ public class OperatorMatchScript {
private final String script;

public boolean execute(GroovyWorkflowRequest request) {
return GroovyScriptCacheContext.getInstance()
return FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -25,7 +25,7 @@ public class RouterNodeScript {

public String execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
return GroovyScriptCacheContext.getInstance()
return FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -28,7 +28,7 @@ public class SubProcessScript {
public FlowCreateRequest execute(FlowSession session) {
FlowRecord flowRecord = session.getCurrentRecord();
GroovyScriptRequest request = new GroovyScriptRequest(session);
FlowCreateRequest flowCreateRequest = GroovyScriptCacheContext.getInstance()
FlowCreateRequest flowCreateRequest = FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
flowCreateRequest.setParentRecordId(flowRecord.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.codingapi.flow.script.runtime.FlowScriptContext;
import com.codingapi.flow.session.FlowSession;
import com.codingapi.springboot.script.annotation.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;
import com.codingapi.flow.script.runtime.FlowScriptRuntimeContext;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -24,7 +24,7 @@ public class TriggerScript {

public void execute(FlowSession session) {
GroovyScriptRequest request = new GroovyScriptRequest(session);
GroovyScriptCacheContext.getInstance()
FlowScriptRuntimeContext.getInstance()
.getGroovyScript(script)
.invoke(Map.of("$bind", new GroovyScriptBind(FlowScriptContext.getInstance())), request);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.codingapi.flow.script.runtime;

import com.codingapi.flow.cache.FlowRuntimeScriptLocalCache;
import com.codingapi.springboot.script.GroovyScript;
import com.codingapi.springboot.script.cache.GroovyScriptCacheContext;

/**
* 流程运行时脚本代理。
* <p>
* 脚本统一获取入口,用于隔离流程设计阶段与运行时:
* <ul>
* <li>运行态(线程缓存中存在当前运行时的脚本快照):优先使用快照内容构造一个
* 独立的脚本对象返回,不会修改全局缓存中的脚本对象,从而避免设计期修改污染在途流程。</li>
* <li>非运行态(无运行时快照):直接返回全局脚本缓存中的脚本对象,代理逻辑不干预,
* 行为与原有实现完全一致。</li>
* </ul>
* 说明:脚本编译产物缓存以脚本内容的 SHA256 为键,因此使用同一脚本key执行快照内容
* 时会按内容独立编译缓存,与设计期修改后的新内容互不串扰。
*/
public class FlowScriptRuntimeContext {

private final static FlowScriptRuntimeContext instance = new FlowScriptRuntimeContext();

public static FlowScriptRuntimeContext getInstance() {
return instance;
}

/**
* 获取脚本对象。运行时优先使用快照内容,否则走全局脚本缓存。
*
* @param key 脚本key
* @return 脚本对象
*/
public GroovyScript getGroovyScript(String key) {
GroovyScript cached = GroovyScriptCacheContext.getInstance().getGroovyScript(key);
String snapshot = FlowRuntimeScriptLocalCache.getInstance().get(key);
if (snapshot == null) {
// 非运行态:不干预,返回全局缓存中的脚本对象
return cached;
}
// 运行态:使用运行时快照内容构造独立脚本对象,不修改全局缓存对象
GroovyScript.Builder builder = GroovyScript.builder(key)
.script(snapshot)
.method(cached != null && cached.getMethod() != null ? cached.getMethod() : "run");
if (cached != null) {
builder.returnType(cached.getReturnType())
.typeOne(cached.getTypeOne())
.typeTwo(cached.getTypeTwo())
.binds(cached.getBinds())
.requests(cached.getRequests());
}
return builder.build();
}
}
Loading