karafka 2.1.10 → 2.1.12

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: 78db49b9cd20426b92ad1a3417b9bc2e79e9efad7f7d11e42873ffda75b850c2
4
- data.tar.gz: 40b2a338c11ad9d6d07fdb0b82f422fe8f64417805db85a9bd111f9bce29039f
3
+ metadata.gz: de7a5880846f3b3cdab696683f4753bebdb6d133648297e930a415949937d1f5
4
+ data.tar.gz: df12badb044151bccbecb3832302182794af543b1740d9a939f984b299bd1521
5
5
  SHA512:
6
- metadata.gz: a522abfbe63ebde9255032b5c6760016a014b8952f8c3f593c754479921408451ac0aeca632ba32d1fcefac78acd97a110e777949f6e70587d454febf5ad34f5
7
- data.tar.gz: d12c97a4829bb0278041ce20e38f21c4894c77a7c9d4b3e4c1c222c502632fe03b0cce3d224f4b8c28ec3743c9c51e41c98a53310761687e92ce587445eae300
6
+ metadata.gz: 17fb8af9c36c3df7e6ef084aab4de9d796710cf6a324cbbac4be29a57dc09f254bac817ec0b44e2a0cf0d2b8aae69ab3834eb59c93bce4d4a540d8000808f31f
7
+ data.tar.gz: 8fedb0f5dfe436bd3854caf5a4ac0da367345be98e059e47ca24dd9d31d414aaf25debc66533965f9fdbdd3b5a78aeb4d719929b1ee274f5f3a36b3737ee2393
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Karafka framework changelog
2
2
 
3
+ ## 2.1.12 (2023-08-25)
4
+ - [Fix] Fix a case where DLQ + VP without intermediate marking would mark earlier message then the last one.
5
+
6
+ ## 2.1.11 (2023-08-23)
7
+ - [Enhancement] Expand the error handling for offset related queries with timeout error retries.
8
+ - [Enhancement] Allow for connection proxy timeouts configuration.
9
+
3
10
  ## 2.1.10 (2023-08-21)
4
11
  - [Enhancement] Introduce `connection.client.rebalance_callback` event for instrumentation of rebalances.
5
12
  - [Refactor] Introduce low level commands proxy to handle deviation in how we want to run certain commands and how rdkafka-ruby runs that by design.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- karafka (2.1.10)
4
+ karafka (2.1.12)
5
5
  karafka-core (>= 2.1.1, < 2.2.0)
6
6
  thor (>= 0.20)
7
7
  waterdrop (>= 2.6.6, < 3.0.0)
@@ -33,7 +33,7 @@ GEM
33
33
  karafka-core (2.1.1)
34
34
  concurrent-ruby (>= 1.1)
35
35
  karafka-rdkafka (>= 0.13.1, < 0.14.0)
36
- karafka-rdkafka (0.13.3)
36
+ karafka-rdkafka (0.13.4)
37
37
  ffi (~> 1.15)
38
38
  mini_portile2 (~> 2.6)
39
39
  rake (> 12)
@@ -26,6 +26,12 @@ en:
26
26
  internal.process_format: needs to be present
27
27
  internal.routing.builder_format: needs to be present
28
28
  internal.routing.subscription_groups_builder_format: needs to be present
29
+ internal.connection.proxy.query_watermark_offsets.timeout_format: needs to be an integer bigger than 0
30
+ internal.connection.proxy.query_watermark_offsets.max_attempts_format: needs to be an integer bigger than 0
31
+ internal.connection.proxy.query_watermark_offsets.wait_time_format: needs to be an integer bigger than 0
32
+ internal.connection.proxy.offsets_for_times.timeout_format: needs to be an integer bigger than 0
33
+ internal.connection.proxy.offsets_for_times.max_attempts_format: needs to be an integer bigger than 0
34
+ internal.connection.proxy.offsets_for_times.wait_time_format: needs to be an integer bigger than 0
29
35
  key_must_be_a_symbol: All keys under the kafka settings scope need to be symbols
30
36
  max_timeout_vs_pause_max_timeout: pause_timeout must be less or equal to pause_max_timeout
31
37
  shutdown_timeout_vs_max_wait_time: shutdown_timeout must be more than max_wait_time
@@ -10,20 +10,13 @@ module Karafka
10
10
  # do still want to be able to alter some functionalities. This wrapper helps us do it when
11
11
  # it would be needed
12
12
  class Proxy < SimpleDelegator
13
- # Timeout on the watermark query
14
- WATERMARK_REQUEST_TIMEOUT = 5_000
13
+ # Errors on which we want to retry
14
+ RETRYABLE_ERRORS = %i[
15
+ all_brokers_down
16
+ timed_out
17
+ ].freeze
15
18
 
