qyu 1.0.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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE +21 -0
  8. data/README.md +90 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/server +17 -0
  12. data/bin/setup +8 -0
  13. data/examples/bin/simple +7 -0
  14. data/examples/config.rb +22 -0
  15. data/examples/simple/create_workflow.rb +18 -0
  16. data/examples/simple/enqueue_job.rb +8 -0
  17. data/examples/simple/worker.rb +32 -0
  18. data/lib/qyu.rb +74 -0
  19. data/lib/qyu/config.rb +35 -0
  20. data/lib/qyu/errors.rb +4 -0
  21. data/lib/qyu/errors/base.rb +8 -0
  22. data/lib/qyu/errors/could_not_fetch_task.rb +18 -0
  23. data/lib/qyu/errors/invalid_queue_name.rb +12 -0
  24. data/lib/qyu/errors/invalid_task_attributes.rb +12 -0
  25. data/lib/qyu/errors/job_not_found.rb +14 -0
  26. data/lib/qyu/errors/lock_already_acquired.rb +12 -0
  27. data/lib/qyu/errors/lock_not_acquired.rb +12 -0
  28. data/lib/qyu/errors/message_not_received.rb +12 -0
  29. data/lib/qyu/errors/not_implemented_error.rb +12 -0
  30. data/lib/qyu/errors/payload_validation_error.rb +12 -0
  31. data/lib/qyu/errors/task_not_found.rb +15 -0
  32. data/lib/qyu/errors/task_status_update_failed.rb +15 -0
  33. data/lib/qyu/errors/unknown_validation_option.rb +12 -0
  34. data/lib/qyu/errors/unsync_error.rb +12 -0
  35. data/lib/qyu/errors/workflow_descriptor_validation_error.rb +14 -0
  36. data/lib/qyu/errors/workflow_not_found.rb +15 -0
  37. data/lib/qyu/factory.rb +26 -0
  38. data/lib/qyu/models.rb +9 -0
  39. data/lib/qyu/models/concerns/workflow_descriptor_validator.rb +117 -0
  40. data/lib/qyu/models/enums/status.rb +44 -0
  41. data/lib/qyu/models/job.rb +174 -0
  42. data/lib/qyu/models/task.rb +218 -0
  43. data/lib/qyu/models/workflow.rb +85 -0
  44. data/lib/qyu/queue.rb +5 -0
  45. data/lib/qyu/queue/base.rb +46 -0
  46. data/lib/qyu/queue/memory/adapter.rb +90 -0
  47. data/lib/qyu/store.rb +5 -0
  48. data/lib/qyu/store/base.rb +106 -0
  49. data/lib/qyu/store/memory/adapter.rb +187 -0
  50. data/lib/qyu/ui.rb +56 -0
  51. data/lib/qyu/ui/helpers/pagination.rb +35 -0
  52. data/lib/qyu/ui/public/bootstrap.min.css +5 -0
  53. data/lib/qyu/ui/public/paper-dashboard.css +3315 -0
  54. data/lib/qyu/ui/public/script.js +28 -0
  55. data/lib/qyu/ui/public/style.css +6 -0
  56. data/lib/qyu/ui/views/footer.erb +18 -0
  57. data/lib/qyu/ui/views/helpers/pagination.erb +49 -0
  58. data/lib/qyu/ui/views/jobs.erb +58 -0
  59. data/lib/qyu/ui/views/kaminari/_first_page.html.erb +3 -0
  60. data/lib/qyu/ui/views/kaminari/_gap.html.erb +3 -0
  61. data/lib/qyu/ui/views/kaminari/_last_page.html.erb +3 -0
  62. data/lib/qyu/ui/views/kaminari/_next_page.html.erb +3 -0
  63. data/lib/qyu/ui/views/kaminari/_page.html.erb +9 -0
  64. data/lib/qyu/ui/views/kaminari/_paginator.html.erb +15 -0
  65. data/lib/qyu/ui/views/kaminari/_prev_page.html.erb +3 -0
  66. data/lib/qyu/ui/views/layout.erb +33 -0
  67. data/lib/qyu/ui/views/navbar.erb +29 -0
  68. data/lib/qyu/ui/views/pagination.erb +19 -0
  69. data/lib/qyu/ui/views/show_job.erb +55 -0
  70. data/lib/qyu/ui/views/sidebar.erb +17 -0
  71. data/lib/qyu/ui/views/task_row.erb +26 -0
  72. data/lib/qyu/utils.rb +17 -0
  73. data/lib/qyu/version.rb +3 -0
  74. data/lib/qyu/workers.rb +10 -0
  75. data/lib/qyu/workers/base.rb +126 -0
  76. data/lib/qyu/workers/concerns/callback.rb +38 -0
  77. data/lib/qyu/workers/concerns/failure_queue.rb +23 -0
  78. data/lib/qyu/workers/concerns/payload_validator.rb +124 -0
  79. data/lib/qyu/workers/sync.rb +63 -0
  80. data/qyu.gemspec +36 -0
  81. metadata +278 -0
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Qyu
4
+ module Workers
5
+ module Concerns
6
+ module Callback
7
+ # Meant to add callbacks to Qyu::Worker
8
+ #
9
+ # Usage:
10
+ #
11
+ # Qyu::Worker.new do
12
+ # callback :execute, :after do
13
+ # # Do something after execution
14
+ # end
15
+ # end
16
+ #
17
+
18
+ def callback(method, type, &block)
19
+ @_callbacks ||= {}
20
+ @_callbacks[method] ||= {}
21
+ @_callbacks[method][type] = block
22
+ end
23
+
24
+ def run_callbacks(method, &block)
25
+ find_callback(method, :before)&.call
26
+ find_callback(method, :around) ? find_callback(method, :around).call(block) : yield
27
+ find_callback(method, :after)&.call
28
+ end
29
+
30
+ private
31
+
32
+ def find_callback(method, type)
33
+ @_callbacks.dig(method, type) if @_callbacks.is_a?(Hash)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Qyu
4
+ module Workers
5
+ module Concerns
6
+ # Qyu::Concerns::FailureQueue
7
+ module FailureQueue
8
+ # Adds ability to workers enqueue failed task to another queue
9
+ #
10
+ # Qyu::Worker.new do
11
+ # failure_queue true
12
+ # # or
13
+ # failure_queue false
14
+ # end
15
+ #
16
+
17
+ def failure_queue(fq)
18
+ @failure_queue = fq
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Qyu
4
+ module Workers
5
+ module Concerns
6
+ # Qyu::Concerns::PayloadValidator
7
+ module PayloadValidator
8
+ # Adds ability to workers to perform validations on
9
+ # params for the task to be processed
10
+ #
11
+ # Usage:
12
+ #
13
+ # Qyu::Worker.new do
14
+ # validates :user_id, presence: true, type: :integer, unless: :no_user
15
+ # validates :name, presence: true, type: :string
16
+ # validates :account_id, absence: true, if: :customer_id
17
+ # validates :account_id, presence: true, unless: :customer_id
18
+ # end
19
+ #
20
+
21
+ def validates(parameter, opts = {})
22
+ @_validations ||= {}
23
+ @_validations[parameter.to_s] = Qyu::Utils.stringify_hash_keys(opts)
24
+ end
25
+
26
+ def validate_payload!(model)
27
+ return unless @_validations
28
+ payload = Qyu::Utils.stringify_hash_keys(model.payload || {})
29
+ validation_errors = {}
30
+ @_validations.each do |attribute, opts|
31
+ # example: attribute :name
32
+ # example opts { presence: true, type: integer }
33
+ next unless if_validation(payload, opts['if'])
34
+ next unless unless_validation(payload, opts['unless'])
35
+ opts.map do |option, value|
36
+ error = run_validation(option, payload[attribute.to_s], value)
37
+ # next if error is nil
38
+ next unless error
39
+ validation_errors["#{attribute}.#{option}"] = error
40
+ end
41
+ end
42
+
43
+ if validation_errors.size.positive?
44
+ fail Qyu::Errors::PayloadValidationError, validation_errors
45
+ end
46
+ nil
47
+ end
48
+
49
+ private
50
+
51
+ def run_validation(option, param, value)
52
+ # Skip if and unless conditionals (return nil)
53
+ return if option.eql?('if')
54
+ return if option.eql?('unless')
55
+ # supported options are presence, absence and type
56
+ __send__(option, param, value)
57
+ rescue NoMethodError
58
+ raise Qyu::Errors::UnknownValidationOption, option
59
+ end
60
+
61
+ def presence(param, value)
62
+ return unless value
63
+ return unless param.nil?
64
+ { expected: 'present' }
65
+ end
66
+
67
+ def absence(param, value)
68
+ return unless value
69
+ return if param.nil?
70
+ { expected: 'absent' }
71
+ end
72
+
73
+ def type(param, data_type)
74
+ __send__("#{data_type}_type_validator", param)
75
+ end
76
+
77
+ # DataType validators
78
+ def integer_type_validator(param)
79
+ type_validator('integer', [Integer], param.class)
80
+ end
81
+
82
+ def string_type_validator(param)
83
+ type_validator('string', [String, Symbol], param.class)
84
+ end
85
+
86
+ def number_type_validator(param)
87
+ type_validator('number', [Integer, Float], param.class)
88
+ end
89
+
90
+ def boolean_type_validator(param)
91
+ type_validator('boolean', [TrueClass, FalseClass], param.class)
92
+ end
93
+
94
+ def hash_type_validator(param)
95
+ type_validator('hash', [Hash], param.class)
96
+ end
97
+
98
+ def array_type_validator(param)
99
+ type_validator('array', [Array], param.class)
100
+ end
101
+
102
+ def type_validator(type_name, data_types, param_class)
103
+ return if data_types.include?(param_class)
104
+ { expected: type_name, got: param_class.name.downcase }
105
+ end
106
+
107
+ # Conditonal validation
108
+ def if_validation(payload, key)
109
+ # TODO: support block passing "return yield if block_given?"
110
+ return true if key.nil?
111
+ return true if payload[key.to_s]
112
+ false
113
+ end
114
+
115
+ def unless_validation(payload, key)
116
+ # TODO: support block passing "return yield if block_given?"
117
+ return true if key.nil?
118
+ return true unless payload[key.to_s]
119
+ false
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Qyu
4
+ module Workers
5
+ class Sync < Base
6
+ def work(queue_name)
7
+ super do |task|
8
+ job = task.job
9
+ task_names_to_wait_for = job.tasks_to_wait_for(task)
10
+ log(:debug, "Task names to wait for: #{task_names_to_wait_for}")
11
+ task_names_to_wait_for.each do |task_name|
12
+ sync_condition = job.sync_condition(task, task_name)
13
+ log(:debug, "Task: #{task_name}, Sync condition: #{sync_condition}")
14
+ if respond_to?(sync_condition['function'], true)
15
+ __send__(sync_condition['function'], job, task, task_name, sync_condition['param'])
16
+ else
17
+ fail Qyu::Errors::NotImplementedError
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def eq_completed(job, task, task_name_to_wait_for, sync_param_name)
26
+ sync_param_value = task.payload[sync_param_name]
27
+ log(:debug, "Task: #{task_name_to_wait_for}, Sync param value: #{sync_param_value}")
28
+ parent_task_id = task.parent_task_id
29
+ log(:debug, "Task: #{task_name_to_wait_for}, Parent task ID: #{parent_task_id}")
30
+ task_ids = job.find_task_ids_by_name_and_ancestor_task_id(task_name_to_wait_for, parent_task_id)
31
+ log(:debug, "Task: #{task_name_to_wait_for}, Task IDs: #{task_ids}")
32
+
33
+ if task_ids.size < sync_param_value
34
+ log(:debug, 'Re-enqueuing sync task')
35
+ fail Qyu::Errors::UnsyncError
36
+ end
37
+
38
+ check_completion!(task_ids)
39
+ end
40
+
41
+ def completed(job, task, task_name_to_wait_for, _sync_param_name)
42
+ parent_task_id = task.parent_task_id
43
+ log(:debug, "Task: #{task_name_to_wait_for}, Parent task ID: #{parent_task_id}")
44
+ task_ids = job.find_task_ids_by_name_and_ancestor_task_id(task_name_to_wait_for, parent_task_id)
45
+ log(:debug, "Task: #{task_name_to_wait_for}, Task IDs: #{task_ids}")
46
+ if task_ids.empty?
47
+ log(:debug, 'Re-enqueuing sync task')
48
+ fail Qyu::Errors::UnsyncError
49
+ end
50
+ check_completion!(task_ids)
51
+ end
52
+
53
+ def check_completion!(task_ids)
54
+ task_ids.each do |task_id|
55
+ state = Qyu::Status.find(task_id)
56
+ log(:debug, "[CHECK_COMPLETION] Task ID: #{task_id}, Status: #{state.status}")
57
+ next if state.completed?
58
+ fail Qyu::Errors::UnsyncError
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "qyu/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "qyu"
8
+ spec.version = Qyu::VERSION
9
+ spec.authors = ['Elod Peter', 'Mohamed Osama']
10
+ spec.email = ['bejmuller@gmail.com', 'mohamed.o.alnagdy@gmail.com']
11
+
12
+ spec.summary = 'Distributed task execution system for complex workflows'
13
+ spec.description = 'Distributed task execution system for complex workflows'
14
+ spec.homepage = 'https://github.com/FindHotel/qyu'
15
+ spec.required_ruby_version = '>= 2.4'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_runtime_dependency 'activesupport', '~> 5.1'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.16'
27
+ spec.add_development_dependency 'dotenv'
28
+ spec.add_development_dependency 'rack-test'
29
+ spec.add_development_dependency 'pry'
30
+ spec.add_development_dependency 'pry-byebug'
31
+ spec.add_development_dependency 'rake', '~> 10.0'
32
+ spec.add_development_dependency 'rspec', '~> 3.5'
33
+ spec.add_development_dependency 'simplecov'
34
+ spec.add_development_dependency 'sinatra'
35
+ spec.add_development_dependency 'timecop', '~> 0.8'
36
+ end
metadata ADDED
@@ -0,0 +1,278 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qyu
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Elod Peter
8
+ - Mohamed Osama
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2018-02-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '5.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '5.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.16'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.16'
42
+ - !ruby/object:Gem::Dependency
43
+ name: dotenv
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rack-test
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: pry-byebug
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rake
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '10.0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '10.0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: rspec
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '3.5'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '3.5'
126
+ - !ruby/object:Gem::Dependency
127
+ name: simplecov
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: sinatra
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: timecop
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: '0.8'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '0.8'
168
+ description: Distributed task execution system for complex workflows
169
+ email:
170
+ - bejmuller@gmail.com
171
+ - mohamed.o.alnagdy@gmail.com
172
+ executables: []
173
+ extensions: []
174
+ extra_rdoc_files: []
175
+ files:
176
+ - ".gitignore"
177
+ - ".rspec"
178
+ - ".travis.yml"
179
+ - CODE_OF_CONDUCT.md
180
+ - Gemfile
181
+ - LICENSE
182
+ - README.md
183
+ - Rakefile
184
+ - bin/console
185
+ - bin/server
186
+ - bin/setup
187
+ - examples/bin/simple
188
+ - examples/config.rb
189
+ - examples/simple/create_workflow.rb
190
+ - examples/simple/enqueue_job.rb
191
+ - examples/simple/worker.rb
192
+ - lib/qyu.rb
193
+ - lib/qyu/config.rb
194
+ - lib/qyu/errors.rb
195
+ - lib/qyu/errors/base.rb
196
+ - lib/qyu/errors/could_not_fetch_task.rb
197
+ - lib/qyu/errors/invalid_queue_name.rb
198
+ - lib/qyu/errors/invalid_task_attributes.rb
199
+ - lib/qyu/errors/job_not_found.rb
200
+ - lib/qyu/errors/lock_already_acquired.rb
201
+ - lib/qyu/errors/lock_not_acquired.rb
202
+ - lib/qyu/errors/message_not_received.rb
203
+ - lib/qyu/errors/not_implemented_error.rb
204
+ - lib/qyu/errors/payload_validation_error.rb
205
+ - lib/qyu/errors/task_not_found.rb
206
+ - lib/qyu/errors/task_status_update_failed.rb
207
+ - lib/qyu/errors/unknown_validation_option.rb
208
+ - lib/qyu/errors/unsync_error.rb
209
+ - lib/qyu/errors/workflow_descriptor_validation_error.rb
210
+ - lib/qyu/errors/workflow_not_found.rb
211
+ - lib/qyu/factory.rb
212
+ - lib/qyu/models.rb
213
+ - lib/qyu/models/concerns/workflow_descriptor_validator.rb
214
+ - lib/qyu/models/enums/status.rb
215
+ - lib/qyu/models/job.rb
216
+ - lib/qyu/models/task.rb
217
+ - lib/qyu/models/workflow.rb
218
+ - lib/qyu/queue.rb
219
+ - lib/qyu/queue/base.rb
220
+ - lib/qyu/queue/memory/adapter.rb
221
+ - lib/qyu/store.rb
222
+ - lib/qyu/store/base.rb
223
+ - lib/qyu/store/memory/adapter.rb
224
+ - lib/qyu/ui.rb
225
+ - lib/qyu/ui/helpers/pagination.rb
226
+ - lib/qyu/ui/public/bootstrap.min.css
227
+ - lib/qyu/ui/public/paper-dashboard.css
228
+ - lib/qyu/ui/public/script.js
229
+ - lib/qyu/ui/public/style.css
230
+ - lib/qyu/ui/views/footer.erb
231
+ - lib/qyu/ui/views/helpers/pagination.erb
232
+ - lib/qyu/ui/views/jobs.erb
233
+ - lib/qyu/ui/views/kaminari/_first_page.html.erb
234
+ - lib/qyu/ui/views/kaminari/_gap.html.erb
235
+ - lib/qyu/ui/views/kaminari/_last_page.html.erb
236
+ - lib/qyu/ui/views/kaminari/_next_page.html.erb
237
+ - lib/qyu/ui/views/kaminari/_page.html.erb
238
+ - lib/qyu/ui/views/kaminari/_paginator.html.erb
239
+ - lib/qyu/ui/views/kaminari/_prev_page.html.erb
240
+ - lib/qyu/ui/views/layout.erb
241
+ - lib/qyu/ui/views/navbar.erb
242
+ - lib/qyu/ui/views/pagination.erb
243
+ - lib/qyu/ui/views/show_job.erb
244
+ - lib/qyu/ui/views/sidebar.erb
245
+ - lib/qyu/ui/views/task_row.erb
246
+ - lib/qyu/utils.rb
247
+ - lib/qyu/version.rb
248
+ - lib/qyu/workers.rb
249
+ - lib/qyu/workers/base.rb
250
+ - lib/qyu/workers/concerns/callback.rb
251
+ - lib/qyu/workers/concerns/failure_queue.rb
252
+ - lib/qyu/workers/concerns/payload_validator.rb
253
+ - lib/qyu/workers/sync.rb
254
+ - qyu.gemspec
255
+ homepage: https://github.com/FindHotel/qyu
256
+ licenses: []
257
+ metadata: {}
258
+ post_install_message:
259
+ rdoc_options: []
260
+ require_paths:
261
+ - lib
262
+ required_ruby_version: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - ">="
265
+ - !ruby/object:Gem::Version
266
+ version: '2.4'
267
+ required_rubygems_version: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - ">="
270
+ - !ruby/object:Gem::Version
271
+ version: '0'
272
+ requirements: []
273
+ rubyforge_project:
274
+ rubygems_version: 2.7.4
275
+ signing_key:
276
+ specification_version: 4
277
+ summary: Distributed task execution system for complex workflows
278
+ test_files: []