roundhousekiq 1.0.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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/Guardfile +44 -0
- data/LICENSE.txt +22 -0
- data/README.md +120 -0
- data/Rakefile +10 -0
- data/bin/roundhousekiq +17 -0
- data/chuck-norris.png +0 -0
- data/lib/roundhousekiq/configuration.rb +15 -0
- data/lib/roundhousekiq/runner.rb +103 -0
- data/lib/roundhousekiq/version.rb +3 -0
- data/lib/roundhousekiq/worker.rb +26 -0
- data/lib/roundhousekiq/worker_definition.rb +32 -0
- data/lib/roundhousekiq/workers.rb +42 -0
- data/lib/roundhousekiq.rb +19 -0
- data/roundhousekiq.gemspec +31 -0
- data/spec/fixtures/dummy_worker.rb +6 -0
- data/spec/roundhousekiq/configuration_spec.rb +17 -0
- data/spec/roundhousekiq/runner_spec.rb +350 -0
- data/spec/roundhousekiq/worker_definition_spec.rb +76 -0
- data/spec/roundhousekiq/worker_spec.rb +64 -0
- data/spec/roundhousekiq/workers_spec.rb +71 -0
- data/spec/roundhousekiq_spec.rb +34 -0
- data/spec/spec_helper.rb +84 -0
- metadata +207 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c3d38ff3867de7878b149a1d42eec8cb890a8e56
|
4
|
+
data.tar.gz: b2b98a7563c1a9b1e5bf6710108f3fcd9f9f39ef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b3a50b8d5dbe7c744d4bcea0cf5a00bc7baf97a70c943dab37ff4b3876fd2ec4e3d7ce372a799f0235411e4494f0d3532445d3ee88c318474983e59fd539241d
|
7
|
+
data.tar.gz: e97745b71d28ded61c9197fefe0a6e93227413c0d82579ae36d0a025a2fe3e624d33a09a6a5bc2a29edaa3189e17434a47aee3f778b29efa4acc77ba271a6e42
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
roundhousekiq
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
2
|
+
require "guard/rspec/dsl"
|
3
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
4
|
+
|
5
|
+
# Feel free to open issues for suggestions and improvements
|
6
|
+
|
7
|
+
# RSpec files
|
8
|
+
rspec = dsl.rspec
|
9
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
10
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
11
|
+
watch(rspec.spec_files)
|
12
|
+
|
13
|
+
# Ruby files
|
14
|
+
ruby = dsl.ruby
|
15
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
16
|
+
|
17
|
+
# Rails files
|
18
|
+
rails = dsl.rails(view_extensions: %w(erb haml slim))
|
19
|
+
dsl.watch_spec_files_for(rails.app_files)
|
20
|
+
dsl.watch_spec_files_for(rails.views)
|
21
|
+
|
22
|
+
watch(rails.controllers) do |m|
|
23
|
+
[
|
24
|
+
rspec.spec.("routing/#{m[1]}_routing"),
|
25
|
+
rspec.spec.("controllers/#{m[1]}_controller"),
|
26
|
+
rspec.spec.("acceptance/#{m[1]}")
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Rails config changes
|
31
|
+
watch(rails.spec_helper) { rspec.spec_dir }
|
32
|
+
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
|
33
|
+
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
34
|
+
|
35
|
+
# Capybara features specs
|
36
|
+
watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
|
37
|
+
watch(rails.layouts) { |m| rspec.spec.("features/#{m[1]}") }
|
38
|
+
|
39
|
+
# Turnip features and steps
|
40
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
41
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
42
|
+
Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
43
|
+
end
|
44
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Moritz Lawitschka
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+

|
2
|
+
|
3
|
+
# Roundhousekiq
|
4
|
+
|
5
|
+

|
6
|
+

|
7
|
+

|
8
|
+

|
9
|
+

|
10
|
+
|
11
|
+
Small AMQP to Sidekiq bridge, allowing Sidekiq jobs to be triggered via AMQP.
|
12
|
+
You define your Sidekiq jobs as usual, but instead of manually invoking the
|
13
|
+
jobs, you define to which AMQP event the worker should listen on.
|
14
|
+
|
15
|
+
Take for example a fleet of services all reporting their current status every
|
16
|
+
once in a while to your central monitoring service. Because these services do
|
17
|
+
not care about when their status report is being processed and by whom, they
|
18
|
+
simple send it via your AMQP server's `status` exchange and let others handle
|
19
|
+
the rest.
|
20
|
+
|
21
|
+
The monitoring service now uses Roundhousekiq to asynchronously process these
|
22
|
+
status reports and to keep the load from the main server process, it does the
|
23
|
+
processing in background using Sidekiq. Simply set up a new Sidekiq worker,
|
24
|
+
specify the AMQP exchange and routing key to listen on, and let Roundhousekiq
|
25
|
+
handle the AMQP bindings and finding the right worker for each message:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class StatusWorker
|
29
|
+
include Sidekiq::Worker
|
30
|
+
include Roundhousekiq::Worker
|
31
|
+
|
32
|
+
# AMQP configuration
|
33
|
+
exchange_name 'status'
|
34
|
+
exchange_type :topic
|
35
|
+
queue_name 'roundhousekiq_status_worker'
|
36
|
+
routing_key 'status.*'
|
37
|
+
|
38
|
+
# Attributes:
|
39
|
+
# payload: Parsed JSON payload directly from AMQP
|
40
|
+
def perform(payload)
|
41
|
+
# Heavy computing action...
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
## Installation
|
48
|
+
|
49
|
+
Add this line to your application's Gemfile:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
gem 'roundhousekiq'
|
53
|
+
```
|
54
|
+
|
55
|
+
And then execute:
|
56
|
+
|
57
|
+
$ bundle
|
58
|
+
|
59
|
+
Or install it yourself as:
|
60
|
+
|
61
|
+
$ gem install roundhousekiq
|
62
|
+
|
63
|
+
## Usage
|
64
|
+
|
65
|
+
1. Create an initializer in _config/initializers/roundhousekiq.rb_ and specify
|
66
|
+
your AMQP host.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
Roundhousekiq.configure do |config|
|
70
|
+
# AMQP host address
|
71
|
+
# config.host = '127.0.0.1'
|
72
|
+
|
73
|
+
# AMQP host port
|
74
|
+
# config.port = '5672'
|
75
|
+
|
76
|
+
# AMQP vhost to be connected to
|
77
|
+
# config.vhost = '/'
|
78
|
+
|
79
|
+
# User credentials
|
80
|
+
# config.username = 'guest'
|
81
|
+
# config.password = 'guest'
|
82
|
+
|
83
|
+
# Prefetch count on all queues Roundhousekiq will subscribe to
|
84
|
+
# config.prefetch = 256
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
2. Create your first worker. This worker does only differ from a normal Sidekiq
|
89
|
+
worker in the `Roundhousekiq::Worker` module being included and specifying which
|
90
|
+
exchange and routing key to listen on:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
class Worker
|
94
|
+
include Sidekiq::Worker
|
95
|
+
include Roundhousekiq::Worker
|
96
|
+
|
97
|
+
exchange_name 'amq.topic'
|
98
|
+
exchange_type :topic
|
99
|
+
queue_name 'worker'
|
100
|
+
routing_key 'work'
|
101
|
+
|
102
|
+
def perform(payload)
|
103
|
+
# ...
|
104
|
+
end
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
A persistent queue named _worker_ bound to the _amq.topic_ exchange with the
|
109
|
+
routing key _work_ will be created. Each time a message arrives in that
|
110
|
+
queue, this worker will be triggered.
|
111
|
+
|
112
|
+
You do not have to specify a queue name, if you do not want to have a
|
113
|
+
persistent queue. AMQP will automatically create a queue for that worker,
|
114
|
+
which is being deleted once the Roundhousekiq daemon shuts down.
|
115
|
+
|
116
|
+
3. Run the Roundhousekiq daemon from the root of your Rails project:
|
117
|
+
|
118
|
+
```shell
|
119
|
+
$ bundle exec roundhousekiq
|
120
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
# Default directory to look in is `/spec`
|
5
|
+
# Run with `rake spec`
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
7
|
+
task.rspec_opts = ['--color', '--format', 'documentation']
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :spec
|
data/bin/roundhousekiq
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Load Rails environment
|
4
|
+
ENV['RAILS_ENV'] ||= 'development'
|
5
|
+
require File.expand_path('./config/boot')
|
6
|
+
require File.expand_path('./config/environment')
|
7
|
+
|
8
|
+
# Always pre-load Rails application
|
9
|
+
::Rails.application.eager_load!
|
10
|
+
|
11
|
+
runner = Roundhousekiq::Runner.new
|
12
|
+
runner.run
|
13
|
+
|
14
|
+
# Trap `Kill `
|
15
|
+
Signal.trap("TERM") do
|
16
|
+
runner.shutdown
|
17
|
+
end
|
data/chuck-norris.png
ADDED
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Roundhousekiq
|
2
|
+
class Configuration < Struct.new(:host, :port, :vhost, :username, :password, :prefetch)
|
3
|
+
def initialize
|
4
|
+
# AMQP connection
|
5
|
+
self.host = '127.0.0.1'
|
6
|
+
self.port = '5672'
|
7
|
+
self.vhost = '/'
|
8
|
+
self.prefetch = 256
|
9
|
+
|
10
|
+
# AMQP auth
|
11
|
+
self.username = 'guest'
|
12
|
+
self.password = 'guest'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Roundhousekiq
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
attr_accessor :connection, :channel, :queue, :consumer, :shutdown_runner,
|
5
|
+
:exchange, :error_exchange, :queues, :queue_worker_map
|
6
|
+
|
7
|
+
##################################
|
8
|
+
# Public API
|
9
|
+
##################################
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
self.queues = []
|
13
|
+
self.queue_worker_map = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
establish_connection
|
18
|
+
create_channel
|
19
|
+
create_exchanges_and_queues
|
20
|
+
setup_subscribers
|
21
|
+
end
|
22
|
+
|
23
|
+
def shutdown
|
24
|
+
# Give runner time to finish its work
|
25
|
+
self.shutdown_runner = true
|
26
|
+
sleep 10
|
27
|
+
|
28
|
+
# Spawn new thread for closing the connection. Connection cannot be closed
|
29
|
+
# from current thread (being in TRAP context).
|
30
|
+
Thread.new { self.connection.try :close }
|
31
|
+
|
32
|
+
# Sleep again to wait for connection close
|
33
|
+
sleep 10
|
34
|
+
end
|
35
|
+
|
36
|
+
def shutdown?
|
37
|
+
self.shutdown_runner
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
##################################
|
42
|
+
# Connection
|
43
|
+
##################################
|
44
|
+
|
45
|
+
def establish_connection
|
46
|
+
options = { properties: self.class.client_settings }
|
47
|
+
|
48
|
+
self.connection = Bunny.new self.class.connection_settings, options
|
49
|
+
self.connection.start
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.connection_settings
|
53
|
+
config = Roundhousekiq.config.to_h
|
54
|
+
config.select { |k, v| %i(host port vhost username password).include? k }
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.client_settings
|
58
|
+
Bunny::Session::DEFAULT_CLIENT_PROPERTIES.merge product: 'Roundhousekiq'
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_channel
|
62
|
+
self.channel = self.connection.create_channel
|
63
|
+
self.channel.prefetch Roundhousekiq.config.prefetch
|
64
|
+
self.channel
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_exchanges_and_queues
|
68
|
+
Workers.definitions.each do |worker, definition|
|
69
|
+
exchange = self.channel.exchange(
|
70
|
+
definition.exchange[:name],
|
71
|
+
type: definition.exchange[:type],
|
72
|
+
durable: true
|
73
|
+
)
|
74
|
+
|
75
|
+
queue = self.channel.queue(
|
76
|
+
definition.queue[:name],
|
77
|
+
auto_delete: definition.queue[:auto_delete],
|
78
|
+
durable: definition.queue[:durable]
|
79
|
+
).bind(exchange, routing_key: definition.queue[:routing_key])
|
80
|
+
|
81
|
+
self.queues << queue
|
82
|
+
self.queue_worker_map[queue] = worker
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def setup_subscribers
|
87
|
+
self.queues.each do |queue|
|
88
|
+
queue.subscribe(manual_ack: true) do |delivery_info, metadata, payload|
|
89
|
+
self.channel.ack delivery_info.delivery_tag
|
90
|
+
process_message queue, payload
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
while not self.shutdown?
|
95
|
+
sleep 5
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def process_message(queue, payload)
|
100
|
+
queue_worker_map[queue].perform_async JSON.parse(payload)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Roundhousekiq
|
2
|
+
module Worker
|
3
|
+
def self.included(base)
|
4
|
+
Workers.register base
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def exchange_name(name)
|
10
|
+
Workers.exchange_name_for self, name
|
11
|
+
end
|
12
|
+
|
13
|
+
def exchange_type(type)
|
14
|
+
Workers.exchange_type_for self, type
|
15
|
+
end
|
16
|
+
|
17
|
+
def queue_name(name)
|
18
|
+
Workers.queue_name_for self, name
|
19
|
+
end
|
20
|
+
|
21
|
+
def routing_key(key)
|
22
|
+
Workers.routing_key_for self, key
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Roundhousekiq
|
2
|
+
class WorkerDefinition
|
3
|
+
|
4
|
+
attr_reader :exchange, :queue
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@exchange = {}
|
8
|
+
@queue = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def exchange_name=(name)
|
12
|
+
exchange[:name] = name
|
13
|
+
end
|
14
|
+
|
15
|
+
def exchange_type=(type)
|
16
|
+
exchange[:type] = type
|
17
|
+
end
|
18
|
+
|
19
|
+
def queue_name=(name)
|
20
|
+
name ||= '' # Default name to empty string
|
21
|
+
|
22
|
+
queue[:name] = name
|
23
|
+
queue[:durable] = name != ''
|
24
|
+
queue[:auto_delete] = name == ''
|
25
|
+
end
|
26
|
+
|
27
|
+
def routing_key=(key)
|
28
|
+
queue[:routing_key] = key
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Roundhousekiq
|
2
|
+
class Workers
|
3
|
+
class << self
|
4
|
+
def register(worker)
|
5
|
+
if definitions.key? worker
|
6
|
+
warn "Worker class #{worker.to_s} already registered"
|
7
|
+
end
|
8
|
+
|
9
|
+
definitions[worker] = WorkerDefinition.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def definitions
|
13
|
+
@@definitions ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def exchange_name_for(worker, name)
|
17
|
+
definition = definitions[worker]
|
18
|
+
fail "Unknown worker class passed: #{worker}" unless definition
|
19
|
+
definition.exchange_name = name
|
20
|
+
end
|
21
|
+
|
22
|
+
def exchange_type_for(worker, type)
|
23
|
+
definition = definitions[worker]
|
24
|
+
fail "Unknown worker class passed: #{worker}" unless definition
|
25
|
+
definition.exchange_type = type
|
26
|
+
end
|
27
|
+
|
28
|
+
def queue_name_for(worker, name)
|
29
|
+
definition = definitions[worker]
|
30
|
+
fail "Unknown worker class passed: #{worker}" unless definition
|
31
|
+
definition.queue_name = name
|
32
|
+
end
|
33
|
+
|
34
|
+
def routing_key_for(worker, key)
|
35
|
+
definition = definitions[worker]
|
36
|
+
fail "Unknown worker class passed: #{worker}" unless definition
|
37
|
+
definition.routing_key = key
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bunny'
|
2
|
+
require 'roundhousekiq/configuration'
|
3
|
+
require 'roundhousekiq/runner'
|
4
|
+
require 'roundhousekiq/version'
|
5
|
+
require 'roundhousekiq/worker'
|
6
|
+
require 'roundhousekiq/workers'
|
7
|
+
require 'roundhousekiq/worker_definition'
|
8
|
+
|
9
|
+
module Roundhousekiq
|
10
|
+
def self.configure
|
11
|
+
@config = Configuration.new
|
12
|
+
yield(@config) if block_given?
|
13
|
+
@config
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.config
|
17
|
+
@config || configure
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'roundhousekiq/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "roundhousekiq"
|
8
|
+
spec.version = Roundhousekiq::VERSION
|
9
|
+
spec.authors = ["Moritz Lawitschka"]
|
10
|
+
spec.email = ["moritz.lawitschka@suitepad.de"]
|
11
|
+
spec.summary = %q{AMQP to Sidekiq bridge}
|
12
|
+
spec.description = %q{Trigger Sidekiq jobs asynchronously over AMQP}
|
13
|
+
spec.homepage = "https://github.com/suitepad-gmbh/roundhousekiq"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = ['roundhousekiq']
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "bunny", "~> 1.7"
|
22
|
+
spec.add_dependency "sidekiq", "~> 3.0"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.3.0"
|
27
|
+
spec.add_development_dependency "rspec-nc", "~> 0.2.0"
|
28
|
+
spec.add_development_dependency "guard", "~> 2.13.0"
|
29
|
+
spec.add_development_dependency "guard-rspec", "~> 4.6.4"
|
30
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
describe Roundhousekiq::Configuration do
|
2
|
+
|
3
|
+
# Method existence
|
4
|
+
it { should respond_to :host }
|
5
|
+
it { should respond_to :host= }
|
6
|
+
it { should respond_to :port }
|
7
|
+
it { should respond_to :port= }
|
8
|
+
it { should respond_to :vhost }
|
9
|
+
it { should respond_to :vhost= }
|
10
|
+
it { should respond_to :username }
|
11
|
+
it { should respond_to :username= }
|
12
|
+
it { should respond_to :password }
|
13
|
+
it { should respond_to :password= }
|
14
|
+
it { should respond_to :prefetch }
|
15
|
+
it { should respond_to :prefetch= }
|
16
|
+
|
17
|
+
end
|