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.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +40 -0
  3. data/.travis.yml +10 -0
  4. data/CHANGELOG.md +11 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +205 -0
  8. data/Rakefile +14 -0
  9. data/bin/emque +5 -0
  10. data/emque-consuming.gemspec +36 -0
  11. data/lib/emque/consuming/actor.rb +21 -0
  12. data/lib/emque/consuming/adapter.rb +47 -0
  13. data/lib/emque/consuming/adapters/rabbit_mq/manager.rb +111 -0
  14. data/lib/emque/consuming/adapters/rabbit_mq/retry_worker.rb +59 -0
  15. data/lib/emque/consuming/adapters/rabbit_mq/worker.rb +87 -0
  16. data/lib/emque/consuming/adapters/rabbit_mq.rb +26 -0
  17. data/lib/emque/consuming/application.rb +112 -0
  18. data/lib/emque/consuming/cli.rb +140 -0
  19. data/lib/emque/consuming/command_receivers/base.rb +37 -0
  20. data/lib/emque/consuming/command_receivers/http_server.rb +103 -0
  21. data/lib/emque/consuming/command_receivers/unix_socket.rb +169 -0
  22. data/lib/emque/consuming/configuration.rb +63 -0
  23. data/lib/emque/consuming/consumer/common.rb +61 -0
  24. data/lib/emque/consuming/consumer.rb +33 -0
  25. data/lib/emque/consuming/consuming.rb +27 -0
  26. data/lib/emque/consuming/control/errors.rb +41 -0
  27. data/lib/emque/consuming/control/workers.rb +23 -0
  28. data/lib/emque/consuming/control.rb +33 -0
  29. data/lib/emque/consuming/core.rb +89 -0
  30. data/lib/emque/consuming/error_tracker.rb +39 -0
  31. data/lib/emque/consuming/generators/application.rb +95 -0
  32. data/lib/emque/consuming/helpers.rb +29 -0
  33. data/lib/emque/consuming/logging.rb +32 -0
  34. data/lib/emque/consuming/message.rb +22 -0
  35. data/lib/emque/consuming/pidfile.rb +54 -0
  36. data/lib/emque/consuming/router.rb +73 -0
  37. data/lib/emque/consuming/runner.rb +168 -0
  38. data/lib/emque/consuming/status.rb +26 -0
  39. data/lib/emque/consuming/tasks.rb +121 -0
  40. data/lib/emque/consuming/transmitter.rb +31 -0
  41. data/lib/emque/consuming/version.rb +5 -0
  42. data/lib/emque/consuming.rb +9 -0
  43. data/lib/emque-consuming.rb +3 -0
  44. data/lib/templates/.gitignore.tt +25 -0
  45. data/lib/templates/Gemfile.tt +6 -0
  46. data/lib/templates/Rakefile.tt +7 -0
  47. data/lib/templates/config/application.rb.tt +42 -0
  48. data/lib/templates/config/environments/development.rb.tt +2 -0
  49. data/lib/templates/config/environments/production.rb.tt +2 -0
  50. data/lib/templates/config/environments/staging.rb.tt +2 -0
  51. data/lib/templates/config/environments/test.rb.tt +2 -0
  52. data/lib/templates/config/routes.rb.tt +8 -0
  53. data/spec/application_spec.rb +28 -0
  54. data/spec/cli_spec.rb +136 -0
  55. data/spec/configuration_spec.rb +47 -0
  56. data/spec/consumer_spec.rb +56 -0
  57. data/spec/control/errors_spec.rb +170 -0
  58. data/spec/control_spec.rb +15 -0
  59. data/spec/core_spec.rb +121 -0
  60. data/spec/dummy/config/application.rb +38 -0
  61. data/spec/dummy/config/environments/test.rb +0 -0
  62. data/spec/dummy/config/routes.rb +0 -0
  63. data/spec/error_tracker_spec.rb +64 -0
  64. data/spec/pidfile_spec.rb +74 -0
  65. data/spec/router_spec.rb +14 -0
  66. data/spec/runner_spec.rb +138 -0
  67. data/spec/spec_helper.rb +43 -0
  68. 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,5 @@
1
+ module Emque
2
+ module Consuming
3
+ VERSION = "1.0.0.beta4"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ require "virtus"
2
+
3
+ module Emque
4
+ module Consuming; end
5
+ end
6
+
7
+ require "emque/consuming/version"
8
+ require "emque/consuming/consuming"
9
+ require "emque/consuming/cli"
@@ -0,0 +1,3 @@
1
+ module Emque; end
2
+
3
+ require "emque/consuming"
@@ -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,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ ruby "2.1.2"
4
+
5
+ gem "rake"
6
+ gem "emque-consuming", :git => "https://github.com/teamsnap/emque-consuming.git"
@@ -0,0 +1,7 @@
1
+ require_relative "config/application"
2
+ require "emque/consuming/tasks"
3
+
4
+ __DIR__ = File.dirname(__FILE__)
5
+ Dir.glob("#{__DIR__}/tasks/*.rake").each do |rake_file|
6
+ import rake_file
7
+ end
@@ -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,2 @@
1
+ <%= @name %>::Application.configure do
2
+ end
@@ -0,0 +1,2 @@
1
+ <%= @name %>::Application.configure do
2
+ end
@@ -0,0 +1,2 @@
1
+ <%= @name %>::Application.configure do
2
+ end
@@ -0,0 +1,2 @@
1
+ <%= @name %>::Application.configure do
2
+ end
@@ -0,0 +1,8 @@
1
+ <%= @name %>::Application.router.map do
2
+ # topic "samples" => SamplesConsumer[, :workers => 2] do
3
+ # map "samples.new" => "new_sample"
4
+ # ...
5
+ # end
6
+
7
+ # ...
8
+ end
@@ -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