promiscuous 0.25 → 0.31.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.
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