sidekiq-merger 0.0.1 → 0.0.4
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 +4 -4
- data/.dockerignore +21 -0
- data/.gemrelease +2 -0
- data/.gitignore +19 -9
- data/.travis.yml +5 -1
- data/Dockerfile +10 -0
- data/Gemfile +3 -1
- data/README.md +68 -6
- data/app/Gemfile +8 -0
- data/app/app.rb +43 -0
- data/app/config.ru +3 -0
- data/app/sidekiq.rb +25 -0
- data/app/some_worker.rb +9 -0
- data/app/unique_worker.rb +9 -0
- data/app/views/index.erb +35 -0
- data/docker-compose-common.yml +7 -0
- data/docker-compose.yml +26 -0
- data/lib/sidekiq/merger.rb +14 -18
- data/lib/sidekiq/merger/flusher.rb +4 -4
- data/lib/sidekiq/merger/merge.rb +113 -0
- data/lib/sidekiq/merger/middleware.rb +6 -4
- data/lib/sidekiq/merger/redis.rb +52 -25
- data/lib/sidekiq/merger/version.rb +1 -1
- data/lib/sidekiq/merger/views/index.erb +41 -0
- data/lib/sidekiq/merger/web.rb +22 -0
- data/misc/web_ui.png +0 -0
- data/sidekiq-merger.gemspec +9 -11
- data/spec/sidekiq/merger/flusher_spec.rb +7 -7
- data/spec/sidekiq/merger/{batch_spec.rb → merge_spec.rb} +31 -17
- data/spec/sidekiq/merger/middleware_spec.rb +12 -6
- data/spec/sidekiq/merger/redis_spec.rb +99 -69
- data/spec/spec_helper.rb +7 -2
- metadata +73 -66
- data/bin/console +0 -7
- data/bin/setup +0 -8
- data/lib/sidekiq/merger/batch.rb +0 -100
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bed498597132701a71bf77a583f97668ce5264c
|
4
|
+
data.tar.gz: 66244be154087fca1647ba21d7b12727167d5106
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01887441761e31726a0c4cb6feff20e55be5202c3fa9c3d00a43ff28b54589c484ddd95f305ac0c589972e27c05c4ae46201ca408af32ee0904aae2b80827e16
|
7
|
+
data.tar.gz: 762fca326555feada8466a1eeda5acf2189a8f9e1b2b979e2568b90ccddbc5371d840833f106640889f1f69a744ce79bfa29ee932cf1f905370586375a74830b
|
data/.dockerignore
ADDED
data/.gemrelease
ADDED
data/.gitignore
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
.bundle/
|
2
|
+
.yardoc
|
3
|
+
Gemfile.lock
|
4
|
+
_yardoc/
|
5
|
+
coverage/
|
6
|
+
doc/
|
7
|
+
pkg/
|
8
|
+
spec/reports/
|
9
|
+
tmp/
|
10
|
+
rdoc/
|
11
|
+
|
12
|
+
*.gem
|
13
|
+
*.rbc
|
14
|
+
|
15
|
+
.ruby-version
|
16
|
+
.ruby-gemset
|
17
|
+
.rvmrc
|
18
|
+
|
19
|
+
.env
|
data/.travis.yml
CHANGED
data/Dockerfile
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
[![Coverage Status][cov-image]][cov-link]
|
7
7
|
[![Code Climate][gpa-image]][gpa-link]
|
8
8
|
|
9
|
-
Merge sidekiq jobs occurring within specific period.
|
9
|
+
Merge sidekiq jobs occurring within specific period. This sidekiq middleware is inspired by [sidekiq-grouping](https://github.com/gzigzigzeo/sidekiq-grouping).
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -18,28 +18,90 @@ gem 'sidekiq-merger'
|
|
18
18
|
|
19
19
|
And then execute:
|
20
20
|
|
21
|
-
|
21
|
+
$ bundle
|
22
22
|
|
23
23
|
Or install it yourself as:
|
24
24
|
|
25
|
-
|
25
|
+
$ gem install sidekiq-merger
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
29
29
|
Add merger option into your workers.
|
30
30
|
|
31
|
-
```
|
32
|
-
class
|
31
|
+
```ruby
|
32
|
+
class SomeWorker
|
33
33
|
include Sidekiq::Worker
|
34
34
|
|
35
35
|
sidekiq_options merger: { key: -> (args) { args[0] } }
|
36
36
|
|
37
|
-
def perform(
|
37
|
+
def perform(*ids)
|
38
38
|
# Do something
|
39
39
|
end
|
40
40
|
end
|
41
41
|
```
|
42
42
|
|
43
|
+
Then, enqueue jobs by `perform_in` or `perform_at`.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
SomeWorker.perform_in 100, 4
|
47
|
+
SomeWorker.perform_in 100, 3
|
48
|
+
SomeWorker.perform_in 100, 5
|
49
|
+
```
|
50
|
+
|
51
|
+
`SomeWorker` will be executed in 100 seconds with args of `[4], [3], [5]`.
|
52
|
+
|
53
|
+
`perform_async` works without merging args.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
SomeWorker.perform_async 4
|
57
|
+
SomeWorker.perform_async 3
|
58
|
+
SomeWorker.perform_async 5
|
59
|
+
```
|
60
|
+
|
61
|
+
In this case, `SomeWorker` will be executed 3 times with args of `[4]`, `[3]` and `[5]`.
|
62
|
+
|
63
|
+
## Options
|
64
|
+
|
65
|
+
### `key` (optional, default: `nil`)
|
66
|
+
|
67
|
+
Defines merge key so different arguments can be merged.
|
68
|
+
|
69
|
+
Format: `String` or `Proc`
|
70
|
+
e.g. `sidekiq_options merger: { key: -> (args) { args[0..1] } }`
|
71
|
+
|
72
|
+
### `unique` (optional, default: `false`)
|
73
|
+
|
74
|
+
Prevents enqueue of jobs with identical arguments.
|
75
|
+
|
76
|
+
Format: `Boolean`
|
77
|
+
e.g. `true`
|
78
|
+
|
79
|
+
## Web UI
|
80
|
+
|
81
|
+

|
82
|
+
|
83
|
+
Add this line to your `config/routes.rb` to activate web UI:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
require "sidekiq/merger/web"
|
87
|
+
```
|
88
|
+
|
89
|
+
## Test
|
90
|
+
|
91
|
+
$ bundle exec rspec
|
92
|
+
|
93
|
+
The test coverage is available at `./coverage/index.html`.
|
94
|
+
|
95
|
+
To check the behavior of this plugin, you can run docker containers.
|
96
|
+
|
97
|
+
$ docker-compose up
|
98
|
+
|
99
|
+
Then, open `http://localhost:3000/`.
|
100
|
+
|
101
|
+
## Lint
|
102
|
+
|
103
|
+
$ bundle exec rubocop
|
104
|
+
|
43
105
|
## Contributing
|
44
106
|
|
45
107
|
1. Fork it
|
data/app/Gemfile
ADDED
data/app/app.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative "./sidekiq"
|
2
|
+
require "sinatra/base"
|
3
|
+
require "rack/flash"
|
4
|
+
require "sidekiq/web"
|
5
|
+
require "sidekiq-status/web"
|
6
|
+
require "sidekiq/merger/web"
|
7
|
+
|
8
|
+
class App < Sinatra::Application
|
9
|
+
enable :sessions
|
10
|
+
use Rack::Flash
|
11
|
+
|
12
|
+
get "/" do
|
13
|
+
erb :index
|
14
|
+
end
|
15
|
+
|
16
|
+
post "/some_worker/perform_in" do
|
17
|
+
n = rand(10)
|
18
|
+
SomeWorker.perform_in((params[:in] || 60).to_i, n)
|
19
|
+
flash[:notice] = "Added #{n} to SomeWorker"
|
20
|
+
redirect "/"
|
21
|
+
end
|
22
|
+
|
23
|
+
post "/some_worker/perform_async" do
|
24
|
+
n = rand(10)
|
25
|
+
SomeWorker.perform_async(n)
|
26
|
+
flash[:notice] = "Added #{n} to SomeWorker"
|
27
|
+
redirect "/"
|
28
|
+
end
|
29
|
+
|
30
|
+
post "/unique_worker/perform_in" do
|
31
|
+
n = rand(10)
|
32
|
+
UniqueWorker.perform_in((params[:in] || 60).to_i, n)
|
33
|
+
flash[:notice] = "Added #{n} to UniqueWorker"
|
34
|
+
redirect "/"
|
35
|
+
end
|
36
|
+
|
37
|
+
post "/unique_worker/perform_async" do
|
38
|
+
n = rand(10)
|
39
|
+
UniqueWorker.perform_async(n)
|
40
|
+
flash[:notice] = "Added #{n} to UniqueWorker"
|
41
|
+
redirect "/"
|
42
|
+
end
|
43
|
+
end
|
data/app/config.ru
ADDED
data/app/sidekiq.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "active_support/core_ext/numeric/time"
|
2
|
+
require "sidekiq"
|
3
|
+
require "sidekiq-status"
|
4
|
+
require "sidekiq-merger"
|
5
|
+
require_relative "./some_worker"
|
6
|
+
require_relative "./unique_worker"
|
7
|
+
|
8
|
+
expiration = 30.minutes
|
9
|
+
|
10
|
+
Sidekiq.configure_client do |config|
|
11
|
+
config.redis = { url: "redis://#{ENV["REDIS_HOST"]}:#{ENV["REDIS_PORT"]}" }
|
12
|
+
config.client_middleware do |chain|
|
13
|
+
chain.add Sidekiq::Status::ClientMiddleware, expiration: expiration
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Sidekiq.configure_server do |config|
|
18
|
+
config.redis = { url: "redis://#{ENV["REDIS_HOST"]}:#{ENV["REDIS_PORT"]}" }
|
19
|
+
config.server_middleware do |chain|
|
20
|
+
chain.add Sidekiq::Status::ServerMiddleware, expiration: expiration
|
21
|
+
end
|
22
|
+
config.client_middleware do |chain|
|
23
|
+
chain.add Sidekiq::Status::ClientMiddleware, expiration: expiration
|
24
|
+
end
|
25
|
+
end
|
data/app/some_worker.rb
ADDED
data/app/views/index.erb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta charset="UTF-8">
|
4
|
+
</head>
|
5
|
+
<body>
|
6
|
+
<h1>Sidekiq Merger</h1>
|
7
|
+
<% if flash[:notice] %>
|
8
|
+
<p style="color: green; font-weight: bold;"><%= flash[:notice] %></p>
|
9
|
+
<% end %>
|
10
|
+
<p>
|
11
|
+
<a href="/sidekiq" target="_blank">Open sidekiq console</a>
|
12
|
+
</p>
|
13
|
+
<h2>Workers</h2>
|
14
|
+
<div style="margin-left: 20px;">
|
15
|
+
<h3>SomeWorker</h3>
|
16
|
+
<div>
|
17
|
+
<form action="/some_worker/perform_in" method="post" style="display: inline-block;">
|
18
|
+
<input type="submit" name="perform_in" value="perform_in">
|
19
|
+
</form>
|
20
|
+
<form action="/some_worker/perform_in" method="post" style="display: inline-block;">
|
21
|
+
<input type="submit" name="perform_async" value="perform_async">
|
22
|
+
</form>
|
23
|
+
</div>
|
24
|
+
<h3>UniqueWorker</h3>
|
25
|
+
<div>
|
26
|
+
<form action="/some_worker/perform_in" method="post" style="display: inline-block;">
|
27
|
+
<input type="submit" name="perform_in" value="perform_in">
|
28
|
+
</form>
|
29
|
+
<form action="/some_worker/perform_in" method="post" style="display: inline-block;">
|
30
|
+
<input type="submit" name="perform_async" value="perform_async">
|
31
|
+
</form>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</body>
|
35
|
+
</html>
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
version: '2.1'
|
2
|
+
services:
|
3
|
+
worker:
|
4
|
+
extends:
|
5
|
+
file: 'docker-compose-common.yml'
|
6
|
+
service: app
|
7
|
+
command: bundle exec sidekiq -r ./sidekiq.rb
|
8
|
+
links:
|
9
|
+
- redis
|
10
|
+
environment:
|
11
|
+
- REDIS_HOST=redis
|
12
|
+
- REDIS_PORT=6379
|
13
|
+
web:
|
14
|
+
extends:
|
15
|
+
file: 'docker-compose-common.yml'
|
16
|
+
service: app
|
17
|
+
command: bundle exec rackup -p 3000 --host 0.0.0.0
|
18
|
+
ports:
|
19
|
+
- 3000:3000
|
20
|
+
links:
|
21
|
+
- redis
|
22
|
+
environment:
|
23
|
+
- REDIS_HOST=redis
|
24
|
+
- REDIS_PORT=6379
|
25
|
+
redis:
|
26
|
+
image: redis:latest
|
data/lib/sidekiq/merger.rb
CHANGED
@@ -9,25 +9,21 @@ require_relative "merger/logging_observer"
|
|
9
9
|
module Sidekiq::Merger
|
10
10
|
class << self
|
11
11
|
attr_accessor :logger
|
12
|
-
end
|
13
|
-
|
14
|
-
self.logger ||= Sidekiq.logger
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
def start!
|
14
|
+
interval = Sidekiq::Merger::Config.poll_interval
|
15
|
+
observer = Sidekiq::Merger::LoggingObserver.new(logger)
|
16
|
+
flusher = Sidekiq::Merger::Flusher.new(logger)
|
17
|
+
task = Concurrent::TimerTask.new(
|
18
|
+
execution_interval: interval
|
19
|
+
) { flusher.flush }
|
20
|
+
task.add_observer(observer)
|
21
|
+
logger.info(
|
22
|
+
"[Sidekiq::Merger] Started polling merges every #{interval} seconds"
|
23
|
+
)
|
24
|
+
task.execute
|
25
|
+
end
|
18
26
|
end
|
19
27
|
|
20
|
-
|
21
|
-
interval = Sidekiq::Merger::Config.poll_interval
|
22
|
-
observer = Sidekiq::Merger::LoggingObserver.new(logger)
|
23
|
-
flusher = Sidekiq::Merger::Flusher.new(logger)
|
24
|
-
task = Concurrent::TimerTask.new(
|
25
|
-
execution_interval: interval
|
26
|
-
) { flusher.flush }
|
27
|
-
task.add_observer(observer)
|
28
|
-
logger.info(
|
29
|
-
"[Sidekiq::Merger] Started polling batches every #{interval} seconds"
|
30
|
-
)
|
31
|
-
task.execute
|
32
|
-
end
|
28
|
+
self.logger = Sidekiq.logger
|
33
29
|
end
|
@@ -4,12 +4,12 @@ class Sidekiq::Merger::Flusher
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def flush
|
7
|
-
|
8
|
-
unless
|
7
|
+
merges = Sidekiq::Merger::Merge.all.select(&:can_flush?)
|
8
|
+
unless merges.empty?
|
9
9
|
@logger.info(
|
10
|
-
"[Sidekiq::Merger] Trying to flush
|
10
|
+
"[Sidekiq::Merger] Trying to flush merged queues: #{merges.map(&:full_merge_key).join(",")}"
|
11
11
|
)
|
12
|
-
|
12
|
+
merges.each(&:flush)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|