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
@@ -1,7 +1,9 @@
1
1
  module Promiscuous::Config
2
2
  mattr_accessor :app, :logger, :error_notifier, :backend, :amqp_url,
3
- :redis_url, :queue_options, :heartbeat, :bareback,
4
- :recovery, :prefetch
3
+ :redis_url, :redis_urls, :redis_slave_url, :redis_stats_url,
4
+ :stats_interval, :queue_options, :heartbeat, :bareback,
5
+ :hash_size, :recovery, :prefetch, :recovery_timeout,
6
+ :socket_timeout, :subscriber_threads
5
7
 
6
8
  def self.backend=(value)
7
9
  @@backend = value
@@ -13,17 +15,44 @@ module Promiscuous::Config
13
15
  class_variables.each { |var| class_variable_set(var, nil) }
14
16
  end
15
17
 
16
- def self.configure(&block)
17
- block.call(self)
18
+ def self.best_amqp_backend
19
+ if RUBY_PLATFORM == 'java'
20
+ begin
21
+ require 'hot_bunnies'
22
+ :hot_bunnies
23
+ rescue LoadError
24
+ :bunny
25
+ end
26
+ else
27
+ :bunny
28
+ end
29
+ end
30
+
31
+ def self._configure(&block)
32
+ block.call(self) if block
18
33
 
19
- self.app ||= Rails.application.class.parent_name.underscore rescue nil if defined?(Rails)
20
- self.amqp_url ||= 'amqp://guest:guest@localhost:5672'
21
- self.redis_url ||= 'redis://localhost/'
22
- self.backend ||= :rubyamqp
23
- self.queue_options ||= {:durable => true, :arguments => {'x-ha-policy' => 'all'}}
24
- self.heartbeat ||= 60
25
- self.prefetch ||= 1000
26
- self.logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDERR).tap { |l| l.level = Logger::WARN }
34
+ self.app ||= Rails.application.class.parent_name.underscore rescue nil if defined?(Rails)
35
+ self.amqp_url ||= 'amqp://guest:guest@localhost:5672'
36
+ self.redis_url ||= 'redis://localhost/'
37
+ self.redis_urls ||= [self.redis_url]
38
+ #self.redis_slave_url ||= nil
39
+ self.redis_stats_url ||= self.redis_urls.first
40
+ self.stats_interval ||= 0
41
+ self.socket_timeout ||= 10
42
+ self.backend ||= best_amqp_backend
43
+ self.queue_options ||= {:durable => true, :arguments => {'x-ha-policy' => 'all'}}
44
+ self.heartbeat ||= 60
45
+ self.bareback ||= false
46
+ self.hash_size ||= 2**20 # one million keys ~ 200Mb.
47
+ self.recovery ||= false
48
+ self.prefetch ||= 1000
49
+ self.recovery_timeout ||= 10
50
+ self.logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDERR).tap { |l| l.level = Logger::WARN }
51
+ self.subscriber_threads ||= 10
52
+ end
53
+
54
+ def self.configure(&block)
55
+ self._configure(&block)
27
56
 
28
57
  unless self.app
29
58
  raise "Promiscuous.configure: please give a name to your app with \"config.app = 'your_app_name'\""
@@ -31,6 +60,38 @@ module Promiscuous::Config
31
60
 
32
61
  # amqp connection is done in when setting the backend
33
62
  Promiscuous::Redis.connect
63
+
64
+ hook_fork
65
+ end
66
+
67
+ def self.hook_fork
68
+ return if @fork_hooked
69
+
70
+ Kernel.module_eval do
71
+ alias_method :fork_without_promiscuous, :fork
72
+
73
+ def fork(&block)
74
+ Promiscuous.disconnect
75
+ pid = if block
76
+ fork_without_promiscuous do
77
+ Promiscuous.connect
78
+ block.call
79
+ end
80
+ else
81
+ fork_without_promiscuous
82
+ end
83
+ Promiscuous.connect
84
+ pid
85
+ rescue Exception => e
86
+ puts e
87
+ puts e.backtrace.join("\n")
88
+ raise e
89
+ end
90
+
91
+ module_function :fork
92
+ end
93
+
94
+ @fork_hooked = true
34
95
  end
35
96
 
36
97
  def self.configured?
