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 +4 -4
- data/README.md +98 -6
- data/lib/jobly.rb +1 -0
- data/lib/jobly/commands/worker.rb +25 -3
- data/lib/jobly/job.rb +46 -3
- data/lib/jobly/job_extensions/actions.rb +55 -0
- data/lib/jobly/job_extensions/option_accessors.rb +29 -0
- data/lib/jobly/refinements/convert_to_typed.rb +2 -0
- data/lib/jobly/refinements/keyword_args.rb +15 -0
- data/lib/jobly/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e477c569a3ff769ded464f2d52e4775b254b348464057de68d3a63f2eec053c
|
4
|
+
data.tar.gz: 4bfdc207e0b541a52eb7e363cce13ed54635ed0b63e15e61ac5f2b17959ec98d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
`
|
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
|
data/lib/jobly.rb
CHANGED
@@ -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 [
|
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
|
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
|
data/lib/jobly/job.rb
CHANGED
@@ -2,15 +2,58 @@ module Jobly
|
|
2
2
|
class Job
|
3
3
|
include Sidekiq::Worker
|
4
4
|
include Sidekiq::Status::Worker
|
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
|
9
|
-
|
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
|
data/lib/jobly/version.rb
CHANGED
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.
|
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-
|
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
|