tresque 0.0.2

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.
@@ -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