promiscuous 0.25 → 0.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/lib/promiscuous/amqp/bunny.rb +1 -1
  2. data/lib/promiscuous/amqp/null.rb +1 -0
  3. data/lib/promiscuous/amqp/ruby_amqp.rb +17 -14
  4. data/lib/promiscuous/amqp.rb +4 -2
  5. data/lib/promiscuous/cli.rb +9 -16
  6. data/lib/promiscuous/common.rb +1 -1
  7. data/lib/promiscuous/config.rb +4 -2
  8. data/lib/promiscuous/error/connection.rb +8 -1
  9. data/lib/promiscuous/error/publisher.rb +7 -1
  10. data/lib/promiscuous/publisher/active_record.rb +1 -0
  11. data/lib/promiscuous/publisher/amqp.rb +2 -1
  12. data/lib/promiscuous/publisher/base.rb +4 -0
  13. data/lib/promiscuous/publisher/lint.rb +1 -1
  14. data/lib/promiscuous/publisher/model/active_record.rb +25 -0
  15. data/lib/promiscuous/publisher/model/mongoid.rb +108 -0
  16. data/lib/promiscuous/publisher/model.rb +71 -19
  17. data/lib/promiscuous/publisher/mongoid/embedded.rb +8 -4
  18. data/lib/promiscuous/publisher/mongoid.rb +12 -9
  19. data/lib/promiscuous/publisher.rb +1 -1
  20. data/lib/promiscuous/redis.rb +52 -0
  21. data/lib/promiscuous/subscriber/mongoid.rb +1 -2
  22. data/lib/promiscuous/subscriber/worker/message.rb +46 -0
  23. data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +168 -0
  24. data/lib/promiscuous/subscriber/worker/pump.rb +47 -0
  25. data/lib/promiscuous/subscriber/worker/runner.rb +7 -0
  26. data/lib/promiscuous/subscriber/worker.rb +39 -47
  27. data/lib/promiscuous/version.rb +1 -1
  28. data/lib/promiscuous/worker.rb +1 -5
  29. data/lib/promiscuous.rb +1 -1
  30. metadata +86 -20
  31. data/lib/promiscuous/common/worker.rb +0 -52
  32. data/lib/promiscuous/publisher/mongoid/defer.rb +0 -75
  33. data/lib/promiscuous/publisher/mongoid/defer_embedded.rb +0 -25
  34. data/lib/promiscuous/publisher/worker.rb +0 -101
  35. data/lib/promiscuous/subscriber/mongoid/versioning.rb +0 -40
@@ -3,7 +3,7 @@ module Promiscuous::AMQP:: Bunny
3
3
 
4
4
  def self.connect
5
5
  require 'bunny'
6
- self.connection = ::Bunny.new(Promiscuous::Config.server_uri, { :heartbeat => Promiscuous::Config.heartbeat })
6
+ self.connection = ::Bunny.new(Promiscuous::Config.amqp_url, { :heartbeat => Promiscuous::Config.heartbeat })
7
7
  self.connection.start
8
8
  end
9
9
 
@@ -6,6 +6,7 @@ module Promiscuous::AMQP::Null
6
6
  end
7
7
 
8
8
  def self.connected?
9
+ true
9
10
  end
10
11
 
11
12
  def self.publish(options={})
@@ -4,30 +4,30 @@ module Promiscuous::AMQP::RubyAMQP
4
4
  def self.connect
5
5
  require 'amqp'
6
6
 
7
- amqp_options = if Promiscuous::Config.server_uri
8
- uri = URI.parse(Promiscuous::Config.server_uri)
9
- raise "Please use amqp://user:password@host:port/vhost" if uri.scheme != 'amqp'
7
+ amqp_options = if Promiscuous::Config.amqp_url
8
+ url = URI.parse(Promiscuous::Config.amqp_url)
9
+ raise "Please use amqp://user:password@host:port/vhost" if url.scheme != 'amqp'
10
10
 
11
11
  {
12
- :host => uri.host,
13
- :port => uri.port,
14
- :scheme => uri.scheme,
15
- :user => uri.user,
16
- :pass => uri.password,
17
- :vhost => uri.path.empty? ? "/" : uri.path,
12
+ :host => url.host,
13
+ :port => url.port,
14
+ :scheme => url.scheme,
15
+ :user => url.user,
16
+ :pass => url.password,
17
+ :vhost => url.path.empty? ? "/" : url.path,
18
18
  :heartbeat => Promiscuous::Config.heartbeat
19
19
  }
