GithubHelp home page GithubHelp logo

dromara / liteflow Goto Github PK

View Code? Open in Web Editor NEW
2.7K 44.0 384.0 8.81 MB

Lightweight, fast, stable, and programmable component-based rule engine/process engine. Component reuse, synchronous/asynchronous orchestration, dynamic orchestration, multi-language scripting support, complex nested rules, hot deployment, smooth refreshing. Let you improve your development efficiency!

License: Apache License 2.0

Java 99.95% Groovy 0.03% CodeQL 0.02% Python 0.01%
component dsl flow-engine hot-reload java-rule-engine rule-engine workflow-engine java-rule rules-engine

liteflow's Introduction

logo

中文

Your star is my motivation to keep going. If you like LiteFlow, please help me with a star in the upper right corner.

Overview

LiteFlow is a lightweight and powerful rules engine framework, which can be used in the field of complex componenzed business orchestration. DSL rules drive the whole complex business, and can achieve smooth refresh hot deployment, supporting the embedding of multiple scripting language rules. Help the system become more silky and flexible.

LiteFlow was officially open source in 2020 and won the title of "the Most Popular Open Source software" in China in 2021. Gitee-GVP award in 2022. It is an open source project that is growing rapidly.

LiteFlow is a community-driven project. We take community building very seriously. We have a community of more than 4000 users who can respond to any problems or suggestions they encounter.

You can find out how to join the community on the official website!

Demo projects: DEMO1 | DEMO2

Feature

  • Component definition unified: All logic is a component, for all logic to provide a unified component implementation, small size, large energy.
  • Rules lightweight: based on the rules file to arrange the process, learning the rules entry only takes 5 minutes, a read both understand.
  • Rule diversification: rules support XML, JSON, YML three rule file writing methods, which you like to use.
  • Arbitrary arrangement: Synchronous asynchronous mixing, no matter how complex the logic process, using LiteFlow rules, are easy to do, see the rules file to see how the logic works.
  • Rules can be loaded from anywhere: The framework provides implementations of local file configuration sources and ZK configuration sources, as well as an extension interface that allows you to store rules anywhere.
  • Elegant hot refresh mechanism: Rule changes, instant change of application rules without restarting your application. High concurrency does not cause any errors in executing rules due to refreshing rules.
  • Wide support: LiteFlow works regardless of whether your project is built on Springboot, Spring, or any other Java framework.
  • JDK support: From JDK8 to JDK17. Don't worry about JDK versions.
  • Full Springboot support: Supports Springboot 2.X through the latest Springboot 3.X.
  • Scripting language support: You can define script language nodes that support Groovy, Javascript, QLExpress, Python, Lua, and Aviator. More script languages will be supported in the future.
  • Rule nesting support: You can use simple expressions to create multiple nested complex logic layouts if you want.
  • Component retry support: Components can support retry, and each component can customize the retry configuration and specify exceptions.
  • Context isolation mechanism: Reliable context isolation mechanism, you do not have to worry about high concurrency data flow.
  • Declarative component support: You can make any of your classes become components in seconds.
  • Detailed step information: How your link performs, how much time each component takes, what errors are reported at a glance.
  • Stable and reliable: has been iterating for more than 2 years, running stably on the core systems of major companies.
  • Excellent performance: the framework itself consumes little extra performance, depending on the efficiency of your component execution.
  • Built-in simple monitoring: Built-in a command line monitoring framework, you can know the running time ranking of each component.

What scenarios apply

LiteFlow is a choreographed rules engine that is best at decoupling your systems. If you have a complex system with bloated code, the LiteFlow framework is a great solution.

LiteFlow uses regular expressions to drive the engine that you define. Have you ever thought about how to write multithreaded process choreography like the following?

These processes can be easily solved with LiteFlow! The framework has a very low threshold to learn the expression language, but it can accomplish extremely high complexity of the choreography.

LiteFlow has an extremely detailed and easy-to-understand documentation, it can help you solve more than 95% of your problems when using the framework.

LiteFlow has 1500 test cases and more. Complete documentation and comprehensive test case coverage guarantee the stability of LiteFlow framework!

Looking forward to your use!

DISCORD LINK

Discord Link: https://discord.gg/MpdBSBnFTu

👑LF CLUB Community

LF CLUB is a premium paid community founded by the author of LiteFlow.

LF CLUB can help all users of the LiteFlow framework, as well as potential developers who want to use LiteFlow.

LF CLUB provides the following services:

1.Weekly releases of a condensed analysis series for LF. As long as users study along with the Planet series articles, they will definitely be able to fully grasp LF.

2.Provide a Q&A service where members can ask unlimited questions and receive detailed replies and guidance on the same day.

3.Each enrolled user is entitled to two remote one-on-one tutoring sessions per year as part of the remote assistance service.

4.Every 1 to 2 days, there will be updates on LF's current progress and the focus of the next version.

The LF CLUB can solve all the problems you encounter when using the LiteFlow framework. It offers a series of courses to help you gain a deep understanding of the LiteFlow framework. Unlike the WeChat community, the LF CLUB prioritizes the importance of questions and provides detailed answers.

Exclusive content helps you gain a profound understanding without the need to search for answers on other platforms. The author personally teaches, providing expert guidance at your fingertips, eliminating the need to seek help from others.

To join the LF CLUB, please scan the QR code below or click on the image to go directly to the website.

🦾Sponsor

MISBoot低代码开发平台

云程企业级低代码平台

驰骋工作流引擎

FastBee物联网平台

JNPF低代码开发平台

WECHAT OFFICIAL ACCOUNT

Since the community group is over 200 people, you need to be invited to join the group. Follow the WECHAT OFFICIAL ACCOUNT and click Personal WeChat to add me, I can invite you into the group

official-wx

Open source is not easy, please sponsor LiteFlow if you support it

support

liteflow's People

Contributors

0xlau avatar 1956025812 avatar 875082356 avatar aaronchen2012 avatar bryan31 avatar chisheyao avatar cnahyz avatar contantlearn avatar coufran avatar dale-lew avatar hanhuafeng avatar kugaaa avatar leoleewithwarmpants avatar limerence-zou avatar luoyi-yu avatar mchgood avatar mrzhang-badminton avatar mysinglelive avatar noear avatar ousinka avatar rainzs avatar shelikesnow avatar sika-code-cloud avatar superpg-wa avatar tclxfei3-liu avatar tonny0812 avatar wangtl avatar yuan2006 avatar zendwang avatar zy-zzf2000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

liteflow's Issues