16
- # Timeout on the TPL request query
17
- TPL_REQUEST_TIMEOUT = 5_000
18
-
19
- # How many attempts we want to take for something that would end up with all_brokers_down
20
- BROKERS_DOWN_MAX_ATTEMPTS = 3
21
-
22
- # How long should we wait in between all_brokers_down
23
- BROKERS_DOWN_BACKOFF_TIME = 1
24
-
25
- private_constant :WATERMARK_REQUEST_TIMEOUT, :BROKERS_DOWN_MAX_ATTEMPTS,
26
- :BROKERS_DOWN_BACKOFF_TIME, :TPL_REQUEST_TIMEOUT
19
+ private_constant :RETRYABLE_ERRORS
27
20
 
28
21
  attr_accessor :wrapped
29
22
 
@@ -36,6 +29,7 @@ module Karafka
36
29
  # wrap an already wrapped object with another proxy level. Simplifies passing consumers
37
30
  # and makes it safe to wrap without type checking
38
31
  @wrapped = obj.is_a?(self.class) ? obj.wrapped : obj
32
+ @config = ::Karafka::App.config.internal.connection.proxy
39
33
  end
40
34
 
41
35
  # Proxies the `#query_watermark_offsets` with extra recovery from timeout problems.
@@ -46,12 +40,14 @@ module Karafka
46
40
  # @param partition [Partition]
47
41
  # @return [Array<Integer, Integer>] watermark offsets
48
42
  def query_watermark_offsets(topic, partition)
49
- with_brokers_down_retry do
50
- @wrapped.query_watermark_offsets(
51
- topic,
52
- partition,
53
- WATERMARK_REQUEST_TIMEOUT
54
- )
43
+ l_config = @config.query_watermark_offsets
44
+
45
+ with_broker_errors_retry(
46
+ # required to be in seconds, not ms
47
+ wait_time: l_config.wait_time / 1_000.to_f,
48
+ max_attempts: l_config.max_attempts
49
+ ) do
50
+ @wrapped.query_watermark_offsets(topic, partition, l_config.timeout)
55
51
  end
56
52
  end
57
53
 
@@ -61,8 +57,14 @@ module Karafka
61
57
  # @param tpl [Rdkafka::Consumer::TopicPartitionList] tpl to get time offsets
62
58
  # @return [Rdkafka::Consumer::TopicPartitionList] tpl with time offsets
63
59
  def offsets_for_times(tpl)
64
- with_brokers_down_retry do
65
- @wrapped.offsets_for_times(tpl, TPL_REQUEST_TIMEOUT)
60
+ l_config = @config.offsets_for_times
61
+
62
+ with_broker_errors_retry(
63
+ # required to be in seconds, not ms
64
+ wait_time: l_config.wait_time / 1_000.to_f,
65
+ max_attempts: l_config.max_attempts
66
+ ) do
67
+ @wrapped.offsets_for_times(tpl, l_config.timeout)
66
68
  end
67
69
  end
68
70
 
@@ -71,16 +73,20 @@ module Karafka
71
73
  # Runs expected block of code with few retries on all_brokers_down
72
74
  # librdkafka can return `all_brokers_down` for scenarios when broker is overloaded or not
73
75
  # reachable due to latency.
74
- def with_brokers_down_retry
76
+ # @param max_attempts [Integer] how many attempts (not retries) should we take before failing
77
+ # completely.
78
+ # @param wait_time [Integer, Float] how many seconds should we wait. It uses `#sleep` of Ruby
79
+ # so it needs time in seconds.
80
+ def with_broker_errors_retry(max_attempts:, wait_time: 1)
75
81
  attempt ||= 0
76
82
  attempt += 1
77
83
 
78
84
  yield
79
85
  rescue Rdkafka::RdkafkaError => e
80
- raise if e.code != :all_brokers_down
86
+ raise unless RETRYABLE_ERRORS.include?(e.code)
81
87
 
82
- if attempt <= BROKERS_DOWN_MAX_ATTEMPTS
83
- sleep(BROKERS_DOWN_BACKOFF_TIME)
88
+ if attempt <= max_attempts
89
+ sleep(wait_time)
84
90
 
85
91
  retry
86
92
  end
@@ -39,6 +39,22 @@ module Karafka
39
39
  required(:status) { |val| !val.nil? }
40
40
  required(:process) { |val| !val.nil? }
41
41
 
42
+ nested(:connection) do
43
+ nested(:proxy) do
44
+ nested(:query_watermark_offsets) do
45
+ required(:timeout) { |val| val.is_a?(Integer) && val.positive? }
46
+ required(:max_attempts) { |val| val.is_a?(Integer) && val.positive? }
47
+ required(:wait_time) { |val| val.is_a?(Integer) && val.positive? }
48
+ end
49
+
50
+ nested(:offsets_for_times) do
51
+ required(:timeout) { |val| val.is_a?(Integer) && val.positive? }
52
+ required(:max_attempts) { |val| val.is_a?(Integer) && val.positive? }
53
+ required(:wait_time) { |val| val.is_a?(Integer) && val.positive? }
54
+ end
55
+ end
56
+ end
57
+
42
58
  nested(:routing) do