@@ -0,0 +1,18 @@
1
+ module Promiscuous::Convenience
2
+ extend self
3
+
4
+ def without_promiscuous
5
+ raise "No block given" unless block_given?
6
+ old_disabled, Promiscuous.disabled = Promiscuous.disabled, true
7
+ yield
8
+ ensure
9
+ Promiscuous.disabled = old_disabled
10
+ end
11
+ end
12
+
13
+ class ::Array
14
+ def without_promiscuous
15
+ raise "What is this block?" if block_given?
16
+ self
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ require 'fnv'
2
+
3
+ class Promiscuous::Dependency
4
+ attr_accessor :internal_key, :version
5
+
6
+ def initialize(*args)
7
+ @internal_key = args.join('/')
8
+
9
+ if @internal_key =~ /^[0-9]+$/
10
+ @internal_key = @internal_key.to_i
11
+ @hash = @internal_key
12
+ else
13
+ @hash = FNV.new.fnv1a_32(@internal_key)
14
+
15
+ if Promiscuous::Config.hash_size.to_i > 0
16
+ # We hash dependencies to have a O(1) memory footprint in Redis.
17
+ # The hashing needs to be deterministic across instances in order to
18
+ # function properly.
19
+ @internal_key = @hash % Promiscuous::Config.hash_size.to_i
20
+ @hash = @internal_key
21
+ end
22
+ end
23
+ end
24
+
25
+ def key(role)
26
+ Promiscuous::Key.new(role).join(@internal_key)
27
+ end
28
+
29
+ def redis_node(distributed_redis=nil)
30
+ distributed_redis ||= Promiscuous::Redis.master
31
+ distributed_redis.nodes[@hash % distributed_redis.nodes.size]
32
+ end
33
+
34
+ def as_json(options={})
35
+ @version ? [@internal_key, @version].join(':') : @internal_key
36
+ end
37
+
38
+ def self.parse(payload)
39
+ case payload
40
+ when /^(.+):([0-9]+)$/ then new($1).tap { |d| d.version = $2.to_i }
41
+ when /^(.+)$/ then new($1)
42
+ end
43
+ end
44
+
45
+ def to_s
46
+ as_json.to_s
47
+ end
48
+
49
+ # We need the eql? method to function properly (we use ==, uniq, ...) in operation
50
+ # XXX The version is not taken in account.
51
+ def eql?(other)
52
+ self.internal_key == other.internal_key
53
+ end
54
+ alias == eql?
55
+
56
+ def hash
57
+ self.internal_key.hash
58
+ end
59
+ end
@@ -0,0 +1,36 @@
1
+ module Promiscuous::DSL
2
+ def define(&block)
3
+ instance_eval(&block)
4
+ end
5
+
6
+ def publish(model, options={}, &block)
7
+ Definition.new(:publish, model, options).instance_eval(&block)
8
+ end
9
+
10
+ def subscribe(model, options={}, &block)
11
+ Definition.new(:subscribe, model, options).instance_eval(&block)
12
+ end
13
+
14
+ class Definition
15
+ def initialize(mode, model, options)
16
+ @mode = mode
17
+ @model = model
18
+ @options = options
19
+ @model_class = @model.to_s.singularize.classify.constantize
20
+
21
+ promiscuous_include = mode == :publish ? Promiscuous::Publisher : Promiscuous::Subscriber
22
+ @model_class.class_eval { include promiscuous_include }
23
+ end
24
+
25
+ def attributes(*fields)
26
+ options = fields.extract_options!
27
+ @model_class.__send__(@mode, *fields, @options.merge(options))
28
+ end
29
+
30
+ def track_dependencies_of(field)
31
+ @model_class.track_dependencies_of(field)
32
+ end
33
+
34
+ alias attribute attributes
35
+ end
36
+ end
@@ -1,4 +1,6 @@
1
1
  module Promiscuous::Error
2
2
  extend Promiscuous::Autoload
3
- autoload :Connection, :Publisher, :Subscriber, :Recover
3
+ autoload :Base, :Connection, :Publisher, :Subscriber, :Recovery,
4
+ :Dependency, :MissingContext, :AlreadyProcessed,
5
+ :LockUnavailable, :LostLock
4
6
  end
@@ -0,0 +1,5 @@
1
+ class Promiscuous::Error::AlreadyProcessed < Promiscuous::Error::Base
2
+ def to_s
3
+ "Skipping message (already processed)"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ class Promiscuous::Error::Base < RuntimeError; end
@@ -1,17 +1,19 @@
1
- class Promiscuous::Error::Connection < RuntimeError
1
+ class Promiscuous::Error::Connection < Promiscuous::Error::Base
2
2
  attr_accessor :service, :url
3
3
 
4
4
  def initialize(options={})
5
5
  super(nil)
6
6
  self.service = options[:service]
7
- self.url = Promiscuous::Config.__send__("#{service}_url")
7
+ self.url = case service
8
+ when :zookeeper then "zookeeper://#{Promiscuous::Config.zookeeper_hosts}"
9
+ when :redis then Promiscuous::Config.redis_url
10
+ when :amqp then Promiscuous::Config.amqp_url
11
+ end
8
12
  end
9
13
 
