karafka 2.1.10 → 2.1.12

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: 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���