background_queue 0.2.0
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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/.rvmrc +48 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +20 -0
- data/README.md +69 -0
- data/Rakefile +42 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/background_queue.gemspec +158 -0
- data/bin/bg_queue +26 -0
- data/lib/background_queue.rb +8 -0
- data/lib/background_queue/client.rb +96 -0
- data/lib/background_queue/client_lib/command.rb +36 -0
- data/lib/background_queue/client_lib/config.rb +109 -0
- data/lib/background_queue/client_lib/connection.rb +105 -0
- data/lib/background_queue/client_lib/job_handle.rb +19 -0
- data/lib/background_queue/command.rb +49 -0
- data/lib/background_queue/config.rb +118 -0
- data/lib/background_queue/server_lib/balanced_queue.rb +108 -0
- data/lib/background_queue/server_lib/config.rb +339 -0
- data/lib/background_queue/server_lib/event_connection.rb +133 -0
- data/lib/background_queue/server_lib/event_server.rb +35 -0
- data/lib/background_queue/server_lib/job.rb +252 -0
- data/lib/background_queue/server_lib/job_registry.rb +30 -0
- data/lib/background_queue/server_lib/lru.rb +193 -0
- data/lib/background_queue/server_lib/owner.rb +54 -0
- data/lib/background_queue/server_lib/priority_queue.rb +156 -0
- data/lib/background_queue/server_lib/queue_registry.rb +123 -0
- data/lib/background_queue/server_lib/server.rb +314 -0
- data/lib/background_queue/server_lib/sorted_workers.rb +52 -0
- data/lib/background_queue/server_lib/task.rb +79 -0
- data/lib/background_queue/server_lib/task_registry.rb +51 -0
- data/lib/background_queue/server_lib/thread_manager.rb +121 -0
- data/lib/background_queue/server_lib/worker.rb +18 -0
- data/lib/background_queue/server_lib/worker_balancer.rb +97 -0
- data/lib/background_queue/server_lib/worker_client.rb +94 -0
- data/lib/background_queue/server_lib/worker_thread.rb +70 -0
- data/lib/background_queue/utils.rb +40 -0
- data/lib/background_queue/worker/base.rb +46 -0
- data/lib/background_queue/worker/calling.rb +59 -0
- data/lib/background_queue/worker/config.rb +35 -0
- data/lib/background_queue/worker/environment.rb +70 -0
- data/lib/background_queue/worker/worker_loader.rb +94 -0
- data/lib/background_queue_server.rb +21 -0
- data/lib/background_queue_worker.rb +5 -0
- data/spec/background_queue/client_lib/command_spec.rb +75 -0
- data/spec/background_queue/client_lib/config_spec.rb +156 -0
- data/spec/background_queue/client_lib/connection_spec.rb +170 -0
- data/spec/background_queue/client_spec.rb +95 -0
- data/spec/background_queue/command_spec.rb +34 -0
- data/spec/background_queue/config_spec.rb +134 -0
- data/spec/background_queue/server_lib/balanced_queue_spec.rb +122 -0
- data/spec/background_queue/server_lib/config_spec.rb +443 -0
- data/spec/background_queue/server_lib/event_connection_spec.rb +190 -0
- data/spec/background_queue/server_lib/event_server_spec.rb +48 -0
- data/spec/background_queue/server_lib/integration/full_test_spec.rb +247 -0
- data/spec/background_queue/server_lib/integration/queue_integration_spec.rb +98 -0
- data/spec/background_queue/server_lib/integration/serialize_spec.rb +127 -0
- data/spec/background_queue/server_lib/job_registry_spec.rb +65 -0
- data/spec/background_queue/server_lib/job_spec.rb +525 -0
- data/spec/background_queue/server_lib/owner_spec.rb +33 -0
- data/spec/background_queue/server_lib/priority_queue_spec.rb +182 -0
- data/spec/background_queue/server_lib/server_spec.rb +353 -0
- data/spec/background_queue/server_lib/sorted_workers_spec.rb +122 -0
- data/spec/background_queue/server_lib/task_registry_spec.rb +69 -0
- data/spec/background_queue/server_lib/task_spec.rb +20 -0
- data/spec/background_queue/server_lib/thread_manager_spec.rb +106 -0
- data/spec/background_queue/server_lib/worker_balancer_spec.rb +127 -0
- data/spec/background_queue/server_lib/worker_client_spec.rb +196 -0
- data/spec/background_queue/server_lib/worker_thread_spec.rb +125 -0
- data/spec/background_queue/utils_spec.rb +27 -0
- data/spec/background_queue/worker/base_spec.rb +35 -0
- data/spec/background_queue/worker/calling_spec.rb +103 -0
- data/spec/background_queue/worker/environment_spec.rb +67 -0
- data/spec/background_queue/worker/worker_loader_spec.rb +103 -0
- data/spec/background_queue_spec.rb +7 -0
- data/spec/resources/config-client.yml +7 -0
- data/spec/resources/config-serialize.yml +12 -0
- data/spec/resources/config.yml +12 -0
- data/spec/resources/example_worker.rb +4 -0
- data/spec/resources/example_worker_with_error.rb +4 -0
- data/spec/resources/test_worker.rb +8 -0
- data/spec/shared/queue_registry_shared.rb +216 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/default_task.rb +9 -0
- data/spec/support/private.rb +23 -0
- data/spec/support/simple_server.rb +28 -0
- data/spec/support/simple_task.rb +58 -0
- data/spec/support/test_worker_server.rb +205 -0
- metadata +254 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'background_queue_worker'
|
3
|
+
|
4
|
+
|
5
|
+
describe BackgroundQueue::Worker::Environment do
|
6
|
+
|
7
|
+
let(:logger) {
|
8
|
+
l = double("logger")
|
9
|
+
l.stub(:debug)
|
10
|
+
l.stub(:info)
|
11
|
+
l.stub(:error)
|
12
|
+
l.stub(:warn)
|
13
|
+
l
|
14
|
+
}
|
15
|
+
|
16
|
+
let(:params) {
|
17
|
+
{
|
18
|
+
:auth=>"ABCD",
|
19
|
+
:task=>{:params=>{:a=>"b"}, :owner_id=>'oid', :job_id=>'jid', :id=>'tid', :priority=>1}.to_json,
|
20
|
+
:server_port=>213
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
let(:response) {
|
25
|
+
double("resp")
|
26
|
+
}
|
27
|
+
|
28
|
+
let(:request) {
|
29
|
+
double("req", :remote_ip=>"192.168.1.1")
|
30
|
+
}
|
31
|
+
|
32
|
+
let(:controller) {
|
33
|
+
double("controller", :logger=>logger, :response=>response, :params=>params, :request=>request)
|
34
|
+
}
|
35
|
+
|
36
|
+
|
37
|
+
context "#init_params" do
|
38
|
+
it "will load task data from params" do
|
39
|
+
subject.init_params(params)
|
40
|
+
subject.params[:a].should eq("b")
|
41
|
+
subject.owner_id.should eq("oid")
|
42
|
+
subject.job_id.should eq("jid")
|
43
|
+
subject.task_id.should eq("tid")
|
44
|
+
subject.priority.should eq(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "will error if the task definition is not valid json" do
|
48
|
+
params[:task] = '[123'
|
49
|
+
expect { subject.init_params(params) }.to raise_exception
|
50
|
+
end
|
51
|
+
|
52
|
+
it "will error if the task definition is not a json hash" do
|
53
|
+
params[:task] = '[123]'
|
54
|
+
expect { subject.init_params(params) }.to raise_exception("Invalid json root object (should be hash)")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "#init_server_address" do
|
59
|
+
it "will get the server ip from the request" do
|
60
|
+
subject.init_server_address(controller)
|
61
|
+
subject.server_address.port.should eq(213)
|
62
|
+
subject.server_address.host.should eq("192.168.1.1")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'background_queue_worker'
|
3
|
+
|
4
|
+
class ThisWorkerExists
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
describe BackgroundQueue::Worker::WorkerLoader do
|
9
|
+
|
10
|
+
let(:worker_entry) {
|
11
|
+
BackgroundQueue::Worker::WorkerLoader::WorkerEntry.new(:worker, :path, Time.at(10), :worker_name)
|
12
|
+
}
|
13
|
+
|
14
|
+
context "#worker_class_name" do
|
15
|
+
it "will convert to camelcase" do
|
16
|
+
subject.worker_class_name("something").should eq("Something")
|
17
|
+
subject.worker_class_name("something_else").should eq("SomethingElse")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
context "#worker_path" do
|
23
|
+
it "will get the worker path using the worker name" do
|
24
|
+
BackgroundQueue::Worker::Config.worker_path = "ROOT"
|
25
|
+
subject.worker_path("something").should eq("ROOT/something.rb")
|
26
|
+
subject.worker_path("something_else").should eq("ROOT/something_else.rb")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "#load_worker" do
|
31
|
+
it "will wrap a worker in a worker entry if the file loads and defines the worker class" do
|
32
|
+
subject.should_receive(:load_file).with(:path).and_return(true)
|
33
|
+
subject.should_receive(:load_class).with(:worker_name, :path).and_return(:clazz)
|
34
|
+
subject.should_receive(:worker_path).with(:worker_name).and_return(:path)
|
35
|
+
File.should_receive(:mtime).with(:path).and_return(:datestamp)
|
36
|
+
worker_entry = subject.load_worker(:worker_name)
|
37
|
+
worker_entry.worker.should eq(:clazz)
|
38
|
+
worker_entry.name.should eq(:worker_name)
|
39
|
+
worker_entry.datestamp.should eq(:datestamp)
|
40
|
+
worker_entry.path.should eq(:path)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "#load_file" do
|
45
|
+
it "will load a file if it is a valid ruby file" do
|
46
|
+
path = File.expand_path(File.dirname(__FILE__) + '/../../resources/example_worker.rb')
|
47
|
+
subject.load_file(path)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "will raise an error if the file does not exist" do
|
51
|
+
path = File.expand_path(File.dirname(__FILE__) + '/../../resources/example_worker_not_found.rb')
|
52
|
+
expect { subject.load_file(path) }.to raise_exception
|
53
|
+
end
|
54
|
+
|
55
|
+
it "will raise an error if the file is not valid ruby" do
|
56
|
+
path = File.expand_path(File.dirname(__FILE__) + '/../../resources/example_worker_with_error.rb')
|
57
|
+
expect { subject.load_file(path) }.to raise_exception
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "#load_class" do
|
62
|
+
it "will create an instance of the worker class" do
|
63
|
+
subject.load_class("this_worker_exists", "path").class.name.should eq("ThisWorkerExists")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "will error if the class is not found" do
|
67
|
+
expect { subject.load_class("this_worker_does_not_exist", "path") }.to raise_exception("path did not define ThisWorkerDoesNotExist")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "#reload_if_updated" do
|
72
|
+
it "will reload the worker if the filestamp has changed" do
|
73
|
+
File.should_receive(:mtime).with(:path).and_return(Time.at(11))
|
74
|
+
subject.should_receive(:load_file).with(:path).and_return(true)
|
75
|
+
subject.should_receive(:load_class).with(:worker_name).and_return(:new_worker)
|
76
|
+
|
77
|
+
subject.reload_if_updated(worker_entry)
|
78
|
+
worker_entry.worker.should eq(:new_worker)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "will not reload the worker if the filestamp has not changed" do
|
82
|
+
File.should_receive(:mtime).with(:path).and_return(Time.at(10))
|
83
|
+
subject.reload_if_updated(worker_entry)
|
84
|
+
worker_entry.worker.should eq(:worker)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "#get_worker" do
|
89
|
+
it "will load the worker if not in cache" do
|
90
|
+
subject.should_receive(:load_worker).with(:worker_name).and_return(worker_entry)
|
91
|
+
subject.get_worker(:worker_name).should eq(:worker)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "will cache the results" do
|
95
|
+
subject.should_receive(:load_worker).with(:worker_name).and_return(worker_entry)
|
96
|
+
subject.should_receive(:reload_if_updated).with(worker_entry).and_return(nil)
|
97
|
+
subject.get_worker(:worker_name).should eq(:worker)
|
98
|
+
subject.get_worker(:worker_name).should eq(:worker)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
development:
|
2
|
+
address:
|
3
|
+
host: 127.0.0.1
|
4
|
+
port: 3000
|
5
|
+
workers:
|
6
|
+
- http://127.0.0.1:8001/background_queue
|
7
|
+
secret: this_is_used_to_make_sure_it_is_secure
|
8
|
+
connections_per_worker: 10
|
9
|
+
system_task_options:
|
10
|
+
domain: the_default_domain
|
11
|
+
task_file: /tmp/bq_tasks
|
12
|
+
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require 'background_queue_server'
|
2
|
+
|
3
|
+
shared_examples "a queue registry" do
|
4
|
+
|
5
|
+
context "queue registry management" do
|
6
|
+
|
7
|
+
subject { new_instance }
|
8
|
+
|
9
|
+
it "will create an queue" do
|
10
|
+
subject.should_receive(:create_queue).with(:queue_id) { :the_queue}
|
11
|
+
subject.__prv__get_queue(:queue_id, true).should eq([false, :the_queue])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "will find existing queue" do
|
15
|
+
subject.should_receive(:create_queue).with(:queue_id) { :the_queue}
|
16
|
+
subject.__prv__get_queue(:queue_id, true)
|
17
|
+
subject.stub(:create_queue).with(:queue_id) { :this_should_not_be_used }
|
18
|
+
subject.__prv__get_queue(:queue_id, true).should eq([true, :the_queue])
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
context "queue items" do
|
25
|
+
let(:queue_class) { described_class.queue_class }
|
26
|
+
|
27
|
+
let(:task1) { SimpleTask.new(:owner_id, :job_id, :task_id, 3) }
|
28
|
+
let(:task2) { SimpleTask.new(:owner_id2, :job_id, :task_id2, 2) }
|
29
|
+
|
30
|
+
before do
|
31
|
+
queue_class.any_instance.stub(:add_item) do |item|
|
32
|
+
@priority = item.priority if @priority.nil? || @priority > item.priority
|
33
|
+
end
|
34
|
+
|
35
|
+
queue_class.any_instance.stub(:priority) do
|
36
|
+
@priority
|
37
|
+
end
|
38
|
+
|
39
|
+
queue_class.any_instance.stub(:set_priority) do |priority|
|
40
|
+
@priority = priority
|
41
|
+
end
|
42
|
+
|
43
|
+
queue_class.any_instance.stub(:next_item) do
|
44
|
+
@priority += 1 #just assume we lower priority...
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "#add_item" do
|
49
|
+
|
50
|
+
context "new queue" do
|
51
|
+
|
52
|
+
subject { new_instance }
|
53
|
+
|
54
|
+
it "tracks if the queue priority changed" do
|
55
|
+
in_queue, queue = subject.__prv__get_queue(:queue_id, true)
|
56
|
+
subject.__prv__track_priority_when_adding_to_queue(queue, task1).should eq([true, nil])
|
57
|
+
end
|
58
|
+
|
59
|
+
it "will add with correct priority" do
|
60
|
+
|
61
|
+
subject.add_item(task1)
|
62
|
+
subject.__prv__get_queues.should have(1).items
|
63
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "existing queue" do
|
68
|
+
|
69
|
+
subject {
|
70
|
+
bg = new_instance
|
71
|
+
bg.add_item(task1)
|
72
|
+
bg
|
73
|
+
}
|
74
|
+
|
75
|
+
it "will re-prioritise existing queue to higher priority" do
|
76
|
+
subject.__prv__get_queues.should have(1).items
|
77
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
78
|
+
subject.add_item(SimpleTask.new(:owner_id, :job_id, :task_id2, 2))
|
79
|
+
subject.__prv__get_queues.should have(1).items
|
80
|
+
subject.__prv__get_queues.first.priority.should eq(2)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "will not re-prioritise existing owner to lower priority" do
|
84
|
+
subject.__prv__get_queues.should have(1).items
|
85
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
86
|
+
subject.add_item(SimpleTask.new(:owner_id, :job_id, :task_id2, 4))
|
87
|
+
subject.__prv__get_queues.should have(1).items
|
88
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "#next_item" do
|
94
|
+
|
95
|
+
subject {
|
96
|
+
bg = new_instance
|
97
|
+
bg.stub(:get_queue_id_from_item) { |item| item.owner_id}
|
98
|
+
bg.add_item(task1)
|
99
|
+
bg.add_item(task2)
|
100
|
+
bg
|
101
|
+
}
|
102
|
+
|
103
|
+
it "will add to stalled items if no items left for queue" do
|
104
|
+
subject.should_receive(:remove_item_from_queue).with(any_args) { [true, 2, :task]}
|
105
|
+
queue_class.any_instance.stub(:empty?) { true }
|
106
|
+
subject.should_receive(:stall_queue)
|
107
|
+
subject.__prv__get_queue_for_priority(2, false)
|
108
|
+
subject.next_item.should eq(:task)
|
109
|
+
subject.__prv__get_queues.should have(1).items
|
110
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
111
|
+
#make sure the owner was removed
|
112
|
+
subject.__prv__get_queue(:owner_id2, true).first.should eq(false)
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
it "will lower priority when items left are lower priority" do
|
118
|
+
subject.should_receive(:remove_item_from_queue).with(any_args) { [true, 2, :task]}
|
119
|
+
queue_class.any_instance.stub(:empty?) { false }
|
120
|
+
|
121
|
+
subject.__prv__get_queue(:owner_id2, true).last.set_priority(3)
|
122
|
+
|
123
|
+
subject.next_item
|
124
|
+
subject.__prv__get_queues.should have(1).items
|
125
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
126
|
+
subject.__prv__get_queues.first.should have(2).items
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
context "#remove_item_from_queue" do
|
133
|
+
|
134
|
+
subject {
|
135
|
+
bg = new_instance
|
136
|
+
bg.stub(:get_queue_id_from_item) { |item| item.owner_id}
|
137
|
+
bg.add_item(task1)
|
138
|
+
bg.add_item(task2)
|
139
|
+
bg
|
140
|
+
}
|
141
|
+
|
142
|
+
it "tracks if priority changed when removing next item" do
|
143
|
+
owner = double("owner")
|
144
|
+
owner.stub(:priority) { @priority ||= 2 }
|
145
|
+
owner.stub(:next_item) { @priority += 1; :task }
|
146
|
+
|
147
|
+
subject.__prv__remove_item_from_queue(owner, :next).should eq([true, 2, :task])
|
148
|
+
end
|
149
|
+
|
150
|
+
it "tracks if priority unchanged when removing next item" do
|
151
|
+
owner = double("owner")
|
152
|
+
owner.stub(:priority) { @priority ||= 2 }
|
153
|
+
owner.stub(:next_item) {:task }
|
154
|
+
|
155
|
+
subject.__prv__remove_item_from_queue(owner, :next).should eq([false, 2, :task])
|
156
|
+
end
|
157
|
+
|
158
|
+
it "tracks if priority changed when removing specific item" do
|
159
|
+
owner = double("owner")
|
160
|
+
owner.stub(:priority) { @priority ||= 2 }
|
161
|
+
owner.stub(:remove_item) { @priority += 1; :task }
|
162
|
+
|
163
|
+
subject.__prv__remove_item_from_queue(owner, :task).should eq([true, 2, :task])
|
164
|
+
end
|
165
|
+
|
166
|
+
it "tracks if priority unchanged when removing specific item" do
|
167
|
+
owner = double("owner")
|
168
|
+
owner.stub(:priority) { @priority ||= 2 }
|
169
|
+
owner.stub(:remove_item) {:task }
|
170
|
+
|
171
|
+
subject.__prv__remove_item_from_queue(owner, :task).should eq([false, 2, :task])
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
context "#remove_item" do
|
178
|
+
|
179
|
+
subject {
|
180
|
+
bg = new_instance
|
181
|
+
bg.stub(:get_queue_id_from_item) { |item| item.owner_id}
|
182
|
+
bg.add_item(task1)
|
183
|
+
bg.add_item(task2)
|
184
|
+
bg
|
185
|
+
}
|
186
|
+
|
187
|
+
it "will remove the queue if no items left for queue" do
|
188
|
+
subject.should_receive(:remove_item_from_queue).with(any_args) { [true, 3, :task]}
|
189
|
+
queue_class.any_instance.stub(:empty?) { true }
|
190
|
+
|
191
|
+
subject.remove_item(task1)
|
192
|
+
subject.__prv__get_queues.should have(1).items
|
193
|
+
subject.__prv__get_queues.first.priority.should eq(2)
|
194
|
+
#make sure the owner was removed
|
195
|
+
subject.__prv__get_queue(:owner_id, false).first.should be_false
|
196
|
+
end
|
197
|
+
|
198
|
+
it "will lower priority when items left are lower priority" do
|
199
|
+
|
200
|
+
subject.add_item(SimpleTask.new(:owner_id2, :job_id, :task_id3, 3))
|
201
|
+
|
202
|
+
subject.should_receive(:remove_item_from_queue).with(any_args) { [true, 2, :task]}
|
203
|
+
queue_class.any_instance.stub(:empty?) { false }
|
204
|
+
|
205
|
+
subject.__prv__get_queue(:owner_id2, true).last.set_priority(3) #need to manually set the priority to 3 because we are mocking remove_item_from_queue
|
206
|
+
|
207
|
+
subject.remove_item(task2)
|
208
|
+
subject.__prv__get_queues.should have(1).items #both owners should be at same priority (3)
|
209
|
+
subject.__prv__get_queues.first.priority.should eq(3)
|
210
|
+
subject.__prv__get_queues.first.should have(2).items
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
end
|