com.yomahub.liteflow.exception.WhenTimeoutException: Timed out when executing the component[t3]

2024-01-24 15:39:01.949 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-3] c.e.c.handle.iterator.MaterialGather : =========工站号:OP10,物料采集,处理开始============
2024-01-24 15:39:01.949 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-4] c.eline.client.handle.iterator.PRGather : =========工站号:OP10,工序控制和工位结果,处理开始============
2024-01-24 15:39:01.949 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-5] c.e.c.handle.iterator.QualityGather : =========工站号:OP10,参数采集,处理开始============
2024-01-24 15:39:01.949 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-6] com.yomahub.liteflow.flow.element.Node : [e74c627c265a418fbabb500c98daba34]:[O]start component[t4] execution
2024-01-24 15:39:01.950 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-6] c.e.client.handle.iterator.StockGather : =========工站号:OP10,库存采集,处理开始============
2024-01-24 15:39:01.964 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-3] c.e.c.handle.iterator.MaterialGather : =========工站号:OP10,采集精追数据:[]=======
2024-01-24 15:39:01.973 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-3] c.e.c.handle.iterator.MaterialGather : =========工站号:OP10,采集物料数据:[RecordMaterialCollect(id=null, barcode=2400005, productCode=EH32, stationCode=OP10, stationName=OP10电机上线, orderCode=2131, materialBarcode=10000T0033440100000, materialCode=T0033440, materialName=电机壳体, workCard=null, shiftCode=SH001, createTime=Wed Jan 24 15:39:01 CST 2024)]=======
2024-01-24 15:39:01.974 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-3] c.e.c.handle.iterator.MaterialGather : =========工站号:OP10,物料采集,处理结束============
2024-01-24 15:39:01.974 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-3] c.e.c.handle.iterator.MaterialGather : [e74c627c265a418fbabb500c98daba34]:component[t1] finished in 24 milliseconds
2024-01-24 15:39:01.979 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-4] c.eline.client.handle.iterator.PRGather : =========工站号:OP10,保存工序控制:RecordProcessControl(id=12, barcode=2400005, routeCode=EH32_routelist, currentStationCode=OP10, nextStationCodes=OP20,OP30, createTime=Wed Jan 24 15:39:01 CST 2024, updateTime=null)============
2024-01-24 15:39:01.989 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-5] c.e.c.handle.iterator.QualityGather : [e74c627c265a418fbabb500c98daba34]:component[t3] finished in 39 milliseconds
2024-01-24 15:39:01.993 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-4] c.eline.client.handle.iterator.PRGather : =========工站号:OP10,采集工位结果:RecordStationResult(id=43, barcode=2400005, productCode=EH32, modelCode=1, stationCode=OP10, stationName=OP10电机上线, worklineCode=DJ01, orderCode=2131, shiftCode=SH001, palletNumber=1, workCard=null, isRework=false, result=1, createTime=Wed Jan 24 15:39:01 CST 2024)============
2024-01-24 15:39:01.993 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-4] c.eline.client.handle.iterator.PRGather : =========工站号:OP10,工序控制和工位结果,处理结束============
2024-01-24 15:39:01.993 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-4] c.eline.client.handle.iterator.PRGather : [e74c627c265a418fbabb500c98daba34]:component[t2] finished in 44 milliseconds
2024-01-24 15:39:01.999 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-6] c.e.client.handle.iterator.StockGather : =========工站号:OP10,库存采集,处理结束============
2024-01-24 15:39:01.999 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [ pool-13-thread-6] c.e.client.handle.iterator.StockGather : [e74c627c265a418fbabb500c98daba34]:component[t4] finished in 49 milliseconds
2024-01-24 15:39:02.000 39046ad77a6e42849f96e4e83d4cad4c WARN 53380 --- [68.8.81:20881-thread-1] c.y.l.f.p.s.AllOfParallelExecutor : [e74c627c265a418fbabb500c98daba34]:executing thread has reached max-wait-seconds, thread canceled.Execute-item: [t3]
2024-01-24 15:39:02.000 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [68.8.81:20881-thread-1] c.y.l.f.p.s.AllOfParallelExecutor : [e74c627c265a418fbabb500c98daba34]:when-executor[t3] execute failed. errorResume [false].
2024-01-24 15:39:02.002 39046ad77a6e42849f96e4e83d4cad4c ERROR 53380 --- [68.8.81:20881-thread-1] c.y.l.f.e.condition.CatchCondition : [e74c627c265a418fbabb500c98daba34]:catch exception:Timed out when executing the component[t3]

com.yomahub.liteflow.exception.WhenTimeoutException: Timed out when executing the component[t3]
at com.yomahub.liteflow.flow.parallel.WhenFutureObj.timeOut(WhenFutureObj.java:45)
at com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor.wrappedFutureObj(ParallelStrategyExecutor.java:55)
at com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor.lambda$getWhenAllTaskList$2(ParallelStrategyExecutor.java:149)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor.getWhenAllTaskList(ParallelStrategyExecutor.java:150)
at com.yomahub.liteflow.flow.parallel.strategy.AllOfParallelExecutor.execute(AllOfParallelExecutor.java:21)
at com.yomahub.liteflow.flow.element.condition.WhenCondition.executeAsyncCondition(WhenCondition.java:72)
at com.yomahub.liteflow.flow.element.condition.WhenCondition.executeCondition(WhenCondition.java:56)
at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:54)
at com.yomahub.liteflow.flow.element.condition.ThenCondition.executeCondition(ThenCondition.java:44)
at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:54)
at com.yomahub.liteflow.flow.element.condition.CatchCondition.executeCondition(CatchCondition.java:35)
at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:54)
at com.yomahub.liteflow.flow.element.Chain.execute(Chain.java:92)
at com.yomahub.liteflow.core.FlowExecutor.doExecute(FlowExecutor.java:403)
at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:323)
at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:269)
at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:264)
at com.eline.client.handle.common.WorkComplete.handle(WorkComplete.java:27)
at com.eline.client.handle.DefaultNodeHandler.lambda$handle$2(DefaultNodeHandler.java:61)
at java.util.Optional.ifPresent(Optional.java:159)
at com.eline.client.handle.DefaultNodeHandler.handle(DefaultNodeHandler.java:55)
at org.apache.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java)
at org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:47)
at org.apache.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:84)
at org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:56)
at org.apache.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:56)
at com.eline.client.filter.TraceIdFilter.invoke(TraceIdFilter.java:38)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:77)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:46)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:91)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:52)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:192)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:129)
at org.apache.dubbo.rpc.protocol.FilterNode.invoke(FilterNode.java:61)
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:148)
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.received(DubboProtocol.java:155)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:177)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
at java.lang.Thread.run(Thread.java:748)

