hanami-events-cloud_pubsub 2.9.0 → 3.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5ffe95cabc82141bd06ee9514ad0af66aaba9c5ebc719190e7cc9efba855274
4
- data.tar.gz: 119b219d3294f50b37a13daa36a4a55edf0d85f5ac14e82676fee3cad62f135a
3
+ metadata.gz: fd0a13431ee107060d1d5df6dac57392e421053f13e58dc9d7144bb01008be12
4
+ data.tar.gz: d71e132eee40d004bf01827de7b5782ae1ca77b909fd884288bb0fc84f6d9a30
5
5
  SHA512:
6
- metadata.gz: a3475491db3dab17ab2fd423c056dca407977321223bd457903b3773bdbd7ef9080b2446e70305e8e64f136d6bd434c157b90ae72bd48f91bd388cb060005ee3
7
- data.tar.gz: 93bd30e26d6a85281f21dfd394f6aa7ea41a340459426f8b280f798e56b1fb3dc857390e6384e8d4605a286cbd313174eab2207e971e0c02374663cd91180744
6
+ metadata.gz: 5740b2f509eca29b70870b32adf7508bdc776a9d2efea0c41540fef600d26464eed902752b8095d5e3f028a04a08d5b13f7bc4b8ad313d24c008b96973542a8e
7
+ data.tar.gz: e75c53c924ab42ca5db76d02217e2e2f82ce83f1ae6e63e85640cfab894380282bca5bad9deeabb64970d88d2788ceaf5aec09999af4d8e8342ec5eac46180fe
@@ -2,9 +2,10 @@
2
2
  inherit_from: .rubocop_todo.yml
3
3
 
4
4
  AllCops:
5
+ NewCops: enable
5
6
  Exclude:
