jobly 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c291317ad0589ae8edc781249eed56684185e31e7b376a71c426ca31cade67f9
4
- data.tar.gz: 5bf18f622297cc8446e7e5c3ec3fcc28584cc41a5d80f611fde5e339f44f09ed
3
+ metadata.gz: 2e477c569a3ff769ded464f2d52e4775b254b348464057de68d3a63f2eec053c
4
+ data.tar.gz: 4bfdc207e0b541a52eb7e363cce13ed54635ed0b63e15e61ac5f2b17959ec98d
5
5
  SHA512:
6
- metadata.gz: db20fe73b659b6a90234537a5058d908ed857e1c1b11092afae45d60bb9bfc4565c8d865a104f54c931518197c6fb834d65fe0c1f36734b3e77ffb6daee81ac0
7
- data.tar.gz: 96757bbd1e809d05d6a752cce7bfc4a9c0967d83a78ef913f1ed9c807575dc6c415c31d2a7c6ce4adc629c7aade641bbcb088ff5e5c00b130b5df26c964aba19
6
+ metadata.gz: 1a427c799068ede5b6a1b97b92f22d14cbc6569cd373d06168058e75f7b91a7cc3bb54e9a91774327ca557bef6c9de54af9e0f28bb7359db514ff7ef1f0bcad3
7
+ data.tar.gz: deacef64bbfa47d091134103d7450701a5dcdda4e9f5c21175c05969d17b9370552abc7f8e930a00d2271fc79669752e7aec0a5781d1c0e58cb59060b6fd6f82
data/README.md CHANGED
@@ -15,20 +15,34 @@ Compact job server with API, CLI, Web UI and a Sidekiq heart.
15
15
 
16
16
  ---
17
17
 
