rails-engine / flow_core

FlowCore is a Rails engine to help you build your automation or business process application.
MIT License
174 stars 19 forks source link

工作流的定义可以修改吗 #27

Open jiyarong opened 2 years ago

jiyarong commented 2 years ago

比如你seed.rb里的定义,deploy之后,我以后中间想继续插流程,可以吗

jasl commented 2 years ago

seed.rb 里的代码是利用我提供的 DSL 去定义 Petrinet,所以你执行后会产生一个新 Workflow,不会替代已有的

jiyarong commented 2 years ago

问一个设计上的问题,很显然在一个erp系统里,一个workflow走到不同的环节所要完成的task肯定是大相径庭的,我是否应该为所有的transition定义不同的trigger,还是所有transition用相同的trigger,然后根据workflow目前走到的位置去下发不同的task。还有就是一个transition如果没有trigger,从业务层来说感觉就和workflow失联了 @jasl

jasl commented 2 years ago

问一个设计上的问题,很显然在一个erp系统里,一个workflow走到不同的环节所要完成的task肯定是大相径庭的,我是否应该为所有的transition定义不同的trigger,还是所有transition用相同的trigger,然后根据workflow目前走到的位置去下发不同的task。还有就是一个transition如果没有trigger,从业务层来说感觉就和workflow失联了

每个 transition 应该有不同的trigger,因为这一步骤的流转配置是配置在 trigger 上的,虽然绝大多数步骤都是相似的,但是审批人之类的条件信息还是不同的,如果多个 transition 共享一个trigger,如果trigger 被修改,引发的对流程的破坏会更大

jiyarong commented 2 years ago

我想请教一下,审批驳回的逻辑,也就是你之前例子里面ltractive routing,用DSL怎么配出来,是在某个节点,output两个place,一个指向后面的place,一个指向前面的place,然后通过ArcGuard来判断去哪吗

FlowCore::Definition.new name: "Simple sequence" do |net|
  net.start_place :start, name: "Start"
  net.end_place :end, name: "End"

  net.transition :t1, input: :start, output: :p1
  net.transition :t2, input: :p1, output: %i[start end]
end.deploy!

@jasl

jasl commented 2 years ago

我想请教一下,审批驳回的逻辑,也就是你之前例子里面ltractive routing,用DSL怎么配出来,是在某个节点,output两个place,一个指向后面的place,一个指向前面的place,然后通过ArcGuard来判断去哪吗

FlowCore::Definition.new name: "Simple sequence" do |net|
  net.start_place :start, name: "Start"
  net.end_place :end, name: "End"

  net.transition :t1, input: :start, output: :p1
  net.transition :t2, input: :p1, output: %i[start end]
end.deploy!

@jasl

先稍等啊,我手头有点事要出门一趟,我晚上到家回复你。。。

jasl commented 2 years ago

我想请教一下,审批驳回的逻辑,也就是你之前例子里面ltractive routing,用DSL怎么配出来,是在某个节点,output两个place,一个指向后面的place,一个指向前面的place,然后通过ArcGuard来判断去哪吗

FlowCore::Definition.new name: "Simple sequence" do |net|
  net.start_place :start, name: "Start"
  net.end_place :end, name: "End"

  net.transition :t1, input: :start, output: :p1
  net.transition :t2, input: :p1, output: %i[start end]
end.deploy!

@jasl

你要在哪年的RubyConfChina微信群可以加我好友,这样有问题问我更方便

jiyarong commented 2 years ago

我想请教一下,审批驳回的逻辑,也就是你之前例子里面ltractive routing,用DSL怎么配出来,是在某个节点,output两个place,一个指向后面的place,一个指向前面的place,然后通过ArcGuard来判断去哪吗

FlowCore::Definition.new name: "Simple sequence" do |net|
  net.start_place :start, name: "Start"
  net.end_place :end, name: "End"

  net.transition :t1, input: :start, output: :p1
  net.transition :t2, input: :p1, output: %i[start end]
end.deploy!

@jasl

先稍等啊,我手头有点事要出门一趟,我晚上到家回复你。。。

多谢了

jiyarong commented 5 months ago

