jobly 0.1.3 → 0.2.0

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: 2e477c569a3ff769ded464f2d52e4775b254b348464057de68d3a63f2eec053c
4
- data.tar.gz: 4bfdc207e0b541a52eb7e363cce13ed54635ed0b63e15e61ac5f2b17959ec98d
3
+ metadata.gz: 19d048c26e395618f64751b5d44598f0456782733361ea19f301bb8a3c30f056
4
+ data.tar.gz: c9407a5d8ac2915115448a6de9d022127fc92d06b81e1952835680c6309f00cc
5
5
  SHA512:
6
- metadata.gz: 1a427c799068ede5b6a1b97b92f22d14cbc6569cd373d06168058e75f7b91a7cc3bb54e9a91774327ca557bef6c9de54af9e0f28bb7359db514ff7ef1f0bcad3
7
- data.tar.gz: deacef64bbfa47d091134103d7450701a5dcdda4e9f5c21175c05969d17b9370552abc7f8e930a00d2271fc79669752e7aec0a5781d1c0e58cb59060b6fd6f82
6
+ metadata.gz: 9debe7765379021f9fda73fceecbd70b5967fe8b61c1888d628814be0f0e8302d51a7ce49b1c2c610750b8590611768f0e4b1b14ab041d4f0fa12f3a8e3cde8c
7
+ data.tar.gz: e6cb27d5c6ff080c6518e360d2b4409332548f07b4d26cfcb94ad4040ea08751daaa46df2476b1dc512ddda0e899dc0e8a48ac7b95e31c13dbcccca232b4964a
data/README.md CHANGED
@@ -22,24 +22,6 @@ Compact job server with API, CLI, Web UI and a Sidekiq heart.
22
22
 
23
23
  ---
24
24
 