20
20
  end
21
21
 
22
22
  connection = ::AMQP.connect(amqp_options)
23
- self.channel = ::AMQP::Channel.new(connection, :auto_recovery => true, :prefetch => 100)
23
+ self.channel = ::AMQP::Channel.new(connection, :auto_recovery => true, :prefetch => 1000)
24
24
 
25
25
  connection.on_tcp_connection_loss do |conn|
26
26
  unless conn.reconnecting?
27
27
  Promiscuous.warn "[connection] Lost connection. Reconnecting..."
28
28
  conn.periodically_reconnect(2)
29
29
 
30
- exception = Promiscuous::Error::Connection.new 'Lost connection'
30
+ exception = Promiscuous::Error::Connection.new(:amqp, 'Lost connection')
31
31
  Promiscuous::Worker.stop # TODO XXX This doesn't belong here. hooks ?
32
32
  Promiscuous::Config.error_notifier.try(:call, exception)
33
33
  end
@@ -76,12 +76,15 @@ module Promiscuous::AMQP::RubyAMQP
76
76
  info_msg = "(#{options[:exchange_name]}) #{options[:key]} -> #{options[:payload]}"
77
77
 
78
78
  unless channel.connection.connected?
79
- raise Promiscuous::Error::Connection.new 'Not connected'
79
+ raise Promiscuous::Error::Connection.new(:amqp, 'Not connected')
80
80
  end
81
81
 
82
82
  Promiscuous.debug "[publish] #{info_msg}"
83
- exchange(options[:exchange_name]).
84
- publish(options[:payload], :routing_key => options[:key], :persistent => true)
83
+
84
+ EM.next_tick do
85
+ exchange(options[:exchange_name]).
86
+ publish(options[:payload], :routing_key => options[:key], :persistent => true)
87
+ end
85
88
  end
86
89
 
87
90
  def self.exchange(name)
@@ -5,8 +5,10 @@ module Promiscuous::AMQP
5
5
  EXCHANGE = 'promiscuous'.freeze
6
6
 
7
7
  class << self
8
- def backend
9
- Promiscuous::Config.backend
8
+ attr_accessor :backend
9
+
10
+ def backend=(value)
11
+ @backend = "Promiscuous::AMQP::#{value.to_s.camelize.gsub(/amqp/, 'AMQP')}".constantize unless value.nil?
10
12
  end
11
13
 
12
14
  delegate :connect, :disconnect, :connected?, :publish, :open_queue, :to => :backend
@@ -39,20 +39,6 @@ class Promiscuous::CLI
39
39
  end
40
40
  end
41
41
 
42
- def publish(options={})
43
- replicate do
44
- Promiscuous::Worker.replicate(options)
45
- print_status "Replicating with #{Promiscuous::Publisher::Mongoid::Defer.klasses.count} publishers"
46
- end
47
- end
48
-
49
- def subscribe(options={})
50
- replicate do
51
- Promiscuous::Worker.replicate(options)
52
- print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
53
- end
54
- end
55
-
56
42
  def publish_sync(options={})
57
43
  print_status "Replicating #{options[:criteria]}..."
58
44
  criteria = eval(options[:criteria])
@@ -66,6 +52,13 @@ class Promiscuous::CLI
66
52
  print_status "Done. You may switch your subscriber worker back to regular mode, and delete the sync queues"
67
53
  end
68
54
 
55
+ def subscribe(options={})
56
+ replicate do
57
+ Promiscuous::Worker.replicate
58
+ print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
59
+ end
60
+ end
61
+
69
62
  def subscribe_sync(options={})
70
63
  replicate do
71
64
  # Create the regular queue if needed, so we don't lose messages.
@@ -74,7 +67,7 @@ class Promiscuous::CLI
74
67
  print_status "WARNING: --- SYNC MODE ----"
75
68
  print_status "WARNING: Make sure you are not running the regular subscriber worker (it's racy)"
76
69
  print_status "WARNING: --- SYNC MODE ----"
77
- Promiscuous::Worker.replicate(options)
70
+ Promiscuous::Worker.replicate
78
71
  print_status "Replicating with #{Promiscuous::Subscriber::AMQP.subscribers.count} subscribers"
