promiscuous 0.53.1 → 0.90.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/lib/promiscuous.rb +25 -28
  2. data/lib/promiscuous/amqp.rb +27 -8
  3. data/lib/promiscuous/amqp/bunny.rb +131 -16
  4. data/lib/promiscuous/amqp/fake.rb +52 -0
  5. data/lib/promiscuous/amqp/hot_bunnies.rb +56 -0
  6. data/lib/promiscuous/amqp/null.rb +6 -6
  7. data/lib/promiscuous/cli.rb +108 -24
  8. data/lib/promiscuous/config.rb +73 -12
  9. data/lib/promiscuous/convenience.rb +18 -0
  10. data/lib/promiscuous/dependency.rb +59 -0
  11. data/lib/promiscuous/dsl.rb +36 -0
  12. data/lib/promiscuous/error.rb +3 -1
  13. data/lib/promiscuous/error/already_processed.rb +5 -0
  14. data/lib/promiscuous/error/base.rb +1 -0
  15. data/lib/promiscuous/error/connection.rb +7 -5
  16. data/lib/promiscuous/error/dependency.rb +111 -0
  17. data/lib/promiscuous/error/lock_unavailable.rb +12 -0
  18. data/lib/promiscuous/error/lost_lock.rb +12 -0
  19. data/lib/promiscuous/error/missing_context.rb +29 -0
  20. data/lib/promiscuous/error/publisher.rb +5 -15
  21. data/lib/promiscuous/error/recovery.rb +7 -0
  22. data/lib/promiscuous/error/subscriber.rb +2 -4
  23. data/lib/promiscuous/key.rb +36 -0
  24. data/lib/promiscuous/loader.rb +12 -16
  25. data/lib/promiscuous/middleware.rb +112 -0
  26. data/lib/promiscuous/publisher.rb +7 -4
  27. data/lib/promiscuous/publisher/context.rb +92 -0
  28. data/lib/promiscuous/publisher/mock_generator.rb +72 -0
  29. data/lib/promiscuous/publisher/model.rb +3 -86
  30. data/lib/promiscuous/publisher/model/active_record.rb +8 -15
  31. data/lib/promiscuous/publisher/model/base.rb +136 -0
  32. data/lib/promiscuous/publisher/model/ephemeral.rb +69 -0
  33. data/lib/promiscuous/publisher/model/mock.rb +61 -0
  34. data/lib/promiscuous/publisher/model/mongoid.rb +57 -100
  35. data/lib/promiscuous/{common/lint.rb → publisher/operation.rb} +1 -1
  36. data/lib/promiscuous/publisher/operation/base.rb +707 -0
  37. data/lib/promiscuous/publisher/operation/mongoid.rb +370 -0
  38. data/lib/promiscuous/publisher/worker.rb +22 -0
  39. data/lib/promiscuous/railtie.rb +21 -3
  40. data/lib/promiscuous/redis.rb +132 -40
  41. data/lib/promiscuous/resque.rb +12 -0
  42. data/lib/promiscuous/sidekiq.rb +15 -0
  43. data/lib/promiscuous/subscriber.rb +9 -20
  44. data/lib/promiscuous/subscriber/model.rb +4 -104
  45. data/lib/promiscuous/subscriber/model/active_record.rb +10 -0
  46. data/lib/promiscuous/subscriber/model/base.rb +96 -0
  47. data/lib/promiscuous/subscriber/model/mongoid.rb +86 -0
  48. data/lib/promiscuous/subscriber/model/observer.rb +37 -0
  49. data/lib/promiscuous/subscriber/operation.rb +167 -0
  50. data/lib/promiscuous/subscriber/payload.rb +34 -0
  51. data/lib/promiscuous/subscriber/worker.rb +22 -18
  52. data/lib/promiscuous/subscriber/worker/message.rb +48 -25
  53. data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +273 -181
  54. data/lib/promiscuous/subscriber/worker/pump.rb +17 -43
  55. data/lib/promiscuous/subscriber/worker/recorder.rb +24 -0
  56. data/lib/promiscuous/subscriber/worker/runner.rb +24 -3
  57. data/lib/promiscuous/subscriber/worker/stats.rb +62 -0
  58. data/lib/promiscuous/timer.rb +38 -0
  59. data/lib/promiscuous/version.rb +1 -1
  60. metadata +98 -143
  61. data/README.md +0 -33
  62. data/lib/promiscuous/amqp/ruby_amqp.rb +0 -140
  63. data/lib/promiscuous/common.rb +0 -4
  64. data/lib/promiscuous/common/class_helpers.rb +0 -12
  65. data/lib/promiscuous/common/lint/base.rb +0 -24
  66. data/lib/promiscuous/common/options.rb +0 -51
  67. data/lib/promiscuous/ephemeral.rb +0 -14
  68. data/lib/promiscuous/error/recover.rb +0 -1
  69. data/lib/promiscuous/observer.rb +0 -5
  70. data/lib/promiscuous/publisher/active_record.rb +0 -7
  71. data/lib/promiscuous/publisher/amqp.rb +0 -18
  72. data/lib/promiscuous/publisher/attributes.rb +0 -32
  73. data/lib/promiscuous/publisher/base.rb +0 -23
  74. data/lib/promiscuous/publisher/class.rb +0 -36
  75. data/lib/promiscuous/publisher/envelope.rb +0 -7
  76. data/lib/promiscuous/publisher/ephemeral.rb +0 -9
  77. data/lib/promiscuous/publisher/lint.rb +0 -35
  78. data/lib/promiscuous/publisher/lint/amqp.rb +0 -14
  79. data/lib/promiscuous/publisher/lint/attributes.rb +0 -12
  80. data/lib/promiscuous/publisher/lint/base.rb +0 -5
  81. data/lib/promiscuous/publisher/lint/class.rb +0 -15
  82. data/lib/promiscuous/publisher/lint/polymorphic.rb +0 -22
  83. data/lib/promiscuous/publisher/mock.rb +0 -79
  84. data/lib/promiscuous/publisher/mongoid.rb +0 -33
  85. data/lib/promiscuous/publisher/mongoid/embedded.rb +0 -27
  86. data/lib/promiscuous/publisher/mongoid/embedded_many.rb +0 -12
  87. data/lib/promiscuous/publisher/polymorphic.rb +0 -8
  88. data/lib/promiscuous/subscriber/active_record.rb +0 -11
  89. data/lib/promiscuous/subscriber/amqp.rb +0 -25
  90. data/lib/promiscuous/subscriber/attributes.rb +0 -35
  91. data/lib/promiscuous/subscriber/base.rb +0 -29
  92. data/lib/promiscuous/subscriber/class.rb +0 -29
  93. data/lib/promiscuous/subscriber/dummy.rb +0 -19
  94. data/lib/promiscuous/subscriber/envelope.rb +0 -18
  95. data/lib/promiscuous/subscriber/lint.rb +0 -30
  96. data/lib/promiscuous/subscriber/lint/amqp.rb +0 -21
  97. data/lib/promiscuous/subscriber/lint/attributes.rb +0 -21
  98. data/lib/promiscuous/subscriber/lint/base.rb +0 -14
  99. data/lib/promiscuous/subscriber/lint/class.rb +0 -13
  100. data/lib/promiscuous/subscriber/lint/polymorphic.rb +0 -39
  101. data/lib/promiscuous/subscriber/mongoid.rb +0 -27
  102. data/lib/promiscuous/subscriber/mongoid/embedded.rb +0 -17
  103. data/lib/promiscuous/subscriber/mongoid/embedded_many.rb +0 -44
  104. data/lib/promiscuous/subscriber/observer.rb +0 -26
  105. data/lib/promiscuous/subscriber/polymorphic.rb +0 -36
  106. data/lib/promiscuous/subscriber/upsert.rb +0 -12
