burstflow 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|