问一个设计上的问题,很显然在一个erp系统里,一个workflow走到不同的环节所要完成的task肯定是大相径庭的,我是否应该为所有的transition定义不同的trigger,还是所有transition用相同的trigger,然后根据workflow目前走到的位置去下发不同的task。还有就是一个transition如果没有trigger,从业务层来说感觉就和workflow失联了

每个 transition 应该有不同的trigger,因为这一步骤的流转配置是配置在 trigger 上的,虽然绝大多数步骤都是相似的,但是审批人之类的条件信息还是不同的,如果多个 transition 共享一个trigger,如果trigger 被修改,引发的对流程的破坏会更大

如果要为每个transition定义不同的trigger,我应该继承你哪个类,实现什么方法,才能达成这样的效果

jasl commented 5 months ago

问一个设计上的问题,很显然在一个erp系统里,一个workflow走到不同的环节所要完成的task肯定是大相径庭的,我是否应该为所有的transition定义不同的trigger,还是所有transition用相同的trigger,然后根据workflow目前走到的位置去下发不同的task。还有就是一个transition如果没有trigger,从业务层来说感觉就和workflow失联了

每个 transition 应该有不同的trigger,因为这一步骤的流转配置是配置在 trigger 上的,虽然绝大多数步骤都是相似的,但是审批人之类的条件信息还是不同的,如果多个 transition 共享一个trigger,如果trigger 被修改,引发的对流程的破坏会更大

如果要为每个transition定义不同的trigger,我应该继承你哪个类,实现什么方法,才能达成这样的效果

默认似乎就是 “为每个transition定义不同的trigger”,Transition has one Trigger https://github.com/rails-engine/flow_core/blob/master/app/models/flow_core/transition.rb#L24

Transition trigger 的例子参考参考 Dummy app 比如人工审批 https://github.com/rails-engine/flow_core/blob/master/test/dummy/app/models/flow_kit/transition_triggers/human_task.rb

jiyarong commented 5 months ago

问一个设计上的问题,很显然在一个erp系统里,一个workflow走到不同的环节所要完成的task肯定是大相径庭的,我是否应该为所有的transition定义不同的trigger,还是所有transition用相同的trigger,然后根据workflow目前走到的位置去下发不同的task。还有就是一个transition如果没有trigger,从业务层来说感觉就和workflow失联了

每个 transition 应该有不同的trigger,因为这一步骤的流转配置是配置在 trigger 上的,虽然绝大多数步骤都是相似的,但是审批人之类的条件信息还是不同的,如果多个 transition 共享一个trigger,如果trigger 被修改,引发的对流程的破坏会更大

如果要为每个transition定义不同的trigger,我应该继承你哪个类,实现什么方法,才能达成这样的效果

默认似乎就是 “为每个transition定义不同的trigger”,Transition has one Trigger https://github.com/rails-engine/flow_core/blob/master/app/models/flow_core/transition.rb#L24

Transition trigger 的例子参考参考 Dummy app 比如人工审批 https://github.com/rails-engine/flow_core/blob/master/test/dummy/app/models/flow_kit/transition_triggers/human_task.rb

你这HumanTask继承Trigger,就是在on_task_enable中决定下发什么任务,这和我之前理解的用法是一样的,你意思这种做法就是为每个任务定义不同的trigger了吗,我以为比如还有human2Task,human3Task

jiyarong commented 5 months ago

非常抱歉两年后还来打扰你,我们的业务经过两年的发展后,流程趋于稳定,但流程复杂度非常高,不找个这样的库不太行了

车辆交付流程图 (1)

jasl commented 5 months ago

问一个设计上的问题,很显然在一个erp系统里,一个workflow走到不同的环节所要完成的task肯定是大相径庭的,我是否应该为所有的transition定义不同的trigger,还是所有transition用相同的trigger,然后根据workflow目前走到的位置去下发不同的task。还有就是一个transition如果没有trigger,从业务层来说感觉就和workflow失联了

每个 transition 应该有不同的trigger,因为这一步骤的流转配置是配置在 trigger 上的,虽然绝大多数步骤都是相似的,但是审批人之类的条件信息还是不同的,如果多个 transition 共享一个trigger,如果trigger 被修改,引发的对流程的破坏会更大