79
72
  end
80
73
  end
@@ -88,7 +81,7 @@ class Promiscuous::CLI
88
81
 
89
82
  opts.separator ""
90
83
  opts.separator "Actions:"
91
- opts.separator " publish"
84
+ opts.separator " publish (sync only)"
92
85
  opts.separator " subscribe"
93
86
  opts.separator ""
94
87
  opts.separator "Options:"
@@ -1,4 +1,4 @@
1
1
  module Promiscuous::Common
2
2
  extend Promiscuous::Autoload
3
- autoload :Options, :Lint, :ClassHelpers, :Worker
3
+ autoload :Options, :Lint, :ClassHelpers
4
4
  end
@@ -1,8 +1,9 @@
1
1
  module Promiscuous::Config
2
- mattr_accessor :app, :logger, :error_notifier, :backend, :server_uri, :queue_options, :heartbeat
2
+ mattr_accessor :app, :logger, :error_notifier, :backend, :amqp_url, :redis_url, :queue_options, :heartbeat
3
3
 
4
4
  def self.backend=(value)
5
- @@backend = "Promiscuous::AMQP::#{value.to_s.camelize.gsub(/amqp/, 'AMQP')}".constantize unless value.nil?
5
+ @@backend = value
6
+ Promiscuous::AMQP.backend = value unless value.nil?
6
7
  end
7
8
 
8
9
  def self.configure(&block)
@@ -16,5 +17,6 @@ module Promiscuous::Config
16
17
  self.heartbeat ||= 60
17
18
 
18
19
  Promiscuous::AMQP.connect
20
+ Promiscuous::Redis.connect
19
21
  end
20
22
  end
@@ -1 +1,8 @@
1
- class Promiscuous::Error::Connection < RuntimeError; end
1
+ class Promiscuous::Error::Connection < RuntimeError
2
+ attr_accessor :which
3
+
4
+ def initialize(which, msg)
5
+ self.which = which
6
+ super(msg)
7
+ end
8
+ end
@@ -1,5 +1,5 @@
1
1
  class Promiscuous::Error::Publisher < RuntimeError
2
- attr_accessor :inner, :instance, :out_of_sync
2
+ attr_accessor :inner, :instance, :payload, :out_of_sync
3
3
 
4
4
  def initialize(inner, options={})
5
5
  super(nil)
@@ -7,6 +7,7 @@ class Promiscuous::Error::Publisher < RuntimeError
7
7
  set_backtrace(inner.backtrace)
8
8
  self.inner = inner
9
9
  self.instance = options[:instance]
10
+ self.payload = options[:payload]
10
11
  self.out_of_sync = options[:out_of_sync]
11
12
  end
12
13
 
@@ -16,6 +17,11 @@ class Promiscuous::Error::Publisher < RuntimeError
16
17
  msg = "#{msg} while publishing #{instance.inspect}"
17
18
  msg = "FATAL (out of sync) #{msg}" if out_of_sync
18
19
  end
20
+
21
+ if payload
22
+ msg = "#{msg} payload: #{payload}"
23
+ end
24
+
19
25
  msg
20
26
  end
21
27
 
@@ -3,4 +3,5 @@ class Promiscuous::Publisher::ActiveRecord < Promiscuous::Publisher::Base
3
3
  include Promiscuous::Publisher::Attributes
4
4
  include Promiscuous::Publisher::AMQP
5
5
  include Promiscuous::Publisher::Model
6
+ include Promiscuous::Publisher::Model::ActiveRecord
6
7
  end
@@ -4,10 +4,11 @@ module Promiscuous::Publisher::AMQP
4
4
 
5
5
  def publish
6
6
  exchange_name = Promiscuous::AMQP::EXCHANGE
7
+ options[:personality] = 'new'
7
8
  exchange_name += ".#{options[:personality]}" if options[:personality]
8
9
  Promiscuous::AMQP.publish(:exchange_name => exchange_name, :key => to, :payload => payload.to_json)
9
10
  rescue Exception => e
10
- raise Promiscuous::Error::Publisher.new(e, :instance => instance, :out_of_sync => true)
11
+ raise_out_of_sync(e, payload.to_json)
11
12
  end
12
13
 
13
14
  def payload
@@ -16,4 +16,8 @@ class Promiscuous::Publisher::Base
16
16
  load_options(options)
