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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e37fe908ba22a89b01f43680721ad466544bb1eef47cc8bc95ea26d7a77c00d
4
- data.tar.gz: 1a052885996e219ec88a60d1e890e7b7b49b855b30bef3b073d1b3a98cc19167
3
+ metadata.gz: 811e973c52672a22910d4cbd3cea630788de539f951d0ed5b83185e7bf7b8dc6
4
+ data.tar.gz: 8cac78ded90082dbf6a66c77fb4d2969b3a30846192f27c20d15ae0bae86670a
5
5
  SHA512:
6
- metadata.gz: ad2e77a5043dcbd124a489ef4e0cb047fe3ef15de5db8d23eab6aea2c0f331299cefedb19f9100378db82555cc094ec535ad7d86383b4d50dcb21e5f7b6baada
7
- data.tar.gz: af92427c841e043165b8ad2c7179f83bb1edd4906ebef9adcd54eddaedbde9669b695f8ecfbe486399b846b03b2da5898360ff6be6b82c290e8a0caa23a86ce7
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
- It's based on [Workflow Net](http://mlwiki.org/index.php/Workflow_Nets) technique.
12
+ WorkflowCore is originally designed for Business Process Management (BPM), in this scenario:
13
13
 
14
- The gem provides:
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
- - Models to describe workflow nets
17
- - Models to describe workflow instances
18
- - Interfaces to define transitions
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
- - Make sure transit must be an atomic operation, and help developers to avoiding Rails' nested transaction pitfalls.
31
- - Consider consequences of changing the Net, well handle Net changes. e.g: what about running instances?
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 on database).
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
- ### Features
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
- class_name: "WorkflowCore::Transition"
12
+ class_name: "WorkflowCore::Transition"
11
13
  belongs_to :output_transition, optional: true, foreign_key: "output_transition_id",
12
- class_name: "WorkflowCore::Transition"
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
- class_name: "WorkflowCore::Token"
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
- foreign_key: "output_transition_id", class_name: "WorkflowCore::Place"
12
+ foreign_key: "output_transition_id", class_name: "WorkflowCore::Place"
11
13
  has_many :output_places, dependent: :destroy,
12
- foreign_key: "input_transition_id", class_name: "WorkflowCore::Place"
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
@@ -2,6 +2,8 @@
2
2
 
3
3
  module WorkflowCore
4
4
  class Workflow < ApplicationRecord
5
+ include WorkflowCore::Concerns::Models::Workflow
6
+
5
7
  self.table_name = "workflows"
6
8
 
7
9
  has_one :start_place, class_name: "WorkflowCore::Place", dependent: :destroy
@@ -2,6 +2,8 @@
2
2
 
3
3
  module WorkflowCore
4
4
  class WorkflowInstance < ApplicationRecord
5
+ include WorkflowCore::Concerns::Models::WorkflowInstance
6
+
5
7
  self.table_name = "workflow_instances"
6
8
 
7
9
  belongs_to :workflow
@@ -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
@@ -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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkflowCore::Concerns
4
+ module Models
5
+ module Place
6
+ extend ActiveSupport::Concern
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkflowCore::Concerns
4
+ module Models
5
+ module Token
6
+ extend ActiveSupport::Concern
7
+ end
8
+ end
9
+ 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
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkflowCore::Concerns
4
+ module Models
5
+ module Workflow
6
+ extend ActiveSupport::Concern
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkflowCore::Concerns
4
+ module Models
5
+ module WorkflowInstance
6
+ extend ActiveSupport::Concern
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WorkflowCore
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  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.1
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: 2018-09-26 00:00:00.000000000 Z
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: '5.2'
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: '5.2'
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
- rubyforge_project:
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