如果要为每个transition定义不同的trigger,我应该继承你哪个类,实现什么方法,才能达成这样的效果

默认似乎就是 “为每个transition定义不同的trigger”,Transition has one Trigger https://github.com/rails-engine/flow_core/blob/master/app/models/flow_core/transition.rb#L24 Transition trigger 的例子参考参考 Dummy app 比如人工审批 https://github.com/rails-engine/flow_core/blob/master/test/dummy/app/models/flow_kit/transition_triggers/human_task.rb

你这HumanTask继承Trigger,就是在on_task_enable中决定下发什么任务,这和我之前理解的用法是一样的,你意思这种做法就是为每个任务定义不同的trigger了吗,我以为比如还有human2Task,human3Task

因为是通过 has_one 关联的具体的 trigger,所以你直接指向不同的 trigger 记录就能设置不同的了

jasl commented 5 months ago

非常抱歉两年后还来打扰你,我们的业务经过两年的发展后,流程趋于稳定,但流程复杂度非常高,不找个这样的库不太行了

车辆交付流程图 (1)

欢迎交流,这个库我觉得没过时,表单部分 Rails 8 会有一个官方的虚拟模型方案,所以等 8 出来我可以再维护下

jasl commented 5 months ago

这个流程我感觉不难,你看看能否通过 dummy app 能否配出来你的流程?

jiyarong commented 5 months ago

这个流程我感觉不难,你看看能否通过 dummy app 能否配出来你的流程?

用你这个理论上是不难,并行合并,再并行,再合并,用aasm是搞不出来,很难用一个单一状态来描述我的货物处于哪个阶段

jasl commented 5 months ago

这个流程我感觉不难,你看看能否通过 dummy app 能否配出来你的流程?

用你这个理论上是不难,并行合并,再并行,再合并,用aasm是搞不出来

状态机肯定表达不了并行,我记得我20年在 RubyConf China 上分享过不同的工作流的原理的优缺点对比,你可以翻翻~

我这两三年是去做区块链啦,所以就离这个远了

jiyarong commented 5 months ago

你的Demo运行时有错误,不知道是升到rails7的原因,还是我是苹果芯片版的mac

Screenshot 2024-04-25 at 14 49 28

而且你这个生成图的依赖看着就挺吓人,我能否不用你这套,简单的用我部署的workflow的结构,找个其他的画流程图的应用把图画出来,纯前端JS画都行,不知道你有没有相关推荐,编辑流程图好像也没太大必要,有新环节,重新搞一个workflow出来就行了

jasl commented 5 months ago

你的Demo运行时有错误,不知道是升到rails7的原因,还是我是苹果芯片版的mac

Screenshot 2024-04-25 at 14 49 28

而且你这个生成图的依赖看着就挺吓人,我能否不用你这套,简单的用我部署的workflow的结构,找个其他的画流程图的应用把图画出来,纯前端JS画都行,不知道你有没有相关推荐

这个错误是你没装 graphviz 文档提了 你跑 brew install graphviz 就行了

我懒得写前端而且我也不知道哪个通用,所以用 graphviz 来画了就,丑是丑了点,但是能用

jasl commented 5 months ago

而且你这个生成图的依赖看着就挺吓人

我不知道你说的是什么,我只提供了 graphviz 的流程图绘制和导出,这是个纯文本格式

jiyarong commented 4 months ago

兄弟,问个问题,你这个流程能回滚吗,比如到了某一步,发现上一个环节的人数据填错了,这个时候咋办

jasl commented 4 months ago

兄弟,问个问题,你这个流程能回滚吗,比如到了某一步,发现上一个环节的人数据填错了,这个时候咋办

需要支持回滚的步骤都加个连接到上一步的流转就好了,包括驳回都是这么支持的

jiyarong commented 4 months ago

兄弟,你这个arc_guard在配置的时候怎么写的,看的不是太懂

FlowCore::Definition.new name: "Car Process Test" do |net|
  net.start_place :start
  net.end_place :end

  net.transition :a1, input: :start, output: %i[p1 p2] do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  ...
end.deploy!

比如这个p1,p2分别设置arc_guard怎么写

jiyarong commented 4 months ago

