sidekiq-amigo 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1dc6d4ac6f9e7a89afecc711780ceeeb3ab1204435a19be2683623256b2abc49
4
- data.tar.gz: 725dc4719b949d5f93bd84125ed6d2bea713be872f7e8413e6509d90c9090544
3
+ metadata.gz: 56470f3e16978212a6e8a23d970c7709c0f24854b80c15d522989389e0cc829e
4
+ data.tar.gz: 2bed22f2a190e056aa715814f460ba009fd2c2d3884e6d34eb866084659af962
5
5
  SHA512:
6
- metadata.gz: e1a5e2c7beab44fecabb7d7b7f9f610ce1138029eb247b46c04d90399550d976990f6db36717c73f225c195318ea303b1607984878167dfac4087024e809c735
7
- data.tar.gz: 807e4c88665fd4ac7a6a4004e654de2a697b4ebd7c90546be7f965955ecd84690f2e0f5eebe913d31e2673f32f7bbd560e05695f79154284f3d7bd8a6ee77eb9
6
+ metadata.gz: 18ac44e7cffa487844980f937193ac4601585e380aa08c85599591181271e3ded429271be3407d120e0bf280c541c0f9c28ca23c2c5e9a528deda26c16ca8735
7
+ data.tar.gz: 243229bf9a1f661eb6ef4b9fe847a979634fa729df34e756016f6f2c403ae1e8f73d444e437e640b86d300e38169a391b72f1676a49e985aeac11d41684c4974
@@ -16,18 +16,28 @@ module Amigo
16
16
  end
17
17
 
18
18
  module_function def snapshot_async_state(opts={})
19
- old_hooks = Amigo.subscribers.to_a
19
+ old_subscribers = Amigo.subscribers.to_a
20
20
  old_jobs = Amigo.registered_jobs.to_a
21
21
  old_failure = Amigo.on_publish_error
22
22
 
23
+ new_subscribers = opts.fetch(:subscribers, [])
24
+ new_jobs = opts.fetch(:jobs, [])
25
+
26
+ @active_snapshots ||= 0
27
+ if @active_snapshots.positive?
28
+ new_subscribers = old_subscribers + new_subscribers
29
+ new_jobs = old_jobs = new_jobs
30
+ end
23
31
  begin
24
32
  Amigo.on_publish_error = opts[:on_error] if opts.key?(:on_error)
25
- Amigo.subscribers.replace(opts[:subscribers]) if opts.key?(:subscribers)
26
- Amigo.registered_jobs.replace(opts[:jobs]) if opts.key?(:jobs)
33
+ Amigo.subscribers.replace(new_subscribers) if opts.key?(:subscribers)
34
+ Amigo.registered_jobs.replace(new_jobs) if opts.key?(:jobs)
35
+ @active_snapshots += 1
27
36
  yield
28
37
  ensure
38
+ @active_snapshots -= 1
29
39
  Amigo.on_publish_error = old_failure
30
- Amigo.subscribers.replace(old_hooks)
40
+ Amigo.subscribers.replace(old_subscribers)
31
41
  Amigo.registered_jobs.replace(old_jobs)
32
42
  end
33
43
  end
data/lib/amigo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Amigo
4
- VERSION = "1.2.1"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/amigo.rb CHANGED
@@ -140,7 +140,18 @@ module Amigo
140
140
  # An Array of callbacks to be run when an event is published.
141
141
  attr_accessor :subscribers
142
142
 
143
- # A single callback to be run when an event publication errors.
143
+ # A single callback to be run when an event publication errors,
144
+ # almost always due to an error in a subscriber.
145
+ #
146
+ # The callback receives the exception, the event being published, and the erroring subscriber.
147
+ #
148
+ # If this is not set, errors from subscribers will be re-raised immediately,
149
+ # since broken subscribers usually indicate a broken application.
150
+ #
151
+ # Note also that when an error occurs, Amigo.log is always called first.
152
+ # You do NOT need a callback that just logs and swallows the error.
153
+ # If all you want to do is log, and not propogate the error,
154
+ # you can use `Amigo.on_publish_error = proc {}`.
144
155
  attr_accessor :on_publish_error
