queue_client 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +40 -0
- data/lib/queue_client.rb +35 -0
- data/lib/viki/queue/logger.rb +9 -0
- data/lib/viki/queue/message.rb +56 -0
- data/lib/viki/queue/runner.rb +64 -0
- data/lib/viki/queue/service.rb +51 -0
- data/lib/viki/queue/version.rb +5 -0
- data/queue_client.gemspec +25 -0
- data/readme.md +106 -0
- data/spec/queue/authentication_spec.rb +13 -0
- data/spec/queue/write_spec.rb +74 -0
- data/spec/runner/run_spec.rb +75 -0
- data/spec/spec_helper.rb +16 -0
- data/t +2 -0
- metadata +146 -0
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
queue-client
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3-p448
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
queue_client (1.0.0)
|
5
|
+
amqp (= 0.9.8)
|
6
|
+
bunny (= 0.9.0.pre7)
|
7
|
+
eventmachine (= 1.0.0)
|
8
|
+
oj (= 2.0.5)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
amq-client (0.9.12)
|
14
|
+
amq-protocol (>= 1.2.0)
|
15
|
+
eventmachine
|
16
|
+
amq-protocol (1.3.0)
|
17
|
+
amqp (0.9.8)
|
18
|
+
amq-client (~> 0.9.5)
|
19
|
+
amq-protocol (>= 0.9.4)
|
20
|
+
eventmachine
|
21
|
+
bunny (0.9.0.pre7)
|
22
|
+
amq-protocol (>= 1.2.0)
|
23
|
+
diff-lcs (1.1.3)
|
24
|
+
eventmachine (1.0.0)
|
25
|
+
oj (2.0.5)
|
26
|
+
rspec (2.12.0)
|
27
|
+
rspec-core (~> 2.12.0)
|
28
|
+
rspec-expectations (~> 2.12.0)
|
29
|
+
rspec-mocks (~> 2.12.0)
|
30
|
+
rspec-core (2.12.2)
|
31
|
+
rspec-expectations (2.12.1)
|
32
|
+
diff-lcs (~> 1.1.3)
|
33
|
+
rspec-mocks (2.12.2)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
queue_client!
|
40
|
+
rspec (>= 2.12.0)
|
data/lib/queue_client.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'oj'
|
2
|
+
require 'bunny'
|
3
|
+
|
4
|
+
module Viki
|
5
|
+
module Queue
|
6
|
+
@host = 'localhost'
|
7
|
+
@port = 5672
|
8
|
+
@username = 'guest'
|
9
|
+
@password = 'guest'
|
10
|
+
class << self
|
11
|
+
attr_accessor :host, :port, :username, :password, :client_name, :_service
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.configure(&block)
|
15
|
+
block.call self
|
16
|
+
raise "Viki::Queue.client_name not set" unless client_name
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.service
|
21
|
+
Viki::Queue._service ||= Service.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.reconnect
|
25
|
+
Viki::Queue._service.stop
|
26
|
+
Viki::Queue._service = Service.new({routing: Viki::Queue._service.routing})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require_relative 'viki/queue/logger'
|
32
|
+
require_relative 'viki/queue/message'
|
33
|
+
require_relative 'viki/queue/runner'
|
34
|
+
require_relative 'viki/queue/service'
|
35
|
+
require_relative 'viki/queue/version'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Viki::Queue
|
2
|
+
module Message
|
3
|
+
def create_message(resource, id, payload=nil)
|
4
|
+
write(prepare_message([:create, resource, id, payload]))
|
5
|
+
end
|
6
|
+
|
7
|
+
def update_message(resource, id, payload=nil)
|
8
|
+
write(prepare_message([:update, resource, id, payload]))
|
9
|
+
end
|
10
|
+
|
11
|
+
def delete_message(resource, id, payload=nil)
|
12
|
+
write(prepare_message([:delete, resource, id, payload]))
|
13
|
+
end
|
14
|
+
|
15
|
+
def bulk(*events)
|
16
|
+
write_many(events.map { |e| prepare_message(e) })
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def write(payload)
|
22
|
+
routing_key = "#{Viki::Queue._service.routing}.#{payload[:resource]}.#{payload[:action]}"
|
23
|
+
message = Oj.dump(payload, mode: :compat)
|
24
|
+
opts = {routing_key: routing_key, timestamp: Time.now.to_i, persistent: true}
|
25
|
+
attemps = 5
|
26
|
+
while attemps > 0
|
27
|
+
begin
|
28
|
+
send_to_queue(message, opts)
|
29
|
+
break
|
30
|
+
rescue Exception => e
|
31
|
+
attemps -= 1
|
32
|
+
if attemps > 0
|
33
|
+
sleep(0.5)
|
34
|
+
Viki::Queue.reconnect()
|
35
|
+
else
|
36
|
+
Viki::Queue::Logger.log('Failed to write in queue. Exiting.', e)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def send_to_queue(message, opts)
|
43
|
+
Viki::Queue._service.exchange.publish(message, opts)
|
44
|
+
end
|
45
|
+
|
46
|
+
def write_many(payload)
|
47
|
+
payload.each { |p| write(p) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def prepare_message(payload)
|
51
|
+
m = {action: payload[0], resource: payload[1], id: payload[2], _meta: {client_name: Viki::Queue.client_name}}
|
52
|
+
m[:payload] = payload[3] unless payload[3].nil?
|
53
|
+
m
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'amqp'
|
2
|
+
|
3
|
+
module Viki::Queue
|
4
|
+
module Runner
|
5
|
+
def run(queue, router, config={})
|
6
|
+
config = {iterations: 1, fail_pause: 10}.merge(config)
|
7
|
+
|
8
|
+
begin
|
9
|
+
EventMachine.run do
|
10
|
+
connection = AMQP.connect({
|
11
|
+
host: Viki::Queue.host,
|
12
|
+
port: Viki::Queue.port,
|
13
|
+
username: Viki::Queue.username,
|
14
|
+
password: Viki::Queue.password})
|
15
|
+
channel = AMQP::Channel.new(connection)
|
16
|
+
loops = 0
|
17
|
+
channel.prefetch(1).queue(queue, :durable => true).subscribe(:ack => true) do |metadata, message|
|
18
|
+
processed = false
|
19
|
+
for i in 1..10 do
|
20
|
+
begin
|
21
|
+
payload = Oj.load(message, symbol_keys: true)
|
22
|
+
if payload[:_meta]
|
23
|
+
payload[:_meta][:timestamp] = metadata.timestamp
|
24
|
+
else
|
25
|
+
payload[:_meta] = {timestamp: metadata.timestamp}
|
26
|
+
end
|
27
|
+
|
28
|
+
if process(router, payload) == true
|
29
|
+
processed = true
|
30
|
+
metadata.ack
|
31
|
+
break
|
32
|
+
end
|
33
|
+
rescue => e
|
34
|
+
router.error(e)
|
35
|
+
end
|
36
|
+
sleep(config[:fail_pause])
|
37
|
+
end
|
38
|
+
|
39
|
+
unless processed
|
40
|
+
router.error("Failed to process message: #{message}")
|
41
|
+
connection.close { EventMachine.stop }
|
42
|
+
end
|
43
|
+
|
44
|
+
loops += 1
|
45
|
+
if loops == config[:iterations]
|
46
|
+
connection.close { EventMachine.stop }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
rescue Interrupt
|
51
|
+
puts "Queue is interrupt. Good night!"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def process(router, message)
|
58
|
+
unless message.nil?
|
59
|
+
method = "#{message[:action]}_#{message[:resource]}"
|
60
|
+
router.send(method, message)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Viki::Queue
|
2
|
+
class Service
|
3
|
+
include Viki::Queue::Message
|
4
|
+
include Viki::Queue::Runner
|
5
|
+
|
6
|
+
attr_accessor :routing, :exchange
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@connection = Bunny.new({
|
10
|
+
host: Viki::Queue.host,
|
11
|
+
port: Viki::Queue.port,
|
12
|
+
username: Viki::Queue.username,
|
13
|
+
password: Viki::Queue.password,
|
14
|
+
keepalive: true,
|
15
|
+
threaded: false,
|
16
|
+
socket_timeout: 0,
|
17
|
+
connect_timeout: 0})
|
18
|
+
@connection.start
|
19
|
+
@channel = @connection.create_channel
|
20
|
+
@exchange = @channel.topic("general", durable: true)
|
21
|
+
@routing = opts.fetch(:routing, 'resources')
|
22
|
+
end
|
23
|
+
|
24
|
+
def stop
|
25
|
+
@connection.stop
|
26
|
+
rescue
|
27
|
+
end
|
28
|
+
|
29
|
+
def subscribe(queue, resources)
|
30
|
+
resources.each do |r|
|
31
|
+
@channel.queue(queue, durable: true).bind(@exchange, :routing_key => "#{@routing}.#{r}.#")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def unsubscribe(queue, resources)
|
36
|
+
resources.each do |r|
|
37
|
+
@channel.queue(queue, durable: true).unbind(@exchange, :routing_key => "#{@routing}.#{r}.#")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def route(route)
|
42
|
+
return if route.nil? or route == ""
|
43
|
+
route = route[0...-1] if route[-1] == '.'
|
44
|
+
@routing = route
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete(queue)
|
48
|
+
@channel.queue(queue, durable: true).delete()
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "viki/queue/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ["Viki"]
|
7
|
+
gem.email = ["engineering@viki.com"]
|
8
|
+
gem.description = %q{A client for Viki's queue}
|
9
|
+
gem.homepage = "https://github.com/viki-org/queue-client"
|
10
|
+
gem.summary = %q{A client for Viki's queue}
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "queue_client"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Viki::Queue::VERSION
|
18
|
+
|
19
|
+
gem.add_development_dependency "rspec", ">= 2.12.0"
|
20
|
+
|
21
|
+
gem.add_runtime_dependency "bunny", "0.9.0.pre7"
|
22
|
+
gem.add_runtime_dependency "eventmachine", "1.0.0"
|
23
|
+
gem.add_runtime_dependency "amqp", "0.9.8"
|
24
|
+
gem.add_runtime_dependency "oj", "2.0.5"
|
25
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
#Queue
|
2
|
+
|
3
|
+
## Configuration
|
4
|
+
Viki::Queue.configure do |config|
|
5
|
+
config.client_name = "my_app"
|
6
|
+
config.host = "queue.dev.viki.io"
|
7
|
+
config.port = "5672"
|
8
|
+
config.username = "username"
|
9
|
+
config.password = "password"
|
10
|
+
end
|
11
|
+
|
12
|
+
It defaults to localhost queues.
|
13
|
+
|
14
|
+
## Initialize
|
15
|
+
queue_service = Viki::Queue.service
|
16
|
+
|
17
|
+
## Subscribe
|
18
|
+
Before being able to consume from a queue, you must first subscribe to some resources:
|
19
|
+
|
20
|
+
queue_service.subscribe('gaia-applications', ['application', 'user'])
|
21
|
+
|
22
|
+
This creates a queue named *gaia_applications* which will monitor the *application* and *user* resources, i.e. it will subscribe to `resources.application.#` and `resources.user.#`. It is possible to change the root of the route path by using the `.route(new_route)` command as described below (see *routing*).
|
23
|
+
|
24
|
+
## Unsubscribe
|
25
|
+
You can unsubscribe from some resources:
|
26
|
+
|
27
|
+
queue_service.unsubscribe('gaia-applications', ['user'])
|
28
|
+
|
29
|
+
This leaves a queue named *gaia_applications* which only monitors the *application* resource, i.e. it will subscribe to `resources.application.#`. It is possible to change the root of the route path by using the `.route(new_route)` command as described below (see *routing*).
|
30
|
+
|
31
|
+
## Deletion
|
32
|
+
You can delete a queue and all of its queued events:
|
33
|
+
|
34
|
+
queue_service.delete('gaia_applications')
|
35
|
+
|
36
|
+
## Routing
|
37
|
+
By default, all the messages will be routed under `resources.RESOURCE_NAME.ACTION`, e.g. `resources.videos.create`.It is possible to modify the root of the route.
|
38
|
+
|
39
|
+
queue_service.route('delayed_jobs.subbing')
|
40
|
+
queue_service.create_message(:compile, '3v')
|
41
|
+
|
42
|
+
This commands will create a message under the route `delayed_jobs.subbing.compile.create`.
|
43
|
+
|
44
|
+
On the other hand, by default subscriptions are routed via `resources.RESOURCE_NAME.#`, e.g. `resources.videos.#`.
|
45
|
+
|
46
|
+
queue_service.route('services.gaia')
|
47
|
+
queue_service.subscribe('gaia-consumer', [apps])
|
48
|
+
|
49
|
+
This will create a new queue called `gaia-consumer` that is subscribed to `services.gaia.apps.#`.
|
50
|
+
|
51
|
+
*Note* that the part `.resource.action` is always present in both examples, changing the route only affects the root of it.
|
52
|
+
|
53
|
+
#Messages
|
54
|
+
|
55
|
+
Messages have always the following structure:
|
56
|
+
|
57
|
+
action: mandatory, it will always be 'create', 'update' or 'delete'
|
58
|
+
resource: mandatory
|
59
|
+
id: mandatory
|
60
|
+
payload: optional attribute.
|
61
|
+
|
62
|
+
## Writing
|
63
|
+
Use the `create_message`, `update_message` and `delete_message` methods:
|
64
|
+
|
65
|
+
queue_service.create_message(:application, '38a')
|
66
|
+
queue_service.update_message(:user, '9003u')
|
67
|
+
queue_service.delete_message(:container, '50c')
|
68
|
+
|
69
|
+
An optional payload parameter can be supplied:
|
70
|
+
|
71
|
+
queue_service.create_message(:application, '38a', {name: 'gaia'})
|
72
|
+
|
73
|
+
This will create a message in the queue that looks like:
|
74
|
+
|
75
|
+
{action: 'create', resource: 'application', id: '38a', payload: {name: 'gaia'} }
|
76
|
+
|
77
|
+
### Bulk write
|
78
|
+
Multiple events can be sent at once:
|
79
|
+
|
80
|
+
queue_service.bulk([:create, :video, '1v'], [:update, :user, '1u', 'optional_payload'], [:delete, :container, '1c'])
|
81
|
+
|
82
|
+
The events will be queued in-order.
|
83
|
+
|
84
|
+
## Consumption
|
85
|
+
|
86
|
+
Consumption involves using the built-in runner and providing a routing class:
|
87
|
+
|
88
|
+
Class GaiaRouter
|
89
|
+
def self.delete_application(event)
|
90
|
+
# do something
|
91
|
+
true
|
92
|
+
end
|
93
|
+
def self.error(error)
|
94
|
+
# handle
|
95
|
+
end
|
96
|
+
end
|
97
|
+
queue_service.run(QUEUE_NAME, GaiaRouter)
|
98
|
+
|
99
|
+
The method names look like `ACTION_RESOURCE`, where `ACTION` can be `create`, `update` or `delete`. The `RESOURCE` can be any resource. *Note* that if noone is registered for listening the kind of resource you are sending, the message will just be dropped. There's no need to `close` the queue, simply return true when the event has been successfully processed. *Note* that a message is only acknowledged to the queue when the processing method returns true.
|
100
|
+
|
101
|
+
If an exception is raised while processing the message, the runner will call the error method of the router with the exception. Afterwards, the runner will wait before trying to reprocess the same message again.
|
102
|
+
|
103
|
+
`run` takes a 3rd optional argument to configure the runner, possible values are:
|
104
|
+
|
105
|
+
* `iterations`: The number of iterations to run, i.e. of messages to process. 0 means loop forever (DEFAULT 1).
|
106
|
+
* `fail_pause`: Seconds to pause until trying to reprocess a failed message (DEFAULT 10)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Viki::Queue do
|
4
|
+
describe 'authentication' do
|
5
|
+
it 'should fail is wrong username/pasword is given' do
|
6
|
+
Viki::Queue.configure do |c|
|
7
|
+
c.username = 'wrong'
|
8
|
+
c.password = 'alsowrong'
|
9
|
+
end
|
10
|
+
expect{ Viki::Queue.service.create_message(:kitten, '22k') }.to raise_error(Bunny::PossibleAuthenticationFailureError)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Viki::Queue do
|
4
|
+
describe "write" do
|
5
|
+
it "writes a create event" do
|
6
|
+
assert({action: 'create', resource: 'kitten', id: '22k', _meta: {client_name: 'testing'}}) do
|
7
|
+
Viki::Queue.service.create_message(:kitten, '22k')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "writes an update event" do
|
12
|
+
assert({action: 'update', resource: 'kitten', id: '22k', _meta: {client_name: 'testing'}}) do
|
13
|
+
Viki::Queue.service.update_message(:kitten, '22k')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "writes a delete event" do
|
18
|
+
assert({action: 'delete', resource: 'kitten', id: '22k', _meta: {client_name: 'testing'}}) do
|
19
|
+
Viki::Queue.service.delete_message(:kitten, '22k')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "sends payload when provided" do
|
24
|
+
assert({action: 'create', resource: 'kitten', id: '22k', payload: [1,2,3], _meta: {client_name: 'testing'}}) do
|
25
|
+
Viki::Queue.service.create_message(:kitten, '22k', [1,2,3])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "writes multiple events at once" do
|
30
|
+
assert([
|
31
|
+
{action: 'create', resource: 'kitten', id: '22k', payload: 'some_payload', _meta: {client_name: 'testing'}},
|
32
|
+
{action: 'delete', resource: 'dogs', id: '34', _meta: {client_name: 'testing'}}], 2) do
|
33
|
+
Viki::Queue.service.bulk([:create, :kitten, '22k', 'some_payload'], [:delete, :dogs, '34'])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "writes the client name" do
|
38
|
+
assert({action: 'create', resource: 'kitten', _meta: {client_name: 'testing'}, id: '22k', _meta: {client_name: 'testing'}}) do
|
39
|
+
orig = Viki::Queue.client_name
|
40
|
+
Viki::Queue.client_name = "testing"
|
41
|
+
Viki::Queue.service.create_message(:kitten, '22k')
|
42
|
+
Viki::Queue.client_name = orig
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def assert(message, total=1)
|
49
|
+
EventMachine.run do
|
50
|
+
connection = AMQP.connect(host: Viki::Queue.host, port: Viki::Queue.port)
|
51
|
+
channel = AMQP::Channel.new(connection)
|
52
|
+
q = channel.queue("", exclusive: true)
|
53
|
+
routing_key = message.class == Array ? "resources.#" : "resources.#{message[:resource]}.#"
|
54
|
+
q.bind("general", routing_key: routing_key) do
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
count = 0
|
58
|
+
q.subscribe do |m|
|
59
|
+
m = Oj.load(m, symbol_keys: true)
|
60
|
+
if message.class == Array
|
61
|
+
message.include?(m).should == true
|
62
|
+
else
|
63
|
+
m.should == message
|
64
|
+
end
|
65
|
+
count += 1
|
66
|
+
if count == total
|
67
|
+
connection.close { EventMachine.stop }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Viki::Queue::Runner do
|
4
|
+
describe "run" do
|
5
|
+
it "polls the queue and noops a nil" do
|
6
|
+
fakeRouter = Class.new do
|
7
|
+
def self.create_application(e)
|
8
|
+
e[:resource].should == 'application'
|
9
|
+
e[:action].should == 'create'
|
10
|
+
e[:id].should == '22a'
|
11
|
+
true
|
12
|
+
end
|
13
|
+
def self.error(e)
|
14
|
+
puts(%{===> e: %s} % [(e).inspect])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
q = Viki::Queue.service
|
18
|
+
q.subscribe('a_queue', ['application'])
|
19
|
+
q.create_message(:application, '22a')
|
20
|
+
q.run('a_queue', fakeRouter)
|
21
|
+
q.delete('a_queue')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "includes the timestamp and the existing meta" do
|
25
|
+
fakeRouter = Class.new do
|
26
|
+
def self.create_application(e)
|
27
|
+
meta = e.delete(:_meta)
|
28
|
+
meta.include?(:timestamp).should == true
|
29
|
+
meta[:client_name].should == "testing"
|
30
|
+
true
|
31
|
+
end
|
32
|
+
def self.error(e)
|
33
|
+
puts(%{===> e: %s} % [(e).inspect])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
q = Viki::Queue.service
|
37
|
+
q.subscribe('a_queue', ['application'])
|
38
|
+
orig = Viki::Queue.client_name
|
39
|
+
Viki::Queue.client_name = "testing"
|
40
|
+
q.create_message(:application, '22a')
|
41
|
+
Viki::Queue.client_name = orig
|
42
|
+
q.run('a_queue', fakeRouter)
|
43
|
+
q.delete('a_queue')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "iterates multiple times" do
|
47
|
+
fakeRouter = Class.new do
|
48
|
+
class << self
|
49
|
+
attr_accessor :count
|
50
|
+
end
|
51
|
+
def self.create_application(e)
|
52
|
+
@count ||= 0
|
53
|
+
@count += 1
|
54
|
+
true
|
55
|
+
end
|
56
|
+
def self.update_video(e)
|
57
|
+
@count ||= 0
|
58
|
+
@count += 1
|
59
|
+
true
|
60
|
+
end
|
61
|
+
def self.error(e)
|
62
|
+
puts(%{===> e: %s} % [(e).inspect])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
Time.stub(:now).and_return(Time.at(323232323))
|
66
|
+
q = Viki::Queue.service
|
67
|
+
q.subscribe('the-queue', ['application', 'video'])
|
68
|
+
q.create_message(:application, '22a')
|
69
|
+
q.update_message(:video, '1v')
|
70
|
+
q.run('the-queue', fakeRouter, iterations: 2)
|
71
|
+
fakeRouter.count.should == 2
|
72
|
+
q.delete('the-queue')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../lib/queue_client'
|
2
|
+
require 'amqp'
|
3
|
+
require 'json'
|
4
|
+
Dir["./spec/support/**/*.rb"].each { |f| require f }
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.before(:each) {
|
8
|
+
Viki::Queue.configure do |c|
|
9
|
+
c.host = 'localhost'
|
10
|
+
c.port = 5672
|
11
|
+
c.username = 'guest'
|
12
|
+
c.password = 'guest'
|
13
|
+
c.client_name = 'testing'
|
14
|
+
end
|
15
|
+
}
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: queue_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Viki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.12.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.12.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bunny
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - '='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.9.0.pre7
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - '='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.0.pre7
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: eventmachine
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - '='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.0.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: amqp
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.8
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.8
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: oj
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - '='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.0.5
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - '='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.0.5
|
94
|
+
description: A client for Viki's queue
|
95
|
+
email:
|
96
|
+
- engineering@viki.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .ruby-gemset
|
102
|
+
- .ruby-version
|
103
|
+
- Gemfile
|
104
|
+
- Gemfile.lock
|
105
|
+
- lib/queue_client.rb
|
106
|
+
- lib/viki/queue/logger.rb
|
107
|
+
- lib/viki/queue/message.rb
|
108
|
+
- lib/viki/queue/runner.rb
|
109
|
+
- lib/viki/queue/service.rb
|
110
|
+
- lib/viki/queue/version.rb
|
111
|
+
- queue_client.gemspec
|
112
|
+
- readme.md
|
113
|
+
- spec/queue/authentication_spec.rb
|
114
|
+
- spec/queue/write_spec.rb
|
115
|
+
- spec/runner/run_spec.rb
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- t
|
118
|
+
homepage: https://github.com/viki-org/queue-client
|
119
|
+
licenses: []
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ! '>='
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 1.8.24
|
139
|
+
signing_key:
|
140
|
+
specification_version: 3
|
141
|
+
summary: A client for Viki's queue
|
142
|
+
test_files:
|
143
|
+
- spec/queue/authentication_spec.rb
|
144
|
+
- spec/queue/write_spec.rb
|
145
|
+
- spec/runner/run_spec.rb
|
146
|
+
- spec/spec_helper.rb
|