workflow_core 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +79 -43
- data/app/models/workflow_core/place.rb +4 -2
- data/app/models/workflow_core/token.rb +3 -1
- data/app/models/workflow_core/transition.rb +4 -6
- data/app/models/workflow_core/workflow.rb +2 -0
- data/app/models/workflow_core/workflow_instance.rb +2 -0
- data/db/migrate/20180910200203_create_workflow_places.rb +2 -2
- data/db/migrate/20180912223722_create_workflow_tokens.rb +3 -3
- data/lib/workflow_core.rb +6 -1
- data/lib/workflow_core/concerns/models/place.rb +9 -0
- data/lib/workflow_core/concerns/models/token.rb +9 -0
- data/lib/workflow_core/concerns/models/transition.rb +27 -0
- data/lib/workflow_core/concerns/models/workflow.rb +9 -0
- data/lib/workflow_core/concerns/models/workflow_instance.rb +9 -0
- data/lib/workflow_core/version.rb +1 -1
- metadata +18 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 811e973c52672a22910d4cbd3cea630788de539f951d0ed5b83185e7bf7b8dc6
|
4
|
+
data.tar.gz: 8cac78ded90082dbf6a66c77fb4d2969b3a30846192f27c20d15ae0bae86670a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 316fef5691389a031987ec16a194d242d5b961511ec20dac720841e07eff364958d210072dd61b6abbec87daa7337e27359450ccbb27e4a2cb09e219dd39ba17
|
7
|
+
data.tar.gz: 0adeeeba9b7c7a80aa2b11ac73cc1b28c559ad88f5f47f6a987acfa800eac77bd3842e4753a10eb4be3789db5f449edd0e858db72396b6b264298232dec41a11
|
data/README.md
CHANGED
@@ -9,13 +9,40 @@ Workflow Core
|
|
9
9
|
|
10
10
|
A Rails engine which providing essential infrastructure of workflow.
|
11
11
|
|
12
|
-
|
12
|
+
WorkflowCore is originally designed for Business Process Management (BPM), in this scenario:
|
13
13
|
|
14
|
-
|
14
|
+
- Workflows are usually defined by users dynamically
|
15
|
+
- Task may tight with application features
|
16
|
+
- May meet some special or weird requirements
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
WorkflowCore is based on [Workflow Net](http://mlwiki.org/index.php/Workflow_Nets) technique, and only providing essential features for a workflow engine.
|
19
|
+
|
20
|
+
## Features
|
21
|
+
|
22
|
+
### Models to describe workflow net
|
23
|
+
|
24
|
+
Workflow Net is a special case of [Petri net](http://mlwiki.org/index.php/Petri_Nets)
|
25
|
+
|
26
|
+
![](_assets/workflow_net.png)
|
27
|
+
|
28
|
+
There are two kinds of nodes
|
29
|
+
|
30
|
+
- Place (circles): represent the states of a system
|
31
|
+
- Transition (squares): represent state changes
|
32
|
+
|
33
|
+
WorkflowCore provides Place & Transition models that can represent a workflow net, and a Workflow model as root.
|
34
|
+
|
35
|
+
### Models to describe workflow instances
|
36
|
+
|
37
|
+
Workflow net use Token (dots in places) to tracking states of a process, every place can contain one or more tokens.
|
38
|
+
|
39
|
+
WorkflowCore provides WorkflowInstance model represent processes, and it has many tokens.
|
40
|
+
|
41
|
+
### Interfaces to define how to transit
|
42
|
+
|
43
|
+
Transition has a transactional `fire` method which accept a token that would consume it and generate new token(s), developer could create many kinds of transitions and overrides `on_fire` to define how to transit
|
44
|
+
|
45
|
+
In addition, `on_error` is used for error handling.
|
19
46
|
|
20
47
|
## Why “core”
|
21
48
|
|
@@ -27,11 +54,11 @@ BTW, the dummy app is a full-featured app with production level codebase that yo
|
|
27
54
|
|
28
55
|
## Todo
|
29
56
|
|
30
|
-
-
|
31
|
-
- Consider
|
57
|
+
- Find a good way to validate all nodes of the net, when? where? how?
|
58
|
+
- Consider native workflows (those which defined in code and tight with the app) support
|
32
59
|
- Stabilizing interfaces.
|
33
60
|
- Evaluate that can supporting async, scheduled and event-based transition properly.
|
34
|
-
- Efficiency (especially
|
61
|
+
- Efficiency (especially database queries).
|
35
62
|
- Easy to use.
|
36
63
|
- Transforming to graph representation for visualization and other usages (e.g proving [Soundness](http://mlwiki.org/index.php/Workflow_Soundness)).
|
37
64
|
- Polish codebase.
|
@@ -86,41 +113,7 @@ The dummy app integrates with [Form Core](https://github.com/rails-engine/form_c
|
|
86
113
|
|
87
114
|
![](_assets/dummy_overview.png)
|
88
115
|
|
89
|
-
|
90
|
-
|
91
|
-
#### Importing workflow definitions from a BPMN2 xml,
|
92
|
-
|
93
|
-
![](_assets/importing_bpmn.png)
|
94
|
-
|
95
|
-
Because there isn't have a easy-to-use web-based flowchart designer, I implement a stupid BPMN2 importer, it have many restrictions:
|
96
|
-
|
97
|
-
- Only supports `Sequence`, `Start event`, `End event`, `Parallel gateway` and `Exclusive gateway`
|
98
|
-
- Using gateway to fork flows must have corresponding join (or merge) gateway
|
99
|
-
- Only read `name` property, other such as `condition expression` must configure on the dummy app
|
100
|
-
|
101
|
-
You can check `_samples` folder, or you can try a BPMN2 designer (e.g [Camunda modeler](https://github.com/camunda/camunda-modeler)).
|
102
|
-
|
103
|
-
#### Defining form
|
104
|
-
|
105
|
-
![](_assets/defining_form.png)
|
106
|
-
|
107
|
-
You can defining a dynamic form for a workflow.
|
108
|
-
|
109
|
-
In transition's options, you can configure field's accessibility
|
110
|
-
|
111
|
-
#### Exclusive choice configuration supports Ruby expression
|
112
|
-
|
113
|
-
![](_assets/editing_transition.png)
|
114
|
-
|
115
|
-
Exclusive choice is a special transition that needs to configure conditions that determine how to transit to a branch.
|
116
|
-
|
117
|
-
The condition is a Ruby expression, and running in a mRuby sandbox (powered by ScriptCore but it's also undone yet), and you can access form data through `@input[:payload]`, for example, there is a field named `approved`, we can check the field checked by `@input[:payload]["approved"]`
|
118
|
-
|
119
|
-
#### Run a workflow
|
120
|
-
|
121
|
-
That should make sense.
|
122
|
-
|
123
|
-
### Usage
|
116
|
+
**You need to install Graphviz first**
|
124
117
|
|
125
118
|
Clone the repository.
|
126
119
|
|
@@ -140,6 +133,13 @@ Run bundler
|
|
140
133
|
$ bundle install
|
141
134
|
```
|
142
135
|
|
136
|
+
Build mruby engine & engine lib
|
137
|
+
|
138
|
+
```sh
|
139
|
+
$ bin/rails app:script_core:engine:build
|
140
|
+
$ bin/rails app:script_core:engine:compile_lib
|
141
|
+
```
|
142
|
+
|
143
143
|
Preparing database
|
144
144
|
|
145
145
|
```sh
|
@@ -154,6 +154,42 @@ $ bin/rails s
|
|
154
154
|
|
155
155
|
Open your browser, and visit `http://localhost:3000`
|
156
156
|
|
157
|
+
### Features
|
158
|
+
|
159
|
+
#### Importing workflow definitions from a BPMN2 xml,
|
160
|
+
|
161
|
+
![](_assets/importing_bpmn.png)
|
162
|
+
|
163
|
+
Because there isn't have a easy-to-use web-based flowchart designer, I implement a stupid BPMN2 importer, it have many restrictions:
|
164
|
+
|
165
|
+
- Only supports `Sequence`, `Start event`, `End event`, `Parallel gateway` and `Exclusive gateway`
|
166
|
+
- Using gateway to fork flows must have corresponding join (or merge) gateway
|
167
|
+
- Only read `name` property, other such as `condition expression` must configure on the dummy app
|
168
|
+
|
169
|
+
You can check `_samples` folder, I've already provided some samples, or you can try a BPMN2 designer (e.g [Camunda modeler](https://github.com/camunda/camunda-modeler)).
|
170
|
+
|
171
|
+
#### Defining form
|
172
|
+
|
173
|
+
![](_assets/defining_form.png)
|
174
|
+
|
175
|
+
You can defining a dynamic form for a workflow.
|
176
|
+
|
177
|
+
In transition's options, you can configure field's accessibility
|
178
|
+
|
179
|
+
#### Exclusive choice configuration supports Ruby expression
|
180
|
+
|
181
|
+
![](_assets/editing_transition.png)
|
182
|
+
|
183
|
+
Exclusive choice is a special transition that needs to configure conditions that determine how to transit to a branch.
|
184
|
+
|
185
|
+
The condition is a Ruby expression, and running in a mRuby sandbox (powered by [ScriptCore](https://github.com/rails-engine/script_core)),
|
186
|
+
and you can access form data through `Input`, for example, there is a field named `approved`,
|
187
|
+
we can check the field checked by `Input["approved"]`
|
188
|
+
|
189
|
+
#### Run a workflow
|
190
|
+
|
191
|
+
See `Instance` tab, that should make sense.
|
192
|
+
|
157
193
|
## Contributing
|
158
194
|
|
159
195
|
Bug report or pull request are welcome.
|
@@ -2,14 +2,16 @@
|
|
2
2
|
|
3
3
|
module WorkflowCore
|
4
4
|
class Place < ApplicationRecord
|
5
|
+
include WorkflowCore::Concerns::Models::Place
|
6
|
+
|
5
7
|
self.table_name = "workflow_places"
|
6
8
|
|
7
9
|
belongs_to :workflow
|
8
10
|
|
9
11
|
belongs_to :input_transition, optional: true, foreign_key: "input_transition_id",
|
10
|
-
|
12
|
+
class_name: "WorkflowCore::Transition"
|
11
13
|
belongs_to :output_transition, optional: true, foreign_key: "output_transition_id",
|
12
|
-
|
14
|
+
class_name: "WorkflowCore::Transition"
|
13
15
|
|
14
16
|
has_many :tokens
|
15
17
|
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module WorkflowCore
|
4
4
|
class Token < ApplicationRecord
|
5
|
+
include WorkflowCore::Concerns::Models::Token
|
6
|
+
|
5
7
|
self.table_name = "workflow_tokens"
|
6
8
|
|
7
9
|
belongs_to :instance,
|
@@ -10,7 +12,7 @@ module WorkflowCore
|
|
10
12
|
|
11
13
|
belongs_to :place
|
12
14
|
belongs_to :previous, optional: true,
|
13
|
-
|
15
|
+
class_name: "WorkflowCore::Token"
|
14
16
|
|
15
17
|
enum status: {
|
16
18
|
processing: 0,
|
@@ -2,17 +2,15 @@
|
|
2
2
|
|
3
3
|
module WorkflowCore
|
4
4
|
class Transition < ApplicationRecord
|
5
|
+
include WorkflowCore::Concerns::Models::Transition
|
6
|
+
|
5
7
|
self.table_name = "workflow_transitions"
|
6
8
|
|
7
9
|
belongs_to :workflow
|
8
10
|
|
9
11
|
has_many :input_places, dependent: :nullify,
|
10
|
-
|
12
|
+
foreign_key: "output_transition_id", class_name: "WorkflowCore::Place"
|
11
13
|
has_many :output_places, dependent: :destroy,
|
12
|
-
|
13
|
-
|
14
|
-
def fire(_token)
|
15
|
-
raise NotImplementedError
|
16
|
-
end
|
14
|
+
foreign_key: "input_transition_id", class_name: "WorkflowCore::Place"
|
17
15
|
end
|
18
16
|
end
|
@@ -3,8 +3,8 @@
|
|
3
3
|
class CreateWorkflowPlaces < ActiveRecord::Migration[5.2]
|
4
4
|
def change
|
5
5
|
create_table :workflow_places do |t|
|
6
|
-
t.references :input_transition, foreign_key: {to_table: "workflow_transitions"}
|
7
|
-
t.references :output_transition, foreign_key: {to_table: "workflow_transitions"}
|
6
|
+
t.references :input_transition, foreign_key: { to_table: "workflow_transitions" }
|
7
|
+
t.references :output_transition, foreign_key: { to_table: "workflow_transitions" }
|
8
8
|
|
9
9
|
t.string :type, null: false
|
10
10
|
t.references :workflow, foreign_key: true
|
@@ -5,10 +5,10 @@ class CreateWorkflowTokens < ActiveRecord::Migration[5.2]
|
|
5
5
|
create_table :workflow_tokens do |t|
|
6
6
|
t.integer :status, null: false, default: 0
|
7
7
|
|
8
|
-
t.references :place, foreign_key: {to_table: "workflow_places"}
|
9
|
-
t.references :previous, foreign_key: {to_table: "workflow_tokens"}
|
8
|
+
t.references :place, foreign_key: { to_table: "workflow_places" }
|
9
|
+
t.references :previous, foreign_key: { to_table: "workflow_tokens" }
|
10
10
|
|
11
|
-
t.references :instance, foreign_key: {to_table: "workflow_instances"}
|
11
|
+
t.references :instance, foreign_key: { to_table: "workflow_instances" }
|
12
12
|
t.references :workflow, foreign_key: true
|
13
13
|
t.timestamps
|
14
14
|
end
|
data/lib/workflow_core.rb
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
require "workflow_core/engine"
|
4
4
|
|
5
|
+
require "workflow_core/concerns/models/workflow"
|
6
|
+
require "workflow_core/concerns/models/transition"
|
7
|
+
require "workflow_core/concerns/models/place"
|
8
|
+
require "workflow_core/concerns/models/workflow_instance"
|
9
|
+
require "workflow_core/concerns/models/token"
|
10
|
+
|
5
11
|
module WorkflowCore
|
6
|
-
# Your code goes here...
|
7
12
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WorkflowCore::Concerns
|
4
|
+
module Models
|
5
|
+
module Transition
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def fire(token, transaction_options: { requires_new: true }, **options)
|
9
|
+
transaction(**transaction_options) do
|
10
|
+
on_fire(token, transaction_options, options)
|
11
|
+
end
|
12
|
+
rescue StandardError => e
|
13
|
+
rescue_fire_error e
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def on_fire(_token, _transaction_options, **_options)
|
19
|
+
raise NotImplementedError
|
20
|
+
end
|
21
|
+
|
22
|
+
def rescue_fire_error(ex)
|
23
|
+
raise ex
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workflow_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jasl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.0.0.rc1
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 7.0.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 6.0.0.rc1
|
30
|
+
- - "<"
|
25
31
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
32
|
+
version: 7.0.0
|
27
33
|
description: A Rails engine which providing essential infrastructure of workflow.
|
28
34
|
It's based on Workflow Nets.
|
29
35
|
email:
|
@@ -49,6 +55,11 @@ files:
|
|
49
55
|
- db/migrate/20180912223722_create_workflow_tokens.rb
|
50
56
|
- lib/tasks/workflow_core_tasks.rake
|
51
57
|
- lib/workflow_core.rb
|
58
|
+
- lib/workflow_core/concerns/models/place.rb
|
59
|
+
- lib/workflow_core/concerns/models/token.rb
|
60
|
+
- lib/workflow_core/concerns/models/transition.rb
|
61
|
+
- lib/workflow_core/concerns/models/workflow.rb
|
62
|
+
- lib/workflow_core/concerns/models/workflow_instance.rb
|
52
63
|
- lib/workflow_core/engine.rb
|
53
64
|
- lib/workflow_core/version.rb
|
54
65
|
homepage: https://github.com/rails-engine/workflow_core
|
@@ -70,8 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
81
|
- !ruby/object:Gem::Version
|
71
82
|
version: '0'
|
72
83
|
requirements: []
|
73
|
-
|
74
|
-
rubygems_version: 2.7.7
|
84
|
+
rubygems_version: 3.0.4
|
75
85
|
signing_key:
|
76
86
|
specification_version: 4
|
77
87
|
summary: A Rails engine which providing essential infrastructure of workflow. It's
|