6
7
  - bin/*
7
- TargetRubyVersion: 2.4
8
+ TargetRubyVersion: 2.5
8
9
 
9
10
  Metrics/BlockLength:
10
11
  Exclude:
@@ -1,13 +1,24 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-10-30 15:26:46 -0400 using RuboCop version 0.72.0.
3
+ # on 2020-09-25 19:54:44 UTC using RuboCop version 0.89.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
10
- # Configuration parameters: CountComments, ExcludedMethods.
9
+ # Offense count: 2
10
+ # Cop supports --auto-correct.
11
+ Lint/RedundantCopDisableDirective:
12
+ Exclude:
13
+ - 'lib/hanami/events/adapter/cloud_pubsub.rb'
14
+
15
+ # Offense count: 3
16
+ # Configuration parameters: IgnoredMethods.
17
+ Metrics/AbcSize:
18
+ Max: 21
19
+
20
+ # Offense count: 4
21
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods.
11
22
  Metrics/MethodLength:
12
23
  Max: 14
13
24
 
@@ -16,10 +27,3 @@ Metrics/MethodLength:
16
27
  Style/GlobalVars:
17
28
  Exclude:
18
29
  - 'examples/server.rb'
19
-
20
- # Offense count: 35
21
- # Cop supports --auto-correct.
22
- # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
23
- # URISchemes: http, https
24
- Metrics/LineLength:
25
- Max: 96
@@ -8,9 +8,10 @@ GIT
8
8
  PATH
9
9
  remote: .
10
10
  specs:
11
- hanami-events-cloud_pubsub (2.9.0)
11
+ hanami-events-cloud_pubsub (3.0.0)
12
12
  dry-configurable (>= 0.8)
13
- google-cloud-pubsub (>= 0.38.1, < 1.7)
13
+ gapic-common (>= 0.3.4)
14
+ google-cloud-pubsub (>= 0.38.1, < 2.1)
14
15
  hanami-cli (~> 0.2)
15
16
  hanami-events (~> 0.2.0)
16
17
  rack
@@ -37,26 +38,27 @@ GEM
37
38
  dry-equalizer (0.3.0)
38
39
  faraday (1.0.1)
39
40
  multipart-post (>= 1.2, < 3)
41
+ gapic-common (0.3.4)
42
+ google-protobuf (~> 3.12, >= 3.12.2)
43
+ googleapis-common-protos (>= 1.3.9, < 2.0)
44
+ googleapis-common-protos-types (>= 1.0.4, < 2.0)
45
+ googleauth (~> 0.9)
46
+ grpc (~> 1.25)
40
47
  google-cloud-core (1.5.0)
41
48
  google-cloud-env (~> 1.0)
42
49
  google-cloud-errors (~> 1.0)
43
50
  google-cloud-env (1.3.3)
44
51
  faraday (>= 0.17.3, < 2.0)
45
52
  google-cloud-errors (1.0.1)
46
- google-cloud-pubsub (1.6.1)
53
+ google-cloud-pubsub (2.0.0)
47
54
  concurrent-ruby (~> 1.1)
48
- google-cloud-core (~> 1.2)
49
- google-gax (~> 1.8)
50
- googleapis-common-protos (>= 1.3.9, < 2.0)
51
- googleapis-common-protos-types (>= 1.0.4, < 2.0)
52
- grpc-google-iam-v1 (~> 0.6.9)
53
- google-gax (1.8.1)
54
- google-protobuf (~> 3.9)
55
- googleapis-common-protos (>= 1.3.9, < 2.0)
56
- googleauth (~> 0.9)
57
- grpc (~> 1.24)
58
- rly (~> 0.2.3)
59
- google-protobuf (3.12.4)
55
+ google-cloud-core (~> 1.5)
56
+ google-cloud-pubsub-v1 (~> 0.0)
57
+ google-cloud-pubsub-v1 (0.1.2)
58
+ gapic-common (~> 0.3)
59
+ google-cloud-errors (~> 1.0)
60
+ grpc-google-iam-v1 (>= 0.6.10, < 2.0)
61
+ google-protobuf (3.13.0)
60
62
  googleapis-common-protos (1.3.10)
61
63
  google-protobuf (~> 3.11)
62
64
  googleapis-common-protos-types (>= 1.0.5, < 2.0)
@@ -70,8 +72,8 @@ GEM
70
72
  multi_json (~> 1.11)
71
73
  os (>= 0.9, < 2.0)
72
74
  signet (~> 0.14)
73
- grpc (1.30.2)
74
- google-protobuf (~> 3.12)
75
+ grpc (1.32.0)
76
+ google-protobuf (~> 3.13)
75
77
  googleapis-common-protos-types (~> 1.0)
76
78
  grpc-google-iam-v1 (0.6.10)
77
79
  google-protobuf (~> 3.11)
@@ -83,7 +85,7 @@ GEM
83
85
  hanami-utils (1.3.6)
84
86
  concurrent-ruby (~> 1.0)
85
87
  transproc (~> 1.0)
86
- jwt (2.2.1)
88
+ jwt (2.2.2)
87
89
  memoist (0.16.2)
88
90
  method_source (1.0.0)
89
91
  multi_json (1.15.0)
@@ -96,14 +98,13 @@ GEM
96
98
  pry (0.13.1)
97
99
  coderay (~> 1.1)
98
100
  method_source (~> 1.0)
99
- public_suffix (4.0.5)
101
+ public_suffix (4.0.6)
100
102
  rack (2.2.3)
101
103
  rainbow (3.0.0)
102
104
  rake (13.0.1)
103
105
  regexp_parser (1.7.1)
104
106
  request_id (0.4.3)
105
107
  rexml (3.2.4)
106
- rly (0.2.3)
107
108
  rspec (3.9.0)
108
109
  rspec-core (~> 3.9.0)
109
110
  rspec-expectations (~> 3.9.0)
@@ -12,7 +12,7 @@ Hanami::Events::CloudPubsub.setup
12
12
 
13
13
  pubsub = Google::Cloud::Pubsub.new project_id: 'emulator'
14
14
 
15
- events = Hanami::Events.initialize(:cloud_pubsub, pubsub: pubsub, logger: Logger.new(STDOUT))
15
+ events = Hanami::Events.initialize(:cloud_pubsub, pubsub: pubsub, logger: Logger.new($stdout))
16
16
 
17
17
  3.times do
18
18
  events.broadcast('user.deleted', user_id: 1)
@@ -4,6 +4,8 @@ Hanami::Events::CloudPubsub.configure do |config|
4
4
  config.subscriber.streams = 2
5
5
  config.subscriber.threads.push = 2
6
6
  config.subscriber.threads.callback = 2
7
+ config.auto_retry.enabled = true
8
+ config.auto_retry.dead_letter_topic_name = 'my-dead-letter-topic-name'
7
9
 
8
10
  config.subscriptions_loader = -> do
9
11
  $events.subscribe('user.deleted', id: 'testing-2') do |payload|
@@ -15,6 +15,8 @@ Gem::Specification.new do |spec|
15
15
  spec.homepage = 'https://github.com/adHawk/hanami-events-cloud_pubsub'
16
16
  spec.license = 'MIT'
17
17
 
18
+ spec.required_ruby_version = '>= 2.5.0'
19
+
18
20
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
21
  f.match(%r{^(test|spec|features)/})
20
22
  end
@@ -23,7 +25,8 @@ Gem::Specification.new do |spec|
23
25
  spec.require_paths = ['lib']
24
26
 
25
27
  spec.add_dependency 'dry-configurable', '>= 0.8'
26
- spec.add_dependency 'google-cloud-pubsub', '>= 0.38.1', '< 1.7'
28
+ spec.add_dependency 'gapic-common', '>= 0.3.4'
29
+ spec.add_dependency 'google-cloud-pubsub', '>= 0.38.1', '< 2.1'
27
30
  spec.add_dependency 'hanami-cli', '~> 0.2'
28
31
  spec.add_dependency 'hanami-events', '~> 0.2.0'
29
32
  spec.add_dependency 'rack'
@@ -15,7 +15,7 @@ module Hanami
15
15
 
16
16
  def initialize(params)
17
17
  @pubsub = params[:pubsub]
18
- @logger = params[:logger] || Logger.new(STDOUT)
18
+ @logger = params[:logger] || Logger.new($stdout)
19
19
  @listen = params[:listen] || false
20
20
  @subscribers = Concurrent::Array.new
21
21
  @listeners = Concurrent::Array.new
@@ -29,15 +29,21 @@ module Hanami
29
29
  #
30
30
  # @param event [Symbol, String] the event name
31
31
  # @param payload [Hash] the event data
32
- def broadcast(name, payload, **message_opts)
32
+ def broadcast(name, input_payload, **message_opts)
33
33
  event_name = namespaced(name)
34
34
  topic = topic_for event_name
35
- payload = serializer.serialize(payload)
36
- attributes = { id: SecureRandom.uuid, event_name: event_name }
37
-
38
- middleware.invoke(payload, **attributes, **message_opts) do |*args|
39
- topic.publish_async(*args) do |result|
40
- logger.info "Published event #{result.inspect}"
35
+ serialized_payload = serializer.serialize(input_payload)
36
+ attrs = { id: SecureRandom.uuid, event_name: event_name }
37
+
38
+ middleware.invoke(serialized_payload, **attrs, **message_opts) do |payload, **opts|
39
+ topic.publish_async(payload, **opts) do |result|
40
+ msg = result.message.grpc.to_h
41
+
42
+ if result.succeeded?
43
+ logger.info "Published #{name.inspect} published", **msg
44
+ else
45
+ logger.warn "Failed to broadcast #{name.inspect} event", error: result.error, **msg # rubocop:disable Layout/LineLength
46
+ end
41
47
  end
42
48
  end
43
49
  end
@@ -77,7 +83,8 @@ module Hanami
77
83
  handler: method(:call_subscribers),
78
84
  logger: logger,
79
85
  topic: topic,
80
- subscriber_opts: subscriber_opts
86
+ subscriber_opts: subscriber_opts,
87
+ dead_letter_topic: dead_letter_topic
81
88
  )
82
89
 
83
90
  @listeners << listener
@@ -98,7 +105,7 @@ module Hanami
98
105
  @serializer ||= Hanami::Events::Serializer[@serializer_type].new
99
106
  end
100
107
 
101
- # rubocop:disable Metrics/LineLength
108
+ # rubocop:disable Layout/LineLength
102
109
  def topic_for(name)
103
110
  return @topic_registry[name.to_s] if @topic_registry[name.to_s]
104
111
 
@@ -110,7 +117,15 @@ module Hanami
110
117
 
111
118
  @topic_registry[name.to_s] = topic
112
119
  end
113
- # rubocop:enable Metrics/LineLength
120
+ # rubocop:enable Layout/LineLength
121
+
122
+ def dead_letter_topic
123
+ conf = Hanami::Events::CloudPubsub.config.auto_retry
124
+
125
+ return unless conf.enabled
126
+
127
+ topic_for namespaced(conf.dead_letter_topic_name)
128
+ end
114
129
 
115
130
  def namespaced(val, sep: '.')
116
131
  [Hanami::Events::CloudPubsub.namespace, val].compact.join(sep)
@@ -5,7 +5,6 @@ require 'hanami/events'
5
5
  require 'hanami/events/cloud_pubsub/version'
6
6
  require 'hanami/events/cloud_pubsub/middleware/stack'
7
7
  require 'hanami/events/cloud_pubsub/middleware/logging'
8
- require 'hanami/events/cloud_pubsub/middleware/auto_retry'
9
8
  require 'hanami/events/cloud_pubsub/runner'
10
9
  require 'hanami/events/cloud_pubsub/errors'
11
10
  require 'google/cloud/pubsub'
@@ -32,7 +31,7 @@ module Hanami
32
31
  setting :project_id, reader: true
33
32
  setting :auto_create_subscriptions, false, reader: true
34
33
  setting :auto_create_topics, false, reader: true
35
- setting :logger, Logger.new(STDOUT), reader: true
34
+ setting :logger, Logger.new($stdout), reader: true
36
35
  setting :subscriptions_loader, proc {
37
36
  abort <<~MSG
38
37
  ┌────────────────────────────────────────────────────────────────────────────────┐
@@ -58,8 +57,7 @@ module Hanami
58
57
  ], reader: true
59
58
 
60
59
  middleware_stack = Middleware::Stack.new(
61
- Middleware::Logging.new,
62
- Middleware::AutoRetry.new
60
+ Middleware::Logging.new
63
61
  )
64
62
 
65
63
  begin
@@ -89,6 +87,14 @@ module Hanami
89
87
 
90
88
  setting :on_shutdown_handlers, [], reader: true
91
89
 
90
+ setting :auto_retry do
91
+ setting :enabled, false
92
+ setting :max_attempts, 1200
93
+ setting :dead_letter_topic_name
94
+ setting :minimum_backoff, 30
95
+ setting :maximum_backoff, 600
96
+ end
97
+
92
98
  def self.finalize_settings!
93
99
  conf_hash = config.pubsub
94
100
  conf_hash.each { |key, val| Google::Cloud::Pubsub.configure[key] = val }
@@ -102,8 +102,8 @@ module Hanami
102
102
  end
103
103
 
104
104
  def shutdown
105
- STDOUT.flush
106
- STDERR.flush
105
+ $stdout.flush
106
+ $stderr.flush
107
107
  runner.gracefully_shutdown
108
108
  ensure
109
109
  @finished_shutting_down = true
@@ -5,6 +5,7 @@ require 'hanami/events/cloud_pubsub/safe_error_handler'
5
5
  module Hanami
6
6
  module Events
7
7
  module CloudPubsub
8
+ # rubocop:disable Metrics/ClassLength:
8
9
  # @api private
9
10
  class Listener
10
11
  attr_reader :topic,
@@ -13,8 +14,10 @@ module Hanami
13
14
  :logger,
14
15
  :handler,
15
16
  :event_name,
16
- :subscriber_opts,
17
- :middleware
17
+ :input_subscriber_opts,
18
+ :middleware,
19
+ :dead_letter_topic
20
+
18
21
  # rubocop:disable Metrics/ParameterLists
19
22
  def initialize(topic:,
20
23
  logger:,
@@ -22,25 +25,24 @@ module Hanami
22
25
  event_name:,
23
26
  subscriber_id:,
24
27
  subscriber_opts: {},
25
- middleware: CloudPubsub.config.middleware)
28
+ middleware: CloudPubsub.config.middleware,
29
+ dead_letter_topic: nil)
26
30
  @topic = topic
27
31
  @logger = logger
28
32
  @handler = handler
29
33
  @event_name = event_name
30
34
  @subscriber_id = subscriber_id
31
- @subscriber_opts = CloudPubsub.config.subscriber.to_h.merge(subscriber_opts)
35
+ @input_subscriber_opts = subscriber_opts
32
36
  @middleware = middleware
37
+ @dead_letter_topic = dead_letter_topic
33
38
  end
34
39
  # rubocop:enable Metrics/ParameterLists
35
40
 
36
41
  def register
37
42
  subscription = subscription_for(subscriber_id)
38
-
39
- listener = subscription.listen(**subscriber_opts) do |message|
40
- handle_message(message)
41
- end
42
-
43
- logger.debug("Registered listener for #{subscriber_id} with opts #{subscriber_opts}")
43
+ apply_retry_options(subscription)
44
+ listener = subscription.listen(**subscriber_options) { |m| handle_message(m) }
45
+ logger.debug("Registered listener for #{subscriber_id} with: #{subscriber_options}")
44
46
 
45
47
  @subscriber = listener
46
48
 
@@ -86,6 +88,8 @@ module Hanami
86
88
  rescue StandardError => e
87
89
  run_error_handlers(e, message)
88
90
  raise
91
+ ensure
92
+ message.nack! if CloudPubsub.config.auto_retry.enabled
89
93
  end
90
94
 
91
95
  def subscription_for(name)
@@ -120,7 +124,28 @@ module Hanami
120
124
  "a subscription already exists for #{sub_name} " \
121
125
  "but its name #{found_subscription.topic.name} does not match #{@event_name}"
122
126
  end
127
+
128
+ def subscriber_options
129
+ @subscriber_options ||= {
130
+ **CloudPubsub.config.subscriber.to_h,
131
+ **input_subscriber_opts
132
+ }
133
+ end
134
+
135
+ def apply_retry_options(sub)
136
+ return {} unless CloudPubsub.config.auto_retry.enabled
137
+
138
+ sub.retry_policy = Google::Cloud::PubSub::RetryPolicy.new(
139
+ minimum_backoff: CloudPubsub.config.auto_retry.minimum_backoff,
140
+ maximum_backoff: CloudPubsub.config.auto_retry.maximum_backoff
141
+ )
142
+ sub.dead_letter_topic = dead_letter_topic
143
+ sub.dead_letter_max_delivery_attempts = CloudPubsub.config.auto_retry.max_attempts
144
+
145
+ sub
146
+ end
123
147
  end
148
+ # rubocop:enable Metrics/ClassLength:
124
149
  end
125
150
  end
126
151
  end
@@ -40,14 +40,14 @@ module Hanami
40
40
  @entries.shift
41
41
  end
42
42
 
43
- def invoke(*args)
43
+ def invoke(*args, **kwargs)
44
44
  stack = entries.dup
45
45
 
46
46
  traverse_stack = proc do |**opts|
47
47
  if stack.empty?
48
- yield(*args)
48
+ yield(*args, **kwargs, **opts)
49
49
  else
50
- stack.shift.call(*args, **opts, &traverse_stack)
50
+ stack.shift.call(*args, **kwargs, **opts, &traverse_stack)
51
51
  end
52
52
  end
53
53
 
@@ -86,13 +86,12 @@ module Hanami
86
86
  # some reason.
87
87
  #
88
88
  # See: https://github.com/mperham/sidekiq/blob/e447dae961ebc894f12848d9f33446a07ffc67dc/bin/sidekiqload#L74
89
- # rubocop:disable Metrics/AbcSize
90
89
  def debug_info
91
90
  <<~MSG
92
91
  ╔══════ BACKTRACES
93
92
  #{Thread.list.flat_map { |thr| ThreadInspector.new(thr).to_s }.join("\n")}
94
93
  ╠══════ LISTENERS
95
- #{adapter.listeners.map { |lis| '' + lis.format }.join("\n")}
94
+ #{adapter.listeners.map { |lis| "#{lis.format}" }.join("\n")}
96
95
 
97
96
  ╠══════ GENERAL
98
97
  ║ ready?: #{ready?}
@@ -102,7 +101,6 @@ module Hanami
102
101
  ╚══════
103
102
  MSG
104
103
  end
105
- # rubocop:enable Metrics/AbcSize
106
104
 
107
105
  def sleep_for_a_bit
108
106
  sleep @sleep_time
@@ -114,11 +112,9 @@ module Hanami
114
112
  logger.info('Calling custom on_shutdown handler')
115
113
 
116
114
  CloudPubsub.on_shutdown_handlers.each do |handler|
117
- begin
118
- handler.call(adapter)
119
- rescue StandardError => e
120
- logger.warn("Shutdown handler failed (#{e.message})")
121
- end
115
+ handler.call(adapter)
116
+ rescue StandardError => e
117
+ logger.warn("Shutdown handler failed (#{e.message})")
122
118
  end
123
119
  end
124
120
  end
@@ -48,7 +48,7 @@ module Hanami
48
48
  end
49
49
 
50
50
  def join_backtrace(pretty_backtrace)
51
- pretty_backtrace.map! { |line| "║\t" + line }
51
+ pretty_backtrace.map! { |line| "║\t#{line}" }
52
52
  pretty_backtrace << '║'
53
53
  pretty_backtrace.join("\n")
54
54
  end
@@ -3,7 +3,7 @@
3
3
  module Hanami
4
4
  module Events
5
5
  module CloudPubsub
6
- VERSION = '2.9.0'
6
+ VERSION = '3.0.0'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-events-cloud_pubsub
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Ker-Seymer
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-06 00:00:00.000000000 Z
11
+ date: 2020-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-configurable
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gapic-common
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.4
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: google-cloud-pubsub
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -33,7 +47,7 @@ dependencies:
33
47
  version: 0.38.1
34
48
  - - "<"
35
49
  - !ruby/object:Gem::Version
36
- version: '1.7'
50
+ version: '2.1'
37
51
  type: :runtime
38
52
  prerelease: false
39
53
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +57,7 @@ dependencies:
43
57
  version: 0.38.1
44
58
  - - "<"
45
59
  - !ruby/object:Gem::Version
46
- version: '1.7'
60
+ version: '2.1'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: hanami-cli
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -178,7 +192,6 @@ files:
178
192
  - lib/hanami/events/cloud_pubsub/health_check_server.rb
179
193
  - lib/hanami/events/cloud_pubsub/integration.rb
180
194
  - lib/hanami/events/cloud_pubsub/listener.rb
181
- - lib/hanami/events/cloud_pubsub/middleware/auto_retry.rb
182
195
  - lib/hanami/events/cloud_pubsub/middleware/client/request_id.rb
183
196
  - lib/hanami/events/cloud_pubsub/middleware/logging.rb
184
197
  - lib/hanami/events/cloud_pubsub/middleware/prometheus.rb
@@ -195,7 +208,7 @@ homepage: https://github.com/adHawk/hanami-events-cloud_pubsub
195
208
  licenses:
196
209
  - MIT
197
210
  metadata: {}
198
- post_install_message:
211
+ post_install_message:
199
212
  rdoc_options: []
200
213
  require_paths:
201
214
  - lib
@@ -203,7 +216,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
203
216
  requirements:
204
217
  - - ">="
205
218
  - !ruby/object:Gem::Version
206
- version: '0'
219
+ version: 2.5.0
207
220
  required_rubygems_version: !ruby/object:Gem::Requirement
208
221
  requirements:
209
222
  - - ">="
@@ -211,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
224
  version: '0'
212
225
  requirements: []
213
226
  rubygems_version: 3.1.2
214
- signing_key:
227
+ signing_key:
215
228
  specification_version: 4
216
229
  summary: Google Cloud Pub/Sub adapter for the hanami-events gem
217
230
  test_files: []
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- module Events
5
- module CloudPubsub
6
- # Middleware
7
- module Middleware
8
- # Middleware used for automatically acknowledging messages
9
- class AutoRetry
10
- attr_reader :max_attempts
11
-
12
- def initialize(logger: nil, max_attempts: 1200)
13
- @logger = logger
14
- @max_attempts = max_attempts
15
- end
16
-
17
- def call(message, **args)
18
- succeeded = false
19
- failed = false
20
- yield(**args)
21
- succeeded = true
22
- rescue StandardError => e
23
- failed = true
24
- raise e
25
- ensure
26
- ack_or_reject(message, succeeded, failed, args)
27
- end
28
-
29
- private
30
-
31
- def ack_or_reject(message, succeeded, failed, args)
32
- if succeeded
33
- handle_success(message, args)
34
- elsif failed && max_attempts_reached?(args)
35
- handle_max_attempts_reached(message, args)
36
- elsif failed
37
- handle_failure(message, args)
38
- else
39
- handle_unfinished(message, args)
40
- end
41
- end
42
-
43
- def handle_success(message, _args)
44
- message.acknowledge!
45
- logger.debug "Message(#{message.message_id}) was acknowledged"
46
- end
47
-
48
- def max_attempts_reached?(args)
49
- args.key?(:attempts) && args[:attempts] >= max_attempts
50
- end
51
-
52
- def handle_max_attempts_reached(message, _args)
53
- id = message.message_id
54
- msg = 'number of attempts exceeded max attempts ' \
55
- "of #{max_attempts}, acknowledging message"
56
- logger.debug "Message(#{id}) failed, #{msg}"
57
- message.acknowledge!
58
- end
59
-
60
- def handle_failure(message, args)
61
- id = message.message_id
62
- seconds = calculate_backoff_seconds(message, args)
63
- success = message.modify_ack_deadline!(seconds)
64
- msg = "added #{success ? seconds : 0} seconds of delay to ack deadline"
65
- logger.debug "Message(#{id}) failed, #{msg}" if success
66
- end
67
-
68
- def handle_unfinished(message, _args)
69
- id = message.message_id
70
- message.reject!
71
- logger.warn "Message(#{id}) was terminated from outside, rescheduling"
72
- end
73
-
74
- def logger
75
- @logger || CloudPubsub.logger
76
- end
77
-
78
- def calculate_backoff_seconds(_message, args)
79
- amt = if args.key?(:attempts)
80
- count = args[:attempts]
81
- # min + exponential + random smear
82
- 15 + count**4 + (rand(30) * (count + 1))
83
- else
84
- 60
85
- end
86
-
87
- amt > 600 ? 600 : amt
88
- end
89
- end
90
- end
91
- end
92
- end
93
- end