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
@@ -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