17
17
  self.published = true
18
18
  end
19
+
20
+ def raise_out_of_sync(exception, payload)
21
+ raise Promiscuous::Error::Publisher.new(exception, :instance => instance, :out_of_sync => true, :payload => payload)
22
+ end
19
23
  end
@@ -12,7 +12,7 @@ module Promiscuous::Publisher::Lint
12
12
 
13
13
  def self.lint(class_bindings={})
14
14
  if class_bindings.empty?
15
- class_bindings = Promiscuous::Publisher::Mongoid::Defer.klasses.values.reduce({}) do |res, klass|
15
+ class_bindings = Promiscuous::Publisher::Model.klasses.reduce({}) do |res, klass|
16
16
  res[klass] = klass.promiscuous_publisher.to
17
17
  res
18
18
  end
@@ -0,0 +1,25 @@
1
+ module Promiscuous::Publisher::Model::ActiveRecord
2
+ extend ActiveSupport::Concern
3
+
4
+ module ModelInstanceMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ def with_promiscuous(options={}, &block)
8
+ fetch_proc = proc { self.class.find(self.id) }
9
+ self.class.promiscuous_publisher.new(options.merge(:instance => self, :fetch_proc => fetch_proc)).commit(&block)
10
+ end
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
17
+ end
18
+
19
+ module ClassMethods
20
+ def setup_class_binding
21
+ super
22
+ klass.__send__(:include, ModelInstanceMethods) if klass
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,108 @@
1
+ module Promiscuous::Publisher::Model::Mongoid
2
+ extend ActiveSupport::Concern
3
+
4
+ class Commit
5
+ attr_accessor :collection, :selector, :document, :operation
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
12
+
13
+ def klass
14
+ @klass ||= document.try(:[], '_type').try(:constantize) ||
15
+ collection.singularize.camelize.constantize
16
+ rescue NameError
17
+ end
18
+
19
+ def fetch
20
+ case operation
21
+ when :create then klass.new(document, :without_protection => true)
22
+ when :update then klass.with(:consistency => :strong).where(selector).first
23
+ when :destroy then klass.with(:consistency => :strong).where(selector).first
24
+ end
25
+ end
26
+
27
+ def commit(&block)
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
44
+ end
45
+
46
+ def self.hook_mongoid
47
+ Moped::Collection.class_eval do
48
+ alias_method :insert_orig, :insert
49
+ def insert(documents, flags=nil)
50
+ documents = [documents] unless documents.is_a?(Array)
51
+ documents.each do |doc|
52
+ Promiscuous::Publisher::Model::Mongoid::Commit.new(
53
+ :collection => self.name,
54
+ :document => doc,
55
+ :operation => :create
56
+ ).commit do
57
+ insert_orig(doc, flags)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ Moped::Query.class_eval do
64
+ alias_method :update_orig, :update
65
+ def update(change, flags=nil)
66
+ if flags && flags.include?(:multi)
67
+ raise "Promiscuous: Do not use multi updates, update each instance separately"
68
+ end
69
+
70
+ Promiscuous::Publisher::Model::Mongoid::Commit.new(
71
+ :collection => collection.name,
72
+ :selector => selector,
73
+ :operation => :update
74
+ ).commit do
75
+ update_orig(change, flags)
76
+ end
77
+ end
78
+
79
+ alias_method :modify_orig, :modify
80
+ def modify(change, options={})
81
+ Promiscuous::Publisher::Model::Mongoid::Commit.new(
82
+ :collection => collection.name,
83
+ :selector => selector,
84
+ :operation => :update
85
+ ).commit do
86
+ modify_orig(change, options)
87
+ end
88
+ end
89
+
90
+ alias_method :remove_orig, :remove
91
+ def remove
92
+ Promiscuous::Publisher::Model::Mongoid::Commit.new(
93
+ :collection => collection.name,
94
+ :selector => selector,
95
+ :operation => :destroy
96
+ ).commit do
97
+ remove_orig
98
+ end
99
+ end
100
+
101
+ alias_method :remove_all_orig, :remove_all
102
+ def remove_all
103
+ raise "Promiscuous: Do not use delete_all, use destroy_all"
104
+ end
105
+ end
106
+ end
107
+ hook_mongoid
108
+ end
@@ -1,40 +1,92 @@
1
+ require 'crowdtap_redis_lock'
2
+
1
3
  module Promiscuous::Publisher::Model
