promiscuous 0.53.1 → 0.90.0
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.
- data/lib/promiscuous.rb +25 -28
- data/lib/promiscuous/amqp.rb +27 -8
- data/lib/promiscuous/amqp/bunny.rb +131 -16
- data/lib/promiscuous/amqp/fake.rb +52 -0
- data/lib/promiscuous/amqp/hot_bunnies.rb +56 -0
- data/lib/promiscuous/amqp/null.rb +6 -6
- data/lib/promiscuous/cli.rb +108 -24
- data/lib/promiscuous/config.rb +73 -12
- data/lib/promiscuous/convenience.rb +18 -0
- data/lib/promiscuous/dependency.rb +59 -0
- data/lib/promiscuous/dsl.rb +36 -0
- data/lib/promiscuous/error.rb +3 -1
- data/lib/promiscuous/error/already_processed.rb +5 -0
- data/lib/promiscuous/error/base.rb +1 -0
- data/lib/promiscuous/error/connection.rb +7 -5
- data/lib/promiscuous/error/dependency.rb +111 -0
- data/lib/promiscuous/error/lock_unavailable.rb +12 -0
- data/lib/promiscuous/error/lost_lock.rb +12 -0
- data/lib/promiscuous/error/missing_context.rb +29 -0
- data/lib/promiscuous/error/publisher.rb +5 -15
- data/lib/promiscuous/error/recovery.rb +7 -0
- data/lib/promiscuous/error/subscriber.rb +2 -4
- data/lib/promiscuous/key.rb +36 -0
- data/lib/promiscuous/loader.rb +12 -16
- data/lib/promiscuous/middleware.rb +112 -0
- data/lib/promiscuous/publisher.rb +7 -4
- data/lib/promiscuous/publisher/context.rb +92 -0
- data/lib/promiscuous/publisher/mock_generator.rb +72 -0
- data/lib/promiscuous/publisher/model.rb +3 -86
- data/lib/promiscuous/publisher/model/active_record.rb +8 -15
- data/lib/promiscuous/publisher/model/base.rb +136 -0
- data/lib/promiscuous/publisher/model/ephemeral.rb +69 -0
- data/lib/promiscuous/publisher/model/mock.rb +61 -0
- data/lib/promiscuous/publisher/model/mongoid.rb +57 -100
- data/lib/promiscuous/{common/lint.rb → publisher/operation.rb} +1 -1
- data/lib/promiscuous/publisher/operation/base.rb +707 -0
- data/lib/promiscuous/publisher/operation/mongoid.rb +370 -0
- data/lib/promiscuous/publisher/worker.rb +22 -0
- data/lib/promiscuous/railtie.rb +21 -3
- data/lib/promiscuous/redis.rb +132 -40
- data/lib/promiscuous/resque.rb +12 -0
- data/lib/promiscuous/sidekiq.rb +15 -0
- data/lib/promiscuous/subscriber.rb +9 -20
- data/lib/promiscuous/subscriber/model.rb +4 -104
- data/lib/promiscuous/subscriber/model/active_record.rb +10 -0
- data/lib/promiscuous/subscriber/model/base.rb +96 -0
- data/lib/promiscuous/subscriber/model/mongoid.rb +86 -0
- data/lib/promiscuous/subscriber/model/observer.rb +37 -0
- data/lib/promiscuous/subscriber/operation.rb +167 -0
- data/lib/promiscuous/subscriber/payload.rb +34 -0
- data/lib/promiscuous/subscriber/worker.rb +22 -18
- data/lib/promiscuous/subscriber/worker/message.rb +48 -25
- data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +273 -181
- data/lib/promiscuous/subscriber/worker/pump.rb +17 -43
- data/lib/promiscuous/subscriber/worker/recorder.rb +24 -0
- data/lib/promiscuous/subscriber/worker/runner.rb +24 -3
- data/lib/promiscuous/subscriber/worker/stats.rb +62 -0
- data/lib/promiscuous/timer.rb +38 -0
- data/lib/promiscuous/version.rb +1 -1
- metadata +98 -143
- data/README.md +0 -33
- data/lib/promiscuous/amqp/ruby_amqp.rb +0 -140
- data/lib/promiscuous/common.rb +0 -4
- data/lib/promiscuous/common/class_helpers.rb +0 -12
- data/lib/promiscuous/common/lint/base.rb +0 -24
- data/lib/promiscuous/common/options.rb +0 -51
- data/lib/promiscuous/ephemeral.rb +0 -14
- data/lib/promiscuous/error/recover.rb +0 -1
- data/lib/promiscuous/observer.rb +0 -5
- data/lib/promiscuous/publisher/active_record.rb +0 -7
- data/lib/promiscuous/publisher/amqp.rb +0 -18
- data/lib/promiscuous/publisher/attributes.rb +0 -32
- data/lib/promiscuous/publisher/base.rb +0 -23
- data/lib/promiscuous/publisher/class.rb +0 -36
- data/lib/promiscuous/publisher/envelope.rb +0 -7
- data/lib/promiscuous/publisher/ephemeral.rb +0 -9
- data/lib/promiscuous/publisher/lint.rb +0 -35
- data/lib/promiscuous/publisher/lint/amqp.rb +0 -14
- data/lib/promiscuous/publisher/lint/attributes.rb +0 -12
- data/lib/promiscuous/publisher/lint/base.rb +0 -5
- data/lib/promiscuous/publisher/lint/class.rb +0 -15
- data/lib/promiscuous/publisher/lint/polymorphic.rb +0 -22
- data/lib/promiscuous/publisher/mock.rb +0 -79
- data/lib/promiscuous/publisher/mongoid.rb +0 -33
- data/lib/promiscuous/publisher/mongoid/embedded.rb +0 -27
- data/lib/promiscuous/publisher/mongoid/embedded_many.rb +0 -12
- data/lib/promiscuous/publisher/polymorphic.rb +0 -8
- data/lib/promiscuous/subscriber/active_record.rb +0 -11
- data/lib/promiscuous/subscriber/amqp.rb +0 -25
- data/lib/promiscuous/subscriber/attributes.rb +0 -35
- data/lib/promiscuous/subscriber/base.rb +0 -29
- data/lib/promiscuous/subscriber/class.rb +0 -29
- data/lib/promiscuous/subscriber/dummy.rb +0 -19
- data/lib/promiscuous/subscriber/envelope.rb +0 -18
- data/lib/promiscuous/subscriber/lint.rb +0 -30
- data/lib/promiscuous/subscriber/lint/amqp.rb +0 -21
- data/lib/promiscuous/subscriber/lint/attributes.rb +0 -21
- data/lib/promiscuous/subscriber/lint/base.rb +0 -14
- data/lib/promiscuous/subscriber/lint/class.rb +0 -13
- data/lib/promiscuous/subscriber/lint/polymorphic.rb +0 -39
- data/lib/promiscuous/subscriber/mongoid.rb +0 -27
- data/lib/promiscuous/subscriber/mongoid/embedded.rb +0 -17
- data/lib/promiscuous/subscriber/mongoid/embedded_many.rb +0 -44
- data/lib/promiscuous/subscriber/observer.rb +0 -26
- data/lib/promiscuous/subscriber/polymorphic.rb +0 -36
- data/lib/promiscuous/subscriber/upsert.rb +0 -12
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
module Promiscuous::Publisher::Model::ActiveRecord
|
|
2
2
|
extend ActiveSupport::Concern
|
|
3
|
+
include Promiscuous::Publisher::Model::Base
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
extend ActiveSupport::Concern
|
|
5
|
+
# TODO FIXME This needs some serious work. We need to hook deeper.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
included do
|
|
13
|
-
around_create { |&block| with_promiscuous(:operation => :create, &block) }
|
|
14
|
-
around_update { |&block| with_promiscuous(:operation => :update, &block) }
|
|
15
|
-
around_destroy { |&block| with_promiscuous(:operation => :destroy, &block) }
|
|
16
|
-
end
|
|
7
|
+
included do
|
|
8
|
+
around_create { |&block| promiscuous.sync(:operation => :create, &block) }
|
|
9
|
+
around_update { |&block| promiscuous.sync(:operation => :update, &block) }
|
|
10
|
+
around_destroy { |&block| promiscuous.sync(:operation => :destroy, &block) }
|
|
17
11
|
end
|
|
18
12
|
|
|
19
13
|
module ClassMethods
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
klass.__send__(:include, ModelInstanceMethods) if klass
|
|
14
|
+
def __promiscuous_missing_record_exception
|
|
15
|
+
ActiveRecord::RecordNotFound
|
|
23
16
|
end
|
|
24
17
|
end
|
|
25
18
|
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
module Promiscuous::Publisher::Model::Base
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
included do
|
|
5
|
+
class_attribute :publish_to, :published_attrs, :tracked_attrs
|
|
6
|
+
cattr_accessor :published_db_fields # There is one on each root class, none on the subclasses
|
|
7
|
+
self.published_attrs = []
|
|
8
|
+
self.tracked_attrs = []
|
|
9
|
+
self.published_db_fields = []
|
|
10
|
+
track_dependencies_of :id
|
|
11
|
+
Promiscuous::Publisher::Model.publishers[self.promiscuous_collection_name] = self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module PromiscuousMethodsBase
|
|
15
|
+
def initialize(instance)
|
|
16
|
+
@instance = instance
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def sync(options={}, &block)
|
|
20
|
+
options = {:instance => @instance, :operation => :update}.merge(options)
|
|
21
|
+
Promiscuous::Publisher::Operation::Base.new(options).execute(&block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def payload(options={})
|
|
25
|
+
# It's nice to see the entire payload in one piece, not merged 36 times
|
|
26
|
+
# TODO migrate this format to something that makes more sense once the store is out
|
|
27
|
+
msg = {}
|
|
28
|
+
msg[:__amqp__] = @instance.class.publish_to
|
|
29
|
+
msg[:type] = @instance.class.publish_as # for backward compatibility
|
|
30
|
+
msg[:ancestors] = @instance.class.ancestors.select { |a| a < Promiscuous::Publisher::Model::Base }.map(&:publish_as)
|
|
31
|
+
msg[:id] = @instance.id.to_s
|
|
32
|
+
if @instance.respond_to?(:promiscuous_payload)
|
|
33
|
+
msg[:payload] = @instance.promiscuous_payload
|
|
34
|
+
else
|
|
35
|
+
msg[:payload] = self.attributes unless options[:with_attributes] == false
|
|
36
|
+
end
|
|
37
|
+
msg
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def attributes
|
|
41
|
+
Hash[@instance.class.published_attrs.map { |attr| [attr, self.attribute(attr)] }]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def attribute(attr)
|
|
45
|
+
value = @instance.__send__(attr)
|
|
46
|
+
value = value.promiscuous.payload if value.respond_to?(:promiscuous)
|
|
47
|
+
value
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_dependency(attr, value)
|
|
51
|
+
return nil unless value
|
|
52
|
+
@collection ||= @instance.class.promiscuous_collection_name
|
|
53
|
+
Promiscuous::Dependency.new(@collection, attr, value)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def tracked_dependencies(options={})
|
|
57
|
+
# FIXME This is not sufficient, we need to consider the previous and next
|
|
58
|
+
# values in case of an update.
|
|
59
|
+
# Note that the caller expect the id dependency to come first
|
|
60
|
+
@instance.class.tracked_attrs
|
|
61
|
+
.map { |attr| [attr, @instance.__send__(attr)] }
|
|
62
|
+
.map { |attr, value| get_dependency(attr, value) }
|
|
63
|
+
.compact
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class PromiscuousMethods
|
|
68
|
+
include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def promiscuous
|
|
72
|
+
# XXX Not thread safe
|
|
73
|
+
@promiscuous ||= self.class.const_get(:PromiscuousMethods).new(self)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def valid?(*args)
|
|
77
|
+
# Validations are not dependencies
|
|
78
|
+
# TODO we should yell if the user is trying to write
|
|
79
|
+
without_promiscuous { super }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
module ClassMethods
|
|
83
|
+
# all methods are virtual
|
|
84
|
+
|
|
85
|
+
def publish(*args, &block)
|
|
86
|
+
options = args.extract_options!
|
|
87
|
+
attributes = args.map(&:to_sym)
|
|
88
|
+
|
|
89
|
+
# TODO reject invalid options
|
|
90
|
+
|
|
91
|
+
if attributes.present? && self.publish_to && options[:to] && self.publish_to != options[:to]
|
|
92
|
+
raise 'versionned publishing is not supported yet'
|
|
93
|
+
end
|
|
94
|
+
self.publish_to ||= options[:to] || "#{Promiscuous::Config.app}/#{self.name.underscore}"
|
|
95
|
+
@publish_as = options[:as].to_s if options[:as]
|
|
96
|
+
|
|
97
|
+
([self] + descendants).each do |klass|
|
|
98
|
+
# When the user passes :use => [:f1, :f2] for example, operation/mongoid.rb
|
|
99
|
+
# can track f1 and f2 as fields important for the publishing.
|
|
100
|
+
# It's important for virtual attributes. The published_db_fields is global
|
|
101
|
+
# for the entire subclass tree.
|
|
102
|
+
klass.published_db_fields |= [options[:use]].flatten.map(&:to_sym) if options[:use]
|
|
103
|
+
klass.published_db_fields |= attributes # aliased fields are resolved later
|
|
104
|
+
klass.published_attrs |= attributes
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def track_dependencies_of(*attributes)
|
|
109
|
+
([self] + descendants).each { |klass| klass.tracked_attrs |= attributes.map(&:to_sym) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def promiscuous_collection_name
|
|
113
|
+
self.name.pluralize.underscore
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def get_operation_class_for(operation)
|
|
117
|
+
Promiscuous::Publisher::Operation::Base
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def publish_as
|
|
121
|
+
@publish_as || name
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def inherited(subclass)
|
|
125
|
+
super
|
|
126
|
+
subclass.published_attrs = self.published_attrs.dup
|
|
127
|
+
subclass.tracked_attrs = self.tracked_attrs.dup
|
|
128
|
+
# no copy for published_db_fields
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
class None; end
|
|
132
|
+
def promiscuous_missing_record_exception
|
|
133
|
+
None
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module Promiscuous::Publisher::Model::Ephemeral
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
include Promiscuous::Publisher::Model::Base
|
|
4
|
+
|
|
5
|
+
attr_accessor :id, :new_record, :destroyed
|
|
6
|
+
|
|
7
|
+
module PromiscuousMethodsEphemeral
|
|
8
|
+
def attribute(attr)
|
|
9
|
+
value = super
|
|
10
|
+
if value.is_a?(Array) &&
|
|
11
|
+
value.first.is_a?(Promiscuous::Publisher::Model::Ephemeral)
|
|
12
|
+
value = {:__amqp__ => '__promiscuous__/embedded_many',
|
|
13
|
+
:payload => value.map(&:promiscuous).map(&:payload)}
|
|
14
|
+
end
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class PromiscuousMethods
|
|
20
|
+
include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
|
|
21
|
+
include Promiscuous::Publisher::Model::Ephemeral::PromiscuousMethodsEphemeral
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize(attrs={})
|
|
25
|
+
self.id ||= 'none'
|
|
26
|
+
self.new_record = true
|
|
27
|
+
self.destroyed = false
|
|
28
|
+
attrs.each { |attr, value| __send__("#{attr}=", value) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def save
|
|
32
|
+
operation = :create
|
|
33
|
+
operation = :update unless self.new_record
|
|
34
|
+
operation = :destroy if self.destroyed
|
|
35
|
+
promiscuous.sync(:operation => operation)
|
|
36
|
+
self.new_record = false
|
|
37
|
+
true
|
|
38
|
+
end
|
|
39
|
+
alias :save! :save
|
|
40
|
+
|
|
41
|
+
def update_attributes(attrs)
|
|
42
|
+
attrs.each { |attr, value| __send__("#{attr}=", value) }
|
|
43
|
+
save
|
|
44
|
+
end
|
|
45
|
+
alias :update_attributes! :update_attributes
|
|
46
|
+
|
|
47
|
+
def destroy
|
|
48
|
+
self.destroyed = true
|
|
49
|
+
save
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def attributes
|
|
53
|
+
Hash[self.class.published_attrs.map { |attr| [attr, __send__(attr)] }]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module ClassMethods
|
|
57
|
+
def publish(*args)
|
|
58
|
+
super
|
|
59
|
+
published_attrs.each do |attr|
|
|
60
|
+
# TODO do not overwrite existing methods
|
|
61
|
+
attr_accessor attr
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def create(attributes)
|
|
66
|
+
new(attributes).tap { |m| m.save }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Promiscuous::Publisher::Model::Mock
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
include Promiscuous::Publisher::Model::Ephemeral
|
|
4
|
+
|
|
5
|
+
included { class_attribute :mock_options }
|
|
6
|
+
|
|
7
|
+
def initialize(attrs={})
|
|
8
|
+
self.id = __get_new_id
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def __get_new_id
|
|
13
|
+
if self.class.mock_options.try(:[], :id) == :bson
|
|
14
|
+
BSON::ObjectId.new
|
|
15
|
+
else
|
|
16
|
+
# XXX Not thread safe
|
|
17
|
+
@@next_id ||= 1
|
|
18
|
+
@@next_id += 1
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class PromiscuousMethods
|
|
23
|
+
include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
|
|
24
|
+
include Promiscuous::Publisher::Model::Ephemeral::PromiscuousMethodsEphemeral
|
|
25
|
+
|
|
26
|
+
def sync(options={}, &block)
|
|
27
|
+
payload = self.payload
|
|
28
|
+
payload[:operation] = options[:operation] || :update
|
|
29
|
+
Promiscuous::Subscriber::Worker::Message.new(MultiJson.dump(payload)).process
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module ClassMethods
|
|
34
|
+
def publish_as
|
|
35
|
+
# The mocks are in the publisher's namespace, so we need to remove that.
|
|
36
|
+
@publish_as ||= ($2 if self.name =~ /^(.+)::Publishers::(.+)$/)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def mock(options={})
|
|
40
|
+
self.mock_options = options
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def publish(*args, &block)
|
|
44
|
+
super
|
|
45
|
+
|
|
46
|
+
args.extract_options!
|
|
47
|
+
attributes = args
|
|
48
|
+
attr_accessor(*attributes)
|
|
49
|
+
|
|
50
|
+
# Hacks for associations on the factory
|
|
51
|
+
associations = attributes.map { |attr| $1 if attr =~ /^(.*)_id$/ }.compact
|
|
52
|
+
associations.each do |attr|
|
|
53
|
+
attr_accessor(attr)
|
|
54
|
+
define_method("#{attr}=") do |value|
|
|
55
|
+
instance_variable_set("@#{attr}", value)
|
|
56
|
+
instance_variable_set("@#{attr}_id", value.nil? ? value : value.id)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,129 +1,86 @@
|
|
|
1
1
|
module Promiscuous::Publisher::Model::Mongoid
|
|
2
2
|
extend ActiveSupport::Concern
|
|
3
|
+
include Promiscuous::Publisher::Model::Base
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def initialize(options={})
|
|
7
|
-
self.collection = options[:collection]
|
|
8
|
-
self.selector = options[:selector]
|
|
9
|
-
self.document = options[:document]
|
|
10
|
-
self.operation = options[:operation]
|
|
11
|
-
end
|
|
5
|
+
mattr_accessor :collection_mapping
|
|
6
|
+
self.collection_mapping = {}
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
# We hook at the database driver level
|
|
9
|
+
require 'promiscuous/publisher/operation/mongoid'
|
|
10
|
+
included do
|
|
11
|
+
# Important for the query hooks (see ../operation/mongoid.rb)
|
|
12
|
+
# We want the root class when we do a collection name lookup
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
when :update then klass.with(:consistency => :strong).where(selector).first
|
|
23
|
-
when :destroy then klass.with(:consistency => :strong).where(selector).first
|
|
24
|
-
end
|
|
14
|
+
root_class = self.collection.name.singularize.camelize.constantize
|
|
15
|
+
unless self == root_class
|
|
16
|
+
raise "Please include Promiscuous::Publisher in #{root_class} first (the root class)"
|
|
25
17
|
end
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
return block.call unless klass
|
|
29
|
-
|
|
30
|
-
# We bypass the call if instance == nil, the destroy or the update would
|
|
31
|
-
# have had no effect
|
|
32
|
-
instance = fetch
|
|
33
|
-
return if instance.nil?
|
|
34
|
-
|
|
35
|
-
return block.call unless instance.class.respond_to?(:promiscuous_publisher)
|
|
36
|
-
|
|
37
|
-
self.selector = {:id => instance.id}
|
|
38
|
-
|
|
39
|
-
publisher = instance.class.promiscuous_publisher
|
|
40
|
-
publisher.new(:operation => operation,
|
|
41
|
-
:instance => instance,
|
|
42
|
-
:fetch_proc => method(:fetch)).commit(&block)
|
|
43
|
-
end
|
|
19
|
+
Promiscuous::Publisher::Model::Mongoid.collection_mapping[self.collection.name] = self
|
|
44
20
|
end
|
|
45
21
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def promiscuous_sync
|
|
50
|
-
publisher = self.class.promiscuous_publisher
|
|
22
|
+
class PromiscuousMethods
|
|
23
|
+
include Promiscuous::Publisher::Model::Base::PromiscuousMethodsBase
|
|
51
24
|
|
|
52
|
-
|
|
25
|
+
def sync(options={}, &block)
|
|
26
|
+
raise "Use promiscuous.sync on the parent instance" if @instance.embedded?
|
|
27
|
+
super
|
|
28
|
+
end
|
|
53
29
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
30
|
+
def attribute(attr)
|
|
31
|
+
value = super
|
|
32
|
+
if value.is_a?(Array) &&
|
|
33
|
+
value.respond_to?(:ancestors) &&
|
|
34
|
+
value.ancestors.any? { |a| a == Promiscuous::Publisher::Model::Mongoid }
|
|
35
|
+
value = {:__amqp__ => '__promiscuous__/embedded_many',
|
|
36
|
+
:payload => value.map(&:promiscuous).map(&:payload)}
|
|
37
|
+
end
|
|
38
|
+
value
|
|
57
39
|
end
|
|
58
40
|
end
|
|
59
41
|
|
|
60
42
|
module ClassMethods
|
|
61
|
-
|
|
43
|
+
# TODO DRY this up with the publisher side
|
|
44
|
+
def publish(*args, &block)
|
|
62
45
|
super
|
|
63
|
-
|
|
64
|
-
end
|
|
65
|
-
end
|
|
46
|
+
return unless block
|
|
66
47
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
documents.each do |doc|
|
|
73
|
-
Promiscuous::Publisher::Model::Mongoid::Commit.new(
|
|
74
|
-
:collection => self.name,
|
|
75
|
-
:document => doc,
|
|
76
|
-
:operation => :create
|
|
77
|
-
).commit do
|
|
78
|
-
insert_orig(doc, flags)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
48
|
+
begin
|
|
49
|
+
@in_publish_block = true
|
|
50
|
+
block.call
|
|
51
|
+
ensure
|
|
52
|
+
@in_publish_block = false
|
|
81
53
|
end
|
|
82
54
|
end
|
|
83
55
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
Promiscuous::Publisher::Model::Mongoid::Commit.new(
|
|
92
|
-
:collection => collection.name,
|
|
93
|
-
:selector => selector,
|
|
94
|
-
:operation => :update
|
|
95
|
-
).commit do
|
|
96
|
-
update_orig(change, flags)
|
|
56
|
+
def self.publish_on(method, options={})
|
|
57
|
+
define_method(method) do |name, *args, &block|
|
|
58
|
+
super(name, *args, &block)
|
|
59
|
+
if @in_publish_block
|
|
60
|
+
name = args.last[:as] if args.last.is_a?(Hash) && args.last[:as]
|
|
61
|
+
publish(name)
|
|
97
62
|
end
|
|
98
63
|
end
|
|
64
|
+
end
|
|
99
65
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
:collection => collection.name,
|
|
104
|
-
:selector => selector,
|
|
105
|
-
:operation => :update
|
|
106
|
-
).commit do
|
|
107
|
-
modify_orig(change, options)
|
|
108
|
-
end
|
|
109
|
-
end
|
|
66
|
+
publish_on :field
|
|
67
|
+
publish_on :embeds_one
|
|
68
|
+
publish_on :embeds_many
|
|
110
69
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
:collection => collection.name,
|
|
115
|
-
:selector => selector,
|
|
116
|
-
:operation => :destroy
|
|
117
|
-
).commit do
|
|
118
|
-
remove_orig
|
|
119
|
-
end
|
|
120
|
-
end
|
|
70
|
+
def promiscuous_collection_name
|
|
71
|
+
self.collection.name
|
|
72
|
+
end
|
|
121
73
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
74
|
+
def get_operation_class_for(operation)
|
|
75
|
+
if operation == :create
|
|
76
|
+
Moped::PromiscuousCollectionWrapper::PromiscuousCollectionOperation
|
|
77
|
+
else
|
|
78
|
+
Moped::PromiscuousQueryWrapper::PromiscuousQueryOperation
|
|
125
79
|
end
|
|
126
80
|
end
|
|
81
|
+
|
|
82
|
+
def promiscuous_missing_record_exception
|
|
83
|
+
Mongoid::Errors::DocumentNotFound
|
|
84
|
+
end
|
|
127
85
|
end
|
|
128
|
-
hook_mongoid
|
|
129
86
|
end
|