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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +1 -3
  3. data/Gemfile.lock +119 -0
  4. data/burstflow.gemspec +10 -6
  5. data/config/database.yml +4 -3
  6. data/db/migrate/20180101000001_create_workflow.rb +1 -0
  7. data/db/schema.rb +13 -7
  8. data/lib/burstflow.rb +11 -0
  9. data/lib/burstflow/job.rb +102 -0
  10. data/lib/burstflow/job/callbacks.rb +55 -0
  11. data/lib/burstflow/job/exception.rb +8 -0
  12. data/lib/burstflow/job/initialization.rb +35 -0
  13. data/lib/{burst → burstflow/job}/model.rb +1 -3
  14. data/lib/burstflow/job/state.rb +125 -0
  15. data/lib/burstflow/manager.rb +123 -0
  16. data/lib/burstflow/railtie.rb +6 -0
  17. data/lib/burstflow/version.rb +3 -0
  18. data/lib/burstflow/worker.rb +59 -0
  19. data/lib/burstflow/workflow.rb +207 -0
  20. data/lib/burstflow/workflow/builder.rb +91 -0
  21. data/lib/burstflow/workflow/callbacks.rb +66 -0
  22. data/lib/{burst/workflow_helper.rb → burstflow/workflow/configuration.rb} +8 -39
  23. data/lib/burstflow/workflow/exception.rb +8 -0
  24. data/lib/generators/burstflow/install/install_generator.rb +22 -0
  25. data/lib/generators/burstflow/install/templates/create_workflow.rb +15 -0
  26. data/spec/builder_spec.rb +63 -0
  27. data/spec/{burst_spec.rb → burstflow_spec.rb} +1 -1
  28. data/spec/generators/install_generator_spec.rb +27 -0
  29. data/spec/job_spec.rb +18 -8
  30. data/spec/spec_helper.rb +4 -1
  31. data/spec/support/database_clean.rb +4 -1
  32. data/spec/workflow_spec.rb +397 -147
  33. metadata +45 -21
  34. data/db/migrate/20180101000001_create_workflow.rb +0 -13
  35. data/db/seeds.rb +0 -1
  36. data/lib/burst.rb +0 -37
  37. data/lib/burst/builder.rb +0 -48
  38. data/lib/burst/configuration.rb +0 -27
  39. data/lib/burst/job.rb +0 -187
  40. data/lib/burst/manager.rb +0 -79
  41. data/lib/burst/worker.rb +0 -42
  42. data/lib/burst/workflow.rb +0 -148
  43. data/spec/cases_spec.rb +0 -180
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 24e4b83edc403cfa7903a0aa9fe90ab8fe0968d5
4
- data.tar.gz: ff4e300d06ab5152d9ed07913b6cb88c73afefd6
2
+ SHA256:
3
+ metadata.gz: 435e3f0b3dba1c654d192d3f5f4cb1687bfe55e6c60f03e6fcb4643946603f0a
4
+ data.tar.gz: e5390d5f58fb4a2e3503516f0c0744bce0cac68411edf56477e82d84a9f9ed87
5
5
  SHA512:
6
- metadata.gz: d123b0cde794b44e1d5c969084823a299033f0d551a8a4f2790bb1622914abdb19ae3d11b1f29f9cf9c3e97edd5a68423aae8ecb785308c0e04d34507390f468
7
- data.tar.gz: e9af6f93dcae06d5d60ec1f71d746de2d9ef49e783f081a76fe854085686355e53a040978262d22ef1df7534500fca1a7caf7644cc95e531eaab9ab9aac5c19c
6
+ metadata.gz: fcb37c6b28837184136c25333cfaa3bd403bb953b9aa8dc8fe5971d499013650664444b5415aa50e2530218a88d07107e5032f90cc3ef3cd5114bd8593752669
7
+ data.tar.gz: ae739a9ab5a48b10512c3461e4720e54e564722192fca3aaf36123a48ed3a1c36de28483d19fd975659b2586637120be3dd32068f62e5bb2a294a1f6c8177e33
data/Gemfile CHANGED
@@ -5,12 +5,10 @@ platforms :mri, :ruby do
5
5
  gem 'yajl-ruby'
6
6
  end
7
7
 
8
- gem 'rake'
9
-
10
8
  group :test do
11
9
  gem 'activesupport'
12
- gem 'awesome_print'
13
10
  gem 'database_cleaner'
14
11
  gem 'otr-activerecord'
15
12
  gem 'pg', '~> 0.21.0'
13
+ gem 'awesome_print'
16
14
  end
@@ -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
@@ -1,14 +1,16 @@
1
- lib = File.expand_path('lib', __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
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 = '0.1.1'
8
+ spec.version = Burstflow::VERSION
7
9
  spec.authors = ['Samoilenko Yuri']
8
10
  spec.email = ['kinnalru@gmail.com']
9
- spec.summary = 'Burst is a parallel workflow runner using ActiveRecord and ActiveJob'
10
- spec.description = 'Burst is a parallel workflow runner using ActiveRecord and ActiveJob. It has dependency, result pipelining and suspend/resume ability'
11
- spec.homepage = 'https://github.com/RnD-Soft/burst'
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
@@ -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'] || 'burst_test' %>
7
- pool: 4
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
- <<: *base
12
+ <<: *base
13
+
13
14
 
14
15
  production:
15
16
  <<: *base
@@ -0,0 +1 @@
1
+ ../../lib/generators/burstflow/install/templates/create_workflow.rb
@@ -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: 20_180_101_000_001) do
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 'pgcrypto'
16
- enable_extension 'plpgsql'
16
+ enable_extension "pgcrypto"
17
+ enable_extension "plpgsql"
17
18
 
18
- create_table 'burst_workflows', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
19
- t.jsonb 'flow', default: {}, null: false
20
- t.datetime 'created_at', null: false
21
- t.datetime 'updated_at', null: false
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
@@ -0,0 +1,11 @@
1
+ require 'burstflow/railtie' if defined?(Rails)
2
+
3
+ require 'active_support/all'
4
+
5
+ require 'burstflow/workflow'
6
+ require 'burstflow/job'
7
+ require 'burstflow/worker'
8
+
9
+ module Burstflow
10
+
11
+ end
@@ -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,8 @@
1
+ class Burstflow::Job::InternalError < ::RuntimeError
2
+ attr_accessor :job
3
+
4
+ def initialize(job, message)
5
+ @job = job
6
+ super(message)
7
+ end
8
+ 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