2024-01-24 15:39:02.005 39046ad77a6e42849f96e4e83d4cad4c INFO 53380 --- [68.8.81:20881-thread-1] com.yomahub.liteflow.flow.element.Node : [e74c627c265a418fbabb500c98daba34]:[O]start component[z] execution
2024-01-24 15:39:02.008 39046ad77a6e42849f96e4e83d4cad4c ERROR 53380 --- [68.8.81:20881-thread-1] c.e.c.handle.common.ExceptionHandler : ============工站号:OP10,服务异常=============

我用When执行的时间才1秒左右,他就报超时,问题出现在哪里

组件ID可否支持名称空间功能

问题:业务组件ID没有名称空间的概念,且业务组件ID相同,组件之间互相覆盖
风险:1、没有名称空间,大型系统组件管理困难 2、组件ID相同,相互覆盖,这是一个很大安全隐患,如果后发布的组件ID同生产已有组件ID相同,将影响生产该业务运行

这有一个bug

这是我的测试demo的代码
@LiteflowComponent("a") @Slf4j public class ACmp extends NodeComponent { @Override public void process() { log.info("a正在执行"); } }
@LiteflowComponent("b") @Slf4j public class BCmp extends NodeComponent { @Override public void process() { log.info("b正在执行"); } }
@LiteflowComponent("c") @Slf4j public class CCmp extends NodeComponent { @Override public void process() { log.info("c正在执行"); } }
串行执行,或者串行+并行,是没有问题的,比如
<?xml version="1.0" encoding="UTF-8"?> <flow> <nodes> <node id="a" class="org.example.liteFlow.ACmp"/> <node id="b" class="org.example.liteFlow.BCmp"/> <node id="c" class="org.example.liteFlow.CCmp"/> </nodes> <chain name="chain1"> THEN( a, WHEN(b,c) ); </chain> </flow>
如果仅仅是并行执行,就会出现问题。如下
<?xml version="1.0" encoding="UTF-8"?> <flow> <nodes> <node id="a" class="org.example.liteFlow.ACmp"/> <node id="b" class="org.example.liteFlow.BCmp"/> <node id="c" class="org.example.liteFlow.CCmp"/> </nodes> <chain name="chain1"> WHEN(b,c); </chain> </flow>
就会报超时的ERROR
com.yomahub.liteflow.exception.WhenTimeoutException: Timed out when executing the component[b],when-max-timeout-seconds config is:15(s) at com.yomahub.liteflow.flow.parallel.WhenFutureObj.timeOut(WhenFutureObj.java:45) ~[liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.flow.element.condition.WhenCondition.lambda$executeAsyncCondition$2(WhenCondition.java:96) ~[liteflow-core-2.9.7.jar:2.9.7] at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_73] at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[na:1.8.0_73] at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[na:1.8.0_73] at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) ~[na:1.8.0_73] at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_73] at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_73] at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_73] at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_73] at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_73] at com.yomahub.liteflow.flow.element.condition.WhenCondition.executeAsyncCondition(WhenCondition.java:100) ~[liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.flow.element.condition.WhenCondition.execute(WhenCondition.java:55) ~[liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.flow.element.Chain.execute(Chain.java:93) ~[liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.core.FlowExecutor.doExecute(FlowExecutor.java:345) [liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:267) [liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:233) [liteflow-core-2.9.7.jar:2.9.7] at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:223) [liteflow-core-2.9.7.jar:2.9.7] at org.example.liteFlow.LiteFlowTest.test(LiteFlowTest.java:18) [classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_73] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:415) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1791) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE] at org.example.TestApplication.main(TestApplication.java:11) ~[classes/:na] 2023-02-19 22:59:27.728 INFO 1944 --- [ main] com.yomahub.liteflow.slot.Slot : [fba792cc914241a7a6a7645e9c6cb518]:CHAIN_NAME[chain1] 2023-02-19 22:59:27.728 INFO 1944 --- [ main] com.yomahub.liteflow.slot.DataBus : [fba792cc914241a7a6a7645e9c6cb518]:slot[0] released 2023-02-19 22:59:27.729 ERROR 1944 --- [lf-when-thead-0] com.yomahub.liteflow.flow.element.Node : [fba792cc914241a7a6a7645e9c6cb518]:component[b] cause error,error:null 2023-02-19 22:59:27.729 ERROR 1944 --- [lf-when-thead-1] com.yomahub.liteflow.flow.element.Node : [fba792cc914241a7a6a7645e9c6cb518]:component[c] cause error,error:null 2023-02-19 22:59:27.856 INFO 1944 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2023-02-19 22:59:27.942 INFO 1944 --- [ main] com.yomahub.liteflow.core.FlowExecutor : flow info loaded from local file,path=config/flow.el.xml 2023-02-19 22:59:28.419 INFO 1944 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator' 2023-02-19 22:59:28.456 INFO 1944 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8001 (http) with context path '' 2023-02-19 22:59:28.465 INFO 1944 --- [ main] org.example.TestApplication : Started TestApplication in 17.496 seconds (JVM running for 18.017)

版本是JDK 1.8 ,项目基于Spring boot2.3.12.RELEASE ,liteflow版本是2.9.7

异步线程池自定义

版本:2.6.3
异步线程池的初始化配置为:
@bean("whenExecutors")
public ExecutorService executorService(LiteflowConfig liteflowConfig) {
return ExecutorHelper.loadInstance().buildExecutor();
}

能否增加@ConditionalOnMissingBean注解,以便用户自定义:
@bean("whenExecutors")
@ConditionalOnMissingBean
public ExecutorService executorService(LiteflowConfig liteflowConfig) {
return ExecutorHelper.loadInstance().buildExecutor();
}

思考以下问题,如果有以下流程,第一个并行组出错还继续,第二个出错不继续。那么如果c报错,会走到e么? 感觉官网写的有问题

image

文档链接

文档内容如下

思考以下问题,如果有以下流程,第一个并行组出错还继续,第二个出错不继续。那么如果c报错,会走到e么

<when errorResume="true" value="a,b"/>
<when errorResume="false" value="c,d"/>
<then value="e"/>

应该是会走到e,因为他们是相通并行组,LiteFlow会进行合并,合并的话,errorResume会参照第一个来进行。也就等价于:

<when errorResume="true" value="a,b,c,d"/>
<then value="e"/>

