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