43
59
  required(:builder) { |val| !val.nil? }
44
60
  required(:subscription_groups_builder) { |val| !val.nil? }
@@ -28,7 +28,7 @@ module Karafka
28
28
 
29
29
  # When we encounter non-recoverable message, we skip it and go on with our lives
30
30
  def handle_after_consume
31
- coordinator.on_finished do
31
+ coordinator.on_finished do |last_group_message|
32
32
  return if revoked?
33
33
 
34
34
  if coordinator.success?
@@ -36,7 +36,7 @@ module Karafka
36
36
 
37
37
  return if coordinator.manual_pause?
38
38
 
39
- mark_as_consumed(messages.last)
39
+ mark_as_consumed(last_group_message)
40
40
  elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
41
41
  retry_after_pause
42
42
  # If we've reached number of retries that we could, we need to skip the first
@@ -31,7 +31,7 @@ module Karafka
31
31
  # DLQ flow is standard here, what is not, is the success component where we need to
32
32
  # take into consideration the filtering
33
33
  def handle_after_consume
34
- coordinator.on_finished do
34
+ coordinator.on_finished do |last_group_message|
35
35
  return if revoked?
36
36
 
37
37
  if coordinator.success?
@@ -39,7 +39,7 @@ module Karafka
39
39
 
40
40
  return if coordinator.manual_pause?
41
41
 
42
- mark_as_consumed(messages.last)
42
+ mark_as_consumed(last_group_message)
43
43
 
44
44
  handle_post_filtering
45
45
  elsif coordinator.pause_tracker.attempt <= topic.dead_letter_queue.max_retries
@@ -126,6 +126,32 @@ module Karafka
126
126
  setting :activity_manager, default: Routing::ActivityManager.new
127
127
  end
128
128
 
129
+ # Namespace for internal connection related settings
130
+ setting :connection do
131
+ # Settings that are altered by our client proxy layer
132
+ setting :proxy do
133
+ # Watermark offsets request settings
134
+ setting :query_watermark_offsets do
135
+ # timeout for this request. For busy or remote clusters, this should be high enough
136
+ setting :timeout, default: 5_000
137
+ # How many times should we try to run this call before raising an error
138
+ setting :max_attempts, default: 3
139
+ # How long should we wait before next attempt in case of a failure
140
+ setting :wait_time, default: 1_000
141
+ end
142
+
143
+ # Offsets for times request settings
144
+ setting :offsets_for_times do
145
+ # timeout for this request. For busy or remote clusters, this should be high enough
146
+ setting :timeout, default: 5_000
147
+ # How many times should we try to run this call before raising an error
148
+ setting :max_attempts, default: 3
149
+ # How long should we wait before next attempt in case of a failure
150
+ setting :wait_time, default: 1_000
151
+ end
152
+ end
153
+ end
154
+
129
155
  setting :processing do
130
156
  # option scheduler [Object] scheduler we will be using
131
157
  setting :scheduler, default: Processing::Scheduler.new
@@ -3,5 +3,5 @@
3
3
  # Main module namespace
4
4
  module Karafka
5
5
  # Current Karafka version
6
- VERSION = '2.1.10'
6
+ VERSION = '2.1.12'
7
7
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: karafka
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.10
4
+ version: 2.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -35,7 +35,7 @@ cert_chain:
35
35
  AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
36
36
  msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
37
37
  -----END CERTIFICATE-----
38
- date: 2023-08-21 00:00:00.000000000 Z
38
+ date: 2023-08-25 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: karafka-core
metadata.gz.sig CHANGED
@@ -1,4 +1,4 @@
1
- дy���]���GmM�R#�u��Y�N���SF|�F#�h@��>��=4���h��6�|�)�+Re�2�$�95*]�s< �2T;E ���|)K6��{G􈒟ʪU�L����:���:T�[�M ���_�ZGi��y9;��B�b0u�P�Pi岥��A~ΰ�(��}��Iq@Q��kS�c
2
- 7����
3
- �����].��`�+g��41*,$[��@���B8>���v ����dy9'2
4
- 6Fnv?����'1ߛNzgzV��ɦ�հS�.�P���̑�UPH\�0���H7���:Ɨ(0���͜�|�`�R��[`xm�����Jt0�n���ܝӶv�-���*s��A1Iq:�"AY�
1
+ z�v�xq�]��98f�N��ա]���
2
+ 4W��x���
3
+ �,����1��cG2b�Q�W�����0��πx��K�<ɛ�+x�5M��O�*�� ��]��cZG���:��Z�ل�7!�DB9>֐���
4
+ QXP5�?|!H:�{#M�ߊKc0��^ؙ�����Q MmW���