所以会走到e


这里我试了好几次都没有走到e,如上图所示 :(
我严重怀疑是这样合并的...(没看源码,望作者看一下)

<when errorResume="true" value="a,b"/>
<when errorResume="false" value="c,d"/>
<then value="e"/>

<when errorResume="false" value="a,b,c,d"/>
<then value="e"/>

Direct self-reference leading to cycle

上手搞个demo运行报错各位大佬给看下
image
image
报错:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: com.yomahub.liteflow.flow.LiteflowResponse["slot"]->com.yomahub.liteflow.slot.Slot["executeSteps"]->java.util.concurrent.ConcurrentLinkedDeque[0]->com.yomahub.liteflow.flow.entity.CmpStep["instance"]->com.example.liteflowdemo.cmp.ACmp["self"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1308) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:948) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:726) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:479) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:318) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1572) ~[jackson-databind-2.15.4.jar:2.15.4]
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1061) ~[jackson-databind-2.15.4.jar:2.15.4]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:483) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:114) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:297) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:190) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:925) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:830) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.5.jar:6.1.5]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.19.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.5.jar:6.1.5]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.19.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.5.jar:6.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.5.jar:6.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.5.jar:6.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at java.base/java.lang.Thread.run(Thread.java:842) ~[na:na]

非SpringBoot环境使用报错

com.yomahub:liteflow-core:2.6.7 版本。
非Spring环境使用。

[INFO]2022-01-04 15:47:23.735 [main] com.yomahub.liteflow.core.FlowExecutor - flow info loaded from local file,path=config/flow.xml,format type=xml
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/util/Assert
at com.yomahub.liteflow.parser.FlowParser.matchRuleResources(FlowParser.java:71)
at com.yomahub.liteflow.parser.LocalXmlFlowParser.parseMain(LocalXmlFlowParser.java:25)
at com.yomahub.liteflow.core.FlowExecutor.init(FlowExecutor.java:102)
at cn.text.shop.jwest.TestFlowLite.main(TestFlowLite.java:17)
Caused by: java.lang.ClassNotFoundException: org.springframework.util.Assert
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

虽然引入org.springframework:spring-context:5.3.14 可以解决以上问题,但非Spring环境应能不依赖Spring framework相关组件。

FlowExecutor 异常优化

private Slot doExecute(String chainId, Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray,
			Integer slotIndex, InnerChainTypeEnum innerChainType) {
		//....

		Chain chain = null;
		try {
			chain = FlowBus.getChain(chainId);

			if (ObjectUtil.isNull(chain)) {
				String errorMsg = StrUtil.format("couldn't find chain with the id[{}]", chainId);
				throw new ChainNotFoundException(errorMsg);
			}
			// 执行chain
			chain.execute(slotIndex);
		}
		catch (ChainEndException e) {
			if (ObjectUtil.isNotNull(chain)) {
				String warnMsg = StrUtil.format("chain[{}] execute end on slot[{}]", chain.getChainId(), slotIndex);
				LOG.warn(warnMsg);
			}
		}
		catch (Exception e) {
			if (ObjectUtil.isNotNull(chain)) {
				String errMsg = StrUtil.format("chain[{}] execute error on slot[{}]", chain.getChainId(), slotIndex);
				if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())) {
					LOG.error(errMsg, e);
				}
				else {
					LOG.error(errMsg);
				}
			}
			else {
				if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())) {
					LOG.error(e.getMessage(), e);
				}
				else {
					LOG.error(e.getMessage());
				}
			}

			// 如果是正常流程需要把异常设置到slot的exception属性里
			// 如果是隐式流程,则需要设置到隐式流程的exception属性里
			if (innerChainType.equals(InnerChainTypeEnum.NONE)) {
				slot.setException(e);
			}
			else {
				slot.setSubException(chainId, e);
			}
		}
		finally {
			if (innerChainType.equals(InnerChainTypeEnum.NONE)) {
				slot.printStep();
				DataBus.releaseSlot(slotIndex);
				LFLoggerManager.removeRequestId();
			}
		}

catch (Exception e) 能否增加配置,异常部分继续往上抛?在不同公司或项目中,往往会有各种各样的异常

主线程挂起,程序不能结束

一、配置文件
`





<chain name="chain1">
    <then value="c,a,b"/> <!-- then表示串行 -->
    <when value="c,a,b"/> <!-- when表示并行 -->
    <then value="a"/> <!-- then表示串行 -->
</chain>

二、程序 public static void main(String[] args) {
FlowExecutor executor = new FlowExecutor();
LiteflowConfig liteflowConfig = new LiteflowConfig();
liteflowConfig.setRuleSource("flow.xml");
executor.setLiteflowConfig(liteflowConfig);
executor.init();
var response = executor.execute2Resp("chain1", "arg");
System.out.println(response.isSuccess());
//程序不能结束,挂起状态
}`
这个是因为配置不正确导致的吗?

关于FlowExecutor 填充元数据后,重新获取数据后,产生数据丢失和线程不安全的问题

我这边在使用 liteflow时 遇到一个问题 基于 liteflow-core 2.6.7
如上图 线程 29 和 30 在 FlowExecutor 装填参数的 时候 row 都是有值 ,而在 ActionComponent(NodeComponent的实现类)中获取到 slot.getRequestData() 的时候 ,row被置空了 而且 线程29 和 线程30 ,数据被污染了(被覆盖了),现象是随机出现的,同样的数据 前一次可能失败,后面的都是成功的 ,问题的发生没有规律性
请问 有遇到过这个情况吗?
微信图片_20230911134425
微信图片_20230911134425_1

关于日志是输出的补充

2023-09-11 13:11:11.238 INFO 16704 [http-nio-9003-exec-30] com.yomahub.liteflow.core.FlowExecutor slot[0] offered
2023-09-11 13:11:11.239 INFO 16704 [http-nio-9003-exec-29] com.yomahub.liteflow.core.FlowExecutor slot[0] offered
2023-09-11 13:11:11.239 INFO 16704 [http-nio-9003-exec-29] com.yomahub.liteflow.core.FlowExecutor requestId[zXVPZq4wdi8RqBrmwedJk] has generated
2023-09-11 13:11:11.239 INFO 16704 [http-nio-9003-exec-30] com.yomahub.liteflow.core.FlowExecutor requestId[EX9O89VV33A2agXpS5tmF] has generated

线程 29 和 30 生成的requestId 是不同的 但是 在slot 槽位的获取上,却同时获取到了 slot[0]

热刷新失败