4
+ extend Promiscuous::Autoload
5
+ autoload :ActiveRecord, :Mongoid
6
+
2
7
  extend ActiveSupport::Concern
3
8
  include Promiscuous::Publisher::Envelope
4
9
 
10
+ mattr_accessor :klasses
11
+ self.klasses = []
12
+
5
13
  def operation
6
14
  options[:operation]
7
15
  end
8
16
 
17
+ def fetch
18
+ case operation
19
+ when :create then instance
20
+ when :update then options[:fetch_proc].call
21
+ when :destroy then nil
22
+ end
23
+ end
24
+
25
+ def version
26
+ {:global => @global_version}
27
+ end
28
+
9
29
  def payload
10
- super.merge(:id => instance.id, :operation => operation)
30
+ if @dummy_commit
31
+ {:version => version, :operation => :dummy}
32
+ else
33
+ super.merge(:id => instance.id, :operation => operation, :version => version)
34
+ end
11
35
  end
12
36
 
13
37
  def include_attributes?
14
38
  operation != :destroy
15
39
  end
16
40
 
41
+ def with_lock(&block)
42
+ return yield if Promiscuous::Config.backend == :null
43
+ return yield if operation == :create
44
+
45
+ key = Promiscuous::Redis.pub_key(instance.id)
46
+ ::RedisLock.new(Promiscuous::Redis, key).retry(50.times).every(0.2).lock_for_update(&block)
47
+ end
48
+
49
+ def instance
50
+ @new_instance || super
51
+ end
52
+
53
+ def commit
54
+ ret = nil
55
+ exception = nil
56
+
57
+ unless Promiscuous::AMQP.connected?
58
+ raise Promiscuous::Error::Connection.new(:amqp, 'Not connected')
59
+ end
60
+
61
+ with_lock do
62
+ @global_version = Promiscuous::Redis.incr(Promiscuous::Redis.pub_key('global'))
63
+ begin
64
+ ret = yield
65
+ rescue Exception => e
66
+ # save it for later
67
+ @dummy_commit = true
68
+ exception = e
69
+ end
70
+
71
+ begin
72
+ @new_instance = fetch
73
+ rescue Exception => e
74
+ raise_out_of_sync(e, payload.to_json)
75
+ end
76
+ end
77
+
78
+ # We always need to publish so that the subscriber can keep up
79
+ publish
80
+
81
+ raise exception if exception
82
+ ret
83
+ end
84
+
85
+
17
86
  module ClassMethods
18
87
  def setup_class_binding
19
88
  super
20
- klass.class_eval do
21
- cattr_accessor :publisher_operation_hooked
22
- return if self.publisher_operation_hooked
23
- self.publisher_operation_hooked = true
24
-
25
- [:create, :update, :destroy].each do |operation|
26
- __send__("after_#{operation}", "promiscuous_publish_#{operation}".to_sym)
27
- define_method "promiscuous_publish_#{operation}" do
28
- self.class.promiscuous_publisher.new(:instance => self, :operation => operation).publish
29
- end
30
- end
31
-
32
- def promiscuous_sync(options={})
33
- options = options.merge({ :instance => self, :operation => :update, :defer => false })
34
- self.class.promiscuous_publisher.new(options).publish
35
- true
36
- end
37
- end if klass
89
+ Promiscuous::Publisher::Model.klasses << klass
38
90
  end
39
91
  end
40
92
  end
@@ -2,16 +2,20 @@ module Promiscuous::Publisher::Mongoid::Embedded
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  def payload
5
- super.merge(:id => instance.id)
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
6
10
  end
7
11
 
8
12
  included do
9
13
  klass.class_eval do
10
14
  callback = proc do
11
- if _parent.respond_to?(:promiscuous_publish_update)
15
+ if _parent.respond_to?(:with_promiscuous)
12
16
  _parent.save
13
- _parent.reload # mongoid is not that smart, so we need to reload here.
14
- _parent.promiscuous_publish_update
17
+ # XXX FIXME mongoid needs help, and we need to deal with that.
18
+ # We'll address that once we hook on moped
15
19
  end
16
20
  end
17
21
 
@@ -1,6 +1,6 @@
1
1
  class Promiscuous::Publisher::Mongoid < Promiscuous::Publisher::Base
