emque-consuming 1.0.0.beta4
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 +40 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +205 -0
- data/Rakefile +14 -0
- data/bin/emque +5 -0
- data/emque-consuming.gemspec +36 -0
- data/lib/emque/consuming/actor.rb +21 -0
- data/lib/emque/consuming/adapter.rb +47 -0
- data/lib/emque/consuming/adapters/rabbit_mq/manager.rb +111 -0
- data/lib/emque/consuming/adapters/rabbit_mq/retry_worker.rb +59 -0
- data/lib/emque/consuming/adapters/rabbit_mq/worker.rb +87 -0
- data/lib/emque/consuming/adapters/rabbit_mq.rb +26 -0
- data/lib/emque/consuming/application.rb +112 -0
- data/lib/emque/consuming/cli.rb +140 -0
- data/lib/emque/consuming/command_receivers/base.rb +37 -0
- data/lib/emque/consuming/command_receivers/http_server.rb +103 -0
- data/lib/emque/consuming/command_receivers/unix_socket.rb +169 -0
- data/lib/emque/consuming/configuration.rb +63 -0
- data/lib/emque/consuming/consumer/common.rb +61 -0
- data/lib/emque/consuming/consumer.rb +33 -0
- data/lib/emque/consuming/consuming.rb +27 -0
- data/lib/emque/consuming/control/errors.rb +41 -0
- data/lib/emque/consuming/control/workers.rb +23 -0
- data/lib/emque/consuming/control.rb +33 -0
- data/lib/emque/consuming/core.rb +89 -0
- data/lib/emque/consuming/error_tracker.rb +39 -0
- data/lib/emque/consuming/generators/application.rb +95 -0
- data/lib/emque/consuming/helpers.rb +29 -0
- data/lib/emque/consuming/logging.rb +32 -0
- data/lib/emque/consuming/message.rb +22 -0
- data/lib/emque/consuming/pidfile.rb +54 -0
- data/lib/emque/consuming/router.rb +73 -0
- data/lib/emque/consuming/runner.rb +168 -0
- data/lib/emque/consuming/status.rb +26 -0
- data/lib/emque/consuming/tasks.rb +121 -0
- data/lib/emque/consuming/transmitter.rb +31 -0
- data/lib/emque/consuming/version.rb +5 -0
- data/lib/emque/consuming.rb +9 -0
- data/lib/emque-consuming.rb +3 -0
- data/lib/templates/.gitignore.tt +25 -0
- data/lib/templates/Gemfile.tt +6 -0
- data/lib/templates/Rakefile.tt +7 -0
- data/lib/templates/config/application.rb.tt +42 -0
- data/lib/templates/config/environments/development.rb.tt +2 -0
- data/lib/templates/config/environments/production.rb.tt +2 -0
- data/lib/templates/config/environments/staging.rb.tt +2 -0
- data/lib/templates/config/environments/test.rb.tt +2 -0
- data/lib/templates/config/routes.rb.tt +8 -0
- data/spec/application_spec.rb +28 -0
- data/spec/cli_spec.rb +136 -0
- data/spec/configuration_spec.rb +47 -0
- data/spec/consumer_spec.rb +56 -0
- data/spec/control/errors_spec.rb +170 -0
- data/spec/control_spec.rb +15 -0
- data/spec/core_spec.rb +121 -0
- data/spec/dummy/config/application.rb +38 -0
- data/spec/dummy/config/environments/test.rb +0 -0
- data/spec/dummy/config/routes.rb +0 -0
- data/spec/error_tracker_spec.rb +64 -0
- data/spec/pidfile_spec.rb +74 -0
- data/spec/router_spec.rb +14 -0
- data/spec/runner_spec.rb +138 -0
- data/spec/spec_helper.rb +43 -0
- metadata +309 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
require "emque/consuming/application"
|
2
|
+
require "emque/consuming/control"
|
3
|
+
require "emque/consuming/pidfile"
|
4
|
+
require "emque/consuming/status"
|
5
|
+
require "emque/consuming/command_receivers/http_server"
|
6
|
+
require "emque/consuming/command_receivers/unix_socket"
|
7
|
+
require "emque/consuming/transmitter"
|
8
|
+
|
9
|
+
module Emque
|
10
|
+
module Consuming
|
11
|
+
class Runner
|
12
|
+
include Emque::Consuming::Helpers
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :instance
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :control, :pidfile, :status
|
19
|
+
|
20
|
+
def initialize(options = {})
|
21
|
+
self.control = Emque::Consuming::Control.new
|
22
|
+
self.options = options
|
23
|
+
self.receivers = []
|
24
|
+
self.status = Emque::Consuming::Status.new
|
25
|
+
apply_options
|
26
|
+
Emque::Consuming.application.initialize_logger
|
27
|
+
self.class.instance = self
|
28
|
+
self.pidfile = options.fetch(:pidfile, default_pidfile)
|
29
|
+
self.pid = Emque::Consuming::Pidfile.new(pidfile)
|
30
|
+
end
|
31
|
+
|
32
|
+
def app
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def console
|
37
|
+
require "pry"
|
38
|
+
Pry.start
|
39
|
+
end
|
40
|
+
|
41
|
+
def http?
|
42
|
+
config.status == :on
|
43
|
+
end
|
44
|
+
|
45
|
+
def phased_restart
|
46
|
+
receivers.each { |r| r.stop && r.start }
|
47
|
+
end
|
48
|
+
|
49
|
+
def restart
|
50
|
+
stop && start
|
51
|
+
end
|
52
|
+
|
53
|
+
def restart_application
|
54
|
+
receivers.first.restart
|
55
|
+
end
|
56
|
+
|
57
|
+
def sock?
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def start
|
62
|
+
exit_if_already_running!
|
63
|
+
daemonize! if daemonize?
|
64
|
+
write_pidfile!
|
65
|
+
@persist = Thread.new { loop { sleep 1 } }
|
66
|
+
set_process_title
|
67
|
+
setup_receivers
|
68
|
+
receivers.each(&:start)
|
69
|
+
persist.join
|
70
|
+
rescue Interrupt
|
71
|
+
stop
|
72
|
+
end
|
73
|
+
|
74
|
+
def stop(timeout: 5)
|
75
|
+
if persist
|
76
|
+
Thread.new do
|
77
|
+
sleep timeout
|
78
|
+
logger.error("Timeout Exceeded. Forcing Shutdown.")
|
79
|
+
persist.exit if persist.alive?
|
80
|
+
end
|
81
|
+
receivers.each(&:stop)
|
82
|
+
logger.info("Graceful shutdown successful.")
|
83
|
+
logger.info("#{config.app_name.capitalize} stopped.")
|
84
|
+
persist.exit if persist.alive?
|
85
|
+
else
|
86
|
+
Emque::Consuming::Transmitter.send(
|
87
|
+
:command => :stop,
|
88
|
+
:socket_path => config.socket_path
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
attr_accessor :options, :persist, :pid, :receivers
|
96
|
+
attr_writer :control, :pidfile, :status
|
97
|
+
|
98
|
+
def apply_options
|
99
|
+
options.each do |attr, val|
|
100
|
+
config.send("#{attr}=", val) if config.respond_to?(attr)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def config
|
105
|
+
Emque::Consuming.application.config
|
106
|
+
end
|
107
|
+
|
108
|
+
def daemonize?
|
109
|
+
options[:daemon]
|
110
|
+
end
|
111
|
+
|
112
|
+
def daemonize!
|
113
|
+
Process.daemon(true, true)
|
114
|
+
|
115
|
+
[$stdout, $stderr].each do |io|
|
116
|
+
File.open(Emque::Consuming.application.logfile, "ab") do |f|
|
117
|
+
io.reopen(f)
|
118
|
+
end
|
119
|
+
io.sync = true
|
120
|
+
end
|
121
|
+
|
122
|
+
$stdin.reopen("/dev/null")
|
123
|
+
end
|
124
|
+
|
125
|
+
def default_pidfile
|
126
|
+
File.join(
|
127
|
+
Emque::Consuming.application.root,
|
128
|
+
"tmp",
|
129
|
+
"pids",
|
130
|
+
"#{config.app_name}.pid"
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
def exit_if_already_running!
|
135
|
+
if pid.running?
|
136
|
+
[
|
137
|
+
"Pid file exists. Process #{pid} active.",
|
138
|
+
"Please ensure app is not running."
|
139
|
+
].each do |msg|
|
140
|
+
logger.error(msg)
|
141
|
+
$stdout.puts(msg)
|
142
|
+
end
|
143
|
+
|
144
|
+
exit
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def set_process_title
|
149
|
+
title = "#{config.app_name} [pidfile: #{pidfile}"
|
150
|
+
title << " | unix socket: #{config.socket_path}" if sock?
|
151
|
+
title << " | http://#{config.status_host}:#{config.status_port}" if http?
|
152
|
+
title << "]"
|
153
|
+
$0 = title
|
154
|
+
end
|
155
|
+
|
156
|
+
def setup_receivers
|
157
|
+
receivers << app
|
158
|
+
receivers << Emque::Consuming::CommandReceivers::UnixSocket.new if sock?
|
159
|
+
receivers << Emque::Consuming::CommandReceivers::HttpServer.new if http?
|
160
|
+
end
|
161
|
+
|
162
|
+
def write_pidfile!
|
163
|
+
pid.write
|
164
|
+
at_exit { FileUtils.rm_f(pidfile) }
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Emque
|
2
|
+
module Consuming
|
3
|
+
class Status
|
4
|
+
include Emque::Consuming::Helpers
|
5
|
+
|
6
|
+
def to_hsh
|
7
|
+
{
|
8
|
+
:app => config.app_name,
|
9
|
+
:errors => {
|
10
|
+
:count => app.error_tracker.count,
|
11
|
+
:expire_after => app.error_tracker.expiration,
|
12
|
+
:limit => app.error_tracker.limit
|
13
|
+
},
|
14
|
+
:workers => {}.tap { |worker_stats|
|
15
|
+
app.manager.workers.each { |topic, workers|
|
16
|
+
worker_stats[topic] = {
|
17
|
+
:count => workers.size
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
alias :to_h :to_hsh
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Emque
|
2
|
+
module Consuming
|
3
|
+
class Tasks
|
4
|
+
include Rake::DSL if defined? Rake::DSL
|
5
|
+
include Emque::Consuming::Helpers
|
6
|
+
|
7
|
+
def install_tasks
|
8
|
+
namespace :emque do
|
9
|
+
desc "Show the current configuration of a running instance " +
|
10
|
+
"(accepts SOCKET)"
|
11
|
+
task :configuration do
|
12
|
+
puts with_transmitter(:send, :configuration)
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Start a pry console"
|
16
|
+
task :console do
|
17
|
+
Emque::Consuming::Runner.new.console
|
18
|
+
end
|
19
|
+
|
20
|
+
namespace :errors do
|
21
|
+
desc "Clear all outstanding errors (accepts SOCKET)"
|
22
|
+
task :clear do
|
23
|
+
puts with_transmitter(:send, :errors, :clear)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Change the number of seconds to SECONDS before future " +
|
27
|
+
"errors expire (accepts SOCKET)"
|
28
|
+
task :expire_after do
|
29
|
+
seconds = ENV.fetch("SECONDS", 3600)
|
30
|
+
puts with_transmitter(:send, :errors, :expire_after, seconds)
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace :limit do
|
34
|
+
desc "Decrease the error limit (accepts SOCKET)"
|
35
|
+
task :down do
|
36
|
+
puts with_transmitter(:send, :errors, :down)
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Increase the error limit (accepts SOCKET)"
|
40
|
+
task :up do
|
41
|
+
puts with_transmitter(:send, :errors, :up)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Show the available routes"
|
47
|
+
task :routes do
|
48
|
+
require "table_print"
|
49
|
+
tp(
|
50
|
+
[].tap { |routes|
|
51
|
+
mappings = router.instance_eval { @mappings }
|
52
|
+
|
53
|
+
mappings.each { |topic, maps|
|
54
|
+
maps.each { |mapping|
|
55
|
+
mapping.instance_eval { @mapping }.each { |route, method|
|
56
|
+
routes << {
|
57
|
+
:route => route,
|
58
|
+
:topic => topic,
|
59
|
+
:consumer => mapping.consumer,
|
60
|
+
:method => method,
|
61
|
+
:workers => router.workers(topic)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
},
|
67
|
+
{:route => {:width => 50}},
|
68
|
+
:topic,
|
69
|
+
:consumer,
|
70
|
+
:method,
|
71
|
+
:workers
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "Restart the workers inside a running instance " +
|
76
|
+
"(does not reload code; accepts SOCKET)"
|
77
|
+
task :restart do
|
78
|
+
with_transmitter(:send, :restart)
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "Show the current status of a running instance " +
|
82
|
+
"(accepts SOCKET)"
|
83
|
+
task :status do
|
84
|
+
puts with_transmitter(:send, :status)
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "Start a new instance (accepts PIDFILE, DAEMON)"
|
88
|
+
task :start do
|
89
|
+
daemon = ENV.fetch("DAEMON", false)
|
90
|
+
pidfile = ENV.fetch("PIDFILE", "tmp/pids/#{config.app_name}.pid")
|
91
|
+
|
92
|
+
Emque::Consuming::Runner.new({
|
93
|
+
:daemon => daemon,
|
94
|
+
:pidfile => pidfile
|
95
|
+
}).start
|
96
|
+
end
|
97
|
+
|
98
|
+
desc "Stop a running instance (accepts SOCKET)"
|
99
|
+
task :stop do
|
100
|
+
resp = with_transmitter(:send, :stop)
|
101
|
+
puts resp.length > 0 ? resp : "stopped"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def with_transmitter(method, command, *args)
|
109
|
+
socket_path = ENV.fetch("SOCKET", config.socket_path)
|
110
|
+
require "emque/consuming/transmitter"
|
111
|
+
Emque::Consuming::Transmitter.send(
|
112
|
+
:command => command,
|
113
|
+
:socket_path => socket_path,
|
114
|
+
:args => args
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
Emque::Consuming::Tasks.new.install_tasks
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "socket"
|
3
|
+
require "oj"
|
4
|
+
|
5
|
+
module Emque
|
6
|
+
module Consuming
|
7
|
+
module Transmitter
|
8
|
+
def self.send(command:, socket_path: "tmp/emque.sock", args: [])
|
9
|
+
if File.exists?(socket_path)
|
10
|
+
socket = UNIXSocket.new(socket_path)
|
11
|
+
socket.send(Oj.dump({
|
12
|
+
:command => command,
|
13
|
+
:args => args
|
14
|
+
}, :mode => :compat), 0)
|
15
|
+
response = socket.recv(10000000)
|
16
|
+
socket.close
|
17
|
+
response
|
18
|
+
else
|
19
|
+
"Socket not found at #{socket_path}"
|
20
|
+
end
|
21
|
+
rescue Errno::ECONNREFUSED
|
22
|
+
FileUtils.rm_f(socket_path) if File.exists?(socket_path)
|
23
|
+
"The UNIX Socket found at #{socket_path} was dead"
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.method_missing(method, *args)
|
27
|
+
send(command: method, args: args)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
*.rbc
|
2
|
+
*.sassc
|
3
|
+
.sass-cache
|
4
|
+
capybara-*.html
|
5
|
+
.rspec
|
6
|
+
.rvmrc
|
7
|
+
/.bundle
|
8
|
+
/vendor/bundle
|
9
|
+
/log/*
|
10
|
+
/logs/*
|
11
|
+
/tmp/*
|
12
|
+
/db/*.sqlite3
|
13
|
+
/public/system/*
|
14
|
+
/coverage/
|
15
|
+
/spec/tmp/*
|
16
|
+
**.orig
|
17
|
+
rerun.txt
|
18
|
+
pickle-email-*.html
|
19
|
+
.project
|
20
|
+
config/initializers/secret_token.rb
|
21
|
+
config/*.yml
|
22
|
+
.ruby-version
|
23
|
+
.rbenv-version
|
24
|
+
/bin/stubs
|
25
|
+
spec/fixtures/vcr_cassettes/*
|
@@ -0,0 +1,42 @@
|
|
1
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
|
2
|
+
require "bundler/setup" if File.exists?(ENV["BUNDLE_GEMFILE"])
|
3
|
+
|
4
|
+
require "emque/consuming"
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
|
7
|
+
|
8
|
+
module <%= @name %>
|
9
|
+
class Application
|
10
|
+
include Emque::Consuming::Application
|
11
|
+
|
12
|
+
initialize_core!
|
13
|
+
|
14
|
+
<%=
|
15
|
+
[].tap { |options_out|
|
16
|
+
if @options.has_key?(:app_name)
|
17
|
+
options_out << "config.app_name = \"#{@options[:app_name]}\""
|
18
|
+
end
|
19
|
+
if @options.has_key?(:error_limit)
|
20
|
+
options_out << "config.error_limit = #{@options[:error_limit]}"
|
21
|
+
end
|
22
|
+
if @options.has_key?(:error_expiration)
|
23
|
+
options_out << "config.error_expiration = #{@options[:error_expiration]}"
|
24
|
+
end
|
25
|
+
options_out << "config.set_adapter(:rabbit_mq)"
|
26
|
+
if @options.has_key?(:status)
|
27
|
+
options_out << "config.status = :on"
|
28
|
+
end
|
29
|
+
if @options.has_key?(:status_host)
|
30
|
+
options_out << "config.status_host = \"#{@options[:status_host]}\""
|
31
|
+
end
|
32
|
+
if @options.has_key?(:status_port)
|
33
|
+
options_out << "config.status_port = #{@options[:status_port]}"
|
34
|
+
end
|
35
|
+
if @options.has_key?(:socket_path)
|
36
|
+
options_out << "config.socket_path = \"#{@options[:socket_path]}\""
|
37
|
+
end
|
38
|
+
}.join("\n ")
|
39
|
+
%>
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Emque::Consuming::Application do
|
4
|
+
describe "#notice_error" do
|
5
|
+
it "does not trigger a shutdown if the limit has not been reached" do
|
6
|
+
Dummy::Application.config.error_limit = 2
|
7
|
+
app = Dummy::Application.new
|
8
|
+
Emque::Consuming::Runner.instance = double(:runner)
|
9
|
+
|
10
|
+
expect(Emque::Consuming::Runner.instance).to_not receive(:stop)
|
11
|
+
|
12
|
+
app.notice_error({ :test => "failure" })
|
13
|
+
end
|
14
|
+
|
15
|
+
it "triggers a shutdown one the error_limit is reached" do
|
16
|
+
Dummy::Application.config.error_limit = 2
|
17
|
+
app = Dummy::Application.new
|
18
|
+
Emque::Consuming::Runner.instance =
|
19
|
+
double(:runner, :status => double(:status, :to_h => {}))
|
20
|
+
|
21
|
+
expect(Emque::Consuming::Runner.instance)
|
22
|
+
.to receive(:stop).exactly(1).times
|
23
|
+
|
24
|
+
app.notice_error({ :test => "failure" })
|
25
|
+
app.notice_error({ :test => "another failure" })
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Emque::Consuming::Cli do
|
4
|
+
describe "starting a console" do
|
5
|
+
it "passes to console command to a new runner instance" do
|
6
|
+
runner = double(:runner, :send => true)
|
7
|
+
|
8
|
+
expect(Emque::Consuming::Runner).to receive(:new).and_return(runner)
|
9
|
+
expect(runner).to receive(:send).with(:console)
|
10
|
+
|
11
|
+
Emque::Consuming::Cli.new(["console"])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "starting an instance" do
|
16
|
+
it "passes the start command to a new runner instance" do
|
17
|
+
runner = double(:runner, :send => true)
|
18
|
+
|
19
|
+
expect(Emque::Consuming::Runner).to receive(:new).and_return(runner)
|
20
|
+
expect(runner).to receive(:send).with(:start)
|
21
|
+
|
22
|
+
Emque::Consuming::Cli.new(["start"])
|
23
|
+
end
|
24
|
+
|
25
|
+
it "passes valid arguments along to the new runner" do
|
26
|
+
command = ["start"]
|
27
|
+
valid_args = [
|
28
|
+
"-P", "tmp/pidfile.pid",
|
29
|
+
"-d",
|
30
|
+
"-S", "tmp/socket.sock",
|
31
|
+
"-e", "20",
|
32
|
+
"-x", "1000",
|
33
|
+
"--app-name", "testing",
|
34
|
+
"--env", "test"
|
35
|
+
]
|
36
|
+
expected_options = {
|
37
|
+
:daemon => true,
|
38
|
+
:pidfile => "tmp/pidfile.pid",
|
39
|
+
:socket_path => "tmp/socket.sock",
|
40
|
+
:error_limit => 20,
|
41
|
+
:error_expiration => 1000,
|
42
|
+
:app_name => "testing",
|
43
|
+
:env => "test"
|
44
|
+
}
|
45
|
+
argv = valid_args + command
|
46
|
+
runner = double(:runner, :send => true)
|
47
|
+
|
48
|
+
expect(Emque::Consuming::Runner).to receive(:new)
|
49
|
+
.with(expected_options)
|
50
|
+
.and_return(runner)
|
51
|
+
|
52
|
+
Emque::Consuming::Cli.new(argv)
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "with no options" do
|
56
|
+
it "passes the default options to the runner" do
|
57
|
+
expected_options = {
|
58
|
+
:daemon => false
|
59
|
+
}
|
60
|
+
runner = double(:runner, :send => true)
|
61
|
+
|
62
|
+
expect(Emque::Consuming::Runner).to receive(:new)
|
63
|
+
.with(expected_options)
|
64
|
+
.and_return(runner)
|
65
|
+
|
66
|
+
Emque::Consuming::Cli.new(["start"])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "stopping an instance" do
|
72
|
+
it "passes the stop command to a new runner instance" do
|
73
|
+
runner = double(:runner, :send => true)
|
74
|
+
|
75
|
+
expect(Emque::Consuming::Runner).to receive(:new).and_return(runner)
|
76
|
+
expect(runner).to receive(:send).with(:stop)
|
77
|
+
|
78
|
+
Emque::Consuming::Cli.new(["stop"])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "creating a new application" do
|
83
|
+
it "passes the new command to a new application generator instance" do
|
84
|
+
generator = double(:generator, :generate => true)
|
85
|
+
|
86
|
+
expect(Emque::Consuming::Generators::Application).to receive(:new)
|
87
|
+
.and_return(generator)
|
88
|
+
expect(generator).to receive(:generate)
|
89
|
+
|
90
|
+
Emque::Consuming::Cli.new(["new", "testapplication"])
|
91
|
+
end
|
92
|
+
|
93
|
+
it "passes valid arguments along to the new application generator" do
|
94
|
+
application_name = "testapplication"
|
95
|
+
command = ["new", application_name]
|
96
|
+
valid_args = [
|
97
|
+
"-P", "tmp/pidfile.pid",
|
98
|
+
"-d",
|
99
|
+
"-S", "tmp/socket.sock",
|
100
|
+
"-e", "20",
|
101
|
+
"-x", "1000",
|
102
|
+
"--app-name", "testing",
|
103
|
+
"--env", "test"
|
104
|
+
]
|
105
|
+
expected_options = {
|
106
|
+
:daemon => true,
|
107
|
+
:pidfile => "tmp/pidfile.pid",
|
108
|
+
:socket_path => "tmp/socket.sock",
|
109
|
+
:error_limit => 20,
|
110
|
+
:error_expiration => 1000,
|
111
|
+
:app_name => "testing",
|
112
|
+
:env => "test"
|
113
|
+
}
|
114
|
+
argv = valid_args + command
|
115
|
+
generator = double(:generator, :generate => true)
|
116
|
+
|
117
|
+
expect(Emque::Consuming::Generators::Application).to receive(:new)
|
118
|
+
.with(expected_options, application_name)
|
119
|
+
.and_return(generator)
|
120
|
+
|
121
|
+
Emque::Consuming::Cli.new(argv)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "exits if no application name is passed" do
|
125
|
+
expect { Emque::Consuming::Cli.new(["new"]) }.to raise_error(SystemExit)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it "exits if an invalid command is passed" do
|
130
|
+
expect { Emque::Consuming::Cli.new(["invalid"]) }.to raise_error(SystemExit)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "exits if help is passed as a command" do
|
134
|
+
expect { Emque::Consuming::Cli.new(["help"]) }.to raise_error(SystemExit)
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Emque::Consuming::Configuration do
|
4
|
+
describe "#log_level" do
|
5
|
+
it "defaults to Logger::INFO" do
|
6
|
+
config = Emque::Consuming::Configuration.new
|
7
|
+
expect(config.log_level).to eq(Logger::INFO)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "prefers the assigned value to the default" do
|
11
|
+
config = Emque::Consuming::Configuration.new
|
12
|
+
config.log_level = Logger::DEBUG
|
13
|
+
expect(config.log_level).to eq(Logger::DEBUG)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#to_hsh" do
|
18
|
+
it "returns a hash" do
|
19
|
+
config = Emque::Consuming::Configuration.new
|
20
|
+
expect(config.to_hsh).to be_a Hash
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns the value of all the accessors" do
|
24
|
+
accessors = [
|
25
|
+
:app_name, :adapter, :env, :error_handlers, :error_limit,
|
26
|
+
:error_expiration, :log_level, :status_port, :status_host, :status,
|
27
|
+
:socket_path, :shutdown_handlers
|
28
|
+
]
|
29
|
+
config = Emque::Consuming::Configuration.new
|
30
|
+
|
31
|
+
hsh = config.to_hsh
|
32
|
+
|
33
|
+
expect(hsh.keys).to eq(accessors)
|
34
|
+
accessors.each do |key|
|
35
|
+
expect(hsh.fetch(key)).to eq(config.send(key))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#to_h" do
|
41
|
+
it "is an alias of to_hsh" do
|
42
|
+
config = Emque::Consuming::Configuration.new
|
43
|
+
|
44
|
+
expect(config.to_h).to eq(config.to_hsh)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|