25
- * [Installation](#installation)
26
- * [What's in the Box](#whats-in-the-box)
27
- * [Quick Start](#quick-start)
28
- * [Usage](#usage)
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)
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)
37
- * [Loading Additional Code](#loading-additional-code)
38
- * [Configuration](#configuration)
39
- * [Worker Configuration](#worker-configuration)
40
-
41
- ---
42
-
43
25
  Follow development progress:
44
26
  [![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
27
 
@@ -48,6 +30,7 @@ Installation
48
30
 
49
31
  $ gem install jobly
50
32
 
33
+ Or with the official [Jobly docker image][2].
51
34
 
52
35
 
53
36
  What's in the Box
@@ -63,205 +46,11 @@ sidekiq backgronud jobs system. It includes the following components:
63
46
 
64
47
 
65
48
 
66
- Quick Start
67
- --------------------------------------------------
68
-
69
- Follow one of these annotated [examples](/examples).
70
-
71
-
72
-
73
- Usage
49
+ Documentation
74
50
  --------------------------------------------------
75
51
 
76
-
77
- ### Server
78
-
79
- To start the server run `jobly server` and open <http://localhost:3000/>
80
- in your browser.
81
-
82
- This will start a webserver with two primary entrypoints:
83
-
84
- - `/` (root) - a dashboard for your background job processes.
85
- - `/do/JobName?param=value` - an API for executing jobs
86
-
87
-
88
- ### Worker
89
-
90
- To start processing jobs, run `jobly worker`
91
-
92
-
93
- ### Running jobs from the command line
94
-
95
- There are three ways to run a job from the command line:
96
-
97
- Run the job locally, without going through any of the background job
98
- processing chain:
99
-
100
- $ jobly run JobName param:value
101
-
102
-
103
- Run the job locally, but wait for a worker to process it.
104
-
105
- $ jobly run --later JobName param:value
106
-
107
-
108
- Send a job through the API (either localhost or remote).
109
-
110
- $ jobly send JobName param:value
111
-
112
-
113
- ### Running jobs through the API
114
-
115
- The API supports running jobs either by GET or by POST in the following URL
116
- structure:
117
-
118
- <http://localhost:3000/do/JobName>
119
-
120
- Using GET:
121
-
122
- ```
123
- $ curl localhost:3000/do/Build?deploy=no
124
- # => {"status":"received","job":"Build","params":{"deploy":"no"}}
125
- ```
126
-
127
- Using POST:
128
-
129
- ```
130
- $ curl -XPOST localhost:3000/do/Build -d deploy=yes
131
- {"status":"received","job":"Build","params":{"deploy":"yes"}}
132
- ```
133
-
134
-
135
- Building Jobs
136
- --------------------------------------------------
137
-
138
- To build a jobs "workspace", start in an empty folder and create a `./jobs`
139
- subfolder inside it. All your job classes go in this folder (configurable).
140
-
141
- All job classes will be loaded by any of Jobly's commands.
142
-
143
-
144
- ### The Job Class
145
-
146
- A job class is a simple Ruby class inheriting from
147
- [`Jobly::Job`](/lib/jobly/job.rb).
148
-
149
- The only requirement is that your class implements an `execute` method that
150
- optionally accepts keyword arguments (recommended), or a hash.
151
-
152
- Example:
153
-
154
- ```ruby
155
- class Hello < Jobly::Job
156
- def execute(name: 'bob')
157
- puts "Hello #{name}"
158
- logger.info "said hello to #{name}"
159
- end
160
- end
161
- ```
162
-
163
- Note that these classes are simply Jobly-flavored sidekiq jobs, with these
164
- key differences:
165
-
166
- - You need to implement `execute` instead of `perform`
167
- - Job arguments are defined as keyword arguments, instead of positional
168
- arguments.
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
- ```
229
-
230
-
231
- Loading Additional Code
232
- --------------------------------------------------
233
-
234
- In case your jobs require additional functionality, you may create the
235
- `./app` folder as a sibling to the `./jobs` folder (configurable).
236
-
237
- Any ruby files in this folder (and subfolders) will be autmatically loaded
238
- and available to your jobs.
239
-
240
-
241
- Configuration
242
- --------------------------------------------------
243
-
244
- Configuring Jobly can be done by one of two methods:
245
-
246
- 1. Setting environment variables.
247
- 2. Adding a `./config/jobly.rb` file.
248
-
249
- See this [example config file](/examples/02-full/config/jobly.rb) for a full
250
- annotated configuration example and a list of options with their respective
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.
52
+ Visit the [Jobly Documentation][1].
265
53
 
266
54
 
267
- [1]: https://github.com/mperham/sidekiq/wiki/Advanced-Options
55
+ [1]: https://jobly.dannyb.co
56
+ [2]: https://github.com/dannyben/docker-jobly
@@ -1,6 +1,7 @@
1
1
  require 'requires'
2
2
  require 'byebug' if ENV['BYEBUG']
3
3
 
4
+ requires 'jobly/extensions'
4
5
  requires 'jobly/refinements'
5
6
  requires 'jobly/job_extensions'
6
7
  require 'jobly/exceptions'
@@ -0,0 +1,21 @@
1
+ class Integer
2
+ def seconds
3
+ self
4
+ end
5
+ alias_method :second, :seconds
6
+
7
+ def minutes
8
+ 60 * seconds
9
+ end
10
+ alias_method :minute, :minutes
11
+
12
+ def hours
13
+ 60 * minutes
14
+ end
15
+ alias_method :hour, :hours
16
+
17
+ def days
18
+ 24 * hours
19
+ end
20
+ alias_method :day, :days
21
+ end
@@ -4,6 +4,7 @@ module Jobly
4
4
  include Sidekiq::Status::Worker
5
5
  include JobExtensions::OptionAccessors
6
6
  include JobExtensions::Actions
7
+ include JobExtensions::Solo
7
8
  using KeywordArgs
8
9
 
9
10
  sidekiq_options retry: 5, backtrace: 5
@@ -34,20 +35,7 @@ module Jobly
34
35
  # implement keyword args.
35
36
  def perform(params={})
36
37
  @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
38
+ run_to_completion if run_before_filter
51
39
  end
52
40
 
53
41
  # Inheriting classes must implement this method only.
@@ -55,5 +43,29 @@ module Jobly
55
43
  raise NotImplementedError
56
44
  end
57
45
 
46
+ private
47
+
48
+ def run_before_filter
49
+ run_actions :before
50
+ if skipped?
51
+ run_actions :skip
52
+ run_actions :after
53
+ return false
54
+ end
55
+ return true
56
+ end
57
+
58
+ def run_to_completion
59
+ params.empty? ? execute : execute(params.to_kwargs)
60
+ run_actions :success
61
+
62
+ rescue
63
+ run_actions :failure
64
+ raise
65
+
66
+ ensure
67
+ run_actions :after
68
+
69
+ end
58
70
  end
59
71
  end
@@ -1,7 +1,6 @@
1
1
  module Jobly
2
2
  module JobExtensions
3
3
  module Actions
4
-
5
4
  def self.included(base)
6
5
  base.extend ClassMethods
7
6
  end
@@ -27,11 +26,24 @@ module Jobly
27
26
  actions[:failure] << (sym || block)
28
27
  end
29
28
 
29
+ def on_skip(sym = nil, &block)
30
+ actions[:skip] ||= []
31
+ actions[:skip] << (sym || block)
32
+ end
33
+
30
34
  def actions
31
35
  @actions ||= {}
32
36
  end
33
37
  end
34
38
 
39
+ def skip_job
40
+ @skipped = true
41
+ end
42
+
43
+ def skipped?
44
+ @skipped
45
+ end
46
+
35
47
  protected
36
48
 
37
49
  def actions
@@ -0,0 +1,54 @@
1
+ require 'jobly/job_extensions/actions'
2
+
3
+ module Jobly
4
+ module JobExtensions
5
+ module Solo
6
+ include Actions
7
+
8
+ def self.included(base)
9
+ base.extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ attr_reader :solo_key
14
+
15
+ def solo(expire: 1.hour, key: nil)
16
+ @solo_key = key if key
17
+ before { solo_locked? ? skip_job : solo_lock(expire) }
18
+ after { solo_unlock }
19
+ end
20
+ end
21
+
22
+ def solo_key
23
+ @solo_key ||= (self.class.solo_key || solo_key!)
24
+ end
25
+
26
+ def solo_key!
27
+ Digest::MD5.hexdigest "#{self.class.name}:#{params}"
28
+ end
29
+
30
+ def solo_full_key
31
+ "jobly:solo:#{solo_key}"
32
+ end
33
+
34
+ def solo_locked?
35
+ Sidekiq.redis do |redis|
36
+ redis.keys(solo_full_key).count >= 1
37
+ end
38
+ end
39
+
40
+ def solo_lock(expire = 1.hour)
41
+ Sidekiq.redis do |redis|
42
+ redis.setex(solo_full_key, expire, "1")
43
+ end
44
+ end
45
+
46
+ def solo_unlock
47
+ Sidekiq.redis do |redis|
48
+ redis.del solo_full_key
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -15,8 +15,8 @@ module Jobly
15
15
  jobs_path: ENV['JOBLY_JOBS_PATH'] || "jobs",
16
16
  config_path: ENV['JOBLY_CONFIG_PATH'] || "config",
17
17
  redis_url: ENV['JOBLY_REDIS_URL'] || "redis://localhost:6379/0",
18
- status_expiration: 30,
19
- jobs_namespace: nil,
18
+ status_expiration: ENV['JOBLY_STATUS_EXPIRATION']&.to_i || 30,
19
+ jobs_namespace: ENV['JOBLY_JOBS_NAMESPACE'],
20
20
  logger: nil,
21
21
  }
22
22
  end
@@ -1,3 +1,3 @@
1
1
  module Jobly
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
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.3
4
+ version: 0.2.0
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-12 00:00:00.000000000 Z
11
+ date: 2019-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mister_bin
@@ -184,9 +184,11 @@ files:
184
184
  - lib/jobly/commands/worker.rb
185
185
  - lib/jobly/config.ru
186
186
  - lib/jobly/exceptions.rb
187
+ - lib/jobly/extensions/integer.rb
187
188
  - lib/jobly/job.rb
188
189
  - lib/jobly/job_extensions/actions.rb
189
190
  - lib/jobly/job_extensions/option_accessors.rb
191
+ - lib/jobly/job_extensions/solo.rb
190
192
  - lib/jobly/jobs.rb
191
193
  - lib/jobly/module_functions.rb
192
194
  - lib/jobly/refinements/argument_converters.rb