jobly 0.1.3 → 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.
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