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,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