resque-bus 0.3.7 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
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