pika_que 0.1.5 → 0.1.6
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/.rspec +1 -1
- data/README.md +19 -13
- data/examples/demo_conpriority.rb +62 -0
- data/examples/demo_priority.rb +10 -19
- data/lib/pika_que.rb +6 -0
- data/lib/pika_que/cli.rb +3 -3
- data/lib/pika_que/configuration.rb +1 -1
- data/lib/pika_que/handlers/error_handler.rb +1 -1
- data/lib/pika_que/handlers/retry_handler.rb +8 -15
- data/lib/pika_que/launcher.rb +4 -4
- data/lib/pika_que/metrics.rb +1 -1
- data/lib/pika_que/processor.rb +1 -1
- data/lib/pika_que/publisher.rb +4 -0
- data/lib/pika_que/subscriber.rb +30 -26
- data/lib/pika_que/version.rb +1 -1
- data/lib/pika_que/worker.rb +1 -1
- data/pika_que.gemspec +1 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9831c848341b3207490dfa3050b377cea179be7
|
4
|
+
data.tar.gz: 7ac6527b9df72fb0e2ea7741fb2e3cff8c36a684
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82309e8a1fa9d93b76f5881f5693059720cc0b496b8a0c7ceacdd20594b6ff70b0575ea8bbf5a0117d0ebffe5243d5da734ca13ac5770ddbcd0b3b58792f6394
|
7
|
+
data.tar.gz: e7ba16c2307b6c53a89db6d51d1320b6d40c26066871aa1a4c54c63aa4f59ca585c121b2ca69aa1b7a13e2de3b62e0ee98fd743c7e1a7c3a42e7de4c8d5a9236
|
data/.rspec
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--format
|
1
|
+
--format progress
|
2
2
|
--color
|
data/README.md
CHANGED
@@ -24,12 +24,10 @@ To create a worker:
|
|
24
24
|
```ruby
|
25
25
|
class PokeWorker
|
26
26
|
include PikaQue::Worker
|
27
|
-
from_queue "
|
27
|
+
from_queue "poke"
|
28
28
|
|
29
29
|
def perform(msg)
|
30
30
|
# do something with msg["greeting"]
|
31
|
-
# or below for active job
|
32
|
-
ActiveJob::Base.execute msg
|
33
31
|
ack!
|
34
32
|
end
|
35
33
|
end
|
@@ -45,21 +43,27 @@ To run server:
|
|
45
43
|
|
46
44
|
$ bundle exec pika_que
|
47
45
|
|
48
|
-
### Rails and ActiveJob
|
49
46
|
|
50
|
-
|
47
|
+
### Rails and ActiveJob Quickstart
|
48
|
+
|
49
|
+
Create workers(not required for ActiveJob) in:
|
51
50
|
|
52
51
|
app/workers
|
53
52
|
|
54
|
-
Create a
|
53
|
+
Create a config file `pika_que.yml` in config:
|
55
54
|
|
56
|
-
config/
|
55
|
+
config/pika_que.yml
|
57
56
|
|
58
|
-
```
|
59
|
-
# pika_que.
|
57
|
+
```yml
|
58
|
+
# pika_que.yml
|
59
|
+
processors:
|
60
|
+
- workers:
|
61
|
+
- queue: default
|
62
|
+
- queue: mailers
|
63
|
+
- queue: your-active-job-queue-name
|
64
|
+
- workers:
|
65
|
+
- worker: PokeWorker
|
60
66
|
|
61
|
-
# setup workers here. see source for available options
|
62
|
-
PikaQue.config.add_processor(workers: [PokeWorker])
|
63
67
|
```
|
64
68
|
|
65
69
|
Set the backend for active job in `config/application.rb`:
|
@@ -68,9 +72,11 @@ Set the backend for active job in `config/application.rb`:
|
|
68
72
|
|
69
73
|
Then run the server.
|
70
74
|
|
71
|
-
|
75
|
+
For more details, see [wiki](https://github.com/dwkoogt/pika_que/wiki/Rails-Setup).
|
76
|
+
|
77
|
+
### Examples
|
72
78
|
|
73
|
-
|
79
|
+
See examples for more usage reference.
|
74
80
|
|
75
81
|
## Development
|
76
82
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# > bundle exec ruby examples/demo_conpriority.rb
|
2
|
+
# https://www.rabbitmq.com/consumer-priority.html
|
3
|
+
# https://www.rabbitmq.com/blog/2013/12/16/using-consumer-priorities-with-rabbitmq/
|
4
|
+
#
|
5
|
+
# Consumer Priority
|
6
|
+
# HighPriorityWorker will process more messages than LowPriorityWorker
|
7
|
+
#
|
8
|
+
require 'pika_que'
|
9
|
+
require 'pika_que/worker'
|
10
|
+
require 'pika_que/runner'
|
11
|
+
|
12
|
+
PikaQue.logger.level = ::Logger::DEBUG
|
13
|
+
|
14
|
+
class HighPriorityWorker
|
15
|
+
include PikaQue::Worker
|
16
|
+
from_queue "pika-que-demo", :priority => 10
|
17
|
+
|
18
|
+
def perform(msg)
|
19
|
+
logger.info "HighPriorityWorker #{msg['msg']}"
|
20
|
+
ack!
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class LowPriorityWorker
|
26
|
+
include PikaQue::Worker
|
27
|
+
from_queue "pika-que-demo", :priority => 1
|
28
|
+
|
29
|
+
def perform(msg)
|
30
|
+
logger.info "LowPriorityWorker #{msg['msg']}"
|
31
|
+
ack!
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
PikaQue.config.add_processor(workers: [LowPriorityWorker], concurrency: 10)
|
37
|
+
PikaQue.config.add_processor(workers: [HighPriorityWorker], concurrency: 10)
|
38
|
+
|
39
|
+
runner = PikaQue::Runner.new
|
40
|
+
|
41
|
+
begin
|
42
|
+
runner.run
|
43
|
+
rescue => e
|
44
|
+
puts e
|
45
|
+
puts e.backtrace.join("\n")
|
46
|
+
end
|
47
|
+
|
48
|
+
sleep 3
|
49
|
+
|
50
|
+
pub = PikaQue::Publisher.new()
|
51
|
+
|
52
|
+
600.times do |i|
|
53
|
+
pub.publish({ msg: "hello world #{i}" }, routing_key: 'pika-que-demo')
|
54
|
+
end
|
55
|
+
|
56
|
+
sleep 3
|
57
|
+
|
58
|
+
runner.stop
|
59
|
+
|
60
|
+
puts "bye"
|
61
|
+
|
62
|
+
exit 1
|
data/examples/demo_priority.rb
CHANGED
@@ -1,35 +1,25 @@
|
|
1
1
|
# > bundle exec ruby examples/demo_priority.rb
|
2
|
+
#
|
3
|
+
# Priority Queue with message priorities
|
4
|
+
#
|
2
5
|
require 'pika_que'
|
3
6
|
require 'pika_que/worker'
|
4
7
|
|
5
8
|
PikaQue.logger.level = ::Logger::DEBUG
|
6
9
|
|
7
|
-
class
|
10
|
+
class PriorityWorker
|
8
11
|
include PikaQue::Worker
|
9
|
-
from_queue "pika-que-priority", :arguments => { :'x-max-priority' => 10 }
|
12
|
+
from_queue "pika-que-priority", :arguments => { :'x-max-priority' => 10 }
|
10
13
|
|
11
14
|
def perform(msg)
|
12
|
-
logger.info msg[
|
15
|
+
logger.info msg['msg']
|
13
16
|
ack!
|
14
17
|
end
|
15
18
|
|
16
19
|
end
|
17
20
|
|
18
|
-
class LowPriorityWorker
|
19
|
-
include PikaQue::Worker
|
20
|
-
from_queue "pika-que-priority", :arguments => { :'x-max-priority' => 10 }, :priority => 1
|
21
|
-
|
22
|
-
def perform(msg)
|
23
|
-
logger.info msg["msg"]
|
24
|
-
ack!
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
workers = [HighPriorityWorker,LowPriorityWorker]
|
30
|
-
|
31
21
|
begin
|
32
|
-
pro = PikaQue::Processor.new(workers:
|
22
|
+
pro = PikaQue::Processor.new(workers: [PriorityWorker], concurrency: 2)
|
33
23
|
pro.start
|
34
24
|
rescue => e
|
35
25
|
puts e
|
@@ -38,9 +28,10 @@ end
|
|
38
28
|
|
39
29
|
sleep 3
|
40
30
|
|
31
|
+
pub = PikaQue::Publisher.new()
|
41
32
|
300.times do |i|
|
42
|
-
|
43
|
-
|
33
|
+
prty = (i % 2) == 0 ? 1 : 10
|
34
|
+
pub.publish({ msg: "hello world #{i} priority #{prty}" }, routing_key: 'pika-que-priority', priority: prty)
|
44
35
|
end
|
45
36
|
|
46
37
|
sleep 3
|
data/lib/pika_que.rb
CHANGED
data/lib/pika_que/cli.rb
CHANGED
@@ -45,7 +45,7 @@ module PikaQue
|
|
45
45
|
|
46
46
|
def init_logger
|
47
47
|
PikaQue::Logging.init_logger(config[:logfile]) if config[:logfile]
|
48
|
-
PikaQue.logger.level = ::Logger::WARN if config[:
|
48
|
+
PikaQue.logger.level = ::Logger::WARN if config[:quiet]
|
49
49
|
PikaQue.logger.level = ::Logger::DEBUG if config[:verbose]
|
50
50
|
end
|
51
51
|
|
@@ -132,8 +132,8 @@ module PikaQue
|
|
132
132
|
opts[:environment] = arg
|
133
133
|
end
|
134
134
|
|
135
|
-
o.on '-q', '--
|
136
|
-
opts[:
|
135
|
+
o.on '-q', '--quiet', "Print quiet output" do |arg|
|
136
|
+
opts[:quiet] = arg
|
137
137
|
end
|
138
138
|
|
139
139
|
o.on '-v', '--verbose', "Print verbose output" do |arg|
|
@@ -76,7 +76,7 @@ module PikaQue
|
|
76
76
|
# }
|
77
77
|
|
78
78
|
def initialize
|
79
|
-
@config = DEFAULT_CONFIG
|
79
|
+
@config = Marshal.load(Marshal.dump(DEFAULT_CONFIG))
|
80
80
|
@config[:amqp] = ENV.fetch('RABBITMQ_URL', 'amqp://guest:guest@localhost:5672')
|
81
81
|
@config[:vhost] = AMQ::Settings.parse_amqp_url(@config[:amqp]).fetch(:vhost, '/')
|
82
82
|
end
|
@@ -36,7 +36,7 @@ module PikaQue
|
|
36
36
|
else
|
37
37
|
PikaQue.logger.debug "ErrorHandler publishing <#{msg}> to [#{@queue.name}]"
|
38
38
|
publish(delivery_info, msg)
|
39
|
-
channel.
|
39
|
+
channel.reject(delivery_info.delivery_tag, false)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -72,7 +72,7 @@ module PikaQue
|
|
72
72
|
|
73
73
|
#####################################################
|
74
74
|
# formula
|
75
|
-
# base X = 0, 30, 60, 120, 180, etc defaults to 0
|
75
|
+
# base X = 0, 15(2x), 30(3x), 45(4x), 60(5x), 120, 180, etc defaults to 0
|
76
76
|
# (X + 15) * 2 ** (count + 1)
|
77
77
|
def self.backoff_periods(max_retries, backoff_base)
|
78
78
|
(1..max_retries).map{ |c| next_ttl(c, backoff_base) }
|
@@ -95,7 +95,12 @@ module PikaQue
|
|
95
95
|
|
96
96
|
def setup_queues
|
97
97
|
if @opts[:retry_mode] == :const
|
98
|
-
|
98
|
+
backoffs = [@opts[:retry_const_backoff]]
|
99
|
+
else
|
100
|
+
backoffs = RetryHandler.backoff_periods(@max_retries, @backoff_base)
|
101
|
+
end
|
102
|
+
|
103
|
+
backoffs.each do |bo|
|
99
104
|
PikaQue.logger.debug "RetryHandler creating queue=#{@retry_name}-#{bo} x-dead-letter-exchange=#{@requeue_name}"
|
100
105
|
backoff_queue = @channel.queue("#{@retry_name}-#{bo}",
|
101
106
|
:durable => queue_durable?,
|
@@ -104,18 +109,6 @@ module PikaQue
|
|
104
109
|
:'x-message-ttl' => bo * @backoff_multiplier
|
105
110
|
})
|
106
111
|
backoff_queue.bind(@retry_exchange, :arguments => { :backoff => bo })
|
107
|
-
else
|
108
|
-
backoffs = RetryHandler.backoff_periods(@max_retries, @backoff_base)
|
109
|
-
backoffs.each do |bo|
|
110
|
-
PikaQue.logger.debug "RetryHandler creating queue=#{@retry_name}-#{bo} x-dead-letter-exchange=#{@requeue_name}"
|
111
|
-
backoff_queue = @channel.queue("#{@retry_name}-#{bo}",
|
112
|
-
:durable => queue_durable?,
|
113
|
-
:arguments => {
|
114
|
-
:'x-dead-letter-exchange' => @requeue_name,
|
115
|
-
:'x-message-ttl' => bo * @backoff_multiplier
|
116
|
-
})
|
117
|
-
backoff_queue.bind(@retry_exchange, :arguments => { :backoff => bo })
|
118
|
-
end
|
119
112
|
end
|
120
113
|
|
121
114
|
PikaQue.logger.debug "RetryHandler creating queue=#{@error_name}"
|
@@ -147,7 +140,7 @@ module PikaQue
|
|
147
140
|
publish_retry(delivery_info, msg, { backoff: backoff_ttl, count: num_attempts })
|
148
141
|
channel.reject(delivery_info.delivery_tag, false)
|
149
142
|
else
|
150
|
-
PikaQue.logger.info "RetryHandler msg=failing,
|
143
|
+
PikaQue.logger.info "RetryHandler msg=failing, retried_count=#{num_attempts - 1}, headers=#{metadata[:headers]}, reason=#{reason}"
|
151
144
|
|
152
145
|
publish_error(delivery_info, msg)
|
153
146
|
channel.reject(delivery_info.delivery_tag, false)
|
data/lib/pika_que/launcher.rb
CHANGED
@@ -80,10 +80,10 @@ module PikaQue
|
|
80
80
|
Thread.list.each do |thread|
|
81
81
|
logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
82
82
|
if thread.backtrace
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
logger.warn thread.backtrace.join("\n")
|
84
|
+
else
|
85
|
+
logger.warn "<no backtrace available>"
|
86
|
+
end
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
data/lib/pika_que/metrics.rb
CHANGED
@@ -11,7 +11,7 @@ module PikaQue
|
|
11
11
|
def self.init_metrics
|
12
12
|
if PikaQue.config[:metrics]
|
13
13
|
@metrics = PikaQue.config[:metrics].new
|
14
|
-
elsif PikaQue.config[:
|
14
|
+
elsif PikaQue.config[:quiet]
|
15
15
|
@metrics = PikaQue::Metrics::NullMetric.new
|
16
16
|
else
|
17
17
|
@metrics = PikaQue::Metrics::LogMetric.new
|
data/lib/pika_que/processor.rb
CHANGED
data/lib/pika_que/publisher.rb
CHANGED
data/lib/pika_que/subscriber.rb
CHANGED
@@ -32,36 +32,40 @@ module PikaQue
|
|
32
32
|
@consumer = queue.subscribe(:block => false, :manual_ack => @opts[:ack], :arguments => worker.consumer_arguments) do | delivery_info, metadata, msg |
|
33
33
|
# TODO make idletime configurable on thread pool? default is 60.
|
34
34
|
pool.post do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
metrics.measure("work.#{worker.class.name}.time") do
|
40
|
-
PikaQue.middleware.invoke(worker, delivery_info, metadata, decoded_msg) do
|
41
|
-
res = worker.work(delivery_info, metadata, decoded_msg)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
logger.debug "done processing #{res} <#{msg}>"
|
45
|
-
rescue => worker_err
|
46
|
-
res = :error
|
47
|
-
error = worker_err
|
48
|
-
notify_reporters(worker_err, worker.class, msg)
|
49
|
-
end
|
35
|
+
handle_message(worker, delivery_info, metadata, msg)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
50
39
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
metrics.increment("work.#{worker.class.name}.handled.noop")
|
40
|
+
def handle_message(worker, delivery_info, metadata, msg)
|
41
|
+
res = nil
|
42
|
+
error = nil
|
43
|
+
begin
|
44
|
+
decoded_msg = @codec.decode(msg)
|
45
|
+
metrics.measure("work.#{worker.class.name}.time") do
|
46
|
+
PikaQue.middleware.invoke(worker, delivery_info, metadata, decoded_msg) do
|
47
|
+
res = worker.work(delivery_info, metadata, decoded_msg)
|
61
48
|
end
|
62
|
-
metrics.increment("work.#{worker.class.name}.processed")
|
63
49
|
end
|
50
|
+
logger.debug "done processing #{res} <#{msg}>"
|
51
|
+
rescue => worker_err
|
52
|
+
res = :error
|
53
|
+
error = worker_err
|
54
|
+
notify_reporters(worker_err, worker.class, msg)
|
55
|
+
end
|
56
|
+
|
57
|
+
if @opts[:ack]
|
58
|
+
begin
|
59
|
+
handler.handle(res, broker.channel, delivery_info, metadata, msg, error)
|
60
|
+
metrics.increment("work.#{worker.class.name}.handled.#{res}")
|
61
|
+
rescue => handler_err
|
62
|
+
notify_reporters(handler_err, handler.class, msg)
|
63
|
+
metrics.increment("work.#{worker.class.name}.handler.error")
|
64
|
+
end
|
65
|
+
else
|
66
|
+
metrics.increment("work.#{worker.class.name}.handled.noop")
|
64
67
|
end
|
68
|
+
metrics.increment("work.#{worker.class.name}.processed")
|
65
69
|
end
|
66
70
|
|
67
71
|
def unsubscribe
|
data/lib/pika_que/version.rb
CHANGED
data/lib/pika_que/worker.rb
CHANGED
@@ -75,7 +75,7 @@ module PikaQue
|
|
75
75
|
alias_method :perform_async, :enqueue
|
76
76
|
|
77
77
|
def enqueue_at(msg, timestamp, opts={})
|
78
|
-
opts[:to_queue] ||= "#{
|
78
|
+
opts[:to_queue] ||= "#{publisher.exchange_name}-delay"
|
79
79
|
work_queue = opts.delete(:routing_key) || (queue_opts[:routing_key] if queue_opts) || queue_name
|
80
80
|
opts[:headers] = { work_at: timestamp, work_queue: work_queue }
|
81
81
|
|
data/pika_que.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pika_que
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dong Wook Koo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.15'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.15'
|
97
111
|
description: Ruby background processor for RabbitMQ.
|
98
112
|
email:
|
99
113
|
- dwkoogt@gmail.com
|
@@ -113,6 +127,7 @@ files:
|
|
113
127
|
- bin/console
|
114
128
|
- bin/setup
|
115
129
|
- examples/demo.rb
|
130
|
+
- examples/demo_conpriority.rb
|
116
131
|
- examples/demo_delay.rb
|
117
132
|
- examples/demo_oneoff.rb
|
118
133
|
- examples/demo_priority.rb
|
@@ -177,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
192
|
version: '0'
|
178
193
|
requirements: []
|
179
194
|
rubyforge_project:
|
180
|
-
rubygems_version: 2.5.2
|
195
|
+
rubygems_version: 2.4.5.2
|
181
196
|
signing_key:
|
182
197
|
specification_version: 4
|
183
198
|
summary: Ruby background processor for RabbitMQ.
|