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.
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
@@ -0,0 +1,7 @@
1
+ class Promiscuous::Error::Recovery < Promiscuous::Error::Base
2
+ def initialize(message, inner=nil)
3
+ message = "#{inner.class}: #{inner} -- #{message}" if inner
4
+ super(message)
5
+ set_backtrace(inner.backtrace) if inner
6
+ end
7
+ end
@@ -1,4 +1,4 @@
1
- class Promiscuous::Error::Subscriber < RuntimeError
1
+ class Promiscuous::Error::Subscriber < Promiscuous::Error::Base
2
2
  attr_accessor :inner, :payload
3
3
 
4
4
  def initialize(inner, options={})
@@ -12,7 +12,5 @@ class Promiscuous::Error::Subscriber < RuntimeError
12
12
  "#{inner.class}: #{inner.message} while processing #{payload}"
13
13
  end
14
14
 
15
- def to_s
16
- message
17
- end
15
+ alias to_s message
18
16
  end
@@ -0,0 +1,36 @@
1
+ class Promiscuous::Key
2
+ def initialize(role, nodes=[], no_join=nil)
3
+ @role = role
4
+ @nodes = nodes
5
+ @no_join = no_join
6
+ end
7
+
8
+ def join(*nodes)
9
+ # --- backward compatiblity code ---
10
+ # TODO remove code
11
+ if nodes == ['global', nil, nil]
12
+ return self.class.new(@role, @nodes + nodes, :no_join)
13
+ end
14
+ if @no_join
15
+ return self.class.new(@role, @nodes)
16
+ end
17
+ # --- backward compatiblity code ---
18
+
19
+ self.class.new(@role, @nodes + nodes)
20
+ end
21
+
22
+ def to_s
23
+ path = []
24
+ case @role
25
+ when :pub then path << 'publishers'
26
+ when :sub then path << 'subscribers'
27
+ end
28
+ path << Promiscuous::Config.app
29
+ path += @nodes.compact
30
+ path.join(':')
31
+ end
32
+
33
+ def as_json(options={})
34
+ to_s
35
+ end
36
+ end
@@ -1,23 +1,19 @@
1
1
  module Promiscuous::Loader
2
- def self.load_descriptors(descriptors=[:publishers, :subscribers])
3
- [descriptors].flatten.each do |descriptor|
4
- dir, file_matcher = case descriptor
5
- when :publishers then %w(publishers **_publisher.rb)
6
- when :subscribers then %w(subscribers **_subscriber.rb)
7
- end
2
+ CONFIG_FILES = %w(config/publishers.rb config/subscribers.rb config/promiscuous.rb)
8
3
 
9
- Dir[Rails.root.join('app', dir, file_matcher)].map do |file|
10
- File.basename(file, ".rb").camelize.constantize
11
- end
4
+ def self.prepare
5
+ CONFIG_FILES.each do |file_name|
6
+ file = defined?(Rails) ? Rails.root.join(file_name) : File.join('.', file_name)
7
+ load file if File.exists?(file)
12
8
  end
9
+
10
+ # A one shot recovery on boot
11
+ Promiscuous::Publisher::Worker.new.try_recover
13
12
  end
14
13
 
15
- def self.unload_descriptors(descriptors=[:publishers, :subscribers])
16
- [descriptors].flatten.each do |descriptor|
17
- dir, file_matcher = case descriptor
18
- when :publishers then # TODO Cleanup publishers
19
- when :subscribers then Promiscuous::Subscriber::AMQP.subscribers.clear
20
- end
21
- end
14
+ def self.cleanup
15
+ Promiscuous::Publisher::Model.publishers.clear
16
+ Promiscuous::Publisher::Model::Mongoid.collection_mapping.clear if defined?(Mongoid)
17
+ Promiscuous::Subscriber::Model.mapping.select! { |k| k.to_s =~ /__promiscuous__/ }
22
18
  end
23
19
  end