10
14
  def message
11
15
  "Lost connection with #{url}"
12
16
  end
13
17
 
14
- def to_s
15
- message
16
- end
18
+ alias to_s message
17
19
  end
@@ -0,0 +1,111 @@
1
+ class Promiscuous::Error::Dependency < Promiscuous::Error::Base
2
+ attr_accessor :dependency_solutions, :operation, :context
3
+
4
+ def initialize(options={})
5
+ self.operation = options[:operation]
6
+ self.context = Promiscuous::Publisher::Context.current
7
+ end
8
+
9
+ # TODO Convert all that with Erb
10
+
11
+ def message
12
+ msg = nil
13
+ case operation.operation
14
+ when :read
15
+ msg = "Promiscuous doesn't have any tracked dependencies to perform this multi read operation.\n" +
16
+ "This is what you can do:\n\n" +
17
+ " 1. Bypass Promiscuous\n\n" +
18
+ " If you don't use the result of this operation in your following writes,\n" +
19
+ " you can wrap your read query in a 'without_promiscuous { }' block.\n" +
20
+ " This is the preferred solution when you are sure that the read doesn't\n" +
21
+ " influence the value of a published attribute.\n\n" +
22
+ " Rule of thumb: Predicates (methods ending with ?) are often suitable for this use case.\n\n"
23
+ cnt = 2
24
+ if operation.operation_ext != :count
25
+ msg += " #{cnt}. Synchronize on individual instances\n\n" +
26
+ " If the collection you are iterating through is small (<10), it becomes intersting\n" +
27
+ " to track instances through their ids instead of the query selector. Example:\n\n" +
28
+ " criteria.without_promiscuous.each do |doc|\n" +
29
+ " next if doc.should_do_something?\n" +
30
+ " doc.reload # tell promiscuous to track the instance\n" +
31
+ " doc.do_something!\n" +
32
+ " end\n\n"
33
+ cnt += 1
34
+ end
35
+ if operation.selector_keys.present?
36
+ msg += " #{cnt}. Track New Dependencies\n\n" +
37
+ " Add #{operation.selector_keys.count == 1 ? "the following line" : "one of the following lines"} " +
38
+ "in the #{operation.instance.class} model:\n\n" +
39
+ " class #{operation.instance.class}\n" +
40
+ operation.selector_keys.map { |field| " track_dependencies_of :#{field}" }.join("\n") + "\n" +
41
+ " end\n\n" +
42
+ (operation.selector_keys.count > 1 ?
43
+ " The more specific field, the better. Promiscuous works better when working with small subsets\n" +
44
+ " For example, tracking something like 'member_id' is a fairly safe choice.\n\n" : "") +
45
+ " Note that dependency tracking slows down your writes. It can be seen as the analogous\n" +
46
+ " of an index on a regular database.\n" +
47
+ " You may find more information about the implications in the Promiscuous wiki (TODO:link).\n\n"
48
+ end
49
+ when :update
50
+ msg = "Promiscuous cannot track dependencies of a multi update operation.\n" +
51
+ "This is what you can do:\n\n" +
52
+ " 1. Instead of doing a multi updates, update each instance separately\n\n" +
53
+ " 2. Do not assign has_many associations directly, but use the << operator instead.\n\n"
54
+ when :destroy
55
+ msg = "Promiscuous cannot track dependencies of a multi delete operation.\n" +
56
+ "This is what you can do:\n\n" +
57
+ " 1. Instead of doing a multi delete, delete each instance separatly.\n\n" +
58
+ " 2. Use destroy_all instead of destroy_all.\n\n" +
59
+ " 3. Declare your has_many relationships with :dependent => :destroy instead of :delete.\n\n"
60
+ end
61
+
62
+ msg += "#{"-" * 100}\n\n"
63
+
64
+ msg += "Promiscuous cannot allow the following "
65
+ case operation.operation_ext || operation.operation
66
+ when :count then msg += 'count'
67
+ when :mapreduce then msg += 'mapreduce'
68
+ when :read then msg += 'each loop'
69
+ when :update then msg += 'multi update'
70
+ when :destroy then msg += 'multi destroy'
71
+ end
72
+ msg += " in the '#{context.name}' context:\n\n"
73
+ msg += " #{self.class.explain_operation(self.operation)}"
74
+ msg += "\n\nProTip: Try again with TRACE=2 in the shell or ENV['TRACE']='2' in the console.\n" unless ENV['TRACE']
75
+ msg
76
+ rescue Exception => e
77
+ "#{e.to_s}\n#{e.backtrace.join("\n")}"
78
+ end
79
+
80
+ def self.explain_operation(operation, limit=100)
81
+ instance = operation.instance
82
+ selector = instance ? get_selector(instance.attributes, limit) : ""
83
+ class_name = instance ? instance.class : "Unknown"
84
+
85
+ if operation.operation == :create
86
+ "#{instance.class}.create(#{selector})"
87
+ else
88
+ case operation.operation_ext || operation.operation
89
+ when :count then verb = 'count'
90
+ when :mapreduce then verb = 'mapreduce(...)'
91
+ when :read then verb = operation.multi? ? 'each { ... }' : 'first'
92
+ when :update then verb = operation.multi? ? 'update_all' : 'update'
93
+ when :destroy then verb = operation.multi? ? 'delete_all' : 'delete'
94
+ end
95
+ msg = "#{class_name}#{selector.present? ? ".where(#{selector})" : ""}.#{verb}"
96
+ if operation.operation == :update && operation.respond_to?(:change) && operation.change
97
+ msg += "(#{get_selector(operation.change, limit)})"
98
+ end
99
+ msg
100
+ end
101
+ end
102
+
103
+ def self.get_selector(attributes, limit=100)
104
+ attributes = attributes['$set'] if attributes.count == 1 && attributes['$set']
105
+ selector = attributes.map { |k,v| ":#{k} => #{v}" }.join(", ")
106
+ selector = "#{selector[0...(limit-3)]}..." if selector.size > limit
107
+ selector
108
+ end
109
+
110
+ alias to_s message
111
+ end
@@ -0,0 +1,12 @@
1
+ class Promiscuous::Error::LockUnavailable < Promiscuous::Error::Base
2
+ def initialize(lock)
3
+ @lock = lock
4
+ end
5
+
6
+ def message
7
+ "The lock is not available on #{@lock}\n" +
8
+ "If an app instance died, the lock will expire in less than a minute."
9
+ end
10
+
11
+ alias to_s message
12
+ end
@@ -0,0 +1,12 @@
1
+ class Promiscuous::Error::LostLock < Promiscuous::Error::Base
2
+ def initialize(lock)
3
+ @lock = lock
4
+ end
5
+
6
+ def message
7
+ "The following lock was lost during the operation and will be recovered if not already done:\n" +
8
+ " #{@lock}"
9
+ end
10
+
11
+ alias to_s message
12
+ end
@@ -0,0 +1,29 @@
1
+ class Promiscuous::Error::MissingContext < Promiscuous::Error::Base
2
+ def message
3
+ require 'erb'
4
+ ERB.new(<<-ERB.gsub(/^\s+<%/, '<%').gsub(/^ {6}/, ''), nil, '-').result(binding)
5
+ Promiscuous needs to execute all your read/write queries in a context for publishing.
6
+ This is what you can do:
7
+ 1. Wrap your operations in a Promiscuous context yourself (jobs, etc.):
8
+
9
+ Promiscuous::Middleware.with_context 'jobs/name' do
10
+ # Code including all your read and write queries
11
+ end
12
+
13
+ 2. Disable Promiscuous completely (only for testing):
14
+
15
+ RSpec.configure do |config|
16
+ config.around do |example|
17
+ without_promiscuous { example.run }
18
+ end
19
+ end
20
+
21
+ Note that opening a context will reactivate promiscuous temporarily
22
+ even if it was disabled.
23
+
24
+ 3. You are in render() in the Rails controller, and you should not write.
25
+ ERB
26
+ end
27
+
28
+ alias to_s message
29
+ end
@@ -1,5 +1,5 @@
1
- class Promiscuous::Error::Publisher < RuntimeError
2
- attr_accessor :inner, :instance, :payload, :out_of_sync
1
+ class Promiscuous::Error::Publisher < Promiscuous::Error::Base
2
+ attr_accessor :inner, :instance, :payload
3
3
 
4
4
  def initialize(inner, options={})
5
5
  super(nil)
@@ -8,24 +8,14 @@ class Promiscuous::Error::Publisher < RuntimeError
8
8
  self.inner = inner
9
9
  self.instance = options[:instance]
10
10
  self.payload = options[:payload]
11
- self.out_of_sync = options[:out_of_sync]
12
11
  end
13
12
 
14
13
  def message
15
14
  msg = "#{inner.class}: #{inner.message}"
16
- if instance
17
- msg = "#{msg} while publishing #{instance.inspect}"
18
- msg = "FATAL (out of sync) #{msg}" if out_of_sync
19
- end
20
-
21
- if payload
22
- msg = "#{msg} payload: #{payload}"
23
- end
24
-
15
+ msg = "#{msg} while publishing #{instance.inspect}" if instance
16
+ msg = "#{msg} payload: #{payload}" if payload
25
17
  msg
26
18
  end
27
19
 
28
- def to_s
29
- message
30
- end
20
+ alias to_s message
31
21
  end