tresque 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,94 @@
1
+ require 'resque-bus'
2
+
3
+ module TResque
4
+ class Registry
5
+ class << self
6
+ def default_weight
7
+ 100
8
+ end
9
+
10
+ def class_hash
11
+ @class_hash ||= {}
12
+ end
13
+
14
+ def queue_hash
15
+ @queue_hash ||= {}
16
+ end
17
+
18
+ def class_list
19
+ class_hash.keys
20
+ end
21
+
22
+ def worker(klass)
23
+ klass = klass.name if klass.is_a?(Class)
24
+ klass = klass.to_s
25
+ class_hash[klass] = 1
26
+ end
27
+
28
+ def queue(queue_name, weight=nil)
29
+ queue_name = queue_name.to_s
30
+ if weight
31
+ # take higher weight
32
+ if !queue_hash[queue_name] || weight > queue_hash[queue_name]
33
+ queue_hash[queue_name] = weight
34
+ end
35
+ else
36
+ queue_hash[queue_name] ||= false
37
+ end
38
+ end
39
+
40
+ def weight(key)
41
+ if !self.queue_hash[key]
42
+ self.default_weight
43
+ else
44
+ self.queue_hash[key]
45
+ end
46
+ end
47
+
48
+ # called to know what queues to set
49
+ def queues
50
+ register_classes
51
+ register_bus
52
+ sorted_queues
53
+ end
54
+
55
+ protected
56
+
57
+ def register_classes
58
+ class_list.each do |klass_name|
59
+ klass = klass_name.constantize
60
+ queue(klass.queue)
61
+ end
62
+ end
63
+
64
+ def register_bus
65
+ manager = QueueBus::TaskManager.new(false)
66
+ manager.queue_names.each do |name|
67
+ queue(name)
68
+ end
69
+ queue("bus_incoming", 1)
70
+ end
71
+
72
+ def sorted_queues
73
+ array = queue_hash.keys.clone.shuffle
74
+ hash = {}
75
+ array.each do |key|
76
+ hash[key] = self.weight(key)
77
+ end
78
+ # sorted with highest weight first
79
+ array.sort!{ |x,y| hash[y] <=> hash[x] }
80
+ array
81
+ end
82
+ end
83
+
84
+ attr_reader :app_key
85
+ def initialize(app_key)
86
+ @app_key = Util.normalize(app_key)
87
+ end
88
+
89
+ def queue(name, weight=nil)
90
+ queue_name = "#{app_key}_#{name}"
91
+ ::TResque::Registry.queue(queue_name, weight)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,92 @@
1
+ require 'resque'
2
+
3
+ module Resque
4
+ class Job
5
+ class << self
6
+ alias :create_without_resque_spec :create
7
+ alias :destroy_without_resque_spec :destroy
8
+ end
9
+
10
+ def self.create(queue, klass, *args)
11
+ return create_without_resque_spec(queue, klass, *args) if ResqueSpec.disable_ext
12
+
13
+ raise ::Resque::NoQueueError.new("Jobs must be placed onto a queue.") if !queue
14
+ raise ::Resque::NoClassError.new("Jobs must be given a class.") if klass.to_s.empty?
15
+ ResqueSpec.enqueue(queue, klass, *args)
16
+ end
17
+
18
+ def self.destroy(queue, klass, *args)
19
+ return destroy_without_resque_spec(queue, klass, *args) if ResqueSpec.disable_ext
20
+
21
+ raise ::Resque::NoQueueError.new("Jobs must have been placed onto a queue.") if !queue
22
+ raise ::Resque::NoClassError.new("Jobs must have been given a class.") if klass.to_s.empty?
23
+
24
+ old_count = ResqueSpec.queue_by_name(queue).size
25
+
26
+ ResqueSpec.dequeue(queue, klass, *args)
27
+
28
+ old_count - ResqueSpec.queue_by_name(queue).size
29
+ end
30
+ end
31
+
32
+ alias :enqueue_without_resque_spec :enqueue
33
+ alias :enqueue_to_without_resque_spec :enqueue_to if Resque.respond_to? :enqueue_to
34
+ alias :reserve_without_resque_spec :reserve
35
+ alias :peek_without_resque_spec :peek
36
+ alias :size_without_resque_spec :size
37
+
38
+ def enqueue(klass, *args)
39
+ return enqueue_without_resque_spec(klass, *args) if ResqueSpec.disable_ext
40
+
41
+ enqueue_to(queue_from_class(klass), klass, *args)
42
+ end
43
+
44
+ def enqueue_to(queue, klass, *args)
45
+ return enqueue_to_without_resque_spec(queue, klass, *args) if ResqueSpec.disable_ext
46
+
47
+ if ResqueSpec.inline
48
+ return if run_before_enqueue(klass, *args)
49
+ run_after_enqueue(klass, *args)
50
+ Job.create(queue, klass, *args)
51
+ else
52
+ return if run_before_enqueue(klass, *args)
53
+ Job.create(queue, klass, *args)
54
+ run_after_enqueue(klass, *args)
55
+ true
56
+ end
57
+ end
58
+
59
+ def peek(queue, start = 0, count = 1)
60
+ return peek_without_resque_spec(queue, start, count) if ResqueSpec.disable_ext
61
+ ResqueSpec.peek(queue, start, count).map do |job|
62
+ job.inject({}) { |a, (k, v)| a[k.to_s] = v; a }
63
+ end
64
+ end
65
+
66
+ def reserve(queue_name)
67
+ return reserve_without_resque_spec(queue_name) if ResqueSpec.disable_ext
68
+
69
+ ResqueSpec.pop(queue_name)
70
+ end
71
+
72
+ def size(queue_name)
73
+ return size_without_resque_spec(queue_name) if ResqueSpec.disable_ext
74
+
75
+ ResqueSpec.queue_by_name(queue_name).count
76
+ end
77
+
78
+ private
79
+
80
+ def run_after_enqueue(klass, *args)
81
+ Plugin.after_enqueue_hooks(klass).each do |hook|
82
+ klass.send(hook, *args)
83
+ end
84
+ end
85
+
86
+ def run_before_enqueue(klass, *args)
87
+ before_hooks = Plugin.before_enqueue_hooks(klass).collect do |hook|
88
+ klass.send(hook, *args)
89
+ end
90
+ before_hooks.any? { |result| result == false }
91
+ end
92
+ end
@@ -0,0 +1,25 @@
1
+ module ResqueSpec
2
+ module Helpers
3
+
4
+ def with_resque
5
+ original = ResqueSpec.inline
6
+ begin
7
+ ResqueSpec.inline = true
8
+ yield
9
+ ensure
10
+ ResqueSpec.inline = original
11
+ end
12
+ end
13
+
14
+ def without_resque_spec
15
+ original = ResqueSpec.disable_ext
16
+ begin
17
+ ResqueSpec.disable_ext = true
18
+ yield
19
+ ensure
20
+ ResqueSpec.disable_ext = original
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,318 @@
1
+ require 'rspec/core'
2
+ require 'rspec/expectations'
3
+ require 'rspec/mocks'
4
+
5
+ module InQueueHelper
6
+ def self.extended(klass)
7
+ klass.instance_eval do
8
+ self.queue_name = nil
9
+ chain :in do |queue_name|
10
+ self.queue_name = queue_name
11
+ end
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ attr_accessor :queue_name
18
+
19
+ def queue(actual)
20
+ if @queue_name
21
+ ResqueSpec.queue_by_name(@queue_name)
22
+ else
23
+ ResqueSpec.queue_for(actual)
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ RSpec::Matchers.define :have_queued do |*expected_args|
30
+ extend InQueueHelper
31
+ include InQueueHelper
32
+ chain :times do |num_times_queued|
33
+ @times = num_times_queued
34
+ @times_info = @times == 1 ? ' once' : " #{@times} times"
35
+ end
36
+
37
+ chain :once do |num_times_queued|
38
+ @times = 1
39
+ @times_info = ' once'
40
+ end
41
+
42
+ match do |actual|
43
+ matched = queue(actual).select do |entry|
44
+ klass = entry.fetch(:class)
45
+ args = entry.fetch(:args)
46
+
47
+ if expected_args.length == 0
48
+ klass.to_s == actual.to_s
49
+ elsif expected_args.length == 1 && expected_args[0].is_a?(Hash) && !expected_args[0].has_key?('tz') && !expected_args[0].has_key?('locale')
50
+ klass.to_s == actual.to_s && args[0].except('locale', 'tz') == expected_args[0]
51
+ else
52
+ klass.to_s == actual.to_s && expected_args == args
53
+ end
54
+ end
55
+
56
+ if @times
57
+ matched.size == @times
58
+ else
59
+ matched.size > 0
60
+ end
61
+ end
62
+
63
+ failure_message do |actual|
64
+ "expected that #{actual} would have [#{expected_args.join(', ')}] queued#{@times_info}"
65
+ end
66
+
67
+ failure_message_when_negated do |actual|
68
+ "expected that #{actual} would not have [#{expected_args.join(', ')}] queued#{@times_info}"
69
+ end
70
+
71
+ description do
72
+ "have queued arguments of [#{expected_args.join(', ')}]#{@times_info}"
73
+ end
74
+ end
75
+
76
+ RSpec::Matchers.define :have_queue_size_of do |size|
77
+ extend InQueueHelper
78
+ include InQueueHelper
79
+
80
+ match do |actual|
81
+ queue(actual).size == size
82
+ end
83
+
84
+ failure_message do |actual|
85
+ "expected that #{actual} would have #{size} entries queued, but got #{queue(actual).size} instead"
86
+ end
87
+
88
+ failure_message_when_negated do |actual|
89
+ "expected that #{actual} would not have #{size} entries queued, but got #{queue(actual).size} instead"
90
+ end
91
+
92
+ description do
93
+ "have a queue size of #{size}"
94
+ end
95
+ end
96
+
97
+ RSpec::Matchers.define :have_queue_size_of_at_least do |size|
98
+ extend InQueueHelper
99
+ include InQueueHelper
100
+ match do |actual|
101
+ queue(actual).size >= size
102
+ end
103
+
104
+ failure_message do |actual|
105
+ "expected that #{actual} would have at least #{size} entries queued, but got #{queue(actual).size} instead"
106
+ end
107
+
108
+ failure_message_when_negated do |actual|
109
+ "expected that #{actual} would not have at least #{size} entries queued, but got #{queue(actual).size} instead"
110
+ end
111
+
112
+ description do
113
+ "have a queue size of at least #{size}"
114
+ end
115
+ end
116
+
117
+ module ScheduleQueueHelper
118
+ def self.extended(klass)
119
+ klass.instance_eval do
120
+ self.queue_name = nil
121
+ chain :queue do |queue_name|
122
+ self.queue_name = queue_name
123
+ end
124
+ end
125
+ end
126
+
127
+ attr_accessor :queue_name
128
+
129
+ def schedule_queue_for(actual)
130
+ if @queue_name
131
+ ResqueSpec.queue_by_name(@queue_name)
132
+ else
133
+ ResqueSpec.schedule_for(actual)
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ RSpec::Matchers.define :have_scheduled do |*expected_args|
140
+ extend ScheduleQueueHelper
141
+ include ScheduleQueueHelper
142
+ chain :at do |timestamp|
143
+ @interval = nil
144
+ @time = timestamp
145
+ @time_info = "at #{@time}"
146
+ end
147
+
148
+ chain :in do |interval|
149
+ @time = nil
150
+ @interval = interval
151
+ @time_info = "in #{@interval} seconds"
152
+ end
153
+
154
+ match do |actual|
155
+ schedule_queue_for(actual).any? do |entry|
156
+ class_matches = entry[:class].to_s == actual.to_s
157
+ args_match = begin
158
+ if expected_args.length == 1 && expected_args[0].is_a?(Hash) && !expected_args[0].has_key?('tz') && !expected_args[0].has_key?('locale')
159
+ entry[:args][0].except('tz', 'locale') == expected_args[0]
160
+ else
161
+ entry[:args] == expected_args
162
+ end
163
+ end
164
+
165
+ time_matches = if @time
166
+ entry[:time] == @time
167
+ elsif @interval
168
+ entry[:time].to_i == (entry[:stored_at] + @interval).to_i
169
+ else
170
+ true
171
+ end
172
+
173
+ class_matches && args_match && time_matches
174
+ end
175
+ end
176
+
177
+ failure_message do |actual|
178
+ ["expected that #{actual} would have [#{expected_args.join(', ')}] scheduled", @time_info].join(' ')
179
+ end
180
+
181
+ failure_message_when_negated do |actual|
182
+ ["expected that #{actual} would not have [#{expected_args.join(', ')}] scheduled", @time_info].join(' ')
183
+ end
184
+
185
+ description do
186
+ "have scheduled arguments"
187
+ end
188
+ end
189
+
190
+ RSpec::Matchers.define :have_scheduled_at do |*expected_args|
191
+ extend ScheduleQueueHelper
192
+ warn "DEPRECATION WARNING: have_scheduled_at(time, *args) is deprecated and will be removed in future. Please use have_scheduled(*args).at(time) instead."
193
+
194
+ match do |actual|
195
+ time = expected_args.first
196
+ other_args = expected_args[1..-1]
197
+ schedule_queue_for(actual).any? { |entry| entry[:class].to_s == actual.to_s && entry[:time] == time && other_args == entry[:args] }
198
+ end
199
+
200
+ failure_message do |actual|
201
+ "expected that #{actual} would have [#{expected_args.join(', ')}] scheduled"
202
+ end
203
+
204
+ failure_message_when_negated do |actual|
205
+ "expected that #{actual} would not have [#{expected_args.join(', ')}] scheduled"
206
+ end
207
+
208
+ description do
209
+ "have scheduled at the given time the arguments"
210
+ end
211
+ end
212
+
213
+ RSpec::Matchers.define :have_schedule_size_of do |size|
214
+ extend ScheduleQueueHelper
215
+
216
+ match do |actual|
217
+ schedule_queue_for(actual).size == size
218
+ end
219
+
220
+ failure_message do |actual|
221
+ "expected that #{actual} would have #{size} scheduled entries, but got #{schedule_queue_for(actual).size} instead"
222
+ end
223
+
224
+ failure_message_when_negated do |actual|
225
+ "expected that #{actual} would have #{size} scheduled entries."
226
+ end
227
+
228
+ description do
229
+ "have schedule size of #{size}"
230
+ end
231
+ end
232
+
233
+ RSpec::Matchers.define :have_schedule_size_of_at_least do |size|
234
+ extend ScheduleQueueHelper
235
+
236
+ match do |actual|
237
+ schedule_queue_for(actual).size >= size
238
+ end
239
+
240
+ failure_message do |actual|
241
+ "expected that #{actual} would have at least #{size} scheduled entries, but got #{schedule_queue_for(actual).size} instead"
242
+ end
243
+
244
+ failure_message_when_negated do |actual|
245
+ "expected that #{actual} would have at least #{size} scheduled entries."
246
+ end
247
+
248
+ description do
249
+ "have schedule size of #{size}"
250
+ end
251
+ end
252
+
253
+
254
+ RSpec::Matchers.define :have_delayed do |method_name|
255
+ extend InQueueHelper
256
+ include InQueueHelper
257
+
258
+ chain :until do |timestamp|
259
+ @when = timestamp.to_i
260
+ end
261
+
262
+ chain :with do |*args|
263
+ @args = args
264
+ end
265
+
266
+ chain :in_lock_namespace do |ns|
267
+ @lock_namespace = ns.to_s
268
+ end
269
+
270
+ chain :with_queue_lock do |lock|
271
+ @queue_lock = lock.to_s
272
+ end
273
+
274
+ chain :with_worker_lock do |lock|
275
+ @worker_lock = lock.to_s
276
+ end
277
+
278
+ match do |class_name|
279
+
280
+ class_name = case class_name
281
+ when Class
282
+ class_name.name
283
+ when String, Symbol
284
+ class_name
285
+ else # instances of objects
286
+ class_name.class.name
287
+ end
288
+
289
+ [@queue_name || ResqueSpec.queues].flatten.compact.each do |queue|
290
+ ResqueSpec.queue_by_name(queue).detect do |entry|
291
+ klass = entry[:class]
292
+ args = entry[:args]
293
+ data = args.first if args.is_a?(Array)
294
+
295
+ matched = data['class_name'] == class_name.to_s
296
+ matched &&= data['method_name'] == method_name.to_s
297
+ matched &&= data['run_at'] == @when if @when
298
+ matched &&= data['args'] == @args if @args
299
+ matched &&= data['lock_namespace'] == @lock_namespace if @lock_namespace
300
+ matched &&= data['queue_lock'] == @queue_lock if @queue_lock
301
+ matched &&= data['worker_lock'] == @worker_lock if @worker_lock
302
+ matched
303
+ end
304
+ end
305
+ end
306
+
307
+ failure_message do |actual|
308
+ "expected that #{method_name} would have been a delayed invocation"
309
+ end
310
+
311
+ failure_message_when_negated do |actual|
312
+ "expected that #{method_name} would not have been delayed"
313
+ end
314
+
315
+ description do
316
+ "#{method_name} should be deplayed"
317
+ end
318
+ end