还有个问题是,比如我的交付流程,有可能最后是“成功交付”,也可能中间某个环节出问题了(比如客户不要了要退款),整个交付要关掉,我就在想,给每个环节加一个arc_guard,出问题了直接走到“交付取消”,那么这个时候“成功交付”和“交付取消”,是2个end_place?还是其实“交付取消”和“交付成功”是一个end_place,不然的话,“交付取消”的流程,整个workflow_instance怎么才能finish

jasl commented 4 months ago

还有个问题是,比如我的交付流程,有可能最后是“成功交付”,也可能中间某个环节出问题了,整个交付要关掉,我就在想,给每个环节加一个arc_guard,出问题了直接走到“交付取消”,那么这个时候“成功交付”和“交付取消”,是2个end_place?还是其实“交付取消”和“交付成功”是一个end_place,不然的话,“交付取消”的流程,整个workflow_instance怎么才能finish

时间太久忘记 PetriNet 的定义了, 如果支持两个 end place 的话,交易成功 和 交易成功 就分别是两个 end place,place 你可以理解就是流程的停靠状态 如果不行的话,就是两个 place,然后 transit 到一个 end place

jiyarong commented 4 months ago

还有个问题是,比如我的交付流程,有可能最后是“成功交付”,也可能中间某个环节出问题了,整个交付要关掉,我就在想,给每个环节加一个arc_guard,出问题了直接走到“交付取消”,那么这个时候“成功交付”和“交付取消”,是2个end_place?还是其实“交付取消”和“交付成功”是一个end_place,不然的话,“交付取消”的流程,整个workflow_instance怎么才能finish

时间太久忘记 PetriNet 的定义了, 如果支持两个 end place 的话,交易成功 和 交易成功 就分别是两个 end place,place 你可以理解就是流程的停靠状态 如果不行的话,就是两个 place,然后 transit 到一个 end place

但是你的定义里面,workflow,has_one: end_place啊

jasl commented 4 months ago

如果不行的话,就是两个 place,然后 transit 到一个 end place

如果不行的话,就是两个 place,然后 transit 到一个 end place 后来编辑了一下,时间久了忘记 PetriNet 的定义了,Flow Core 用的原理是 PetriNet,是一种工作流的实现原理,我应该在 RubyConfChina 2020 有分享过几种工作流的实现原理和优缺点介绍,相关知识可以了解下

jiyarong commented 4 months ago
FlowCore::Definition.new name: "Car Process Test" do |net|
  net.start_place :start
  net.end_place :end

  net.transition :a1, input: :start do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
    t.output :p1, with_guard: { type: FlowCore::ArcGuard }
    t.output :p2
  end
  net.transition :a2, input: :p1, output: :p3 do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  net.transition :a3, input: :p2, output: :p4 do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  net.transition :a4, input: %i[p3 p4], output: :end do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
end.deploy!

我看你的源码,感觉是这样配arc_guard吗

jiyarong commented 4 months ago
FlowCore::Definition.new name: "Car Process Test" do |net|
  net.start_place :start
  net.end_place :end

  net.transition :a1, input: :start do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
    t.output :p1, with_guard: { type: FlowCore::ArcGuard }
    t.output :p2
  end
  net.transition :a2, input: :p1, output: :p3 do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  net.transition :a3, input: :p2, output: :p4 do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  net.transition :a4, input: %i[p3 p4], output: :end do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
end.deploy!

我看你的源码,感觉是这样配arc_guard吗

没错就是这样,就是type还得是FlowCore::ArcGuard的子类

jasl commented 4 months ago
FlowCore::Definition.new name: "Car Process Test" do |net|
  net.start_place :start
  net.end_place :end

  net.transition :a1, input: :start do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
    t.output :p1, with_guard: { type: FlowCore::ArcGuard }
    t.output :p2
  end
  net.transition :a2, input: :p1, output: :p3 do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  net.transition :a3, input: :p2, output: :p4 do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
  net.transition :a4, input: %i[p3 p4], output: :end do |t|
    t.with_trigger Ev::CarProcessTransitionTrigger
  end
end.deploy!

我看你的源码,感觉是这样配arc_guard吗

没错就是这样,就是type还得是FlowCore::ArcGuard的子类

是的 因为基类是个抽象类没意义