background_job 0.0.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/specs.yml +34 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +58 -0
- data/LICENSE.txt +21 -0
- data/README.md +247 -0
- data/Rakefile +2 -0
- data/background_job.gemspec +39 -0
- data/bin/console +14 -0
- data/bin/setup +6 -0
- data/docker-compose.yml +6 -0
- data/lib/background-job.rb +3 -0
- data/lib/background_job/configuration/base.rb +102 -0
- data/lib/background_job/configuration/faktory.rb +6 -0
- data/lib/background_job/configuration/middleware_chain.rb +109 -0
- data/lib/background_job/configuration/sidekiq.rb +23 -0
- data/lib/background_job/configuration.rb +63 -0
- data/lib/background_job/errors.rb +24 -0
- data/lib/background_job/jobs/faktory.rb +87 -0
- data/lib/background_job/jobs/job.rb +126 -0
- data/lib/background_job/jobs/sidekiq.rb +75 -0
- data/lib/background_job/jobs.rb +8 -0
- data/lib/background_job/lock.rb +141 -0
- data/lib/background_job/lock_digest.rb +36 -0
- data/lib/background_job/middleware/unique_job/faktory.rb +41 -0
- data/lib/background_job/middleware/unique_job/sidekiq.rb +48 -0
- data/lib/background_job/middleware/unique_job.rb +67 -0
- data/lib/background_job/mixin/faktory.rb +56 -0
- data/lib/background_job/mixin/shared_interface.rb +49 -0
- data/lib/background_job/mixin/sidekiq.rb +61 -0
- data/lib/background_job/mixin.rb +6 -0
- data/lib/background_job/redis_pool.rb +28 -0
- data/lib/background_job/testing.rb +76 -0
- data/lib/background_job/unique_job.rb +84 -0
- data/lib/background_job/version.rb +5 -0
- data/lib/background_job.rb +87 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7073c14e1fd364a96f5f4ddc812c5d67921905307af97f85bc3d8a0173304093
|
4
|
+
data.tar.gz: 95f18748a479ffa52bf39ac94830080564a95223193c8655c59a36083b6eebc7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa43df351a913191022dc34d5773ec51ab80bfbdf575cad58c1d33845150fa75a443f3e394e00b46da3283f7e0e69a7ed86b4637ef6e2e960ff797021172758f
|
7
|
+
data.tar.gz: c78f2257f401f3d9585f210007cb314da943aaa971dd396cccee703e142d1c949e1c037a8fcbb20bb3e8a623b7db0e36b6feb4fd25f1b42338669913465dfe4b
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Specs
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
services:
|
13
|
+
redis:
|
14
|
+
image: redis
|
15
|
+
options: >-
|
16
|
+
--health-cmd "redis-cli ping"
|
17
|
+
--health-interval 10s
|
18
|
+
--health-timeout 5s
|
19
|
+
--health-retries 5
|
20
|
+
ports:
|
21
|
+
- 6379:6379
|
22
|
+
steps:
|
23
|
+
- uses: actions/checkout@v4
|
24
|
+
- name: Set up Ruby
|
25
|
+
uses: ruby/setup-ruby@v1
|
26
|
+
with:
|
27
|
+
ruby-version: 2.7
|
28
|
+
bundler-cache: true
|
29
|
+
- name: Install dependencies
|
30
|
+
run: bundle install
|
31
|
+
- name: Run tests
|
32
|
+
run: bundle exec rspec
|
33
|
+
env:
|
34
|
+
REDIS_URL: redis://localhost:6379
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.8
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## 0.0.1 - 2024-08-01
|
8
|
+
The first release of the gem
|
9
|
+
* Added: Initial implementation with support to Sidekiq and Faktory backends
|
10
|
+
* UniqueJob middleware to avoid duplicated jobs
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
background_job (0.0.1.rc1)
|
5
|
+
connection_pool
|
6
|
+
multi_json
|
7
|
+
redis
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
awesome_print (1.9.2)
|
13
|
+
coderay (1.1.3)
|
14
|
+
connection_pool (2.4.1)
|
15
|
+
diff-lcs (1.5.1)
|
16
|
+
dotenv (2.8.1)
|
17
|
+
faktory_worker_ruby (2.0.0)
|
18
|
+
connection_pool (~> 2.2, >= 2.2.2)
|
19
|
+
method_source (1.1.0)
|
20
|
+
multi_json (1.15.0)
|
21
|
+
pry (0.14.2)
|
22
|
+
coderay (~> 1.1)
|
23
|
+
method_source (~> 1.0)
|
24
|
+
rake (12.3.3)
|
25
|
+
redis (5.2.0)
|
26
|
+
redis-client (>= 0.22.0)
|
27
|
+
redis-client (0.22.2)
|
28
|
+
connection_pool
|
29
|
+
rspec (3.13.0)
|
30
|
+
rspec-core (~> 3.13.0)
|
31
|
+
rspec-expectations (~> 3.13.0)
|
32
|
+
rspec-mocks (~> 3.13.0)
|
33
|
+
rspec-core (3.13.0)
|
34
|
+
rspec-support (~> 3.13.0)
|
35
|
+
rspec-expectations (3.13.1)
|
36
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
37
|
+
rspec-support (~> 3.13.0)
|
38
|
+
rspec-mocks (3.13.1)
|
39
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
40
|
+
rspec-support (~> 3.13.0)
|
41
|
+
rspec-support (3.13.1)
|
42
|
+
timecop (0.9.10)
|
43
|
+
|
44
|
+
PLATFORMS
|
45
|
+
x86_64-linux
|
46
|
+
|
47
|
+
DEPENDENCIES
|
48
|
+
awesome_print
|
49
|
+
background_job!
|
50
|
+
dotenv
|
51
|
+
faktory_worker_ruby
|
52
|
+
pry
|
53
|
+
rake (~> 12.0)
|
54
|
+
rspec
|
55
|
+
timecop
|
56
|
+
|
57
|
+
BUNDLED WITH
|
58
|
+
2.3.22
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Marcos G. Zimmermann
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,247 @@
|
|
1
|
+
# BackgroundJob
|
2
|
+
|
3
|
+
The purpose of this gem is to provide a simple way to enqueue background jobs in different background job clientes like Sidekiq, Faktory. (More to come). You can push jobs to the clients without actually have the client installed in your system. This is useful for distributed system or data pipelines where you want to use jobs to communicate between different services.
|
4
|
+
|
5
|
+
If you are using a monolithic application, you should use the client directly. Or in a [Ruby on Rails](https://github.com/rails/rails) application consider using [Active Jobs](https://github.com/rails/rails/tree/master/activejob). ActiveJobs integrates with a wider range of services and builtin support.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'background_job'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install background_job
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Right now the gem supports Sidekiq and Faktory. Client configurations will be covered in the next section.
|
26
|
+
|
27
|
+
You can build and push jobs using a simple DSL. The DSL is the same for all clients, but the configurations may vary.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
# Enqueue the 'Accounts::ConfirmationEmailWorker' job
|
31
|
+
# with 'User', 1 arguments to the sidekiq "high_priority_mailing" queue
|
32
|
+
# to be executed as soon as possible.
|
33
|
+
BackgroundJob.sidekiq("Accounts::ConfirmationEmailWorker", queue: 'high_priority_mailing')
|
34
|
+
.with_args("User", 1)
|
35
|
+
.push
|
36
|
+
```
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
# Schedule the 'Accounts::ConfirmationEmailWorker' job
|
40
|
+
# with 'User', 1 arguments to the sidekiq "high_priority_mailing" queue
|
41
|
+
# to be executed in one hour.
|
42
|
+
BackgroundJob.sidekiq("Accounts::ConfirmationEmailWorker", queue: 'high_priority_mailing')
|
43
|
+
.with_args("User", 1)
|
44
|
+
.in(1.hour)
|
45
|
+
.push
|
46
|
+
```
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
# Enqueue the 'Accounts::ConfirmationEmailWorker' job
|
50
|
+
# with 'User', 1 arguments to the faktory "mailing" queue
|
51
|
+
# to be executed as soon as possible.
|
52
|
+
BackgroundJob.faktory("Accounts::ConfirmationEmailWorker", queue: 'mailing')
|
53
|
+
.with_args("User", 1)
|
54
|
+
.push
|
55
|
+
```
|
56
|
+
|
57
|
+
DSL Methods:
|
58
|
+
* `with_args(*args)`: Pass the arguments to the job
|
59
|
+
* `in(time)`: Schedule the job to be executed in the future. The time can be a `Time`, `DateTime`, `ActiveSupport::Duration` or a number of seconds.
|
60
|
+
* `with_job_jid(jid)`: Set the job JID. This is useful to track the job status or cancel it. Optional, it will be generated automatically.
|
61
|
+
* `created_at(time)`: Set the job creation time. Optional, it will be generated automatically.
|
62
|
+
* `enqueue_at(time)`: Set the job enqueue time. Optional, it will be generated automatically.
|
63
|
+
* `push`: Push the job to the client.
|
64
|
+
|
65
|
+
### Sidekiq
|
66
|
+
|
67
|
+
Sidekiq configurations are under a `BackgroundJob.config.sidekiq` config. You must set the `redis` connection where Sidekiq is running.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
BackgroundJob.configure do |conf|
|
71
|
+
conf.sidekiq.redis = { url: 'redis://localhost:6379/0' } # You can pass the Redis instance directly as well
|
72
|
+
# Or using a connection pool
|
73
|
+
conf.sidekiq.redis = ConnectionPool.new(size: 5, timeout: 5) do
|
74
|
+
Redis.new(url: 'redis://localhost:6379/0')
|
75
|
+
end
|
76
|
+
# config.sidekiq.namespace = 'sidekiq' # Optional, default is nil in favor of number of databases of Redis
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
From an YAML file
|
81
|
+
```yaml
|
82
|
+
redis:
|
83
|
+
url: 'redis://localhost:6379/0'
|
84
|
+
jobs:
|
85
|
+
UsesJob:
|
86
|
+
queue: 'default'
|
87
|
+
retry: 3
|
88
|
+
BatchImportJob:
|
89
|
+
queue: 'import'
|
90
|
+
retry: 0
|
91
|
+
```
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
BackgroundJob.config_for(:sidekiq) do |config|
|
95
|
+
config.config_path = 'config/background_job.yml'
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
#### Client DSL for Sidekiq to enqueue jobs
|
100
|
+
|
101
|
+
If your are using Sidekiq in a service that does not have a jobs/worker defined, you may want to specify the list of jobs and their configurations like `queue` and `retry` in the `BackgroundJob.config.sidekiq.jobs` configuration.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
BackgroundJob.configure do |conf|
|
105
|
+
conf.sidekiq.redis = { url: 'redis://localhost:6379/0' }
|
106
|
+
conf.sidekiq.jobs = {
|
107
|
+
"UsesJob" => { queue: 'default', retry: 3 },
|
108
|
+
"BatchImportJob" => { queue: 'import', retry: 0 }
|
109
|
+
}
|
110
|
+
# Default is true, it means that will raise an error if the job is
|
111
|
+
# not specified in the jobs configuration
|
112
|
+
#
|
113
|
+
# conf.sidekiq.strict = false
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
#### Backend Mixins for Sidekiq
|
118
|
+
|
119
|
+
This are optional, you can keep your backend implementation in your application according to the client documentation. But if you want to get benefit of global configurations, or custom middlewares, you can use the provided mixins.
|
120
|
+
|
121
|
+
```diff
|
122
|
+
class Accounts::ConfirmationEmailWorker
|
123
|
+
+ extend BackgroundJob.mixin(:sidekiq, queue: :mailing)
|
124
|
+
- include Sidekiq::Worker
|
125
|
+
- sidekiq_options queue: :mailing
|
126
|
+
|
127
|
+
def perform(resource_type, resource_id)
|
128
|
+
# Do something
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
Now when you call `Accounts::ConfirmationEmailWorker.perform_async` or `Accounts::ConfirmationEmailWorker.perform_in` it will use this gem to push jobs to the backend server with the configurations defined in the mixin and the global configurations.
|
134
|
+
|
135
|
+
### Faktory
|
136
|
+
|
137
|
+
Faktory configurations are under a `BackgroundJob.config.faktory` config. This is in an erly stage. It means that the [faktory_worker_ruby](https://github.com/contribsys/faktory_worker_ruby) gem must be installed in your system.
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
require 'faktory'
|
141
|
+
BackgroundJob.configure do |conf|
|
142
|
+
conf.faktory # Just call it to enable the Faktory client
|
143
|
+
# Default is true, it means that will raise an error if the job is
|
144
|
+
# not specified in the jobs configuration
|
145
|
+
#
|
146
|
+
# conf.faktory.strict = false
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
#### Client DSL for Faktory to enqueue jobs
|
151
|
+
|
152
|
+
If your are using Faktory in a service that does not have a jobs/worker defined, you may want to specify the list of jobs and their configurations like `queue` and `retry` in the `BackgroundJob.config.faktory.jobs` configuration.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
BackgroundJob.configure do |conf|
|
156
|
+
conf.faktory
|
157
|
+
conf.faktory.jobs = {
|
158
|
+
"UsesJob" => { queue: 'default', retry: 3 },
|
159
|
+
"BatchImportJob" => { queue: 'import', retry: 0 }
|
160
|
+
}
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
#### Backend Mixins for Faktory
|
165
|
+
|
166
|
+
This are optional, you can keep your backend implementation in your application according to the client documentation. But if you want to get benefit of global configurations, or custom middlewares, you can use the provided mixins.
|
167
|
+
|
168
|
+
```diff
|
169
|
+
class Accounts::ConfirmationEmailWorker
|
170
|
+
+ extend BackgroundJob.mixin(:faktory, queue: :mailing)
|
171
|
+
- include Faktory::Job
|
172
|
+
|
173
|
+
def perform(resource_type, resource_id)
|
174
|
+
# Do something
|
175
|
+
end
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
Now when you call `Accounts::ConfirmationEmailWorker.perform_async` or `Accounts::ConfirmationEmailWorker.perform_in` it will use this gem to push jobs to the backend server with the configurations defined in the mixin and the global configurations.
|
180
|
+
|
181
|
+
## Middleware
|
182
|
+
|
183
|
+
You can define middlewares to run before and after the job execution. This is useful to add custom logging, error handling, or any other custom behavior. The current version implements a UniqueJob middleware that prevents the job to be enqueued if it is already in the queue. More details in the next section.
|
184
|
+
|
185
|
+
This is an example of a minimal middleware, note the method must return the result or the job will not push the server
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
class MyMiddleware
|
189
|
+
def call(job, conn_pool)
|
190
|
+
puts "Before push"
|
191
|
+
result = yield
|
192
|
+
puts "After push"
|
193
|
+
result
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
BackgroundJob.config_for(:sidekiq) do |config|
|
198
|
+
config.middleware do |chain|
|
199
|
+
chain.add MyMiddleware
|
200
|
+
end
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
### Unique Jobs
|
205
|
+
|
206
|
+
This library provides one experimental technology to avoid enqueue duplicated jobs. Pro versions of sidekiq and faktory provides this functionality. But this project exposes a mechanism to make this control using `Redis`. It's not loaded by default. You can load this function by require and initialize the `UniqueJob` middleware according to the service(`:faktory` or `:sidekiq`).
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
require 'background_job/middleware/unique_job'
|
210
|
+
BackgroundJob::Middleware::UniqueJob::bootstrap(service: :sidekiq)
|
211
|
+
# Or
|
212
|
+
BackgroundJob::Middleware::UniqueJob::bootstrap(service: :faktory)
|
213
|
+
|
214
|
+
# Make sure to add a redis connection to the configuration
|
215
|
+
BackgroundJob.configure do |conf|
|
216
|
+
conf.redis = { url: 'redis://localhost:6379/0' }
|
217
|
+
# Or using a connection pool
|
218
|
+
conf.redis = ConnectionPool.new(size: 5, timeout: 5) do
|
219
|
+
Redis.new(url: 'redis://localhost:6379/0')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
```
|
223
|
+
|
224
|
+
After that just define the `:uniq` settings by worker
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
BackgroundJob.sidekiq('Mailing::SignUpWorker', uniq: { across: :queue, timeout: 120 })
|
228
|
+
.with_args('User', 1)
|
229
|
+
.push
|
230
|
+
```
|
231
|
+
|
232
|
+
You can globally disable/enable this function with the `BackgroundJob.config.sidekiq.unique_job_active = <true|false>`
|
233
|
+
|
234
|
+
## Development
|
235
|
+
|
236
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
237
|
+
|
238
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
239
|
+
|
240
|
+
## Contributing
|
241
|
+
|
242
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/marcosgz/background_job.
|
243
|
+
|
244
|
+
|
245
|
+
## License
|
246
|
+
|
247
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative 'lib/background_job/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'background_job'
|
5
|
+
spec.version = BackgroundJob::VERSION
|
6
|
+
spec.authors = ['Marcos G. Zimmermann']
|
7
|
+
spec.email = ['mgzmaster@gmail.com']
|
8
|
+
|
9
|
+
spec.summary = <<~SUMMARY
|
10
|
+
A generic swappable background job client.
|
11
|
+
SUMMARY
|
12
|
+
spec.description = <<~DESCRIPTION
|
13
|
+
A generic swappable background job client that allows you to push jobs to different background job services.
|
14
|
+
DESCRIPTION
|
15
|
+
|
16
|
+
spec.homepage = 'https://github.com/marcosgz/background_job'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
19
|
+
|
20
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
|
21
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/marcosgz/background_job/issues'
|
23
|
+
spec.metadata['documentation_uri'] = 'https://github.com/marcosgz/background_job'
|
24
|
+
spec.metadata['source_code_uri'] = 'https://github.com/marcosgz/background_job'
|
25
|
+
|
26
|
+
# Specify which files should be added to the gem when it is released.
|
27
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
28
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
29
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
30
|
+
end
|
31
|
+
|
32
|
+
spec.bindir = 'exe'
|
33
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
34
|
+
spec.require_paths = ['lib']
|
35
|
+
|
36
|
+
spec.add_dependency 'redis', '>= 0.0.0'
|
37
|
+
spec.add_dependency 'connection_pool', '>= 0.0.0'
|
38
|
+
spec.add_dependency 'multi_json', '>= 0.0.0'
|
39
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'dotenv/load'
|
5
|
+
require 'pry'
|
6
|
+
require 'awesome_print'
|
7
|
+
require 'background_job'
|
8
|
+
|
9
|
+
BackgroundJob.configure do |config|
|
10
|
+
config.faktory.strict = false
|
11
|
+
config.sidekiq.strict = false
|
12
|
+
end
|
13
|
+
|
14
|
+
Pry.start
|
data/bin/setup
ADDED
data/docker-compose.yml
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BackgroundJob::Configuration::Base
|
4
|
+
class << self
|
5
|
+
private
|
6
|
+
|
7
|
+
def attribute_accessor(field, validator: nil, normalizer: nil, default: nil, write: true, read: true)
|
8
|
+
normalizer ||= :"normalize_#{field}"
|
9
|
+
validator ||= :"validate_#{field}"
|
10
|
+
|
11
|
+
define_method(field) do
|
12
|
+
unless instance_variable_defined?(:"@#{field}")
|
13
|
+
fallback = config_from_yaml[field.to_s] || default
|
14
|
+
return if fallback.nil?
|
15
|
+
|
16
|
+
send(:"#{field}=", fallback.respond_to?(:call) ? fallback.call : fallback)
|
17
|
+
end
|
18
|
+
instance_variable_get(:"@#{field}")
|
19
|
+
end if read
|
20
|
+
|
21
|
+
define_method(:"#{field}=") do |value|
|
22
|
+
value = send(normalizer, field, value) if respond_to?(normalizer, true)
|
23
|
+
send(validator, field, value) if respond_to?(validator, true)
|
24
|
+
|
25
|
+
instance_variable_set(:"@#{field}", value)
|
26
|
+
end if write
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Path to the YAML file with configs
|
31
|
+
attr_reader :config_path
|
32
|
+
|
33
|
+
# A Hash with all jobs definitions. The job class name must be the main hash key
|
34
|
+
# Example:
|
35
|
+
# "FaktoryIndexWorker":
|
36
|
+
# retry: false
|
37
|
+
# queue: "indexing"
|
38
|
+
# adapter: "faktory"
|
39
|
+
# "FaktoryBatchIndexWorker":
|
40
|
+
# retry: 5
|
41
|
+
# queue: "batch_index"
|
42
|
+
# adapter: "faktory"
|
43
|
+
attribute_accessor :jobs, default: {}
|
44
|
+
|
45
|
+
# Global disable the unique_job_active
|
46
|
+
attribute_accessor :unique_job_active, default: false
|
47
|
+
alias unique_job_active? unique_job_active
|
48
|
+
|
49
|
+
# Does not validate if it's when set to false
|
50
|
+
attribute_accessor :strict, default: true
|
51
|
+
alias strict? strict
|
52
|
+
|
53
|
+
def validate_strict_job!(class_name)
|
54
|
+
class_name = class_name.to_s
|
55
|
+
if strict? && !jobs.key?(class_name)
|
56
|
+
raise BackgroundJob::NotDefinedJobError.new(class_name)
|
57
|
+
end
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def config_path=(value)
|
62
|
+
@config_from_yaml = nil
|
63
|
+
@config_path = value
|
64
|
+
end
|
65
|
+
|
66
|
+
def middleware
|
67
|
+
@middleware ||= BackgroundJob::Configuration::MiddlewareChain.new
|
68
|
+
yield @middleware if block_given?
|
69
|
+
@middleware
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
def normalize_jobs(_, value)
|
75
|
+
return unless value.is_a?(Hash)
|
76
|
+
|
77
|
+
hash = {}
|
78
|
+
value.each do |class_name, opts|
|
79
|
+
hash[class_name.to_s] = deep_symbolize_keys(opts)
|
80
|
+
end
|
81
|
+
hash
|
82
|
+
end
|
83
|
+
|
84
|
+
def deep_symbolize_keys(hash)
|
85
|
+
return hash unless hash.is_a?(Hash)
|
86
|
+
|
87
|
+
hash.each_with_object({}) do |(key, value), memo|
|
88
|
+
memo[key.to_sym] = deep_symbolize_keys(value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def config_from_yaml
|
93
|
+
return {} unless config_path
|
94
|
+
|
95
|
+
@config_from_yaml ||= if File.exist?(config_path)
|
96
|
+
YAML.load_file(config_path)
|
97
|
+
else
|
98
|
+
raise BackgroundJob::InvalidConfigError, "The file #{config_path} does not exist."
|
99
|
+
end
|
100
|
+
@config_from_yaml || {}
|
101
|
+
end
|
102
|
+
end
|