resque-bus 0.3.7 → 0.5.7

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 (58) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +2 -2
  3. data/README.mdown +42 -64
  4. data/Rakefile +0 -1
  5. data/lib/resque-bus.rb +13 -305
  6. data/lib/resque_bus/adapter.rb +65 -0
  7. data/lib/resque_bus/compatibility/deprecated.rb +38 -0
  8. data/lib/resque_bus/compatibility/driver.rb +10 -0
  9. data/lib/resque_bus/compatibility/heartbeat.rb +10 -0
  10. data/lib/resque_bus/compatibility/publisher.rb +13 -0
  11. data/lib/resque_bus/compatibility/rider.rb +32 -0
  12. data/lib/resque_bus/compatibility/subscriber.rb +8 -0
  13. data/lib/resque_bus/compatibility/task_manager.rb +8 -0
  14. data/lib/resque_bus/server/views/bus.erb +2 -2
  15. data/lib/resque_bus/server.rb +5 -4
  16. data/lib/resque_bus/tasks.rb +46 -46
  17. data/lib/resque_bus/version.rb +2 -4
  18. data/resque-bus.gemspec +5 -10
  19. data/spec/adapter/compatibility_spec.rb +97 -0
  20. data/spec/adapter/integration_spec.rb +111 -0
  21. data/spec/adapter/publish_at_spec.rb +50 -0
  22. data/spec/adapter/retry_spec.rb +47 -0
  23. data/spec/adapter/support.rb +23 -0
  24. data/spec/adapter_spec.rb +14 -0
  25. data/spec/application_spec.rb +62 -62
  26. data/spec/config_spec.rb +83 -0
  27. data/spec/dispatch_spec.rb +6 -6
  28. data/spec/driver_spec.rb +62 -44
  29. data/spec/heartbeat_spec.rb +4 -4
  30. data/spec/integration_spec.rb +2 -2
  31. data/spec/matcher_spec.rb +29 -29
  32. data/spec/publish_spec.rb +46 -43
  33. data/spec/publisher_spec.rb +7 -0
  34. data/spec/rider_spec.rb +14 -66
  35. data/spec/spec_helper.rb +25 -25
  36. data/spec/subscriber_spec.rb +194 -176
  37. data/spec/subscription_list_spec.rb +1 -1
  38. data/spec/subscription_spec.rb +1 -1
  39. data/spec/worker_spec.rb +32 -0
  40. metadata +47 -58
  41. data/lib/resque_bus/application.rb +0 -115
  42. data/lib/resque_bus/compatibility.rb +0 -24
  43. data/lib/resque_bus/dispatch.rb +0 -61
  44. data/lib/resque_bus/driver.rb +0 -30
  45. data/lib/resque_bus/heartbeat.rb +0 -106
  46. data/lib/resque_bus/local.rb +0 -38
  47. data/lib/resque_bus/matcher.rb +0 -81
  48. data/lib/resque_bus/publisher.rb +0 -12
  49. data/lib/resque_bus/rider.rb +0 -54
  50. data/lib/resque_bus/subscriber.rb +0 -63
  51. data/lib/resque_bus/subscription.rb +0 -55
  52. data/lib/resque_bus/subscription_list.rb +0 -53
  53. data/lib/resque_bus/task_manager.rb +0 -52
  54. data/lib/resque_bus/util.rb +0 -42
  55. data/lib/tasks/resquebus.rake +0 -2
  56. data/spec/compatibility_spec.rb +0 -93
  57. data/spec/publish_at_spec.rb +0 -74
  58. data/spec/redis_spec.rb +0 -13