2
2
  extend Promiscuous::Autoload
3
- autoload :Embedded, :DeferEmbedded, :Defer, :EmbeddedMany
3
+ autoload :Embedded, :EmbeddedMany
4
4
 
5
5
  include Promiscuous::Publisher::Class
6
6
  include Promiscuous::Publisher::Attributes
@@ -8,23 +8,26 @@ class Promiscuous::Publisher::Mongoid < Promiscuous::Publisher::Base
8
8
  include Promiscuous::Publisher::AMQP
9
9
 
10
10
  def self.publish(options)
11
+ check_mongoid_version
11
12
  super
12
13
 
13
14
  if klass.embedded?
14
- if mongoid3?
15
- include Promiscuous::Publisher::Mongoid::DeferEmbedded
16
- else
17
- include Promiscuous::Publisher::Mongoid::Embedded
18
- end
15
+ include Promiscuous::Publisher::Mongoid::Embedded
19
16
  else
20
17
  include Promiscuous::Publisher::Model
21
- include Promiscuous::Publisher::Mongoid::Defer if mongoid3?
18
+ include Promiscuous::Publisher::Model::Mongoid
22
19
  end
23
20
 
24
21
  setup_class_binding
25
22
  end
26
23
 
27
- def self.mongoid3?
28
- Gem.loaded_specs['mongoid'].version >= Gem::Version.new('3.0.0')
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
29
32
  end
30
33
  end
@@ -1,7 +1,7 @@
1
1
  module Promiscuous::Publisher
2
2
  extend Promiscuous::Autoload
3
3
  autoload :ActiveRecord, :AMQP, :Attributes, :Base, :Class, :Envelope, :Lint,
4
- :Mock, :Model, :Mongoid, :Polymorphic, :Worker, :Error, :Ephemeral
4
+ :Mock, :Model, :Mongoid, :Polymorphic, :Error, :Ephemeral
5
5
 
6
6
  def self.lint(*args)
7
7
  Lint.lint(*args)
@@ -0,0 +1,52 @@
1
+ require 'redis'
2
+
3
+ module Promiscuous::Redis
4
+ mattr_accessor :master
5
+
6
+ def self.connect
7
+ self.master = new_connection
8
+ end
9
+
10
+ def self.new_connection
11
+ return Null.new if Promiscuous::Config.backend == :null
12
+
13
+ ::Redis.new(:url => Promiscuous::Config.redis_url).tap { |r| r.client.connect }
14
+ end
15
+
16
+ def self.new_celluloid_connection
17
+ return Null.new if Promiscuous::Config.backend == :null
18
+
19
+ new_connection.tap do |redis|
20
+ redis.client.connection.instance_eval do
21
+ @sock = Celluloid::IO::TCPSocket.from_ruby_socket(@sock)
22
+ @sock.instance_eval do
23
+ extend ::Redis::Connection::SocketMixin
24
+ @timeout = nil
25
+ @buffer = ""
26
+
27
+ def _read_from_socket(nbytes)
28
+ readpartial(nbytes)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.method_missing(name, *args, &block)
36
+ self.master.__send__(name, *args, &block)
37
+ end
38
+
39
+ def self.pub_key(str)
40
+ "publishers:#{Promiscuous::Config.app}:#{str}"
41
+ end
42
+
43
+ def self.sub_key(str)
44
+ "subscribers:#{Promiscuous::Config.app}:#{str}"
45
+ end
46
+
47
+ class Null
48
+ def method_missing(name, *args, &block)
49
+ 0
50
+ end
51
+ end
52
+ end
@@ -1,6 +1,6 @@
1
1
  class Promiscuous::Subscriber::Mongoid < Promiscuous::Subscriber::Base
2
2
  extend Promiscuous::Autoload
3
- autoload :Embedded, :Versioning
3
+ autoload :Embedded
4
4
 
5
5
  include Promiscuous::Subscriber::Class
6
6
  include Promiscuous::Subscriber::Attributes
@@ -20,7 +20,6 @@ class Promiscuous::Subscriber::Mongoid < Promiscuous::Subscriber::Base
20
20
  else
21
21
  include Promiscuous::Subscriber::Model
22
22
  include Promiscuous::Subscriber::Upsert
23
- include Promiscuous::Subscriber::Mongoid::Versioning
24
23
  end
25
24
 
26
25
  setup_class_binding