burstflow 0.1.1 → 0.2.0
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 +5 -5
- data/Gemfile +1 -3
- data/Gemfile.lock +119 -0
- data/burstflow.gemspec +10 -6
- data/config/database.yml +4 -3
- data/db/migrate/20180101000001_create_workflow.rb +1 -0
- data/db/schema.rb +13 -7
- data/lib/burstflow.rb +11 -0
- data/lib/burstflow/job.rb +102 -0
- data/lib/burstflow/job/callbacks.rb +55 -0
- data/lib/burstflow/job/exception.rb +8 -0
- data/lib/burstflow/job/initialization.rb +35 -0
- data/lib/{burst → burstflow/job}/model.rb +1 -3
- data/lib/burstflow/job/state.rb +125 -0
- data/lib/burstflow/manager.rb +123 -0
- data/lib/burstflow/railtie.rb +6 -0
- data/lib/burstflow/version.rb +3 -0
- data/lib/burstflow/worker.rb +59 -0
- data/lib/burstflow/workflow.rb +207 -0
- data/lib/burstflow/workflow/builder.rb +91 -0
- data/lib/burstflow/workflow/callbacks.rb +66 -0
- data/lib/{burst/workflow_helper.rb → burstflow/workflow/configuration.rb} +8 -39
- data/lib/burstflow/workflow/exception.rb +8 -0
- data/lib/generators/burstflow/install/install_generator.rb +22 -0
- data/lib/generators/burstflow/install/templates/create_workflow.rb +15 -0
- data/spec/builder_spec.rb +63 -0
- data/spec/{burst_spec.rb → burstflow_spec.rb} +1 -1
- data/spec/generators/install_generator_spec.rb +27 -0
- data/spec/job_spec.rb +18 -8
- data/spec/spec_helper.rb +4 -1
- data/spec/support/database_clean.rb +4 -1
- data/spec/workflow_spec.rb +397 -147
- metadata +45 -21
- data/db/migrate/20180101000001_create_workflow.rb +0 -13
- data/db/seeds.rb +0 -1
- data/lib/burst.rb +0 -37
- data/lib/burst/builder.rb +0 -48
- data/lib/burst/configuration.rb +0 -27
- data/lib/burst/job.rb +0 -187
- data/lib/burst/manager.rb +0 -79
- data/lib/burst/worker.rb +0 -42
- data/lib/burst/workflow.rb +0 -148
- data/spec/cases_spec.rb +0 -180
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 435e3f0b3dba1c654d192d3f5f4cb1687bfe55e6c60f03e6fcb4643946603f0a
|
4
|
+
data.tar.gz: e5390d5f58fb4a2e3503516f0c0744bce0cac68411edf56477e82d84a9f9ed87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcb37c6b28837184136c25333cfaa3bd403bb953b9aa8dc8fe5971d499013650664444b5415aa50e2530218a88d07107e5032f90cc3ef3cd5114bd8593752669
|
7
|
+
data.tar.gz: ae739a9ab5a48b10512c3461e4720e54e564722192fca3aaf36123a48ed3a1c36de28483d19fd975659b2586637120be3dd32068f62e5bb2a294a1f6c8177e33
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
burstflow (0.2.0)
|
5
|
+
activejob
|
6
|
+
activerecord
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionpack (5.2.2)
|
12
|
+
actionview (= 5.2.2)
|
13
|
+
activesupport (= 5.2.2)
|
14
|
+
rack (~> 2.0)
|
15
|
+
rack-test (>= 0.6.3)
|
16
|
+
rails-dom-testing (~> 2.0)
|
17
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
+
actionview (5.2.2)
|
19
|
+
activesupport (= 5.2.2)
|
20
|
+
builder (~> 3.1)
|
21
|
+
erubi (~> 1.4)
|
22
|
+
rails-dom-testing (~> 2.0)
|
23
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
+
activejob (5.2.2)
|
25
|
+
activesupport (= 5.2.2)
|
26
|
+
globalid (>= 0.3.6)
|
27
|
+
activemodel (5.2.2)
|
28
|
+
activesupport (= 5.2.2)
|
29
|
+
activerecord (5.2.2)
|
30
|
+
activemodel (= 5.2.2)
|
31
|
+
activesupport (= 5.2.2)
|
32
|
+
arel (>= 9.0)
|
33
|
+
activesupport (5.2.2)
|
34
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
35
|
+
i18n (>= 0.7, < 2)
|
36
|
+
minitest (~> 5.1)
|
37
|
+
tzinfo (~> 1.1)
|
38
|
+
arel (9.0.0)
|
39
|
+
awesome_print (1.8.0)
|
40
|
+
builder (3.2.3)
|
41
|
+
concurrent-ruby (1.1.4)
|
42
|
+
crass (1.0.4)
|
43
|
+
database_cleaner (1.7.0)
|
44
|
+
diff-lcs (1.3)
|
45
|
+
erubi (1.8.0)
|
46
|
+
generator_spec (0.9.4)
|
47
|
+
activesupport (>= 3.0.0)
|
48
|
+
railties (>= 3.0.0)
|
49
|
+
globalid (0.4.2)
|
50
|
+
activesupport (>= 4.2.0)
|
51
|
+
hashie (3.6.0)
|
52
|
+
hashie-forbidden_attributes (0.1.1)
|
53
|
+
hashie (>= 3.0)
|
54
|
+
i18n (1.4.0)
|
55
|
+
concurrent-ruby (~> 1.0)
|
56
|
+
loofah (2.2.3)
|
57
|
+
crass (~> 1.0.2)
|
58
|
+
nokogiri (>= 1.5.9)
|
59
|
+
method_source (0.9.2)
|
60
|
+
mini_portile2 (2.4.0)
|
61
|
+
minitest (5.11.3)
|
62
|
+
nokogiri (1.10.1)
|
63
|
+
mini_portile2 (~> 2.4.0)
|
64
|
+
otr-activerecord (1.2.6)
|
65
|
+
activerecord (>= 4.0, < 5.3)
|
66
|
+
hashie-forbidden_attributes (~> 0.1)
|
67
|
+
pg (0.21.0)
|
68
|
+
rack (2.0.6)
|
69
|
+
rack-test (1.1.0)
|
70
|
+
rack (>= 1.0, < 3)
|
71
|
+
rails-dom-testing (2.0.3)
|
72
|
+
activesupport (>= 4.2.0)
|
73
|
+
nokogiri (>= 1.6)
|
74
|
+
rails-html-sanitizer (1.0.4)
|
75
|
+
loofah (~> 2.2, >= 2.2.2)
|
76
|
+
railties (5.2.2)
|
77
|
+
actionpack (= 5.2.2)
|
78
|
+
activesupport (= 5.2.2)
|
79
|
+
method_source
|
80
|
+
rake (>= 0.8.7)
|
81
|
+
thor (>= 0.19.0, < 2.0)
|
82
|
+
rake (12.3.2)
|
83
|
+
rspec (3.8.0)
|
84
|
+
rspec-core (~> 3.8.0)
|
85
|
+
rspec-expectations (~> 3.8.0)
|
86
|
+
rspec-mocks (~> 3.8.0)
|
87
|
+
rspec-core (3.8.0)
|
88
|
+
rspec-support (~> 3.8.0)
|
89
|
+
rspec-expectations (3.8.2)
|
90
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
91
|
+
rspec-support (~> 3.8.0)
|
92
|
+
rspec-mocks (3.8.0)
|
93
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
94
|
+
rspec-support (~> 3.8.0)
|
95
|
+
rspec-support (3.8.0)
|
96
|
+
thor (0.20.3)
|
97
|
+
thread_safe (0.3.6)
|
98
|
+
tzinfo (1.2.5)
|
99
|
+
thread_safe (~> 0.1)
|
100
|
+
yajl-ruby (1.4.1)
|
101
|
+
|
102
|
+
PLATFORMS
|
103
|
+
ruby
|
104
|
+
|
105
|
+
DEPENDENCIES
|
106
|
+
activesupport
|
107
|
+
awesome_print
|
108
|
+
bundler
|
109
|
+
burstflow!
|
110
|
+
database_cleaner
|
111
|
+
generator_spec
|
112
|
+
otr-activerecord
|
113
|
+
pg (~> 0.21.0)
|
114
|
+
rake
|
115
|
+
rspec
|
116
|
+
yajl-ruby
|
117
|
+
|
118
|
+
BUNDLED WITH
|
119
|
+
1.17.2
|
data/burstflow.gemspec
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
$:.push File.expand_path("lib", __dir__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require "burstflow/version"
|
3
5
|
|
4
6
|
Gem::Specification.new do |spec|
|
5
7
|
spec.name = 'burstflow'
|
6
|
-
spec.version =
|
8
|
+
spec.version = Burstflow::VERSION
|
7
9
|
spec.authors = ['Samoilenko Yuri']
|
8
10
|
spec.email = ['kinnalru@gmail.com']
|
9
|
-
spec.summary = '
|
10
|
-
spec.description = '
|
11
|
-
spec.homepage = 'https://github.com/RnD-Soft/
|
11
|
+
spec.summary = 'Burstflow is a parallel workflow runner using ActiveRecord and ActiveJob'
|
12
|
+
spec.description = 'Burstflow is a parallel workflow runner using ActiveRecord and ActiveJob. It has dependency, result pipelining and suspend/resume ability'
|
13
|
+
spec.homepage = 'https://github.com/RnD-Soft/burstflow'
|
12
14
|
spec.license = 'MIT'
|
13
15
|
|
14
16
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -17,7 +19,9 @@ Gem::Specification.new do |spec|
|
|
17
19
|
|
18
20
|
spec.add_dependency 'activejob'
|
19
21
|
spec.add_dependency 'activerecord'
|
22
|
+
|
20
23
|
spec.add_development_dependency 'bundler'
|
21
24
|
spec.add_development_dependency 'rake'
|
22
25
|
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'generator_spec'
|
23
27
|
end
|
data/config/database.yml
CHANGED
@@ -3,13 +3,14 @@ development: &base
|
|
3
3
|
host: <%= ENV['DATABASE_HOST'] || 'localhost' %>
|
4
4
|
port: <%= ENV['DATABASE_PORT'] || 5432 %>
|
5
5
|
encoding: unicode
|
6
|
-
database: <%= ENV['DATABASE_NAME'] || '
|
7
|
-
pool:
|
6
|
+
database: <%= ENV['DATABASE_NAME'] || 'burstflow_test' %>
|
7
|
+
pool: 150
|
8
8
|
username: <%= ENV['DATABASE_USER'] || 'postgres' %>
|
9
9
|
password: <%= ENV['DATABASE_PASS'] || '' %>
|
10
10
|
|
11
11
|
test:
|
12
|
-
|
12
|
+
<<: *base
|
13
|
+
|
13
14
|
|
14
15
|
production:
|
15
16
|
<<: *base
|
@@ -0,0 +1 @@
|
|
1
|
+
../../lib/generators/burstflow/install/templates/create_workflow.rb
|
data/db/schema.rb
CHANGED
@@ -10,14 +10,20 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 2018_01_01_000001) do
|
14
|
+
|
14
15
|
# These are extensions that must be enabled in order to support this database
|
15
|
-
enable_extension
|
16
|
-
enable_extension
|
16
|
+
enable_extension "pgcrypto"
|
17
|
+
enable_extension "plpgsql"
|
17
18
|
|
18
|
-
create_table
|
19
|
-
t.
|
20
|
-
t.
|
21
|
-
t.
|
19
|
+
create_table "burstflow_workflows", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
20
|
+
t.string "type"
|
21
|
+
t.string "status"
|
22
|
+
t.jsonb "flow", default: {}, null: false
|
23
|
+
t.datetime "created_at", null: false
|
24
|
+
t.datetime "updated_at", null: false
|
25
|
+
t.index ["status"], name: "index_burstflow_workflows_on_status"
|
26
|
+
t.index ["type"], name: "index_burstflow_workflows_on_type"
|
22
27
|
end
|
28
|
+
|
23
29
|
end
|
data/lib/burstflow.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require "active_support/rescuable"
|
2
|
+
require "active_job/callbacks"
|
3
|
+
|
4
|
+
class Burstflow::Job
|
5
|
+
require "burstflow/job/exception"
|
6
|
+
require "burstflow/job/model"
|
7
|
+
require "burstflow/job/initialization"
|
8
|
+
require "burstflow/job/state"
|
9
|
+
require "burstflow/job/callbacks"
|
10
|
+
|
11
|
+
include Burstflow::Job::Model
|
12
|
+
include Burstflow::Job::Initialization
|
13
|
+
include Burstflow::Job::State
|
14
|
+
include Burstflow::Job::Callbacks
|
15
|
+
include ActiveSupport::Rescuable
|
16
|
+
|
17
|
+
attr_accessor :workflow, :payloads
|
18
|
+
|
19
|
+
define_stored_attributes :id, :workflow_id, :klass, :params, :incoming, :outgoing, :output, :failure
|
20
|
+
define_stored_attributes :enqueued_at, :started_at, :finished_at, :failed_at, :suspended_at, :resumed_at
|
21
|
+
|
22
|
+
SUSPEND = 'suspend'.freeze
|
23
|
+
|
24
|
+
def save!
|
25
|
+
workflow.with_lock do
|
26
|
+
workflow.set_job(self)
|
27
|
+
workflow.save!
|
28
|
+
yield if block_given?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# execute this code by ActiveJob. You may return Burstflow::Job::SUSPEND to suspend job, or call suspend method
|
33
|
+
def perform
|
34
|
+
end
|
35
|
+
|
36
|
+
def perform_now
|
37
|
+
run_callbacks :perform do
|
38
|
+
perform
|
39
|
+
end
|
40
|
+
rescue => exception
|
41
|
+
rescue_with_handler(exception) || raise
|
42
|
+
end
|
43
|
+
|
44
|
+
# execute this code when resumes after suspending
|
45
|
+
def resume(data)
|
46
|
+
raise InternalError.new(self, "Can't perform resume: not resumed") if !resumed?
|
47
|
+
set_output(data)
|
48
|
+
end
|
49
|
+
|
50
|
+
def resume_now data
|
51
|
+
run_callbacks :resume do
|
52
|
+
resume(data)
|
53
|
+
end
|
54
|
+
rescue => exception
|
55
|
+
rescue_with_handler(exception) || raise
|
56
|
+
end
|
57
|
+
|
58
|
+
# store data to be available for next jobs
|
59
|
+
def set_output(data)
|
60
|
+
self.output = data
|
61
|
+
end
|
62
|
+
|
63
|
+
# mark execution as suspended
|
64
|
+
def suspend
|
65
|
+
raise InternalError.new(self, "Can't suspend: not running") if !running?
|
66
|
+
set_output(SUSPEND)
|
67
|
+
end
|
68
|
+
|
69
|
+
def configure *args, &block
|
70
|
+
workflow.with_lock do
|
71
|
+
|
72
|
+
builder = Burstflow::Workflow::Builder.new(workflow, *args, &block)
|
73
|
+
workflow.flow['jobs_config'] = builder.as_json
|
74
|
+
workflow.save!
|
75
|
+
reload
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def attributes
|
80
|
+
{
|
81
|
+
workflow_id: self.workflow_id,
|
82
|
+
id: self.id,
|
83
|
+
klass: self.klass,
|
84
|
+
params: params,
|
85
|
+
incoming: self.incoming,
|
86
|
+
outgoing: self.outgoing,
|
87
|
+
output: output,
|
88
|
+
started_at: started_at,
|
89
|
+
enqueued_at: enqueued_at,
|
90
|
+
finished_at: finished_at,
|
91
|
+
failed_at: failed_at,
|
92
|
+
suspended_at: suspended_at,
|
93
|
+
resumed_at: resumed_at,
|
94
|
+
failure: self.failure
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Burstflow::Job::Callbacks
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
include ActiveJob::Callbacks
|
4
|
+
|
5
|
+
included do
|
6
|
+
|
7
|
+
define_callbacks :suspend
|
8
|
+
define_callbacks :resume
|
9
|
+
define_callbacks :failure
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
class_methods do
|
14
|
+
|
15
|
+
def before_suspend(*filters, &blk)
|
16
|
+
set_callback(:suspend, :before, *filters, &blk)
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_suspend(*filters, &blk)
|
20
|
+
set_callback(:suspend, :after, *filters, &blk)
|
21
|
+
end
|
22
|
+
|
23
|
+
def around_suspend(*filters, &blk)
|
24
|
+
set_callback(:suspend, :around, *filters, &blk)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def before_resume(*filters, &blk)
|
29
|
+
set_callback(:resume, :before, *filters, &blk)
|
30
|
+
end
|
31
|
+
|
32
|
+
def after_resume(*filters, &blk)
|
33
|
+
set_callback(:resume, :after, *filters, &blk)
|
34
|
+
end
|
35
|
+
|
36
|
+
def around_resume(*filters, &blk)
|
37
|
+
set_callback(:resume, :around, *filters, &blk)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def before_failure(*filters, &blk)
|
42
|
+
set_callback(:failure, :before, *filters, &blk)
|
43
|
+
end
|
44
|
+
|
45
|
+
def after_failure(*filters, &blk)
|
46
|
+
set_callback(:failure, :after, *filters, &blk)
|
47
|
+
end
|
48
|
+
|
49
|
+
def around_failure(*filters, &blk)
|
50
|
+
set_callback(:failure, :around, *filters, &blk)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Burstflow::Job::Initialization
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
|
6
|
+
def initialize(workflow, job_config = {})
|
7
|
+
@workflow = workflow
|
8
|
+
assign_default_values(job_config)
|
9
|
+
end
|
10
|
+
|
11
|
+
def assign_default_values(job_config)
|
12
|
+
set_model(job_config.deep_dup)
|
13
|
+
|
14
|
+
self.id ||= SecureRandom.uuid
|
15
|
+
self.workflow_id ||= @workflow.try(:id)
|
16
|
+
self.klass ||= self.class.to_s
|
17
|
+
self.incoming ||= []
|
18
|
+
self.outgoing ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def reload
|
22
|
+
assign_default_values(@workflow.job_hash(self.id))
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class_methods do
|
28
|
+
|
29
|
+
def from_hash(workflow, job_config)
|
30
|
+
job_config[:klass].constantize.new(workflow, job_config)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|