@@ -1,63 +0,0 @@
1
- module ResqueBus
2
- module Subscriber
3
-
4
- def self.included(base)
5
- base.extend ClassMethods
6
- end
7
-
8
- module ClassMethods
9
-
10
- def application(app_key)
11
- @app_key = ::ResqueBus::Application.normalize(app_key)
12
- end
13
-
14
- def app_key
15
- return @app_key if @app_key
16
- @app_key = ::ResqueBus.default_app_key
17
- return @app_key if @app_key
18
- # module or class_name
19
- val = self.name.to_s.split("::").first
20
- @app_key = ::ResqueBus::Util.underscore(val)
21
- end
22
-
23
- def subscribe(method_name, matcher_hash = nil)
24
- queue_name = ::Resque.queue_from_class(self)
25
- queue_name ||= ::ResqueBus.default_queue
26
- queue_name ||= "#{app_key}_default"
27
- subscribe_queue(queue_name, method_name, matcher_hash)
28
- end
29
-
30
- def subscribe_queue(queue_name, method_name, matcher_hash = nil)
31
- klass = self
32
- matcher_hash ||= {"bus_event_type" => method_name}
33
- sub_key = "#{self.name}.#{method_name}"
34
- dispatcher = ::ResqueBus.dispatcher_by_key(app_key)
35
- dispatcher.add_subscription(queue_name, sub_key, klass.name.to_s, matcher_hash, lambda{ |att| klass.perform(att) })
36
- end
37
-
38
- def transform(method_name)
39
- @transform = method_name
40
- end
41
-
42
- def perform(attributes)
43
- ResqueBus.with_global_attributes(attributes) do
44
- sub_key = attributes["bus_rider_sub_key"]
45
- meth_key = sub_key.split(".").last
46
- resque_bus_execute(meth_key, attributes)
47
- end
48
- end
49
-
50
- def resque_bus_execute(key, attributes)
51
- args = attributes
52
- args = send(@transform, attributes) if @transform
53
- args = [args] unless args.is_a?(Array)
54
- if self.respond_to?(:subscriber_with_attributes)
55
- me = self.subscriber_with_attributes(attributes)
56
- else
57
- me = self.new
58
- end
59
- me.send(key, *args)
60
- end
61
- end
62
- end
63
- end
@@ -1,55 +0,0 @@
1
- module ResqueBus
2
- class Subscription
3
-
4
- class << self
5
- def register(queue, key, class_name, matcher, block)
6
- Subscription.new(queue, key, class_name, matcher, block)
7
- end
8
-
9
- def from_redis(hash)
10
- queue_name = hash["queue_name"].to_s
11
- key = hash["key"].to_s
12
- class_name = hash["class"].to_s
13
- matcher = hash["matcher"]
14
- return nil if key.length == 0 || queue_name.length == 0
15
- Subscription.new(queue_name, key, class_name, matcher, nil)
16
- end
17
-
18
- def normalize(val)
19
- val.to_s.gsub(/\W/, "_").downcase
20
- end
21
- end
22
-
23
- attr_reader :matcher, :executor, :queue_name, :key, :class_name
24
- attr_accessor :app_key # dyanmically set on return from subscription_matches
25
-
26
- def initialize(queue_name, key, class_name, filters, executor=nil)
27
- @queue_name = self.class.normalize(queue_name)
28
- @key = key.to_s
29
- @class_name = class_name.to_s
30
- @matcher = Matcher.new(filters)
31
- @executor = executor
32
- end
33
-
34
- def execute!(attributes)
35
- attributes = attributes.with_indifferent_access if attributes.respond_to?(:with_indifferent_access)
36
- ResqueBus.with_global_attributes(attributes) do
37
- executor.call(attributes)
38
- end
39
- end
40
-
41
- def matches?(attributes)
42
- @matcher.matches?(attributes)
43
- end
44
-
45
- def to_redis
46
- out = {}
47
- out["queue_name"] = queue_name
48
- out["key"] = key
49
- out["class"] = class_name
50
- out["matcher"] = matcher.to_redis
51
- out
52
- end
53
-
54
- end
55
- end
@@ -1,53 +0,0 @@
1
- module ResqueBus
2
- class SubscriptionList
3
-
4
- class << self
5
- def from_redis(redis_hash)
6
- out = SubscriptionList.new
7
-
8
- redis_hash.each do |key, value|
9
- sub = Subscription.from_redis(value)
10
- out.add(sub) if sub
11
- end
12
-
13
- out
14
- end
15
- end
16
-
17
- def to_redis
18
- out = {}
19
- @subscriptions.values.each do |sub|
20
- out[sub.key] = sub.to_redis
21
- end
22
- out
23
- end
24
-
25
- def initialize
26
- @subscriptions = {}
27
- end
28
-
29
- def add(sub)
30
- @subscriptions[sub.key] = sub
31
- end
32
-
33
- def size
34
- @subscriptions.size
35
- end
36
-
37
- def key(key)
38
- @subscriptions[key.to_s]
39
- end
40
-
41
- def all
42
- @subscriptions.values
43
- end
44
-
45
- def matches(attributes)
46
- out = []
47
- all.each do |sub|
48
- out << sub if sub.matches?(attributes)
49
- end
50
- out
51
- end
52
- end
53
- end
@@ -1,52 +0,0 @@
1
- module ResqueBus
2
- class TaskManager
3
-
4
- attr_reader :logging
5
-
6
- def initialize(logging)
7
- @logging = logging
8
- end
9
-
10
- def subscribe!
11
- count = 0
12
- ResqueBus.dispatchers.each do |dispatcher|
13
- subscriptions = dispatcher.subscriptions
14
- if subscriptions.size > 0
15
- count += subscriptions.size
16
- log "Subscribing #{dispatcher.app_key} to #{subscriptions.size} subscriptions"
17
- app = ResqueBus::Application.new(dispatcher.app_key)
18
- app.subscribe(subscriptions, logging)
19
- log " ...done"
20
- end
21
- end
22
- count
23
- end
24
-
25
- def unsubscribe!
26
- count = 0
27
- ResqueBus.dispatchers.each do |dispatcher|
28
- log "Unsubcribing from #{dispatcher.app_key}"
29
- app = ResqueBus::Application.new(dispatcher.app_key)
30
- app.unsubscribe
31
- count += 1
32
- log " ...done"
33
- end
34
- end
35
-
36
- def queue_names
37
- # let's not talk to redis in here. Seems to screw things up
38
- queues = []
39
- ResqueBus.dispatchers.each do |dispatcher|
40
- dispatcher.subscriptions.all.each do |sub|
41
- queues << sub.queue_name
42
- end
43
- end
44
-
45
- queues.uniq
46
- end
47
-
48
- def log(message)
49
- puts(message) if logging
50
- end
51
- end
52
- end
@@ -1,42 +0,0 @@
1
- module ResqueBus
2
- module Util
3
- extend self
4
-
5
- def underscore(camel_cased_word)
6
- word = camel_cased_word.to_s.dup
7
- word.gsub!('::', '/')
8
- # word.gsub!(/(?:([A-Za-z\d])|^)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
9
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
10
- word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
11
- word.tr!("-", "_")
12
- word.downcase!
13
- word
14
- end
15
-
16
- def constantize(camel_cased_word)
17
- names = camel_cased_word.split('::')
18
- names.shift if names.empty? || names.first.empty?
19
-
20
- names.inject(Object) do |constant, name|
21
- if constant == Object
22
- constant.const_get(name)
23
- else
24
- candidate = constant.const_get(name)
25
- next candidate if constant.const_defined?(name, false)
26
- next candidate unless Object.const_defined?(name)
27
-
28
- # Go down the ancestors to check it it's owned
29
- # directly before we reach Object or the end of ancestors.
30
- constant = constant.ancestors.inject do |const, ancestor|
31
- break const if ancestor == Object
32
- break ancestor if ancestor.const_defined?(name, false)
33
- const
34
- end
35
-
36
- # owner is in Object, so raise
37
- constant.const_get(name, false)
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,2 +0,0 @@
1
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
2
- require 'resque_bus/tasks'
@@ -1,93 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "migration compatibility" do
4
- before(:each) do
5
- ResqueBus.dispatch("r1") do
6
- subscribe "event_name" do |attributes|
7
- ResqueBus::Runner1.run(attributes)
8
- end
9
- end
10
-
11
- ResqueBus::TaskManager.new(false).subscribe!
12
-
13
- @incoming = Resque::Worker.new(:resquebus_incoming)
14
- @incoming.register_worker
15
-
16
- @new_incoming = Resque::Worker.new(:bus_incoming)
17
- @new_incoming.register_worker
18
-
19
- @rider = Resque::Worker.new(:r1_default)
20
- @rider.register_worker
21
- end
22
-
23
- it "should still drive as expected" do
24
- val = ResqueBus.redis.lpop("queue:bus_incoming")
25
- val.should == nil
26
-
27
- args = [ JSON.generate({"bus_class_proxy"=>"QueueBus::Driver", "bus_event_type" => "event_name", "two"=>"here", "one"=>1, "id" => 12}) ]
28
- item = {:class => "QueueBus::Worker", :args => args}
29
-
30
- ResqueBus.redis.sadd(:queues, "bus_incoming")
31
- ResqueBus.redis.rpush "queue:bus_incoming", Resque.encode(item)
32
-
33
- ResqueBus::Runner1.value.should == 0
34
-
35
- perform_next_job @new_incoming
36
-
37
- ResqueBus::Runner1.value.should == 0
38
-
39
- perform_next_job @rider
40
-
41
- ResqueBus::Runner1.value.should == 1
42
- end
43
-
44
- it "should still ride as expected" do
45
- val = ResqueBus.redis.lpop("queue:r1_default")
46
- val.should == nil
47
-
48
- args = [ {"bus_rider_app_key"=>"r1", "x" => "y", "bus_event_type" => "event_name",
49
- "bus_rider_sub_key"=>"event_name", "bus_rider_queue" => "default",
50
- "bus_rider_class_name"=>"::ResqueBus::Rider"}]
51
- item = {:class => "ResqueBus::Rider", :args => args}
52
-
53
- args = [ JSON.generate({"bus_class_proxy"=>"QueueBus::Rider","bus_rider_app_key"=>"r1", "x" => "y",
54
- "bus_event_type" => "event_name", "bus_rider_sub_key"=>"event_name",
55
- "bus_rider_queue" => "default"}) ]
56
- item = {:class => "QueueBus::Worker", :args => args}
57
-
58
- ResqueBus.redis.sadd(:queues, "r1_default")
59
- ResqueBus.redis.rpush "queue:r1_default", Resque.encode(item)
60
-
61
- ResqueBus::Runner1.value.should == 0
62
-
63
- perform_next_job @rider
64
-
65
- ResqueBus::Runner1.value.should == 1
66
- end
67
-
68
- it "should still publish as expected" do
69
- val = ResqueBus.redis.lpop("queue:bus_incoming")
70
- val.should == nil
71
-
72
- args = [ JSON.generate({"bus_class_proxy" => "QueueBus::Publisher", "bus_event_type"=>"event_name", "two"=>"here", "one"=>1, "id" => 12}) ]
73
- item = {:class => "QueueBus::Worker", :args => args}
74
-
75
- ResqueBus.redis.sadd(:queues, "bus_incoming")
76
- ResqueBus.redis.rpush "queue:bus_incoming", Resque.encode(item)
77
-
78
- ResqueBus::Runner1.value.should == 0
79
-
80
- perform_next_job @new_incoming # publish
81
-
82
- ResqueBus::Runner1.value.should == 0
83
-
84
- perform_next_job @incoming # drive
85
-
86
- ResqueBus::Runner1.value.should == 0
87
-
88
- perform_next_job @rider # ride
89
-
90
- ResqueBus::Runner1.value.should == 1
91
-
92
- end
93
- end
@@ -1,74 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Publishing an event in the future" do
4
-
5
- before(:each) do
6
- Timecop.freeze(now)
7
- ResqueBus.stub(:generate_uuid).and_return("idfhlkj")
8
- end
9
- after(:each) do
10
- Timecop.return
11
- end
12
- let(:delayed_attrs) { {"bus_delayed_until" => future.to_i,
13
- "bus_id" => "#{now.to_i}-idfhlkj",
14
- "bus_app_hostname" => `hostname 2>&1`.strip.sub(/.local/,'')} }
15
-
16
- let(:bus_attrs) { delayed_attrs.merge({"bus_published_at" => worktime.to_i})}
17
- let(:now) { Time.parse("01/01/2013 5:00")}
18
- let(:future) { Time.at(now.to_i + 60) }
19
- let(:worktime) {Time.at(future.to_i + 1)}
20
-
21
- it "should add it to Redis" do
22
- hash = {:one => 1, "two" => "here", "id" => 12 }
23
- event_name = "event_name"
24
- ResqueBus.publish_at(future, event_name, hash)
25
-
26
- schedule = ResqueBus.redis.zrange("delayed_queue_schedule", 0, 1)
27
- schedule.should == [future.to_i.to_s]
28
-
29
- val = ResqueBus.redis.lpop("delayed:#{future.to_i}")
30
- hash = JSON.parse(val)
31
-
32
- hash["class"].should == "ResqueBus::Publisher"
33
- hash["args"].should == [ "event_name", {"bus_event_type"=>"event_name", "two"=>"here", "one"=>1, "id" => 12}.merge(delayed_attrs) ]
34
- hash["queue"].should == "resquebus_incoming"
35
- end
36
-
37
- it "should move it to the real queue when processing" do
38
- hash = {:one => 1, "two" => "here", "id" => 12 }
39
- event_name = "event_name"
40
-
41
- val = ResqueBus.redis.lpop("queue:resquebus_incoming")
42
- val.should == nil
43
-
44
- ResqueBus.publish_at(future, event_name, hash)
45
-
46
- val = ResqueBus.redis.lpop("queue:resquebus_incoming")
47
- val.should == nil # nothing really added
48
-
49
- # process sceduler now
50
- Resque::Scheduler.handle_delayed_items
51
-
52
- val = ResqueBus.redis.lpop("queue:resquebus_incoming")
53
- val.should == nil # nothing added yet
54
-
55
- # process scheduler in future
56
- Timecop.freeze(worktime) do
57
- Resque::Scheduler.handle_delayed_items
58
-
59
- # added
60
- val = ResqueBus.redis.lpop("queue:resquebus_incoming")
61
- hash = JSON.parse(val)
62
- hash["class"].should == "ResqueBus::Publisher"
63
- hash["args"].should == [ "event_name", {"bus_event_type"=>"event_name", "two"=>"here", "one"=>1, "id" => 12}.merge(delayed_attrs) ]
64
-
65
- ResqueBus::Publisher.perform(*hash["args"])
66
-
67
- val = ResqueBus.redis.lpop("queue:resquebus_incoming")
68
- hash = JSON.parse(val)
69
- hash["class"].should == "ResqueBus::Driver"
70
- hash["args"].should == [ {"bus_event_type"=>"event_name", "two"=>"here", "one"=>1, "id" => 12}.merge(bus_attrs) ]
71
- end
72
- end
73
-
74
- end
data/spec/redis_spec.rb DELETED
@@ -1,13 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Redis Connection" do
4
- it "should use the one specified if given" do
5
- ResqueBus.redis = "localhost:9379"
6
- ResqueBus.redis.instance_variable_get("@redis").client.port.should == 9379
7
- Resque.redis.instance_variable_get("@redis").client.port.should == 6379
8
- end
9
- it "should use the default Resque connection if none specified" do
10
- ResqueBus.redis.instance_variable_get("@redis").client.port.should == 6379
11
- Resque.redis.instance_variable_get("@redis").client.port.should == 6379
12
- end
13
- end