STEP:
1、不停jvm进程,修改了flow xml
1、通过flowExecutor.reloadRule(); 刷新rule
2、不停jvm进程,重新run流程发现还是走的老的流程

一次报错两条error

FlowExecutor#doExecute 的 catch (Exception e) 强制打印error
FlowExecutor#doExecute 的 catch (Exception e) 强制打印error

导致一个错误,两次error日志,相关都关不掉,(无法使用ChainEndException--一条错误日志都没有),
建议加个配置,用户可以关闭打印error,根据LiteflowResponse#getCause()去打印error

使用 2.11.3 版本的starter时和logback冲突

加依赖包以下错误,不加能正常启动,在class-path下放了logback的配置xml

D:\runtime\microsoft\jdk-17.0.4.1+1\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:7510,suspend=y,server=n -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-Dmanagement.endpoints.jmx.exposure.include=*" -javaagent:C:\Users\Crawler\AppData\Local\JetBrains\IntelliJIdea2023.2\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\source\DigitalAgent\build\classes\java\main;D:\source\DigitalAgent\build\resources\main;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.30\f195ee86e6c896ea47a1d39defbe20eb59cd149d\lombok-1.18.30.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-actuator\3.1.5\6e543a2beff6a8e3f98cf6aa3b38495eb47d2ff2\spring-boot-starter-actuator-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.1.5\5fdcfab1fe9d6dddf4352d71f5ed879eb1aa92c2\spring-boot-starter-data-jpa-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.1.5\138c0e0ab493d8a51bb51dfc3b7144d702ff4c26\spring-boot-starter-jdbc-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.1.5\3674e5603cc25bc4dccf73b97d50234332fc3d72\spring-boot-starter-web-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.yomahub\liteflow-core\2.11.3\b4f77bcd74c40333a163a43777f8ac29397af786\liteflow-core-2.11.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.github.loki4j\loki-logback-appender\1.4.2\dafa84bbcb4e687113eaee6ace2029759cc60869\loki-logback-appender-1.4.2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\io.minio\minio\8.5.7\c17d6e693cfba62ad0822fde84336bb2ba814ff3\minio-8.5.7.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.1.5\a14cd17b86261933929566775d80c65b9f7440fc\spring-boot-starter-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-actuator-autoconfigure\3.1.5\a17f2f5c218615d7d55fd62cb1f8923257c621a5\spring-boot-actuator-autoconfigure-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\io.micrometer\micrometer-core\1.11.5\d87189697cd35a09bcd8666c56b58ba39e9a5a3\micrometer-core-1.11.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.11.5\803f341121416365d1c438fe2a7290b146fadc92\micrometer-observation-1.11.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-aop\3.1.5\2ac1f8bf4c2bce13b46d04abafc69a4f1523a08\spring-boot-starter-aop-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.2.13.Final\de458672b40154ab9ecfe7466987ad1772167af8\hibernate-core-6.2.13.Final.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.1.5\6de79da064f0b97c6448e0bfa5d63da9fb6e1582\spring-data-jpa-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.0.13\59b1d3f507f5ed2e4ef357541c464925831bea9b\spring-aspects-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.zaxxer\HikariCP\5.0.1\a74c7f0a37046846e88d54f7cb6ea6d565c65f9c\HikariCP-5.0.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.0.13\67227f30eef525551983ad02071770ea685f2626\spring-jdbc-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.1.5\36ce79c1a5c63ffd72b092eb312cb35ac6edb128\spring-boot-starter-json-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.0.13\df1230a7dde55b9ce9d72670b42d621dc2e481df\spring-webmvc-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-web\6.0.13\c374fcaf34d82d735a1dcf2c496f064488aa2b20\spring-web-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.1.5\4b362b923ec1ca080556c4e55fe4ae73cf5a84d7\spring-boot-starter-tomcat-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\cn.hutool\hutool-core\5.8.11\d3d5deb146e51eef43383202921c7dd4ecc7ff07\hutool-core-5.8.11.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.9\7cf2726fdcfbc8610f9a71fb3ed639871f315340\slf4j-api-2.0.9.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.15.3\a734bc2c47a9453c4efa772461a3aeb273c010d9\jackson-databind-2.15.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.yaml\snakeyaml\1.33\2cd0a87ff7df953f810c344bdf2fe3340b954c69\snakeyaml-1.33.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.dom4j\dom4j\2.1.3\a75914155a9f5808963170ec20653668a2ffd2fd\dom4j-2.1.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.alibaba\transmittable-thread-local\2.12.3\64a5beeb39b66ff08b5a9293ec620a3e0e46be47\transmittable-thread-local-2.12.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.14.9\b69e7fff6c473d3ed2b489cdfd673a091fd94226\byte-buddy-1.14.9.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.alibaba\QLExpress\3.3.2\16368390c79cc58290df1f74faac812f7b4c849e\QLExpress-3.3.2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\commons-beanutils\commons-beanutils\1.9.4\d52b9abcd97f38c81342bb7e7ae1eee9b73cba51\commons-beanutils-1.9.4.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\commons-io\commons-io\2.11.0\a2503f302b11ebde7ebc3df41daebe0e4eea3689\commons-io-2.11.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.4.11\54450c0c783e896a1a6d88c043bd2f1daba1c382\logback-classic-1.4.11.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.15.3\79baf4e605eb3bbb60b1c475d44a7aecceea1d60\jackson-annotations-2.15.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.15.3\60d600567c1862840397bf9ff5a92398edc5797b\jackson-core-2.15.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.carrotsearch.thirdparty\simple-xml-safe\2.7.1\45fda5ac6087bc82a209d8cdb73f8d0dbdcfc7b\simple-xml-safe-2.7.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.google.guava\guava\32.1.3-jre\f306708742ce2bf0fb0901216183bc14073feae\guava-32.1.3-jre.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.squareup.okhttp3\okhttp\4.10.0\cd63657ac15770ed1420647154c9f44645533bef\okhttp-4.10.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.bouncycastle\bcprov-jdk18on\1.76\3a785d0b41806865ad7e311162bfa3fa60b3965b\bcprov-jdk18on-1.76.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.apache.commons\commons-compress\1.24.0\b4b1b5a3d9573b2970fddab236102c0a4d27d35e\commons-compress-1.24.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.xerial.snappy\snappy-java\1.1.10.5\ac605269f3598506196e469f1fb0d7ed5c55059e\snappy-java-1.1.10.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.1.5\8d8a91061baa4347d97a8fe15f3337d943badab\spring-boot-starter-logging-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.1.5\42a5b2ee98f700fba8d8c88d4af7b23266f1de0f\spring-boot-autoconfigure-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.1.5\c188015a5a79f5df65e876dcfdef16148c45fe2c\spring-boot-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-core\6.0.13\cd565c2408e37d2026822b871cd43e69da8ec40e\spring-core-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-actuator\3.1.5\2114b2cfe95907c9e58489792cd5ec53569b9fbf\spring-boot-actuator-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.11.5\3e708f737ba2674823201a836b5858482b183902\micrometer-commons-1.11.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-aop\6.0.13\aae1a18033787c9d324322f4470b12264e773e83\spring-aop-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.20\da562407e43f74c0f8f5f5df4065d85ec1736d01\aspectjweaver-1.9.20.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-orm\6.0.13\604257dc4f28bf178c348a9e12068600838d61d2\spring-orm-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.1.5\227d0b2dd185458c58e89b2a4696d1b752536a72\spring-data-commons-3.1.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-context\6.0.13\4c49af6dde7fce9602049f952b45ca29f30e2a37\spring-context-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-tx\6.0.13\182219d97469f459e0c44033d5dc5260d042cfb\spring-tx-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-beans\6.0.13\5b205c9f2fb07c1367db144ce7ab305f94300604\spring-beans-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.10.1\10839f875928f59c622d675091d51a43ea0dc5f7\antlr4-runtime-4.10.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.15.3\4a20a0e104931bfa72f24ef358c2eb63f1ef2aaf\jackson-datatype-jsr310-2.15.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.15.3\8d251b90c5358677e7d8161e0c2488e6f84f49da\jackson-module-parameter-names-2.15.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.15.3\80158cb020c7bd4e4ba94d8d752a65729dc943b2\jackson-datatype-jdk8-2.15.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-expression\6.0.13\2bedffa4a3850bbbb652a31c47671824b17fbe01\spring-expression-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.15\14cc0999d4a5128dc9bb8862487aa8ed4cd7fcd8\tomcat-embed-websocket-10.1.15.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.15\e3a725405f494abc0fd4f30263c2e6ad87052de1\tomcat-embed-core-10.1.15.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.15\49e784ef48d5fc7bc48d7e2a7ceb57e88b4d58b7\tomcat-embed-el-10.1.15.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\commons-lang\commons-lang\2.4\16313e02a793435009f1e458fa4af5d879f6fb11\commons-lang-2.4.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\commons-logging\commons-logging\1.2\4bfc12adfe4842bf07b657f0369c4cb522955686\commons-logging-1.2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\commons-collections\commons-collections\3.2.2\8ad72fe39fa8c91eaaf12aadb21e0c3661fe26d5\commons-collections-3.2.2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.4.11\2f9f280219a9922a74200eaf7138c4c17fb87c0f\logback-core-1.4.11.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.google.guava\failureaccess\1.0.1\1dcf1de382a0bf95a3d8b0849546c88bac1292c9\failureaccess-1.0.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.google.guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\b421526c5f297295adef1c886e5246c39d4ac629\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.google.code.findbugs\jsr305\3.0.2\25ea2e8b0c338a877313bd4672d3fe056ea78f0d\jsr305-3.0.2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.checkerframework\checker-qual\3.37.0\ba74746d38026581c12166e164bb3c15e90cc4ea\checker-qual-3.37.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.google.errorprone\error_prone_annotations\2.21.1\6d9b10773b5237df178a7b3c1b4208df7d0e7f94\error_prone_annotations-2.21.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.google.j2objc\j2objc-annotations\2.8\c85270e307e7b822f1086b93689124b89768e273\j2objc-annotations-2.8.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.8.22\636bf8b320e7627482771bbac9ed7246773c02bd\kotlin-stdlib-1.8.22.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.20.0\d37f81f8978e2672bc32c82712ab4b3f66624adc\log4j-to-slf4j-2.20.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.9\9ef7c70b248185845f013f49a33ff9ca65b7975\jul-to-slf4j-2.0.9.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.0.13\91ea90f2de4c71dac3cff04882156b00cdca3e0d\spring-jcl-6.0.13.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.squareup.okio\okio-jvm\3.0.0\ab5a73fa2ccb4a36b0b5c69fe10b16d0255bcf8\okio-jvm-3.0.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.8.22\1a8e3601703ae14bb58757ea6b2d8e8e5935a586\kotlin-stdlib-common-1.8.22.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.jetbrains\annotations\13.0\919f0dfe192fb4e063e7dacadee7f8bb9a2672a9\annotations-13.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.20.0\1fe6082e660daf07c689a89c94dc0f49c26b44bb\log4j-api-2.20.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.8.22\b25c86d47d6b962b9cf0f8c3f320c8a10eea3dd1\kotlin-stdlib-jdk8-1.8.22.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.8.22\4dabb8248310d833bb6a8b516024a91fd3d275c\kotlin-stdlib-jdk7-1.8.22.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.mysql\mysql-connector-j\8.0.33\9e64d997873abc4318620264703d3fdb6b02dd5a\mysql-connector-j-8.0.33.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.postgresql\postgresql\42.6.0\7614cfce466145b84972781ab0079b8dea49e363\postgresql-42.6.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.hdrhistogram\HdrHistogram\2.1.12\6eb7552156e0d517ae80cc2247be1427c8d90452\HdrHistogram-2.1.12.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.latencyutils\LatencyUtils\2.0.3\769c0b82cb2421c8256300e907298a9410a2a3d3\LatencyUtils-2.0.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.5.3.Final\c88fc1d8a96d4c3491f55d4317458ccad53ca663\jboss-logging-3.5.3.Final.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\6.0.6.Final\77a5f94b56d49508e0ee334751db5b78e5ccd50c\hibernate-commons-annotations-6.0.6.Final.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\io.smallrye\jandex\3.0.5\c548a4871b552292dbdd65409d3fda145c8925c1\jandex-3.0.5.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.fasterxml\classmate\1.5.1\3fe0bed568c62df5e89f4f174c101eab25345b6c\classmate-1.5.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.3\93af25be25b2c92c83e0ce61cb8b3ed23568f316\jaxb-runtime-4.0.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.1\ca2330866cbc624c7e5ce982e121db1125d23e15\jakarta.xml.bind-api-4.0.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jaxen\jaxen\2.0.0\bd6a33b0fda054a5678010df843cc999f288dc6c\jaxen-2.0.0.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\javax.xml.stream\stax-api\1.0-2\d6337b0de8b25e53e81b922352fbea9f9f57ba0b\stax-api-1.0-2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\net.java.dev.msv\xsdlib\2013.6.1\280f7c45aaec5102cc756d1afdb416b7775f2ef4\xsdlib-2013.6.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\javax.xml.bind\jaxb-api\2.2.12\4c83805595b15acf41d71d49e3add7c0e85baaed\jaxb-api-2.2.12.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\pull-parser\pull-parser\2\c2f040085bfcd35963e9504bec11dac57cd0a86e\pull-parser-2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\xpp3\xpp3\1.1.4c\9b988ea84b9e4e9f1874e390ce099b8ac12cfff5\xpp3-1.1.4c.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.3\e9093b4a82069a1d78ee9a3233ca387bca88861f\jaxb-core-4.0.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.2\640c0d5aff45dbff1e1a1bc09673ff3a02b1ba12\jakarta.activation-api-2.1.2.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\relaxngDatatype\relaxngDatatype\20020414\de7952cecd05b65e0e4370cc93fc03035175eef5\relaxngDatatype-20020414.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.1\eaafaf4eb71b400e4136fc3a286f50e34a68ecb7\angus-activation-2.0.1.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.3\47b8fe31c6d1a3382203af919400527389e01e9c\txw2-4.0.3.jar;D:\runtime\gradle-8.4\repo\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2023.2.1\lib\idea_rt.jar" com.zjuici.agent.DigitalAgentApplication
Connected to the target VM, address: '127.0.0.1:7510', transport: 'socket'
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
Logging system failed to initialize using configuration from 'classpath:logback-spring.xml'
java.lang.IllegalStateException: Could not initialize Logback logging from classpath:logback-spring.xml
at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:250)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.withLoggingSuppressed(LogbackLoggingSystem.java:460)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:242)
at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithSpecificConfig(AbstractLoggingSystem.java:66)
at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:57)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:189)
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:335)
at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:174)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
at com.zjuici.agent.DigitalAgentApplication.main(DigitalAgentApplication.java:10)
Caused by: ch.qos.logback.core.joran.spi.JoranException: Error during parser creation or parser configuration
at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:99)
at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:62)
at ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(GenericXMLConfigurator.java:184)
at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:158)
at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:285)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:247)
... 25 more
Caused by: org.xml.sax.SAXNotRecognizedException: unrecognized feature http://xml.org/sax/features/external-general-entities
at org.gjt.xpp.sax2.Driver.setFeature(Driver.java:178)
at org.gjt.xpp.jaxp11.SAXParserImpl.setFeatures(SAXParserImpl.java:149)
at org.gjt.xpp.jaxp11.SAXParserImpl.(SAXParserImpl.java:132)
at org.gjt.xpp.jaxp11.SAXParserFactoryImpl.newSAXParserImpl(SAXParserFactoryImpl.java:114)
at org.gjt.xpp.jaxp11.SAXParserFactoryImpl.setFeature(SAXParserFactoryImpl.java:142)
at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:88)
... 32 more
Disconnected from the target VM, address: '127.0.0.1:7510', transport: 'socket'