@@ -0,0 +1,112 @@
1
+ class Promiscuous::Middleware
2
+ Context = Promiscuous::Publisher::Context
3
+
4
+ module Controller
5
+ extend ActiveSupport::Concern
6
+
7
+ def process_action(*args)
8
+ full_name = "#{self.class.controller_path}/#{self.action_name}"
9
+ Promiscuous::Middleware.with_context(full_name) { super }
10
+ end
11
+
12
+ def render(*args)
13
+ Promiscuous::Middleware.without_context { super }
14
+ end
15
+ end
16
+
17
+ def self.with_context(*args, &block)
18
+ Promiscuous.context(*args, &block)
19
+ rescue Exception => e
20
+ $promiscuous_last_exception = e if e.is_a? Promiscuous::Error::Base
21
+ pretty_print_exception(e)
22
+ raise e
23
+ end
24
+
25
+ def self.without_context
26
+ # This is different from the method without_promiscuous in convenience.rb
27
+ # That's used for render() and things that are *not* supposed to write.
28
+ # We actually force promiscuous to instrument queries, and make sure that
29
+ # we don't do any write we shouldn't.
30
+ old_context, Context.current = Context.current, nil
31
+ old_disabled, Promiscuous.disabled = Promiscuous.disabled, true
32
+ yield
33
+ rescue Exception => e
34
+ $promiscuous_last_exception = e if e.is_a? Promiscuous::Error::Base
35
+ pretty_print_exception(e)
36
+ raise e
37
+ ensure
38
+ Context.current = old_context
39
+ Promiscuous.disabled = old_disabled
40
+ end
41
+
42
+ def self.pretty_print_exception(e)
43
+ return if $promiscuous_pretty_print_exception_once == :disable || ENV['RAILS_ENV'] == 'production'
44
+ return if e.is_a?(SystemExit)
45
+
46
+ e = e.original_exception if defined?(ActionView::Template::Error) && e.is_a?(ActionView::Template::Error)
47
+
48
+ STDERR.puts
49
+ STDERR.puts "\e[0;#{36}m/---[ Exception: #{e.class} ]#{'-'*[0, 84 - e.class.name.size].max}\e[0m"
50
+ STDERR.puts "\e[0;#{36}m|"
51
+
52
+ highlight_indent = false
53
+ msg = e.to_s.split("\n").map do |line|
54
+ highlight_indent = true if line =~ /The problem comes from the following/ ||
55
+ line =~ /Promiscuous is tracking this read/
56
+ line = "\e[1;#{31}m#{line}\e[0;#{31}m" if highlight_indent && line =~ /^ /
57
+ "\e[0;#{36}m| \e[0;#{31}m#{line}\e[0m"
58
+ end
59
+
60
+ STDERR.puts msg.join("\n")
61
+ STDERR.puts "\e[0;#{36}m|"
62
+ STDERR.puts "\e[0;#{36}m+---[ Backtrace ]--------------------------------------------------------------------------------------\e[0m"
63
+ STDERR.puts "\e[0;#{36}m|"
64
+
65
+ expand = ENV['TRACE'].to_i > 1
66
+ bt = e.backtrace.map do |line|
67
+ line = case line
68
+ when /(rspec-core|instrumentation)/
69
+ "\e[1;30m#{line}\e[0m" if expand
70
+ when /#{Rails.root}\/app\/controllers/
71
+ "\e[1;35m#{line}\e[0m"
72
+ when /#{Rails.root}\/app\/models/
73
+ "\e[1;33m#{line}\e[0m"
74
+ when /#{Rails.root}\/lib/
75
+ "\e[1;34m#{line}\e[0m"
76
+ when /(mongoid|active_record).*`(count|distinct|each|first|last)'$/
77
+ "\e[1;32m#{line}\e[0m"
78
+ when /(mongoid|active_record).*`(create|insert|save|update|modify|remove|remove_all)'$/
79
+ "\e[1;31m#{line}\e[0m"
80
+ when /#{Rails.root}/
81
+ if line =~ /\/support\//
82
+ "\e[1;30m#{line}\e[0m" if expand
83
+ else
84
+ "\e[1;36m#{line}\e[0m"
85
+ end
86
+ else
87
+ "\e[1;30m#{line}\e[0m" if expand
88
+ end
89
+ "\e[0;#{36}m| #{line}" if line
90
+ end
91
+ .compact
92
+ .join("\n")
93
+ STDERR.puts bt
94
+ STDERR.puts "\e[0;#{36}m|"
95
+
96
+ if $cucumber_extra
97
+ STDERR.puts "\e[0;#{36}m+---[ Cucumber ]--------------------------------------------------------------------------------------\e[0m"
98
+ STDERR.puts "\e[0;#{36}m|"
99
+ $cucumber_extra.each_with_index do |line, i|
100
+ line = line.gsub(/([^:]*: )(.*)$/, "\\1\e[1;36m\\2")
101
+ STDERR.puts "\e[0;#{36}m| \e[0;36m#{line}\e[0m"
102
+ STDERR.puts "\e[0;#{36}m|" if i.zero?
103
+ end
104
+ STDERR.puts "\e[0;#{36}m|"
105
+ end
106
+
107
+ STDERR.puts "\e[0;#{36}m\\------------------------------------------------------------------------------------------------------\e[0m"
108
+ STDERR.puts
109
+ $promiscuous_pretty_print_exception_once = :disable if $promiscuous_pretty_print_exception_once
110
+ end
111
+
112
+ end
@@ -1,9 +1,12 @@
1
1
  module Promiscuous::Publisher
2
2
  extend Promiscuous::Autoload