18
+ <table><tr>
19
+ <td width='50%'><a target='_screenshot' href='/demo/terminal.gif'><img src='/demo/terminal.gif'/></a></td>
20
+ <td width='50%'><a target='_screenshot' href='/demo/screen.gif'><img src='/demo/screen.gif'/></a></td>
21
+ </tr></table>
22
+
23
+ ---
24
+
18
25
  * [Installation](#installation)
19
26
  * [What's in the Box](#whats-in-the-box)
20
27
  * [Quick Start](#quick-start)
21
28
  * [Usage](#usage)
22
- * [Server](#server)
23
- * [Worker](#worker)
24
- * [Running jobs from the command line](#running-jobs-from-the-command-line)
25
- * [Running jobs through the API](#running-jobs-through-the-api)
29
+ * [Server](#server)
30
+ * [Worker](#worker)
31
+ * [Running jobs from the command line](#running-jobs-from-the-command-line)
32
+ * [Running jobs through the API](#running-jobs-through-the-api)
26
33
  * [Building Jobs](#building-jobs)
34
+ * [The Job Class](#the-job-class)
35
+ * [Job Options](#job-options)
36
+ * [Before, After, On Failure and On Success](#before-after-on-failure-and-on-success)
27
37
  * [Loading Additional Code](#loading-additional-code)
28
38
  * [Configuration](#configuration)
39
+ * [Worker Configuration](#worker-configuration)
29
40
 
30
41
  ---
31
42
 
43
+ Follow development progress:
44
+ [![Waffle.io - Columns and their card count](https://badge.waffle.io/DannyBen/jobly.svg?columns=all&style=flat-square)](https://waffle.io/DannyBen/jobly)
45
+
32
46
  Installation
33
47
  --------------------------------------------------
34
48
 
@@ -126,8 +140,11 @@ subfolder inside it. All your job classes go in this folder (configurable).
126
140
 
127
141
  All job classes will be loaded by any of Jobly's commands.
128
142
 
143
+
144
+ ### The Job Class
145
+
129
146
  A job class is a simple Ruby class inheriting from
130
- `[Jobly::Job](/lib/jobly/job.rb)`.
147
+ [`Jobly::Job`](/lib/jobly/job.rb).
131
148
 
132
149
  The only requirement is that your class implements an `execute` method that
133
150
  optionally accepts keyword arguments (recommended), or a hash.
@@ -144,12 +161,71 @@ end
144
161
  ```
145
162
 
146
163
  Note that these classes are simply Jobly-flavored sidekiq jobs, with these
147
- differences:
164
+ key differences:
148
165
 
149
166
  - You need to implement `execute` instead of `perform`
150
167
  - Job arguments are defined as keyword arguments, instead of positional
151
168
  arguments.
152
169
 
170
+ #### Job Options
171
+
172
+ The `Jobly::Job` class supports these options:
173
+
174
+ | Key | Default | Purpose
175
+ |-------------|-----------|---------------
176
+ | `queue` | `default` | set the name of the queue for this job.
177
+ | `retries` | `5` | number of times to retry on failure.
178
+ | `backtrace` | `5` | number of backtrace lines to show in case of failures. Can be `true`, `false` or a number of lines to save.
179
+
180
+ For example:
181
+
182
+ ```ruby
183
+ class Deploy < Jobly::Job
184
+ queue 'critical'
185
+ backtrace 10
186
+ retries 3
187
+
188
+ def execute
189
+ puts "Deploying"
190
+ end
191
+ end
192
+ ```
193
+
194
+
195
+ #### Before, After, On Failure and On Success
196
+
197
+ The `Jobly::Job` class supports these callback methods:
198
+
199
+ | Method | Description
200
+ |--------------|-------------
201
+ | `before` | Executes before the job starts
202
+ | `on_success` | Executes after the job finishes, and only if it succeeds
203
+ | `on_failure` | Executes after the job finishes, and only if it fails
204
+ | `after` | Executes after the job finishes, regardless of success or failure
205
+
206
+ Each callback method can either be a block or a symbol that points to a local
207
+ method. WHen using a block, you will have the `params` variable available, with
208
+ all the parameteres sent to the job.
209
+
210
+ For example:
211
+
212
+ ```ruby
213
+ class Greet < Jobly::Job
214
+ before do
215
+ logger.info "Starting with #{params[:message]}"
216
+ end
217
+
218
+ after :reboot_computer
219
+
220
+ def execute(message: "Hello")
221
+ puts message
222
+ end
223
+
224
+ def reboot_computer
225
+ system "reboot"
226
+ end
227
+ end
228
+ ```
153
229
 
154
230
 
155
231
  Loading Additional Code
@@ -173,3 +249,19 @@ Configuring Jobly can be done by one of two methods:
173
249
  See this [example config file](/examples/02-full/config/jobly.rb) for a full
174
250
  annotated configuration example and a list of options with their respective
175
251
  environment variables.
252
+
253
+
254
+ ### Worker Configuration
255
+
256
+ For advanced configuration of the sidekiq worker, beyond what the
257
+ `jobly worker` command provides, you can place YAML files in the config
258
+ folder and point the workers to their config file with
259
+ `jobly worker --config name`.
260
+
261
+ These files are simply [sidekiq configuration files][1].
262
+
263
+ See the [worker-config](/examples/06-worker-config) example for more
264
+ information.
265
+
266
+
267
+ [1]: https://github.com/mperham/sidekiq/wiki/Advanced-Options
@@ -2,6 +2,7 @@ require 'requires'
2
2
  require 'byebug' if ENV['BYEBUG']
3
3
 
4
4
  requires 'jobly/refinements'
5
+ requires 'jobly/job_extensions'
5
6
  require 'jobly/exceptions'
6
7
  require 'jobly/sidekiq'
7
8
  require 'jobly/module_functions'
@@ -2,18 +2,40 @@ module Jobly
2
2
  module Commands
3
3
  class WorkerCmd < Base
4
4
  summary "Start a job worker"
5
- usage "jobly worker [--concurrency COUNT]"
5
+ usage "jobly worker [-c COUNT -C PATH (-q NAME)...]"
6
6
  usage "jobly worker (-h|--help)"
7
7
  option "-c, --concurrency COUNT", "Number of parallel jobs [default: 4]"
8
+ option "-C, --config PATH", "Specify a path to a YAML config file. The provided path should be relative to the global config_path directory and without the yml extension"
9
+ option "-q, --queue NAME[,WEIGHT]", "Specify one or more queues that this worker should handle"
10
+
11
+ example "jobly worker --concurrency 10"
12
+ example "jobly worker -q critical -q default -q low"
13
+ example "jobly worker --config primary"
8
14
 
9
15
  def run
10
- concurrency = args['--concurrency']
11
16
  say "Starting sidekiq"
12
- exec "sidekiq --environment #{Jobly.environment} --concurrency #{concurrency} --require #{boot_file}"
17
+ exec "sidekiq #{options_from_args}"
13
18
  end
14
19
 
15
20
  private
16
21
 
22
+ def options_from_args
23
+ result = []
24
+ result << "--environment #{Jobly.environment}"
25
+ result << "--require \"#{boot_file}\""
26
+ result << "--concurrency #{args['--concurrency']}" if args['--concurrency']
27
+
28
+ if args['--config']
29
+ config_file = "#{Jobly.config_path}/#{args['--config']}.yml"
30
+ raise ArgumentError, "Config not found: #{config_file}" unless File.exist? config_file
31
+ result << "--config \"#{config_file}\""
32
+ end
33
+
34
+ args['--queue'].each { |q| result << "--queue #{q}" }
35
+
36
+ result.join ' '
37
+ end
38
+
17
39
  def boot_file
18
40
  @boot_file ||= File.expand_path '../boot.rb', __dir__
19
41
  end
@@ -2,15 +2,58 @@ module Jobly
2
2
  class Job
3
3
  include Sidekiq::Worker
4
4
  include Sidekiq::Status::Worker
5
- sidekiq_options retry: 5
5
+ include JobExtensions::OptionAccessors
6
+ include JobExtensions::Actions
7
+ using KeywordArgs
6
8
 
9
+ sidekiq_options retry: 5, backtrace: 5
10
+ attr_reader :params
11
+
12
+ class << self
13
+ # Allow inheriting jobs to use `execute_async` instead of
14
+ # `perform_async` for consistency with `execute`
15
+ alias_method :execute_async, :perform_async
16
+
17
+ # Allow calling a job with `JobName.execute` instead of
18
+ # `JobName.new.execute`, for consistency.
19
+ def execute(*args)
20
+ new.execute *args
21
+ end
22
+
23
+ # Allow calling a job with `JobName.perform` instead of
24
+ # `JobName.new.perform`, for consistency.
25
+ def perform(*args)
26
+ new.perform *args
27
+ end
28
+
29
+ end
30
+
31
+ # This is the method sidekiq will call. We capture this call and convert
32
+ # the hash argument which was converted to array on sidekiq's side, back
33
+ # to a hash so we can forward to the job's `execute` method, which may
34
+ # implement keyword args.
7
35
  def perform(params={})
8
- params = params.to_h.transform_keys(&:to_sym)
9
- params.empty? ? execute : execute(params)
36
+ @params = params
37
+ run_actions :before
38
+
39
+ begin
40
+ params.empty? ? execute : execute(params.to_kwargs)
41
+ run_actions :success
42
+
43
+ rescue
44
+ run_actions :failure
45
+ raise
46
+
47
+ ensure
48
+ run_actions :after
49
+
50
+ end
10
51
  end
11
52
 
53
+ # Inheriting classes must implement this method only.
12
54
  def execute(params={})
13
55
  raise NotImplementedError
14
56
  end
57
+
15
58
  end
16
59
  end
@@ -0,0 +1,55 @@
1
+ module Jobly
2
+ module JobExtensions
3
+ module Actions
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def before(sym = nil, &block)
11
+ actions[:before] ||= []
12
+ actions[:before] << (sym || block)
13
+ end
14
+
15
+ def after(sym = nil, &block)
16
+ actions[:after] ||= []
17
+ actions[:after] << (sym || block)
18
+ end
19
+
20
+ def on_success(sym = nil, &block)
21
+ actions[:success] ||= []
22
+ actions[:success] << (sym || block)
23
+ end
24
+
25
+ def on_failure(sym = nil, &block)
26
+ actions[:failure] ||= []
27
+ actions[:failure] << (sym || block)
28
+ end
29
+
30
+ def actions
31
+ @actions ||= {}
32
+ end
33
+ end
34
+
35
+ protected
36
+
37
+ def actions
38
+ self.class.actions
39
+ end
40
+
41
+ def run_actions(list)
42
+ return unless actions[list]
43
+
44
+ actions[list].each do |action|
45
+ if action.is_a? Symbol
46
+ send action
47
+ else
48
+ instance_eval &action
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ module Jobly
2
+ module JobExtensions
3
+ module OptionAccessors
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def options
11
+ sidekiq_options
12
+ end
13
+
14
+ def queue(name)
15
+ options['queue'] = name
16
+ end
17
+
18
+ def retries(count)
19
+ options['retry'] = count
20
+ end
21
+
22
+ def backtrace(count)
23
+ options['backtrace'] = count
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -18,6 +18,8 @@ module Jobly
18
18
 
19
19
  refine String do
20
20
  def convert_to_typed
21
+ return true if ['true', 'yes'].include? self
22
+ return false if ['false', 'no'].include? self
21
23
  Integer self rescue self
22
24
  end
23
25
  end
@@ -0,0 +1,15 @@
1
+ module Jobly
2
+ module KeywordArgs
3
+ refine Hash do
4
+ def to_kwargs
5
+ to_h.transform_keys &:to_sym
6
+ end
7
+ end
8
+
9
+ refine Array do
10
+ def to_kwargs
11
+ to_h.transform_keys &:to_sym
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Jobly
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jobly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-09 00:00:00.000000000 Z
11
+ date: 2019-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mister_bin
@@ -185,10 +185,13 @@ files:
185
185
  - lib/jobly/config.ru
186
186
  - lib/jobly/exceptions.rb
187
187
  - lib/jobly/job.rb
188
+ - lib/jobly/job_extensions/actions.rb
189
+ - lib/jobly/job_extensions/option_accessors.rb
188
190
  - lib/jobly/jobs.rb
189
191
  - lib/jobly/module_functions.rb
190
192
  - lib/jobly/refinements/argument_converters.rb
191
193
  - lib/jobly/refinements/convert_to_typed.rb
194
+ - lib/jobly/refinements/keyword_args.rb
192
195
  - lib/jobly/server.rb
193
196
  - lib/jobly/sidekiq.rb
194
197
  - lib/jobly/version.rb