Process finished with exit code 1

Redis 订阅模式对我来说没法使用

你们的原理是使用下面方法进行订阅
image

但是我使用RMapCache,会出现 \x00 的错误
image
#1 使用 StringRedisTemplate 保存数据,可用
#2 使用 RMapCache 保存数据, 出现\x00, 不可用,不要纠结我用的不是 StringCodec

查了下源码
RedissonClient 执行 lua 脚本就乱了
image

eval "return struct.pack('dLc0', 0, string.len(ARGV[1]), ARGV[1])" 0 "test"
image

我直接询问了 redisson
redisson/redisson#5642
要我直接使用 RMap

这个具体是怎么选?

为什么一个文件配置错了,导致整个项目启动不起来,能不能忽略呢

Error creating bean with name 'liteflowExecutorInit' defined in class path resource [com/yomahub/liteflow/springboot/config/LiteflowMainAutoConfiguration.class]: Invocation of init method failed; nested exception is com.yomahub.liteflow.exception.FlowExecutorNotInitException: init flow executor cause error for path [com.yomahub.liteflow.parser.sql.SQLXmlELParser],reason: An exception occurred while building the node[bluetoothIrrigateControllerScript],component[bluetoothIrrigateControllerScript(蓝牙状态控制器 状态解析)] register error script loading error for node[bluetoothIrrigateControllerScript],error msg:Line 33, Column 22: A method named "onlineState" is not declared in any enclosing class nor any supertype, nor through a static import
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804)

