1. 为什么我们需要运行时构建事件流?
当我们在开发复杂业务系统时,经常会遇到这样的场景:可视化编辑器提供的功能已经无法满足我们的需求。比如在一个电商系统中,当用户下单后需要触发一系列复杂的后续操作——库存扣减、优惠券核销、物流单生成、积分计算、消息通知等。这些操作之间往往存在复杂的依赖关系和条件判断。
可视化编辑器虽然直观,但在处理以下情况时会显得力不从心:
- 需要动态生成流程分支
- 要根据运行时数据决定后续步骤
- 需要处理复杂的异常恢复逻辑
- 流程需要频繁变更且不能停机
这时,我们就需要转向程序化的事件流构建方式。通过代码来动态构建和调整事件流,可以获得更大的灵活性和控制力。
提示:不要一上来就考虑用代码实现所有逻辑,可视化编辑器+程序化扩展的组合往往是最佳实践。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心概念解析:TriggerHandle与ChainHandle
2.1 TriggerHandle:事件触发器
TriggerHandle是事件流的起点,它负责监听和捕获特定的事件。常见的实现方式包括:
- 数据库变更监听
- API调用拦截
- 消息队列消费
- 定时任务触发
一个典型的TriggerHandle定义如下(以TypeScript为例):
typescript复制interface TriggerHandle<T> {
// 唯一标识符
id: string;
// 触发条件判断
predicate: (context: T) => boolean;
// 触发时执行的回调
onTrigger: (context: T) => Promise<void>;
// 错误处理
onError?: (error: Error) => void;
}
2.2 ChainHandle:处理链节点
ChainHandle构成了事件流的处理单元,每个节点负责特定的业务逻辑。关键特性包括:
- 支持同步/异步处理
- 可以修改上下文数据
- 可以决定是否继续后续处理
- 支持重试和回滚
ChainHandle的典型实现:
typescript复制interface ChainHandle<T> {
// 处理优先级
priority: number;
// 是否启用
enabled: boolean;
// 处理逻辑
execute: (context: T) => Promise<boolean>;
// 补偿逻辑(用于回滚)
compensate?: (context: T) => Promise<void>;
}
3. 运行时构建事件流的实现模式
3.1 声明式构建
这种模式适合流程相对固定的场景。我们预先定义好处理链的模板,在运行时根据条件动态选择模板并填充参数。
typescript复制// 定义流程模板
const orderProcessTemplate = {
triggers: ['order.created'],
chains: [
{name: 'inventory', condition: ctx => !ctx.isVirtualProduct},
{name: 'coupon', condition: ctx => ctx.couponUsed},
{name: 'notification', always: true}
]
};
// 运行时构建
function buildRuntimeFlow(order) {
const flow = cloneDeep(orderProcessTemplate);
flow.chains = flow.chains.filter(chain =>
chain.condition ? chain.condition(order) : true
);
return flow;
}
3.2 编程式构建
对于需要高度动态化的场景,我们可以完全通过代码来构建事件流:
typescript复制class FlowBuilder {
private triggers: TriggerHandle[] = [];
private chains: ChainHandle[] = [];
addTrigger(trigger: TriggerHandle) {
this.triggers.push(trigger);
return this;
}
addChain(chain: ChainHandle) {
this.chains.push(chain);
return this;
}
build() {
return {
triggers: this.triggers,
chains: this.chains.sort((a, b) => a.priority - b.priority)
};
}
}
// 使用示例
const flow = new FlowBuilder()
.addTrigger(orderCreatedTrigger)
.addChain(inventoryChain)
.addChain(couponChain)
.build();
3.3 混合式构建
结合声明式和编程式的优点,我们可以创建更灵活的解决方案:
typescript复制function createDynamicFlow(config: FlowConfig, runtimeData: any) {
const builder = new FlowBuilder();
// 添加基础触发器
builder.addTrigger(config.baseTrigger);
// 动态添加处理链
for (const chainDef of config.chainDefinitions) {
if (shouldIncludeChain(chainDef, runtimeData)) {
const chain = createChain(chainDef, runtimeData);
builder.addChain(chain);
}
}
return builder.build();
}
4. 高级应用场景与实现技巧
4.1 条件分支与动态路由
在订单处理流程中,不同类型的订单可能需要不同的处理链:
typescript复制function buildOrderFlow(order) {
const builder = new FlowBuilder();
// 基础触发器
builder.addTrigger(orderCreatedTrigger);
// 根据订单类型添加不同处理链
if (order.type === 'physical') {
builder.addChain(inventoryChain)
.addChain(shippingChain);
} else if (order.type === 'digital') {
builder.addChain(licenseChain);
}
// 通用链
builder.addChain(notificationChain);
return builder.build();
}
4.2 流程监控与调试
运行时构建的事件流需要强大的监控能力:
typescript复制interface FlowMonitor {
// 记录流程执行轨迹
trace: (event: TraceEvent) => void;
// 获取当前流程状态
getState: () => FlowState;
// 重放特定流程
replay: (flowId: string) => Promise<void>;
}
// 使用装饰器模式增强ChainHandle
function withMonitoring(chain: ChainHandle): ChainHandle {
return {
...chain,
async execute(context) {
const startTime = Date.now();
monitor.trace({
type: 'chain_start',
chainId: chain.id,
timestamp: startTime
});
try {
const result = await chain.execute(context);
monitor.trace({
type: 'chain_end',
chainId: chain.id,
duration: Date.now() - startTime,
success: true
});
return result;
} catch (error) {
monitor.trace({
type: 'chain_end',
chainId: chain.id,
duration: Date.now() - startTime,
success: false,
error
});
throw error;
}
}
};
}
4.3 错误处理与恢复
健壮的事件流需要完善的错误处理机制:
typescript复制class ResilientFlow {
private chains: ChainHandle[];
private currentIndex = 0;
constructor(chains: ChainHandle[]) {
this.chains = chains;
}
async execute(context: any) {
while (this.currentIndex < this.chains.length) {
const chain = this.chains[this.currentIndex];
try {
const shouldContinue = await chain.execute(context);
if (!shouldContinue) break;
this.currentIndex++;
} catch (error) {
if (chain.compensate) {
await chain.compensate(context);
}
throw error;
}
}
}
async retry(context: any) {
if (this.currentIndex > 0) {
this.currentIndex--;
return this.execute(context);
}
}
}
5. 性能优化实践
5.1 懒加载处理链
对于大型系统,不是所有处理链都需要立即加载:
typescript复制class LazyChainHandle implements ChainHandle {
private loader: () => Promise<ChainHandle>;
private instance: ChainHandle | null = null;
constructor(loader: () => Promise<ChainHandle>) {
this.loader = loader;
}
async execute(context: any) {
if (!this.instance) {
this.instance = await this.loader();
}
return this.instance.execute(context);
}
}
// 使用示例
const lazyChain = new LazyChainHandle(
