emque-consuming 1.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
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,56 @@
1
+ require "spec_helper"
2
+ require "emque/consuming/consumer"
3
+ require "emque/consuming/consumer/common"
4
+
5
+ class MyConsumer
6
+ include Emque::Consuming.consumer
7
+
8
+ def my_event(message)
9
+ pipe(message, :through => [
10
+ :keep_pipe_going, :another_method
11
+ ])
12
+ end
13
+
14
+ def my_stop_event(message)
15
+ pipe(message, :through => [
16
+ :stop_pipe, :another_method
17
+ ])
18
+ end
19
+
20
+ private
21
+
22
+ def stop_pipe(message)
23
+ message.with(:status => :stop)
24
+ end
25
+
26
+ def keep_pipe_going(message)
27
+ message
28
+ end
29
+
30
+ def another_method(message)
31
+ message
32
+ end
33
+
34
+ end
35
+
36
+ describe Emque::Consuming::Consumer do
37
+ describe "#pipe" do
38
+ context "when continuing pipe" do
39
+ it "calls all methods in the pipe chain" do
40
+ consumer = MyConsumer.new
41
+ message = Emque::Consuming::Message.new
42
+ expect(consumer).to receive(:another_method)
43
+ consumer.my_event message
44
+ end
45
+ end
46
+
47
+ context "when stopping pipe" do
48
+ it "stops after stop method" do
49
+ consumer = MyConsumer.new
50
+ message = Emque::Consuming::Message.new
51
+ expect(consumer).not_to receive(:another_method)
52
+ consumer.my_stop_event message
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,170 @@
1
+ require "spec_helper"
2
+ require "ostruct"
3
+
4
+ describe Emque::Consuming::Control::Errors do
5
+ describe "#clear" do
6
+ it "resets the error_tracker's occurances hash" do
7
+ control = Emque::Consuming::Control::Errors.new
8
+ config = Emque::Consuming::Configuration.new
9
+ error_tracker = Emque::Consuming::ErrorTracker.new
10
+ app = OpenStruct.new
11
+ app.error_tracker = error_tracker
12
+ application = OpenStruct.new
13
+ application.config = config
14
+ application.instance = app
15
+ expect(Emque::Consuming).to receive(:application)
16
+ .at_least(1).times
17
+ .and_return(application)
18
+
19
+ error_tracker.occurrences = {
20
+ :one => 1,
21
+ :two => 2
22
+ }
23
+ control.clear
24
+ expect(error_tracker.occurrences).to eq({})
25
+ end
26
+ end
27
+
28
+ describe "#down" do
29
+ describe "when error_tracker limit is greater than 1" do
30
+ it "lowers the limit by 1" do
31
+ control = Emque::Consuming::Control::Errors.new
32
+ config = Emque::Consuming::Configuration.new
33
+ error_tracker = Emque::Consuming::ErrorTracker.new(:limit => 2)
34
+ app = OpenStruct.new
35
+ app.error_tracker = error_tracker
36
+ application = OpenStruct.new
37
+ application.config = config
38
+ application.instance = app
39
+ expect(Emque::Consuming).to receive(:application)
40
+ .at_least(1).times
41
+ .and_return(application)
42
+
43
+ expect { control.down }.to change { error_tracker.limit }.to(1)
44
+ end
45
+
46
+ it "changes the config error_limit to the same value" do
47
+ control = Emque::Consuming::Control::Errors.new
48
+ config = Emque::Consuming::Configuration.new
49
+ error_tracker = Emque::Consuming::ErrorTracker.new(:limit => 2)
50
+ app = OpenStruct.new
51
+ app.error_tracker = error_tracker
52
+ application = OpenStruct.new
53
+ application.config = config
54
+ application.instance = app
55
+ expect(Emque::Consuming).to receive(:application)
56
+ .at_least(1).times
57
+ .and_return(application)
58
+
59
+ expect { control.down }.to change { config.error_limit }.to(1)
60
+ end
61
+ end
62
+
63
+ describe "when error_tracker limit is 1" do
64
+ it "does not change the limit" do
65
+ control = Emque::Consuming::Control::Errors.new
66
+ config = Emque::Consuming::Configuration.new
67
+ error_tracker = Emque::Consuming::ErrorTracker.new(:limit => 1)
68
+ app = OpenStruct.new
69
+ app.error_tracker = error_tracker
70
+ application = OpenStruct.new
71
+ application.config = config
72
+ application.instance = app
73
+ expect(Emque::Consuming).to receive(:application)
74
+ .at_least(1).times
75
+ .and_return(application)
76
+
77
+ expect { control.down }.to_not change { error_tracker.limit }
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#expire_after" do
83
+ describe "when passed an integer" do
84
+ it "changes the error_tracker expiration value to the value passed" do
85
+ control = Emque::Consuming::Control::Errors.new
86
+ config = Emque::Consuming::Configuration.new
87
+ error_tracker = Emque::Consuming::ErrorTracker.new
88
+ app = OpenStruct.new
89
+ app.error_tracker = error_tracker
90
+ application = OpenStruct.new
91
+ application.config = config
92
+ application.instance = app
93
+ expect(Emque::Consuming).to receive(:application)
94
+ .at_least(1).times
95
+ .and_return(application)
96
+
97
+ expect { control.expire_after(1000) }.to change {
98
+ error_tracker.expiration
99
+ }.to(1000)
100
+ end
101
+
102
+ it "changes the config error_expiration value to the value passed" do
103
+ control = Emque::Consuming::Control::Errors.new
104
+ config = Emque::Consuming::Configuration.new
105
+ error_tracker = Emque::Consuming::ErrorTracker.new
106
+ app = OpenStruct.new
107
+ app.error_tracker = error_tracker
108
+ application = OpenStruct.new
109
+ application.config = config
110
+ application.instance = app
111
+ expect(Emque::Consuming).to receive(:application)
112
+ .at_least(1).times
113
+ .and_return(application)
114
+
115
+ expect { control.expire_after(1000) }.to change {
116
+ config.error_expiration
117
+ }.to(1000)
118
+ end
119
+ end
120
+
121
+ describe "when passed something other than an integer" do
122
+ it "raises an argument error" do
123
+ control = Emque::Consuming::Control::Errors.new
124
+ expect { control.expire_after(:invalid) }.to raise_error(ArgumentError)
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "#up" do
130
+ it "increases the error_tracker limit by 1" do
131
+ control = Emque::Consuming::Control::Errors.new
132
+ config = Emque::Consuming::Configuration.new
133
+ error_tracker = Emque::Consuming::ErrorTracker.new(:limit => 1)
134
+ app = OpenStruct.new
135
+ app.error_tracker = error_tracker
136
+ application = OpenStruct.new
137
+ application.config = config
138
+ application.instance = app
139
+ expect(Emque::Consuming).to receive(:application)
140
+ .at_least(1).times
141
+ .and_return(application)
142
+
143
+ expect { control.up }.to change { error_tracker.limit }.to(2)
144
+ end
145
+
146
+ it "changes the config error_limit to the same value" do
147
+ control = Emque::Consuming::Control::Errors.new
148
+ config = Emque::Consuming::Configuration.new
149
+ error_tracker = Emque::Consuming::ErrorTracker.new(:limit => 1)
150
+ app = OpenStruct.new
151
+ app.error_tracker = error_tracker
152
+ application = OpenStruct.new
153
+ application.config = config
154
+ application.instance = app
155
+ expect(Emque::Consuming).to receive(:application)
156
+ .at_least(1).times
157
+ .and_return(application)
158
+
159
+ expect { control.up }.to change { config.error_limit }.to(2)
160
+ end
161
+ end
162
+
163
+ describe "#retry" do
164
+ it "starts the retry worker" do
165
+ control = Emque::Consuming::Control::Errors.new
166
+ config = Emque::Consuming::Configuration.new
167
+ control.retry
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ describe Emque::Consuming::Control do
4
+ describe "#initialize" do
5
+ it "creates a new errors control object" do
6
+ expect(Emque::Consuming::Control::Errors).to receive(:new)
7
+ Emque::Consuming::Control.new
8
+ end
9
+
10
+ it "creates a new workers control object" do
11
+ expect(Emque::Consuming::Control::Workers).to receive(:new)
12
+ Emque::Consuming::Control.new
13
+ end
14
+ end
15
+ end
data/spec/core_spec.rb ADDED
@@ -0,0 +1,121 @@
1
+ require "spec_helper"
2
+
3
+ describe Emque::Consuming::Core do
4
+ class CoreContainer
5
+ extend Emque::Consuming::Core
6
+ end
7
+
8
+ describe ".extended" do
9
+ it "adds a .root accessor" do
10
+ expect(CoreContainer).to respond_to(:root)
11
+ expect(CoreContainer).to respond_to(:root=)
12
+ end
13
+
14
+ it "adds a .topic_mapping accessor" do
15
+ expect(CoreContainer).to respond_to(:topic_mapping)
16
+ expect(CoreContainer).to respond_to(:topic_mapping=)
17
+ end
18
+
19
+ it "adds a .router accessor" do
20
+ expect(CoreContainer).to respond_to(:router)
21
+ expect(CoreContainer).to respond_to(:router=)
22
+ end
23
+
24
+ it "adds an .instance accessor" do
25
+ expect(CoreContainer).to respond_to(:instance)
26
+ expect(CoreContainer).to respond_to(:instance=)
27
+ end
28
+
29
+ it "adds an alias, configure, for instance_exec" do
30
+ expect(CoreContainer).to respond_to(:configure)
31
+ end
32
+ end
33
+
34
+ describe ".config" do
35
+ describe "when @config is not set" do
36
+ it "initializes a new Emque::Consuming::Configuration object" do
37
+ expect(Emque::Consuming::Configuration).to receive(:new)
38
+ CoreContainer.config
39
+ end
40
+
41
+ it "assigns the new configuration to @config and returns it" do
42
+ config = double(:config)
43
+ expect(Emque::Consuming::Configuration).to receive(:new)
44
+ .and_return(config)
45
+
46
+ expect(CoreContainer.config).to eq(config)
47
+ expect(CoreContainer.instance_variable_get(:@config)).to eq(config)
48
+
49
+ CoreContainer.instance_variable_set(:@config, nil)
50
+ end
51
+ end
52
+
53
+ describe "when @config is set" do
54
+ it "returns the value of @config and does not initialize a new object" do
55
+ config = double(:config)
56
+ klass = Class.new(Object) do
57
+ @config = config
58
+ extend Emque::Consuming::Core
59
+ end
60
+
61
+ expect(Emque::Consuming::Configuration).to_not receive(:new)
62
+ expect(klass.config).to eq(config)
63
+ end
64
+ end
65
+ end
66
+
67
+ describe ".emque_env" do
68
+ it "returns the value of config.env_var if it is set" do
69
+ CoreContainer.config.env = "some_env_name"
70
+
71
+ expect(CoreContainer.emque_env).to eq("some_env_name")
72
+
73
+ CoreContainer.instance_variable_set(:@config, nil)
74
+ end
75
+
76
+ describe "when config.emque_env is not set" do
77
+ it "returns the ENV value, EMQUE_ENV, if it's set" do
78
+ CoreContainer.config.env = nil
79
+ old_emque_env_val = ENV["EMQUE_ENV"]
80
+ ENV["EMQUE_ENV"] = "some_other_env_name"
81
+
82
+ expect(CoreContainer.emque_env).to eq(ENV["EMQUE_ENV"])
83
+
84
+ ENV["EMQUE_ENV"] = old_emque_env_val
85
+ CoreContainer.instance_variable_set(:@config, nil)
86
+ end
87
+
88
+ describe "and the ENV value EMQUE_ENV is not set" do
89
+ it "returns the ENV value, RACK_ENV, if it's set" do
90
+ CoreContainer.config.env = nil
91
+ old_emque_env_val = ENV["EMQUE_ENV"]
92
+ ENV["EMQUE_ENV"] = nil
93
+ old_rack_env_val = ENV["RACK_ENV"]
94
+ ENV["RACK_ENV"] = "yet_another_env_name"
95
+
96
+ expect(CoreContainer.emque_env).to eq(ENV["RACK_ENV"])
97
+
98
+ ENV["EMQUE_ENV"] = old_emque_env_val
99
+ ENV["RACK_ENV"] = old_rack_env_val
100
+ CoreContainer.instance_variable_set(:@config, nil)
101
+ end
102
+
103
+ describe "and the ENV value RACK_ENV is not set" do
104
+ it "defaults to development" do
105
+ CoreContainer.config.env = nil
106
+ old_emque_env_val = ENV["EMQUE_ENV"]
107
+ ENV["EMQUE_ENV"] = nil
108
+ old_rack_env_val = ENV["RACK_ENV"]
109
+ ENV["RACK_ENV"] = nil
110
+
111
+ expect(CoreContainer.emque_env).to eq("development")
112
+
113
+ ENV["EMQUE_ENV"] = old_emque_env_val
114
+ ENV["RACK_ENV"] = old_rack_env_val
115
+ CoreContainer.instance_variable_set(:@config, nil)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,38 @@
1
+ require "emque/consuming"
2
+
3
+ ENV["EMQUE_ENV"] = "test"
4
+
5
+ module Emque
6
+ module Consuming
7
+ module Adapters
8
+ module TestAdapter
9
+ def self.default_options; {}; end
10
+ def self.load; end
11
+ def self.manager
12
+ Emque::Consuming::Adapters::TestAdapter::Manager
13
+ end
14
+
15
+ class Manager
16
+ def async; self; end
17
+ def start; end
18
+ def stop; end
19
+ def worker(topic:, command:); end
20
+ def workers(flatten: false); end
21
+ def retry_errors; end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ module Dummy
29
+ class Application
30
+ include Emque::Consuming::Application
31
+
32
+ self.root = File.expand_path("../..", __FILE__)
33
+
34
+ initialize_core!
35
+
36
+ config.set_adapter(:test_adapter)
37
+ end
38
+ end
File without changes
File without changes
@@ -0,0 +1,64 @@
1
+ require "spec_helper"
2
+ require "emque/consuming/error_tracker"
3
+
4
+ describe Emque::Consuming::ErrorTracker do
5
+ describe "#count" do
6
+ it "returns the number of errors not yet expired" do
7
+ Timecop.freeze do
8
+ tracker = Emque::Consuming::ErrorTracker.new
9
+ tracker.occurrences = {
10
+ :one => Time.now + (10 * 60),
11
+ :two => Time.now,
12
+ :three => Time.now - 60
13
+ }
14
+
15
+ expect(tracker.count).to eq(2)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "#limit_reached?" do
21
+ it "is false initially" do
22
+ tracker = Emque::Consuming::ErrorTracker.new
23
+
24
+ expect(tracker.limit_reached?).to eq(false)
25
+ end
26
+
27
+ it "is true once n(limit) unique values are noticed" do
28
+ tracker = Emque::Consuming::ErrorTracker.new(:limit => 2)
29
+
30
+ tracker.notice_error_for({ :first => "value" })
31
+ expect(tracker.limit_reached?).to eq(false)
32
+
33
+ tracker.notice_error_for({ :first => "value" })
34
+ expect(tracker.limit_reached?).to eq(false)
35
+
36
+ tracker.notice_error_for({ :second => "value" })
37
+ expect(tracker.limit_reached?).to eq(true)
38
+
39
+ tracker.notice_error_for({ :third => "value" })
40
+ expect(tracker.limit_reached?).to eq(true)
41
+ end
42
+
43
+ it "takes expiration time into account" do
44
+ Timecop.freeze do
45
+ current_time = Time.now
46
+
47
+ tracker = Emque::Consuming::ErrorTracker.new(
48
+ :limit => 2, :expiration => 60
49
+ )
50
+
51
+ tracker.notice_error_for({ :first => "value" })
52
+
53
+ Timecop.travel(current_time + 61) do
54
+
55
+ tracker.notice_error_for({ :second => "value" })
56
+ expect(tracker.limit_reached?).to eq(false)
57
+
58
+ tracker.notice_error_for({ :first => "value "})
59
+ expect(tracker.limit_reached?).to eq(true)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,74 @@
1
+ require "spec_helper"
2
+
3
+ describe Emque::Consuming::Pidfile do
4
+ describe "#initialize" do
5
+ it "creates a directory to hold the pidfile if it doesn't exist" do
6
+ path = "spec/dummy/tmp/testingpidpath"
7
+ pidfile = File.join(path, "pidfile.pid")
8
+ expect(Dir.exists?(path)).to eq(false)
9
+ Emque::Consuming::Pidfile.new(pidfile)
10
+ expect(Dir.exists?(path)).to eq(true)
11
+ FileUtils.rm_rf(path)
12
+ end
13
+
14
+ it "loads the pid from the pidfile if it already exists" do
15
+ path = "spec/dummy/tmp/testingpidpath"
16
+ pidfile = File.join(path, "pidfile.pid")
17
+ Emque::Consuming::Pidfile.new(pidfile)
18
+ File.open(pidfile, "w") do |f|
19
+ f.write("1000000")
20
+ end
21
+ pf = Emque::Consuming::Pidfile.new(pidfile)
22
+ expect(pf.to_i).to eq(1000000)
23
+ FileUtils.rm_rf(path)
24
+ end
25
+ end
26
+
27
+ describe "#running?" do
28
+ describe "when the pidfile exists" do
29
+ describe "and the pid is not a valid process" do
30
+ it "deletes the pidfile and returns false" do
31
+ path = "spec/dummy/tmp/testingpidpath"
32
+ pidfile = File.join(path, "pidfile.pid")
33
+ Emque::Consuming::Pidfile.new(pidfile)
34
+ File.open(pidfile, "w") do |f|
35
+ f.write("10000000")
36
+ end
37
+ pf = Emque::Consuming::Pidfile.new(pidfile)
38
+ expect(File.exists?(pidfile)).to eq(true)
39
+ expect(pf.running?).to eq(false)
40
+ expect(File.exists?(pidfile)).to eq(false)
41
+ FileUtils.rm_rf(path)
42
+ end
43
+ end
44
+
45
+ describe "and the pid is a valid process" do
46
+ it "returns true" do
47
+ path = "spec/dummy/tmp/testingpidpath"
48
+ pidfile = File.join(path, "pidfile.pid")
49
+ Emque::Consuming::Pidfile.new(pidfile)
50
+ File.open(pidfile, "w") do |f|
51
+ f.write(Process.pid)
52
+ end
53
+ pf = Emque::Consuming::Pidfile.new(pidfile)
54
+ expect(File.exists?(pidfile)).to eq(true)
55
+ expect(pf.running?).to eq(true)
56
+ FileUtils.rm_rf(path)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "#write" do
63
+ it "writes the current process's pid to the pidfile" do
64
+ path = "spec/dummy/tmp/testingpidpath"
65
+ pidfile = File.join(path, "pidfile.pid")
66
+ pf = Emque::Consuming::Pidfile.new(pidfile)
67
+ expect(File.exists?(pidfile)).to eq(false)
68
+ pf.write
69
+ expect(File.exists?(pidfile)).to eq(true)
70
+ expect(File.read(pidfile).chomp).to eq(Process.pid.to_s)
71
+ FileUtils.rm_rf(path)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+ require "emque/consuming/consumer"
3
+ require "emque/consuming/consumer/common"
4
+
5
+ describe Emque::Consuming::Router do
6
+ describe "#topic" do
7
+ it "uses strings as mapping keys" do
8
+ router = Emque::Consuming::Router.new
9
+ mappings = router.topic("events" => "EventsConsumer") do
10
+ map "events.new" => "new_event"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,138 @@
1
+ require "spec_helper"
2
+
3
+ describe Emque::Consuming::Runner do
4
+ describe "#initialize" do
5
+ it "initializes a new control object" do
6
+ expect(Emque::Consuming::Control).to receive(:new).and_return(nil)
7
+ Emque::Consuming::Runner.new
8
+ end
9
+
10
+ it "initializes a new status object" do
11
+ expect(Emque::Consuming::Status).to receive(:new).and_return(nil)
12
+ Emque::Consuming::Runner.new
13
+ end
14
+
15
+ it "initializes the logger" do
16
+ app = double(:application, :root => "/")
17
+ expect(app).to receive(:config)
18
+ .and_return(Emque::Consuming::Configuration.new)
19
+ expect(Emque::Consuming).to receive(:application)
20
+ .at_least(1).times
21
+ .and_return(app)
22
+ expect(app).to receive(:initialize_logger).and_return(nil)
23
+
24
+ Emque::Consuming::Runner.new
25
+ end
26
+
27
+ it "stores itself on the class variable instance" do
28
+ instance = Emque::Consuming::Runner.new
29
+ expect(Emque::Consuming::Runner.instance).to eq(instance)
30
+ end
31
+
32
+ it "creates a new pidfile object" do
33
+ expect(Emque::Consuming::Pidfile).to receive(:new).and_return(nil)
34
+ Emque::Consuming::Runner.new
35
+ end
36
+
37
+ it "passes valid options to the app configuration" do
38
+ valid_opts = {
39
+ :app_name => "testing",
40
+ :error_limit => 5,
41
+ :status => :one
42
+ }
43
+ invalid_opts = {
44
+ :not => :valid,
45
+ :also => :not_valid,
46
+ :another => 50
47
+ }
48
+
49
+ app = double(:application, :initialize_logger => nil, :root => "/")
50
+ config = Emque::Consuming::Configuration.new
51
+ expect(Emque::Consuming).to receive(:application)
52
+ .at_least(1).times
53
+ .and_return(app)
54
+ expect(app).to receive(:config)
55
+ .at_least(1).times
56
+ .and_return(config)
57
+
58
+ valid_opts.each do |meth, val|
59
+ expect(config).to receive("#{meth}=").with(val)
60
+ end
61
+
62
+ invalid_opts.each do |meth, val|
63
+ expect(config).to_not receive("#{meth}=")
64
+ end
65
+
66
+ Emque::Consuming::Runner.new(valid_opts.merge(invalid_opts))
67
+ end
68
+ end
69
+
70
+ describe "#start" do
71
+ it "exits if the specified pidfile already exists" do
72
+ runner = Emque::Consuming::Runner.new
73
+ expect(runner).to receive(:pid)
74
+ .at_least(1).times
75
+ .and_return(double(:pid, :running? => true))
76
+
77
+ expect { runner.start }.to raise_error(SystemExit)
78
+ end
79
+
80
+ it "daemonizes the process if the daemon option is set" do
81
+ runner = Emque::Consuming::Runner.new(:daemon => true)
82
+ expect(runner).to receive(:receivers).at_least(1).times.and_return([])
83
+ expect(runner).to receive(:persist).and_return(double(:join => true))
84
+ expect(runner).to receive(:pid)
85
+ .at_least(1).times
86
+ .and_return(double(:running? => false, :write => true))
87
+
88
+ expect(runner).to receive(:daemonize!).and_return(true)
89
+ runner.start
90
+ end
91
+
92
+ it "creates a unix socket receiver and starts it" do
93
+ runner = Emque::Consuming::Runner.new
94
+ expect(runner).to receive(:persist).and_return(double(:join => true))
95
+ expect(runner).to receive(:pid)
96
+ .at_least(1).times
97
+ .and_return(double(:running? => false, :write => true))
98
+ socket = double(:unix_socket, :start => true)
99
+
100
+ expect(Emque::Consuming::CommandReceivers::UnixSocket)
101
+ .to receive(:new).and_return(socket)
102
+ expect(socket).to receive(:start)
103
+ runner.start
104
+ end
105
+
106
+ it "creates a http receiver and starts it if the status is set to :on" do
107
+ runner = Emque::Consuming::Runner.new(:status => :on)
108
+ expect(runner).to receive(:persist).and_return(double(:join => true))
109
+ expect(runner).to receive(:pid)
110
+ .at_least(1).times
111
+ .and_return(double(:running? => false, :write => true))
112
+ http = double(:http_server, :start => true)
113
+
114
+ expect(Emque::Consuming::CommandReceivers::HttpServer)
115
+ .to receive(:new).and_return(http)
116
+ expect(http).to receive(:start)
117
+ runner.start
118
+ end
119
+
120
+ it "starts the application" do
121
+ runner = Emque::Consuming::Runner.new
122
+ expect(runner).to receive(:persist).and_return(double(:join => true))
123
+ expect(runner).to receive(:pid)
124
+ .at_least(1).times
125
+ .and_return(double(:running? => false, :write => true))
126
+ socket = double(:unix_socket, :start => true)
127
+ expect(Emque::Consuming::CommandReceivers::UnixSocket)
128
+ .to receive(:new).and_return(socket)
129
+ app = Emque::Consuming.application.new
130
+ expect(Emque::Consuming.application).to receive(:instance)
131
+ .at_least(1).times
132
+ .and_return(app)
133
+
134
+ expect(app).to receive(:start)
135
+ runner.start
136
+ end
137
+ end
138
+ end