liteflow与tlog中的QLExpress版本不一致

liteflow中依赖的QLExpress版本是3.3.0,tlog中依赖的QLExpress版本是3.2.0,导致打包之后包内只有3.2.0版本的QLExpress,liteflow初始化失败.
image
报错信息为QLException类没有找到
image

建议增加Janino插件

Janino是个轻量的java编译器,超级快,所以很多重量级开源软件比如Apache Spark、Apache Flink、Presto都用它做动态代码。xx跳动把动态处理引擎从groovy迁到Janino的一个主要原因就是Janino超级快。
主要代码大致如下:

    public class JaninoScriptExecutor extends ScriptExecutor {
        // 限制:  Janino脚本Evaluator需要事先约定脚本里的变量名
        public static final String JANINO_SCRIPT_PARAMETER_NAME = "ctx";

        //  编译过的Janino脚本Evaluator缓存
        private final Map<String, IScriptEvaluator> compiledScriptMap = new CopyOnWriteHashMap<>();

        @Override
        public void load(String nodeId, String script) {
            // 创建Janino脚本Evaluator
            IScriptEvaluator se = CompilerFactoryFactory.getDefaultCompilerFactory().newScriptEvaluator();
            // 返回值类型指定为Object以支持不同脚本
            se.setReturnType(Object.class);
            // 指定Janino脚本里的变量名及类型,为通用起见,只设置一个Object类型的变量
            se.setParameters(new String[] { JANINO_SCRIPT_PARAMETER_NAME }, new Class[] { Object.class });
            // 编译
            se.cook(script);
            // 缓存编译过的Evaluator
            compiledScriptMap.put(nodeId, se);
        }

        @Override
	public Object executeScript(ScriptExecuteWrap wrap) throws Exception {
            IScriptEvaluator se = compiledScriptMap.get(wrap.getNodeId());
            // 约定首个ContextBean作为Janino脚本参数里的唯一变量,缺省是DefaultContext类型
            Object context = DataBus.getContextBeanList(wrap.getSlotIndex()).get(0);
            return se.evaluate(new Object[] { context });
        }

Janino脚本示例(变量名ctx要和上面插件代码定义的变量名一致):

import com.yomahub.liteflow.slot.DefaultContext;
((DefaultContext) ctx).setData("s1", 666); 

用 Liteflow 运行会偶发一个多线程 InterruptedException 的报错,跟踪定位不到我的业务代码里,

2023-07-25 21:10:01.345 ERROR 1241 -- [ool-3-thread-36] c.y.l.f.element.condition.WhenCondition :365 ||traceid=xgm_pre-20230725211000023508||spanid=0a20d008e1d7834a||cspanid=082230549a18cdb5|| : [a422997680784d6f91f06b7fc28dcbca]:
     there was an error when executing the CompletableFuture

java.lang.InterruptedException: null
	at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:385)
	at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999)
	at com.yomahub.liteflow.flow.element.condition.WhenCondition.executeAsyncCondition(WhenCondition.java:135)
	at com.yomahub.liteflow.flow.element.condition.WhenCondition.executeCondition(WhenCondition.java:57)
	at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:50)
	at com.yomahub.liteflow.flow.element.condition.CatchCondition.executeCondition(CatchCondition.java:31)
	at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:50)
	at com.yomahub.liteflow.flow.element.condition.ThenCondition.executeCondition(ThenCondition.java:44)
	at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:50)
	at com.yomahub.liteflow.flow.element.condition.SwitchCondition.executeCondition(SwitchCondition.java:88)
	at com.yomahub.liteflow.flow.element.Condition.execute(Condition.java:50)
	at com.yomahub.liteflow.flow.element.Chain.execute(Chain.java:92)
	at com.yomahub.liteflow.core.FlowExecutor.doExecute(FlowExecutor.java:399)
	at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:321)
	at com.yomahub.liteflow.core.FlowExecutor.execute2Resp(FlowExecutor.java:271)
	.... 后续省略