3
- autoload :ActiveRecord, :AMQP, :Attributes, :Base, :Class, :Envelope, :Lint,
4
- :Mock, :Model, :Mongoid, :Polymorphic, :Error, :Ephemeral
3
+ autoload :Model, :Operation, :MockGenerator, :Context, :Worker
5
4
 
6
- def self.lint(*args)
7
- Lint.lint(*args)
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Model::Mongoid if defined?(Mongoid::Document) && self < Mongoid::Document
9
+ include Model::ActiveRecord if defined?(ActiveRecord::Base) && self < ActiveRecord::Base
10
+ raise "What kind of model is this? try including Promiscuous::Publisher after all your includes" unless self < Model::Base
8
11
  end
9
12
  end
@@ -0,0 +1,92 @@
1
+ class Promiscuous::Publisher::Context
2
+ # XXX Context are not sharable among threads
3
+
4
+ def self.open(*args, &block)
5
+ old_disabled, Promiscuous.disabled = Promiscuous.disabled, false
6
+ old_current, self.current = self.current, new(*args)
7
+
8
+ begin
9
+ self.current.alt_trace ">>> open >>>", :backtrace => :none if ENV['TRACE']
10
+ yield
11
+ ensure
12
+ self.current.alt_trace "<<< close <<<", :backtrace => :none if ENV['TRACE']
13
+
14
+ self.current.close
15
+ self.current = old_current
16
+ Promiscuous.disabled = old_disabled
17
+ end
18
+ end
19
+
20
+ def self.current
21
+ Thread.current[:promiscuous_context]
22
+ end
23
+
24
+ def self.current=(value)
25
+ Thread.current[:promiscuous_context] = value
26
+ end
27
+
28
+ attr_accessor :name, :operations, :nesting_level, :last_write_dependency
29
+
30
+ def initialize(*args)
31
+ options = args.extract_options!
32
+ @parent = self.class.current unless !!options[:detached_from_parent]
33
+ @last_write_dependency = @parent.try(:last_write_dependency)
34
+ @nesting_level = @parent.try(:nesting_level).to_i + 1
35
+ @name = args.first.try(:to_s)
36
+ @name ||= "#{@parent.next_child_name}" if @parent
37
+ @name ||= 'anonymous'
38
+ @operations = []
39
+ @next_child = 0
40
+
41
+ Promiscuous::AMQP.ensure_connected
42
+ Mongoid::IdentityMap.clear if defined?(Mongoid::IdentityMap)
43
+ end
44
+
45
+ def close
46
+ @parent.try(:close_child, self)
47
+ end
48
+
49
+ def close_child(child)
50
+ @last_write_dependency = child.last_write_dependency if child.last_write_dependency
51
+ end
52
+
53
+ def next_child_name
54
+ @next_child += 1
55
+ "#{name}/#{@next_child}"
56
+ end
57
+
58
+ def add_operation(operation)
59
+ @operations << operation
60
+ trace_operation(operation) if ENV['TRACE']
61
+ end
62
+
63
+ def trace_operation(operation, options={})
64
+ msg = Promiscuous::Error::Dependency.explain_operation(operation, 70)
65
+ trace(msg, options.merge(:color => operation.read? ? '0;32' : '1;31'))
66
+ end
67
+
68
+ def alt_trace(msg, options={})
69
+ trace(msg, options.merge(:alt_fmt => true))
70
+ end
71
+
72
+ def trace(msg, options={})
73
+ backtrace = options[:backtrace]
74
+ alt_fmt = options[:alt_fmt]
75
+ color = alt_fmt ? "1;36" : options[:color]
76
+
77
+ name = "(#{self.name})#{' ' * ([0, 25 - self.name.size].max)}"
78
+ name = ' ' * @nesting_level + name
79
+ STDERR.puts "\e[#{color}m#{name}#{alt_fmt ? '':' '} #{msg}\e[0m"
80
+
81
+ level = ENV['TRACE'].to_i
82
+ if level > 1 && defined?(Rails) && backtrace != :none
83
+ bt = (backtrace || caller)
84
+ .grep(/#{Rails.root}/)
85
+ .map { |line| line.gsub(/#{Rails.root}\/?/, '') }
86
+ .take(level-1)
87
+ .map { |line| "\e[1;#{30}m#{name} #{line}\e[0m" }
88
+ .join("\n")
89
+ STDERR.puts bt
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,72 @@
1
+ require 'erb'
2
+
3
+ module Promiscuous::Publisher::MockGenerator
4
+ def self.generate
5
+ ERB.new(<<-ERB.gsub(/^\s+<%/, '<%').gsub(/^ {6}/, ''), nil, '-').result(binding)
6
+ # ---------------------------------
7
+ # Auto-generated file. Do not edit.
8
+ # ---------------------------------
9
+
10
+ module <%= Promiscuous::Config.app.camelize %>::Publishers
11
+ <% modules.each do |mod| -%>
12
+ <%- if mod.constantize.is_a?(Class) -%>
13
+ class <%= mod %>; end
14
+ <%- else -%>
15
+ module <%= mod %>; end
16
+ <% end -%>
17
+ <% end -%>
18
+
19
+ <% publishers.each do |publisher| -%>
20
+ <% next unless publisher.publish_to -%>
21
+ <% %>
22
+ # ------------------------------------------------------------------
23
+
24
+ class <%= publisher.publish_as %>
25
+ include Promiscuous::Publisher::Model::Mock
26
+ publish :to => '<%= publisher.publish_to %>'
27
+ <% if defined?(Mongoid::Document) && publisher.include?(Mongoid::Document) -%>
28
+ mock :id => :bson
29
+ <% end -%>
30
+ <% %>
31
+ <% attributes_for(publisher).each do |attr| -%>
32
+ publish :<%= attr %>
33
+ <% end -%>
34
+ end
35
+
36
+ <% publisher.descendants.each do |subclass| -%>
37
+ class <%= subclass.publish_as %> < <%= publisher.publish_as %>
38
+ <% attributes_for(subclass, publisher).each do |attr| -%>
39
+ publish :<%= attr %>
40
+ <% end -%>
41
+ end
42
+ <% end -%>
43
+ <% end -%>
44
+ end
45
+ ERB
46
+ end
47
+
48
+ def self.attributes_for(klass, parent=nil)
49
+ attrs = klass.published_attrs
50
+ attrs -= parent.published_attrs if parent
51
+ attrs
52
+ end
53
+
54
+ def self.modules
55
+ publishers
56
+ .map { |publisher| [publisher, *publisher.descendants.map(&:name)] }
57
+ .flatten
58
+ .select { |name| name =~ /::/ }
59
+ .map { |name| name.gsub(/::[^:]+$/, '') }
60
+ .uniq
61
+ .sort
62
+ end
63
+
64
+ def self.publishers
65
+ Promiscuous::Publisher::Model.publishers.values
66
+ .reject { |publisher| publisher.publish_to =~ /^__promiscuous__\// }
67
+ .map { |publisher| [publisher, publisher.descendants] }
68
+ .flatten
69
+ .reject { |publisher| publisher.superclass.respond_to?(:publish_to) &&
70
+ publisher.superclass.publish_to }
71
+ end
72
+ end
@@ -1,90 +1,7 @@
1
- require 'crowdtap_redis_lock'
2
-
3
1
  module Promiscuous::Publisher::Model
4
2
  extend Promiscuous::Autoload
5
- autoload :ActiveRecord, :Mongoid
6
-
7
- extend ActiveSupport::Concern
8
- include Promiscuous::Publisher::Envelope
9
-
10
- mattr_accessor :klasses
11
- self.klasses = []
12
-
13
- def operation
14
- options[:operation]
15
- end
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 payload
26
- super.merge(:id => instance.id, :operation => operation, :version => version)
27
- end
28
-
29
- def include_attributes?
30
- !operation.in? [:destroy, :dummy]
31
- end
32
-
33
- def instance
34
- @new_instance || super
35
- end
36
-
37
- def with_lock(&block)
38
- return yield if Promiscuous::Config.backend == :null
39
- return yield if operation == :create
40
-
41
- key = Promiscuous::Redis.pub_key(instance.id)
42
- # We'll block for 60 seconds before raising an exception
43
- ::RedisLock.new(Promiscuous::Redis, key).retry(300).every(0.2).lock_for_update(&block)
44
- end
45
-
46
- def version
47
- {:global => @global_version}
48
- end
49
-
50
- def update_dependencies
51
- @global_version = Promiscuous::Redis.incr(Promiscuous::Redis.pub_key('global'))
52
- end
53
-
54
- def commit
55
- ret = nil
56
- exception = nil
57
-
58
- Promiscuous::AMQP.ensure_connected
59
-
60
- with_lock do
61
- update_dependencies
62
- begin
63
- ret = yield if block_given?
64
- rescue Exception => e
65
- # we must publish something so the subscriber can sync
66
- # with the updated dependencies
67
- options[:operation] = :dummy
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
- publish
79
-
80
- raise exception if exception
81
- ret
82
- end
3
+ autoload :Base, :ActiveRecord, :Ephemeral, :Mock, :Mongoid
83
4
 
84
- module ClassMethods
85
- def setup_class_binding
86
- super
87
- Promiscuous::Publisher::Model.klasses << klass if klass
88
- end
89
- end
5
+ mattr_accessor :publishers
6
+ self.publishers = {}
90
7
  end