145
156
 
146
157
  # Publish an event with the specified +eventname+ and +payload+
@@ -151,12 +162,18 @@ module Amigo
151
162
  self.subscribers.to_a.each do |hook|
152
163
  hook.call(ev)
153
164
  rescue StandardError => e
154
- self.log(nil, :error, "amigo_subscriber_hook_error", error: e, hook: hook, event: ev)
155
- self.on_publish_error.call(e)
165
+ self.log(nil, :error, "amigo_subscriber_hook_error", error: e, hook: hook, event: ev&.as_json)
166
+ raise e if self.on_publish_error.nil?
167
+ if self.on_publish_error.respond_to?(:arity) && self.on_publish_error.arity == 1
168
+ self.on_publish_error.call(e)
169
+ else
170
+ self.on_publish_error.call(e, ev, hook)
171
+ end
156
172
  end
157
173
  end
158
174
 
159
175
  # Register a hook to be called when an event is sent.
176
+ # If a subscriber errors, on_publish_error is called with the exception, event, and subscriber.
160
177
  def register_subscriber(&block)
161
178
  raise LocalJumpError, "no block given" unless block
162
179
  self.log nil, :info, "amigo_installed_subscriber", block: block
@@ -191,7 +208,15 @@ module Amigo
191
208
 
192
209
  def _subscriber(event)
193
210
  event_json = event.as_json
194
- self.audit_logger_class.perform_async(event_json)
211
+ begin
212
+ self.audit_logger_class.perform_async(event_json)
213
+ rescue StandardError => e
214
+ # If the audit logger cannot perform, let's say because Redis is down,
215
+ # we can run the job manually. This is pretty important for anything used for auditing;
216
+ # it should be as resilient as possible.
217
+ self.log(nil, :error, "amigo_audit_log_subscriber_error", error: e, event: event_json)
218
+ self.audit_logger_class.new.perform(event_json)
219
+ end
195
220
  self.router_class.perform_async(event_json)
196
221
  end
197
222
 
@@ -217,6 +242,14 @@ module Amigo
217
242
  end
218
243
 
219
244
  class Event
245
+ # @param topic [String]
246
+ # @param payload [Array]
247
+ # @return [Webhookdb::Event]
248
+ def self.create(topic, payload)
249
+ return self.new(SecureRandom.uuid, topic, payload)
250
+ end
251
+
252
+ # @return [Webhookdb::Event]
220
253
  def self.from_json(o)
221
254
  return self.new(o["id"], o["name"], o["payload"])
222
255
  end
@@ -252,25 +285,11 @@ module Amigo
252
285
  end
253
286
 
254
287
  protected def safe_stringify(o)
255
- return self.deep_stringify_keys(o) if o.is_a?(Hash)
288
+ return o.utc.strftime("%Y-%m-%dT%H:%M:%S.%LZ") if o.is_a?(Time)
289
+ return o.each_with_object({}) { |(k, v), m| m[k.to_s] = safe_stringify(v) } if o.is_a?(Hash)
290
+ return o.map { |x| safe_stringify(x) } if o.is_a?(Array)
256
291
  return o
257
292
  end
258
-
259
- def deep_stringify_keys(hash)
260
- stringified_hash = {}
261
- hash.each do |k, v|
262
- stringified_hash[k.to_s] =
263
- case v
264
- when Hash
265
- self.deep_stringify_keys(v)
266
- when Array
267
- v.map { |i| i.is_a?(Hash) ? self.deep_stringify_keys(i) : i }
268
- else
269
- v
270
- end
271
- end
272
- stringified_hash
273
- end
274
293
  end
275
294
  end
276
295
 
@@ -278,7 +297,6 @@ Amigo.reset_logging
278
297
  Amigo.synchronous_mode = false
279
298
  Amigo.registered_jobs = []
280
299
  Amigo.subscribers = Set.new
281
- Amigo.on_publish_error = proc {}
282
300
 
283
301
  require "amigo/audit_logger"
284
302
  require "amigo/router"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-amigo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lithic Technology
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-05 00:00:00.000000000 Z
11
+ date: 2022-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq