emque-consuming 1.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|