workflow_core 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+

|
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
|

|
88
115
|
|
89
|
-
|
90
|
-
|
91
|
-
#### Importing workflow definitions from a BPMN2 xml,
|
92
|
-
|
93
|
-

|
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
|
-

|
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
|
-

|
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
|
+

|
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
|
+

|
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
|
+

|
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
|