这个报错堆栈 所能跟踪到最近的业务代码是 执行 LiteflowResponse response = flowExecutor.execute2Resp("", XXX 省略)

也就是定位不到是哪一行业务代码 导致的,像是 Future 线程被外部打断了,请教下这个怎么个排查法?
可以确定的是 没有主动 kill 回收线程的操作,

在OpenJDK19中使用JavaBean交互异常

在OpenJDK19中使用和自定义的JavaBean进行交互( https://liteflow.yomahub.com/pages/d861c8/#%E5%92%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84javabean%E8%BF%9B%E8%A1%8C%E4%BA%A4%E4%BA%92 ) 出现异常,jdk1.8及11下正常
异常信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoBean1' defined in file [D:\test\java\lfdemo\target\classes\com\goodwe\lfdemo\entity\DemoBean1.class]: Initialization of bean failed; nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.Map sun.reflect.annotation.AnnotationInvocationHandler.memberValues accessible: module java.base does not "opens sun.reflect.annotation" to unnamed module @564fabc8
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.28.jar:5.3.28]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920) ~[spring-context-5.3.28.jar:5.3.28]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.28.jar:5.3.28]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.13.jar:2.7.13]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.13.jar:2.7.13]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.13.jar:2.7.13]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.13.jar:2.7.13]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.13.jar:2.7.13]
at com.goodwe.lfdemo.LfdemoApplication.main(LfdemoApplication.java:16) ~[classes/:na]

AopInvocationHandler invode空指针异常

我使用的版本是2.10.6,springboot版本2.7.11,执行到AopInvocationHandler.invoke方法时,入参args为null,导致触发空指针异常

java.lang.ClassCastException: java.lang.NullPointerException cannot be cast to java.lang.reflect.InvocationTargetException
at com.yomahub.liteflow.core.proxy.ComponentProxy$AopInvocationHandler.invoke(ComponentProxy.java:238) ~[liteflow-core-2.10.6.jar:2.10.6]
at com.flow.component.cmp1.ByteBuddy$j$HFDQWR.isAccess(Unknown Source) ~[na:na]
at com.yomahub.liteflow.flow.element.Node.execute(Node.java:135) ~[liteflow-core-2.10.6.jar:2.10.6]

`2.11.4+` 启动不了

[  restartedMain] com.yomahub.liteflow.core.FlowExecutor   : [a] is not exist or [a] is not registered, you need to define a node or chain with id [a] and register it
 EL: THEN(a,b,c);
          ^

com.yomahub.liteflow.exception.ELParseException: [a] is not exist or [a] is not registered, you need to define a node or chain with id [a] and register it
 EL: THEN(a,b,c);
          ^
        at com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder.setEL(LiteFlowChainELBuilder.java:169

如果使用2.11.4-BETA1则正常,项目是spring-boot-starter-web-2.7.14,完全按照官网教程来的,但是在2.11.4+中Node总是无法自动注入

component[tryAppInit] cause error,error:this type is not in the context type passed in

component[tryAppInit] cause error,error:this type is not in the context type passed in

这个怎么回事

2023-06-07 13:45:17.648 | http-nio-9091-exec-4raceId | ERROR | 11012 | http-nio-9091-exec-4 | com.yomahub.liteflow.core.FlowExecutor.doExecute(FlowExecutor.java:391) : [30ba299d661e4f4383e4cd60dc45cc77]:chain[tryapp] execute error on slot[6]
com.yomahub.liteflow.exception.NoSuchContextBeanException: this type is not in the context type passed in
at com.yomahub.liteflow.slot.Slot.getContextBean(Slot.java:393) ~[liteflow-core-2.10.3.jar:2.10.3]
at com.yomahub.liteflow.core.NodeComponent.getContextBean(NodeComponent.java:214) ~[liteflow-core-2.10.3.jar:2.10.3]
at com.minienjoy.meadmin.component.flow.wechat.open.tryapp.tryAppInit.process(tryAppInit.java:14) ~[classes/:?]
at com.yomahub.liteflow.core.NodeComponent.execute(NodeComponent.java:97) ~[liteflow-core-2.10.3.jar:2.10.3]
at com.yomahub.liteflow.flow.executor.NodeExecutor.execute(NodeExecutor.java:33) ~[liteflow-core-2.10.3.jar:2.10.3]
at com.yomahub.liteflow.flow.executor.DefaultNodeExecutor.execute(DefaultNodeExecutor.java:15) ~[liteflow-core-2.10.3.jar:2.10.3]
at com.yomahub.liteflow.flow.element.Node.execute(Node.java:143) ~[liteflow-core-2.10.3.jar:2.10.3]

@bryan31

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.