@@ -1,35 +0,0 @@
1
- module Promiscuous::Publisher::Lint
2
- extend Promiscuous::Autoload
3
- autoload :Base, :Class, :Attributes, :Polymorphic, :AMQP
4
-
5
- def self.get_publisher(klass)
6
- unless klass.respond_to?(:promiscuous_publisher)
7
- raise "#{klass} has no publisher"
8
- end
9
-
10
- klass.promiscuous_publisher
11
- end
12
-
13
- def self.lint(class_bindings={})
14
- if class_bindings.empty?
15
- class_bindings = Promiscuous::Publisher::Model.klasses.reduce({}) do |res, klass|
16
- res[klass] = klass.promiscuous_publisher.to
17
- res
18
- end
19
-
20
- raise "No publishers found" if class_bindings.empty?
21
- end
22
-
23
- class_bindings.each do |klass, to|
24
- pub = get_publisher(klass)
25
-
26
- lint = ::Class.new(Base)
27
- lint.__send__(:include, Class) if pub.include?(Promiscuous::Publisher::Class)
28
- lint.__send__(:include, Attributes) if pub.include?(Promiscuous::Publisher::Attributes)
29
- lint.__send__(:include, AMQP) if pub.include?(Promiscuous::Publisher::AMQP)
30
- lint.__send__(:include, Polymorphic) if pub.include?(Promiscuous::Publisher::Polymorphic)
31
- lint.new(:klass => klass, :publisher => pub, :to => to).lint
32
- end
33
- true
34
- end
35
- end
@@ -1,14 +0,0 @@
1
- module Promiscuous::Publisher::Lint::AMQP
2
- extend ActiveSupport::Concern
3
-
4
- def lint
5
- super
6
-
7
- pub_to = publisher.to
8
- if pub_to != to
9
- raise "#{publisher} publishes #{klass} to #{pub_to} instead of #{to}"
10
- end
11
- end
12
-
13
- included { use_option :to }
14
- end
@@ -1,12 +0,0 @@
1
- module Promiscuous::Publisher::Lint::Attributes
2
- extend ActiveSupport::Concern
3
-
4
- def lint
5
- super
6
-
7
- instance = klass.new
8
- publisher.attributes.each do |attr|
9
- instance.respond_to?(attr) or instance.__send__(attr)
10
- end
11
- end
12
- end
@@ -1,5 +0,0 @@
1
- class Promiscuous::Publisher::Lint::Base
2
- include Promiscuous::Common::Lint::Base
3
-
4
- use_option(:publisher)
5
- end
@@ -1,15 +0,0 @@
1
- module Promiscuous::Publisher::Lint::Class
2
- extend ActiveSupport::Concern
3
-
4
- def lint
5
- super
6
-
7
- if publisher.klass != klass
8
- msg = "Please define a publisher for #{klass}"
9
- msg = "#{msg} because #{parent} is published and you need to cover subclasses" if parent
10
- raise msg
11
- end
12
- end
13
-
14
- included { use_option :klass, :parent }
15
- end
@@ -1,22 +0,0 @@
1
- module Promiscuous::Publisher::Lint::Polymorphic
2
- extend ActiveSupport::Concern
3
-
4
- def lint
5
- super
6
-
7
- unless skip_polymorphic
8
- klass.descendants.each do |subclass|
9
- pub = Promiscuous::Publisher::Lint.get_publisher(subclass)
10
- self.class.new(options.merge(:klass => subclass,
11
- :publisher => pub,
12
- :parent => klass,
13
- :skip_polymorphic => true)).lint
14
- end
15
- end
16
- end
17
-
18
- included do
19
- use_option :klass
20
- use_option :skip_polymorphic
21
- end
22
- end
@@ -1,79 +0,0 @@
1
- class Promiscuous::Publisher::Mock
2
- include Promiscuous::Common::ClassHelpers
3
-
4
- def self.publish(options)
5
- if defined?(attributes)
6
- if options[:attributes]
7
- raise "Do not specify the 'to' field in childrens" if options[:to]
8
- self.attributes = self.attributes + options[:attributes]
9
- end
10
- else
11
- class_attribute :to, :attributes, :klass
12
-
13
- self.to = options[:to]
14
- self.klass = options[:class]
15
- self.attributes = options[:attributes].to_a
16
-
17
- attr_accessor :id, :new_record
18
- end
19
- attr_accessor *attributes
20
-
21
- associations = attributes.map { |attr| $1 if attr =~ /^(.*)_id$/ }.compact
22
- associations.each do |attr|
23
- attr_accessor attr
24
- define_method("#{attr}=") do |value|
25
- instance_variable_set("@#{attr}", value)
26
- instance_variable_set("@#{attr}_id", value.nil? ? value : value.id)
27
- end
28
- end
29
- end
30
-
31
- def self.class_name
32
- self.klass ? self.klass : guess_class_name('Publishers')
33
- end
34
-
35
- def initialize
36
- self.id = BSON::ObjectId.new
37
- self.new_record = true
38
- end
39
-
40
- def save
41
- if payload['__amqp__'].in? Promiscuous::Subscriber::AMQP.subscribers.keys
42
- Promiscuous::Subscriber.process(JSON.parse(payload.to_json))
43
- end
44
- self.new_record = false
45
- true
46
- end
47
- alias :save! :save
48
-
49
- def update_attributes(attrs)
50
- attrs.each { |attr, value| __send__("#{attr}=", value) }
51
- save
52
- end
53
- alias :update_attributes! :update_attributes
54
-
55
- def payload
56
- {
57
- '__amqp__' => self.class.to,
58
- 'id' => self.id,
59
- 'type' => self.class.class_name,
60
- 'operation' => self.new_record ? 'create' : 'update',
61
- 'payload' => Hash[self.class.attributes.map { |attr| [attr.to_s, payload_for(attr)] }]
62
- }
63
- end
64
-
65
- def payload_for(attr)
66
- value = __send__(attr)
67
- value = value.payload if value.is_a?(Promiscuous::Publisher::Mock)
68
- value
69
- end
70
-
71
- def destroy
72
- Promiscuous::Subscriber.process(
73
- '__amqp__' => self.class.to,
74
- 'id' => self.id,
75
- 'type' => self.class.class_name,
76
- 'operation' => 'destroy'
77
- )
78
- end
79
- end
@@ -1,33 +0,0 @@
1
- class Promiscuous::Publisher::Mongoid < Promiscuous::Publisher::Base
2
- extend Promiscuous::Autoload
3
- autoload :Embedded, :EmbeddedMany
4
-
5
- include Promiscuous::Publisher::Class
6
- include Promiscuous::Publisher::Attributes
7
- include Promiscuous::Publisher::Polymorphic
8
- include Promiscuous::Publisher::AMQP
9
-
10
- def self.publish(options)
11
- check_mongoid_version
12
- super
13
-
14
- if klass.embedded?
15
- include Promiscuous::Publisher::Mongoid::Embedded
16
- else
17
- include Promiscuous::Publisher::Model
18
- include Promiscuous::Publisher::Model::Mongoid
19
- end
20
-
21
- setup_class_binding
22
- end
23
-
24
- def self.check_mongoid_version
25
- unless Gem.loaded_specs['mongoid'].version >= Gem::Version.new('3.0.19')
26
- raise "mongoid > 3.0.19 please"
27
- end
28
-
29
- unless Gem.loaded_specs['moped'].version >= Gem::Version.new('1.3.2')
30
- raise "moped > 1.3.2 please"
31
- end
32
- end
33
- end
@@ -1,27 +0,0 @@
1
- module Promiscuous::Publisher::Mongoid::Embedded
2
- extend ActiveSupport::Concern
3
-
4
- def payload
5
- if instance.is_a?(Array)
6
- Promiscuous::Publisher::Mongoid::EmbeddedMany.new(:instance => instance).payload
7
- else
8
- super.merge(:id => instance.id)
9
- end
10
- end
11
-
12
- included do
13
- klass.class_eval do
14
- callback = proc do
15
- if _parent.respond_to?(:with_promiscuous)
16
- _parent.save
17
- # XXX FIXME mongoid needs help, and we need to deal with that.
18
- # We'll address that once we hook on moped
19
- end
20
- end
21
-
22
- after_create callback
23
- after_update callback
24
- after_destroy callback
25
- end
26
- end
27
- end
@@ -1,12 +0,0 @@
1
- class Promiscuous::Publisher::Mongoid::EmbeddedMany < Promiscuous::Publisher::Base
2
- module Payload
3
- def payload
4
- instance.map { |e| e.class.promiscuous_publisher.new(:instance => e).payload }
5
- end
6
- end
7
- include Payload
8
-
9
- include Promiscuous::Publisher::AMQP
10
-
11
- publish :to => '__promiscuous__/embedded_many'
12
- end
@@ -1,8 +0,0 @@
1
- module Promiscuous::Publisher::Polymorphic
2
- extend ActiveSupport::Concern
3
- include Promiscuous::Publisher::Envelope
4
-
5
- def payload
6
- super.merge(:type => instance.class.to_s)
7
- end
8
- end
@@ -1,11 +0,0 @@
1
- class Promiscuous::Subscriber::ActiveRecord < Promiscuous::Subscriber::Base
2
- include Promiscuous::Subscriber::Class
3
- include Promiscuous::Subscriber::Attributes
4
- include Promiscuous::Subscriber::AMQP
5
- include Promiscuous::Subscriber::Model
6
- include Promiscuous::Subscriber::Upsert
7
-
8
- def self.missing_record_exception
9
- ActiveRecord::RecordNotFound
10
- end
11
- end
@@ -1,25 +0,0 @@
1
- module Promiscuous::Subscriber::AMQP
2
- extend ActiveSupport::Concern
3
- include Promiscuous::Subscriber::Envelope
4
-
5
- mattr_accessor :subscribers
6
- self.subscribers = {}
7
-
8
- def self.subscriber_from(payload)
9
- if key = payload.is_a?(Hash) ? payload['__amqp__'] : nil
10
- sub = self.subscribers[key]
11
- sub ||= Promiscuous::Subscriber::Dummy
12
- end
13
- end
14
-
15
- included { use_option :from }
16
-
17
- module ClassMethods
18
- def from=(_)
19
- super
20
- old_sub = Promiscuous::Subscriber::AMQP.subscribers[from]
21
- raise "The subscriber '#{old_sub}' already listen on '#{from}'" if old_sub
22
- Promiscuous::Subscriber::AMQP.subscribers[from] = self
23
- end
24
- end
25
- end
@@ -1,35 +0,0 @@
1
- module Promiscuous::Subscriber::Attributes
2
- extend ActiveSupport::Concern
3
-
4
- def process
5
- super
6
- return unless process_attributes?
7
-
8
- self.class.attributes.each do |attr|
9
- attr = attr.to_s
10
- unless payload.has_key?(attr)
11
- raise "Attribute '#{attr}' is missing from the payload"
12
- end
13
-
14
- options = {}
15
- options[:parent] = instance
16
- options[:old_value] = instance.__send__(attr) if instance.respond_to?(attr)
17
- sub = Promiscuous::Subscriber.subscriber_for(payload[attr], options)
18
-
19
- sub.process
20
- instance.__send__("#{attr}=", sub.instance) if sub.should_update_parent?
21
- end
22
- end
23
-
24
- def process_attributes?
25
- true
26
- end
27
-
28
- included { use_option :attributes }
29
-
30
- module ClassMethods
31
- def attributes=(value)
32
- super(superclass.attributes.to_a + value)
33
- end
34
- end
35
- end
@@ -1,29 +0,0 @@
1
- class Promiscuous::Subscriber::Base
2
- include Promiscuous::Common::Options
3
-
4
- attr_accessor :options
5
-
6
- def initialize(options)
7
- self.options = options
8
- end
9
-
10
- def payload
11
- options[:payload]
12
- end
13
- alias :instance :payload
14
-
15
- def process
16
- end
17
-
18
- def should_update_parent?
19
- true
20
- end
21
-
22
- def subscribe_options
23
- self.class.options
24
- end
25
-
26
- def self.subscribe(options)
27
- load_options(options)
28
- end
29
- end
@@ -1,29 +0,0 @@
1
- module Promiscuous::Subscriber::Class
2
- extend ActiveSupport::Concern
3
- include Promiscuous::Common::ClassHelpers
4
-
5
- def instance
6
- @instance ||= fetch
7
- end
8
-
9
- included { use_option :class, :as => :klass }
10
-
11
- module ClassMethods
12
- def setup_class_binding; end
13
-
14
- def self.subscribe(options)
15
- super
16
- setup_class_binding
17
- end
18
-
19
- def klass=(value)
20
- super
21
- setup_class_binding
22
- end
23
-
24
- def klass
25
- return nil if name.nil?
26
- "::#{super ? super : guess_class_name('Subscribers')}".constantize
27
- end
28
- end
29
- end
@@ -1,19 +0,0 @@
1
- class Promiscuous::Subscriber::Dummy < Promiscuous::Subscriber::Base
2
- include Promiscuous::Subscriber::Class
3
- include Promiscuous::Subscriber::Attributes
4
- include Promiscuous::Subscriber::AMQP
5
- include Promiscuous::Subscriber::Envelope
6
- include Promiscuous::Subscriber::Model
7
-
8
- class DummyInstance
9
- attr_accessor :id
10
- end
11
-
12
- def klass
13
- DummyInstance
14
- end
15
-
16
- def operation
17
- :dummy
18
- end
19
- end
@@ -1,18 +0,0 @@
1
- module Promiscuous::Subscriber::Envelope
2
- extend ActiveSupport::Concern
3
-
4
- module ClassMethods
5
- def use_payload_attribute(attr, options={})
6
- define_method(attr) do
7
- value = payload_with_envelope[attr.to_s]
8
- value = value.to_sym if options[:symbolize]
9
- value
10
- end
11
- end
12
- end
13
-
14
- included do
15
- alias_method :payload_with_envelope, :payload
16
- use_payload_attribute :payload
17
- end
18
- end