emque-consuming 1.0.0.beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +40 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +205 -0
- data/Rakefile +14 -0
- data/bin/emque +5 -0
- data/emque-consuming.gemspec +36 -0
- data/lib/emque/consuming/actor.rb +21 -0
- data/lib/emque/consuming/adapter.rb +47 -0
- data/lib/emque/consuming/adapters/rabbit_mq/manager.rb +111 -0
- data/lib/emque/consuming/adapters/rabbit_mq/retry_worker.rb +59 -0
- data/lib/emque/consuming/adapters/rabbit_mq/worker.rb +87 -0
- data/lib/emque/consuming/adapters/rabbit_mq.rb +26 -0
- data/lib/emque/consuming/application.rb +112 -0
- data/lib/emque/consuming/cli.rb +140 -0
- data/lib/emque/consuming/command_receivers/base.rb +37 -0
- data/lib/emque/consuming/command_receivers/http_server.rb +103 -0
- data/lib/emque/consuming/command_receivers/unix_socket.rb +169 -0
- data/lib/emque/consuming/configuration.rb +63 -0
- data/lib/emque/consuming/consumer/common.rb +61 -0
- data/lib/emque/consuming/consumer.rb +33 -0
- data/lib/emque/consuming/consuming.rb +27 -0
- data/lib/emque/consuming/control/errors.rb +41 -0
- data/lib/emque/consuming/control/workers.rb +23 -0
- data/lib/emque/consuming/control.rb +33 -0
- data/lib/emque/consuming/core.rb +89 -0
- data/lib/emque/consuming/error_tracker.rb +39 -0
- data/lib/emque/consuming/generators/application.rb +95 -0
- data/lib/emque/consuming/helpers.rb +29 -0
- data/lib/emque/consuming/logging.rb +32 -0
- data/lib/emque/consuming/message.rb +22 -0
- data/lib/emque/consuming/pidfile.rb +54 -0
- data/lib/emque/consuming/router.rb +73 -0
- data/lib/emque/consuming/runner.rb +168 -0
- data/lib/emque/consuming/status.rb +26 -0
- data/lib/emque/consuming/tasks.rb +121 -0
- data/lib/emque/consuming/transmitter.rb +31 -0
- data/lib/emque/consuming/version.rb +5 -0
- data/lib/emque/consuming.rb +9 -0
- data/lib/emque-consuming.rb +3 -0
- data/lib/templates/.gitignore.tt +25 -0
- data/lib/templates/Gemfile.tt +6 -0
- data/lib/templates/Rakefile.tt +7 -0
- data/lib/templates/config/application.rb.tt +42 -0
- data/lib/templates/config/environments/development.rb.tt +2 -0
- data/lib/templates/config/environments/production.rb.tt +2 -0
- data/lib/templates/config/environments/staging.rb.tt +2 -0
- data/lib/templates/config/environments/test.rb.tt +2 -0
- data/lib/templates/config/routes.rb.tt +8 -0
- data/spec/application_spec.rb +28 -0
- data/spec/cli_spec.rb +136 -0
- data/spec/configuration_spec.rb +47 -0
- data/spec/consumer_spec.rb +56 -0
- data/spec/control/errors_spec.rb +170 -0
- data/spec/control_spec.rb +15 -0
- data/spec/core_spec.rb +121 -0
- data/spec/dummy/config/application.rb +38 -0
- data/spec/dummy/config/environments/test.rb +0 -0
- data/spec/dummy/config/routes.rb +0 -0
- data/spec/error_tracker_spec.rb +64 -0
- data/spec/pidfile_spec.rb +74 -0
- data/spec/router_spec.rb +14 -0
- data/spec/runner_spec.rb +138 -0
- data/spec/spec_helper.rb +43 -0
- metadata +309 -0
@@ -0,0 +1,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
|
data/spec/router_spec.rb
ADDED
@@ -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
|
data/spec/runner_spec.rb
ADDED
@@ -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
|