karafka 2.2.14 → 2.3.0.alpha2

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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/ci.yml +38 -12
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +24 -0
  6. data/Gemfile.lock +16 -16
  7. data/README.md +0 -2
  8. data/SECURITY.md +23 -0
  9. data/bin/integrations +1 -1
  10. data/config/locales/errors.yml +7 -1
  11. data/config/locales/pro_errors.yml +22 -0
  12. data/docker-compose.yml +1 -1
  13. data/karafka.gemspec +2 -2
  14. data/lib/karafka/admin/acl.rb +287 -0
  15. data/lib/karafka/admin.rb +9 -13
  16. data/lib/karafka/app.rb +5 -3
  17. data/lib/karafka/base_consumer.rb +9 -1
  18. data/lib/karafka/cli/base.rb +1 -1
  19. data/lib/karafka/connection/client.rb +83 -76
  20. data/lib/karafka/connection/conductor.rb +28 -0
  21. data/lib/karafka/connection/listener.rb +159 -42
  22. data/lib/karafka/connection/listeners_batch.rb +5 -11
  23. data/lib/karafka/connection/manager.rb +72 -0
  24. data/lib/karafka/connection/messages_buffer.rb +12 -0
  25. data/lib/karafka/connection/proxy.rb +17 -0
  26. data/lib/karafka/connection/status.rb +75 -0
  27. data/lib/karafka/contracts/config.rb +14 -10
  28. data/lib/karafka/contracts/consumer_group.rb +9 -1
  29. data/lib/karafka/contracts/topic.rb +3 -1
  30. data/lib/karafka/errors.rb +17 -0
  31. data/lib/karafka/instrumentation/logger_listener.rb +3 -0
  32. data/lib/karafka/instrumentation/notifications.rb +13 -5
  33. data/lib/karafka/instrumentation/vendors/appsignal/metrics_listener.rb +31 -28
  34. data/lib/karafka/instrumentation/vendors/datadog/logger_listener.rb +20 -1
  35. data/lib/karafka/instrumentation/vendors/datadog/metrics_listener.rb +15 -12
  36. data/lib/karafka/instrumentation/vendors/kubernetes/liveness_listener.rb +39 -36
  37. data/lib/karafka/pro/base_consumer.rb +47 -0
  38. data/lib/karafka/pro/connection/manager.rb +269 -0
  39. data/lib/karafka/pro/connection/multiplexing/listener.rb +40 -0
  40. data/lib/karafka/pro/iterator/tpl_builder.rb +1 -1
  41. data/lib/karafka/pro/iterator.rb +1 -6
  42. data/lib/karafka/pro/loader.rb +14 -0
  43. data/lib/karafka/pro/processing/coordinator.rb +2 -1
  44. data/lib/karafka/pro/processing/executor.rb +37 -0
  45. data/lib/karafka/pro/processing/expansions_selector.rb +32 -0
  46. data/lib/karafka/pro/processing/jobs/periodic.rb +41 -0
  47. data/lib/karafka/pro/processing/jobs/periodic_non_blocking.rb +32 -0
  48. data/lib/karafka/pro/processing/jobs_builder.rb +14 -3
  49. data/lib/karafka/pro/processing/offset_metadata/consumer.rb +44 -0
  50. data/lib/karafka/pro/processing/offset_metadata/fetcher.rb +131 -0
  51. data/lib/karafka/pro/processing/offset_metadata/listener.rb +46 -0
  52. data/lib/karafka/pro/processing/schedulers/base.rb +39 -23
  53. data/lib/karafka/pro/processing/schedulers/default.rb +12 -14
  54. data/lib/karafka/pro/processing/strategies/default.rb +154 -1
  55. data/lib/karafka/pro/processing/strategies/dlq/default.rb +39 -0
  56. data/lib/karafka/pro/processing/strategies/vp/default.rb +65 -25
  57. data/lib/karafka/pro/processing/virtual_offset_manager.rb +41 -11
  58. data/lib/karafka/pro/routing/features/long_running_job/topic.rb +2 -0
  59. data/lib/karafka/pro/routing/features/multiplexing/config.rb +38 -0
  60. data/lib/karafka/pro/routing/features/multiplexing/contracts/topic.rb +114 -0
  61. data/lib/karafka/pro/routing/features/multiplexing/patches/contracts/consumer_group.rb +42 -0
  62. data/lib/karafka/pro/routing/features/multiplexing/proxy.rb +38 -0
  63. data/lib/karafka/pro/routing/features/multiplexing/subscription_group.rb +42 -0
  64. data/lib/karafka/pro/routing/features/multiplexing/subscription_groups_builder.rb +40 -0
  65. data/lib/karafka/pro/routing/features/multiplexing.rb +59 -0
  66. data/lib/karafka/pro/routing/features/non_blocking_job/topic.rb +32 -0
  67. data/lib/karafka/pro/routing/features/non_blocking_job.rb +37 -0
  68. data/lib/karafka/pro/routing/features/offset_metadata/config.rb +33 -0
  69. data/lib/karafka/pro/routing/features/offset_metadata/contracts/topic.rb +42 -0
  70. data/lib/karafka/pro/routing/features/offset_metadata/topic.rb +65 -0
  71. data/lib/karafka/pro/routing/features/offset_metadata.rb +40 -0
  72. data/lib/karafka/pro/routing/features/patterns/contracts/consumer_group.rb +4 -0
  73. data/lib/karafka/pro/routing/features/patterns/detector.rb +18 -10
  74. data/lib/karafka/pro/routing/features/periodic_job/config.rb +37 -0
  75. data/lib/karafka/pro/routing/features/periodic_job/contracts/topic.rb +44 -0
  76. data/lib/karafka/pro/routing/features/periodic_job/topic.rb +94 -0
  77. data/lib/karafka/pro/routing/features/periodic_job.rb +27 -0
  78. data/lib/karafka/pro/routing/features/virtual_partitions/config.rb +1 -0
  79. data/lib/karafka/pro/routing/features/virtual_partitions/contracts/topic.rb +1 -0
  80. data/lib/karafka/pro/routing/features/virtual_partitions/topic.rb +7 -2
  81. data/lib/karafka/process.rb +5 -3
  82. data/lib/karafka/processing/coordinator.rb +5 -1
  83. data/lib/karafka/processing/executor.rb +16 -10
  84. data/lib/karafka/processing/executors_buffer.rb +19 -4
  85. data/lib/karafka/processing/schedulers/default.rb +3 -2
  86. data/lib/karafka/processing/strategies/default.rb +6 -0
  87. data/lib/karafka/processing/strategies/dlq.rb +36 -0
  88. data/lib/karafka/routing/builder.rb +12 -2
  89. data/lib/karafka/routing/consumer_group.rb +5 -5
  90. data/lib/karafka/routing/features/base.rb +44 -8
  91. data/lib/karafka/routing/features/dead_letter_queue/config.rb +6 -1
  92. data/lib/karafka/routing/features/dead_letter_queue/contracts/topic.rb +1 -0
  93. data/lib/karafka/routing/features/dead_letter_queue/topic.rb +9 -2
  94. data/lib/karafka/routing/subscription_group.rb +2 -2
  95. data/lib/karafka/routing/subscription_groups_builder.rb +11 -2
  96. data/lib/karafka/routing/topic.rb +8 -10
  97. data/lib/karafka/runner.rb +13 -3
  98. data/lib/karafka/server.rb +5 -9
  99. data/lib/karafka/setup/config.rb +17 -0
  100. data/lib/karafka/status.rb +23 -14
  101. data/lib/karafka/templates/karafka.rb.erb +7 -0
  102. data/lib/karafka/time_trackers/partition_usage.rb +56 -0
  103. data/lib/karafka/version.rb +1 -1
  104. data.tar.gz.sig +0 -0
  105. metadata +42 -10
  106. metadata.gz.sig +0 -0
  107. data/lib/karafka/connection/consumer_group_coordinator.rb +0 -48
@@ -0,0 +1,287 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Karafka
4
+ module Admin
5
+ # Struct and set of operations for ACLs management that simplifies their usage.
6
+ # It allows to use Ruby symbol based definitions instead of usage of librdkafka types
7
+ # (it allows to use rdkafka numerical types as well out of the box)
8
+ #
9
+ # We map the numerical values because they are less descriptive and harder to follow.
10
+ #
11
+ # This API works based on ability to create a `Karafka:Admin::Acl` object that can be then used
12
+ # using `#create`, `#delete` and `#describe` class API.
13
+ class Acl
14
+ # Types of resources for which we can assign permissions.
15
+ #
16
+ # Resource refers to any entity within the Kafka ecosystem for which access control can be
17
+ # managed using ACLs (Access Control Lists).
18
+ # These resources represent different components of Kafka, such as topics, consumer groups,
19
+ # and the Kafka cluster itself. ACLs can be applied to these resources to control and
20
+ # restrict reading, writing, and administrative operations, ensuring secure and authorized
21
+ # access to Kafka's functionalities.
22
+ RESOURCE_TYPES_MAP = {
23
+ # `:any` is only used for lookups and cannot be used for permission assignments
24
+ any: Rdkafka::Bindings::RD_KAFKA_RESOURCE_ANY,
25
+ # use when you want to assign acl to a given topic
26
+ topic: Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC,
27
+ # use when you want to assign acl to a given consumer group
28
+ consumer_group: Rdkafka::Bindings::RD_KAFKA_RESOURCE_GROUP,
29
+ # use when you want to assign acl to a given broker
30
+ broker: Rdkafka::Bindings::RD_KAFKA_RESOURCE_BROKER
31
+ }.freeze
32
+
33
+ # Resource pattern types define how ACLs (Access Control Lists) are applied to resources,
34
+ # specifying the scope and applicability of access rules.
35
+ # They determine whether an ACL should apply to a specific named resource, a prefixed group
36
+ # of resources, or all resources of a particular type.
37
+ RESOURCE_PATTERNS_TYPE_MAP = {
38
+ # `:any` is only used for lookups and cannot be used for permission assignments
39
+ any: Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_ANY,
40
+ # Targets resources with a pattern matching for broader control with a single rule.
41
+ match: Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_MATCH,
42
+ # Targets a specific named resource, applying ACLs directly to that resource.
43
+ literal: Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL,
44
+ # Applies ACLs to all resources with a common name prefix, enabling broader control with a
45
+ # single rule.
46
+ prefixed: Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_PREFIXED
47
+ }.freeze
48
+
49
+ # ACL operations define the actions that can be performed on Kafka resources. Each operation
50
+ # represents a specific type of access or action that can be allowed or denied.
51
+ OPERATIONS_MAP = {
52
+ # `:any` is only used for lookups
53
+ any: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_ANY,
54
+ # Grants complete access to a resource, encompassing all possible operations,
55
+ # typically used for unrestricted control.
56
+ all: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_ALL,
57
+ # Grants the ability to read data from a topic or a consumer group.
58
+ read: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ,
59
+ # Allows for writing data on a topic.
60
+ write: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_WRITE,
61
+ # Permits the creation of topics or consumer groups.
62
+ create: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_CREATE,
63
+ # Enables the deletion of topics.
64
+ delete: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_DELETE,
65
+ # Allows modification of topics or consumer groups.
66
+ alter: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_ALTER,
67
+ # Grants the ability to view metadata and configurations of topics or consumer groups.
68
+ describe: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_DESCRIBE,
69
+ # Permits actions that apply to the Kafka cluster, like broker management.
70
+ cluster_action: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_CLUSTER_ACTION,
71
+ # Allows viewing configurations for resources like topics and brokers.
72
+ describe_configs: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_DESCRIBE_CONFIGS,
73
+ # Enables modification of configurations for resources.
74
+ alter_configs: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_ALTER_CONFIGS,
75
+ # Grants the ability to perform idempotent writes, ensuring exactly-once semantics in
76
+ # message production.
77
+ idempotent_write: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_IDEMPOTENT_WRITE
78
+ }.freeze
79
+
80
+ # ACL permission types specify the nature of the access control applied to Kafka resources.
81
+ # These types are used to either grant or deny specified operations.
82
+ PERMISSION_TYPES_MAP = {
83
+ # Used for lookups, indicating no specific permission type.
84
+ any: Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ANY,
85
+ # Grants the specified operations, enabling the associated actions on the resource.
86
+ allow: Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW,
87
+ # Blocks the specified operations, preventing the associated actions on the resource.
88
+ deny: Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_DENY
89
+ }.freeze
90
+
91
+ # Array with all maps used for the Acls support
92
+ ALL_MAPS = [
93
+ RESOURCE_TYPES_MAP,
94
+ RESOURCE_PATTERNS_TYPE_MAP,
95
+ OPERATIONS_MAP,
96
+ PERMISSION_TYPES_MAP
97
+ ].freeze
98
+
99
+ private_constant :RESOURCE_TYPES_MAP, :RESOURCE_PATTERNS_TYPE_MAP, :OPERATIONS_MAP,
100
+ :PERMISSION_TYPES_MAP, :ALL_MAPS
101
+
102
+ # Class level APIs that operate on Acl instances and/or return Acl instances.
103
+ # @note For the sake of consistency all methods from this API return array of Acls
104
+ class << self
105
+ # Creates (unless already present) a given ACL rule in Kafka
106
+ # @param acl [Acl]
107
+ # @return [Array<Acl>] created acls
108
+ def create(acl)
109
+ with_admin_wait do |admin|
110
+ admin.create_acl(**acl.to_native_hash)
111
+ end
112
+
113
+ [acl]
114
+ end
115
+
116
+ # Removes acls matching provide acl pattern.
117
+ # @param acl [Acl]
118
+ # @return [Array<Acl>] deleted acls
119
+ # @note More than one Acl may be removed if rules match that way
120
+ def delete(acl)
121
+ result = with_admin_wait do |admin|
122
+ admin.delete_acl(**acl.to_native_hash)
123
+ end
124
+
125
+ result.deleted_acls.map do |result_acl|
126
+ from_rdkafka(result_acl)
127
+ end
128
+ end
129
+
130
+ # Takes an Acl definition and describes all existing Acls matching its criteria
131
+ # @param acl [Acl]
132
+ # @return [Array<Acl>] described acls
133
+ def describe(acl)
134
+ result = with_admin_wait do |admin|
135
+ admin.describe_acl(**acl.to_native_hash)
136
+ end
137
+
138
+ result.acls.map do |result_acl|
139
+ from_rdkafka(result_acl)
140
+ end
141
+ end
142
+
143
+ # Returns all acls on a cluster level
144
+ # @return [Array<Acl>] all acls
145
+ def all
146
+ describe(
147
+ new(
148
+ resource_type: :any,
149
+ resource_name: nil,
150
+ resource_pattern_type: :any,
151
+ principal: nil,
152
+ operation: :any,
153
+ permission_type: :any,
154
+ host: '*'
155
+ )
156
+ )
157
+ end
158
+
159
+ private
160
+
161
+ # Yields admin instance, allows to run Acl operations and awaits on the final result
162
+ # Makes sure that admin is closed afterwards.
163
+ def with_admin_wait
164
+ Admin.with_admin do |admin|
165
+ yield(admin).wait(max_wait_timeout: Karafka::App.config.admin.max_wait_time)
166
+ end
167
+ end
168
+
169
+ # Takes a rdkafka Acl result and converts it into our local Acl representation. Since the
170
+ # rdkafka Acl object is an integer based on on types, etc we remap it into our "more" Ruby
171
+ # form.
172
+ #
173
+ # @param rdkafka_acl [Rdkafka::Admin::AclBindingResult]
174
+ # return [Acl] mapped acl
175
+ def from_rdkafka(rdkafka_acl)
176
+ new(
177
+ resource_type: rdkafka_acl.matching_acl_resource_type,
178
+ resource_name: rdkafka_acl.matching_acl_resource_name,
179
+ resource_pattern_type: rdkafka_acl.matching_acl_pattern_type,
180
+ principal: rdkafka_acl.matching_acl_principal,
181
+ host: rdkafka_acl.matching_acl_host,
182
+ operation: rdkafka_acl.matching_acl_operation,
183
+ permission_type: rdkafka_acl.matching_acl_permission_type
184
+ )
185
+ end
186
+ end
187
+
188
+ attr_reader :resource_type, :resource_name, :resource_pattern_type, :principal, :host,
189
+ :operation, :permission_type
190
+
191
+ # Initializes a new Acl instance with specified attributes.
192
+ #
193
+ # @param resource_type [Symbol, Integer] Specifies the type of Kafka resource
194
+ # (like :topic, :consumer_group).
195
+ # Accepts either a symbol from RESOURCE_TYPES_MAP or a direct rdkafka numerical type.
196
+ # @param resource_name [String, nil] The name of the Kafka resource
197
+ # (like a specific topic name). Can be nil for certain types of resource pattern types.
198
+ # @param resource_pattern_type [Symbol, Integer] Determines how the ACL is applied to the
199
+ # resource. Uses a symbol from RESOURCE_PATTERNS_TYPE_MAP or a direct rdkafka numerical
200
+ # type.
201
+ # @param principal [String, nil] Specifies the principal (user or client) for which the ACL
202
+ # is being defined. Can be nil if not applicable.
203
+ # @param host [String] (default: '*') Defines the host from which the principal can access
204
+ # the resource. Defaults to '*' for all hosts.
205
+ # @param operation [Symbol, Integer] Indicates the operation type allowed or denied by the
206
+ # ACL. Uses a symbol from OPERATIONS_MAP or a direct rdkafka numerical type.
207
+ # @param permission_type [Symbol, Integer] Specifies whether to allow or deny the specified
208
+ # operation. Uses a symbol from PERMISSION_TYPES_MAP or a direct rdkafka numerical type.
209
+ #
210
+ # Each parameter is mapped to its corresponding value in the respective *_MAP constant,
211
+ # allowing usage of more descriptive Ruby symbols instead of numerical types.
212
+ def initialize(
213
+ resource_type:,
214
+ resource_name:,
215
+ resource_pattern_type:,
216
+ principal:,
217
+ host: '*',
218
+ operation:,
219
+ permission_type:
220
+ )
221
+ @resource_type = map(resource_type, RESOURCE_TYPES_MAP)
222
+ @resource_name = resource_name
223
+ @resource_pattern_type = map(resource_pattern_type, RESOURCE_PATTERNS_TYPE_MAP)
224
+ @principal = principal
225
+ @host = host
226
+ @operation = map(operation, OPERATIONS_MAP)
227
+ @permission_type = map(permission_type, PERMISSION_TYPES_MAP)
228
+ freeze
229
+ end
230
+
231
+ # Converts the Acl into a hash with native rdkafka types
232
+ # @return [Hash] hash with attributes matching rdkafka numerical types
233
+ def to_native_hash
234
+ {
235
+ resource_type: remap(resource_type, RESOURCE_TYPES_MAP),
236
+ resource_name: resource_name,
237
+ resource_pattern_type: remap(resource_pattern_type, RESOURCE_PATTERNS_TYPE_MAP),
238
+ principal: principal,
239
+ host: host,
240
+ operation: remap(operation, OPERATIONS_MAP),
241
+ permission_type: remap(permission_type, PERMISSION_TYPES_MAP)
242
+ }.freeze
243
+ end
244
+
245
+ private
246
+
247
+ # Maps the provided attribute based on the mapping hash and if not found returns the
248
+ # attribute itself. Useful when converting from Acl symbol based representation to the
249
+ # rdkafka one.
250
+ #
251
+ # @param value [Symbol, Integer] The value to be mapped.
252
+ # @param mappings [Hash] The hash containing the mapping data.
253
+ # @return [Integer, Symbol] The mapped value or the original value if not found in mappings.
254
+ def map(value, mappings)
255
+ validate_attribute!(value)
256
+
257
+ mappings.invert.fetch(value, value)
258
+ end
259
+
260
+ # Remaps the provided attribute based on the mapping hash and if not found returns the
261
+ # attribute itself. Useful when converting from Acl symbol based representation to the
262
+ # rdkafka one.
263
+ #
264
+ # @param value [Symbol, Integer] The value to be mapped.
265
+ # @param mappings [Hash] The hash containing the mapping data.
266
+ # @return [Integer, Symbol] The mapped value or the original value if not found in mappings.
267
+ def remap(value, mappings)
268
+ validate_attribute!(value)
269
+
270
+ mappings.fetch(value, value)
271
+ end
272
+
273
+ # Validates that the attribute exists in any of the ACL mappings.
274
+ # Raises an error if the attribute is not supported.
275
+ # @param attribute [Symbol, Integer] The attribute to be validated.
276
+ # @raise [Karafka::Errors::UnsupportedCaseError] raised if attribute not found
277
+ def validate_attribute!(attribute)
278
+ ALL_MAPS.each do |mappings|
279
+ return if mappings.keys.any?(attribute)
280
+ return if mappings.values.any?(attribute)
281
+ end
282
+
283
+ raise Karafka::Errors::UnsupportedCaseError, attribute
284
+ end
285
+ end
286
+ end
287
+ end
data/lib/karafka/admin.rb CHANGED
@@ -258,11 +258,7 @@ module Karafka
258
258
 
259
259
  # @return [Rdkafka::Metadata] cluster metadata info
260
260
  def cluster_info
261
- with_admin do |admin|
262
- admin.instance_variable_get('@native_kafka').with_inner do |inner|
263
- Rdkafka::Metadata.new(inner)
264
- end
265
- end
261
+ with_admin(&:metadata)
266
262
  end
267
263
 
268
264
  # Creates consumer instance and yields it. After usage it closes the consumer instance
@@ -290,6 +286,14 @@ module Karafka
290
286
  consumer&.close
291
287
  end
292
288
 
289
+ # Creates admin instance and yields it. After usage it closes the admin instance
290
+ def with_admin
291
+ admin = config(:producer, {}).admin
292
+ yield(admin)
293
+ ensure
294
+ admin&.close
295
+ end
296
+
293
297
  private
294
298
 
295
299
  # @return [Array<String>] topics names
@@ -304,14 +308,6 @@ module Karafka
304
308
  cluster_info.topics.find { |topic| topic[:topic_name] == name }
305
309
  end
306
310
 
307
- # Creates admin instance and yields it. After usage it closes the admin instance
308
- def with_admin
309
- admin = config(:producer, {}).admin
310
- yield(admin)
311
- ensure
312
- admin&.close
313
- end
314
-
315
311
  # There are some cases where rdkafka admin operations finish successfully but without the
316
312
  # callback being triggered to materialize the post-promise object. Until this is fixed we
317
313
  # can figure out, that operation we wanted to do finished successfully by checking that the
data/lib/karafka/app.rb CHANGED
@@ -75,9 +75,11 @@ module Karafka
75
75
  monitor
76
76
  pro?
77
77
  ].each do |delegated|
78
- define_method(delegated) do
79
- Karafka.send(delegated)
80
- end
78
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
79
+ def #{delegated}
80
+ Karafka.#{delegated}
81
+ end
82
+ RUBY
81
83
  end
82
84
  end
83
85
  end
@@ -11,6 +11,9 @@ module Karafka
11
11
 
12
12
  def_delegators :@coordinator, :topic, :partition
13
13
 
14
+ def_delegators :producer, :produce_async, :produce_sync, :produce_many_async,
15
+ :produce_many_sync
16
+
14
17
  # @return [String] id of the current consumer
15
18
  attr_reader :id
16
19
  # @return [Karafka::Routing::Topic] topic to which a given consumer is subscribed
@@ -219,9 +222,14 @@ module Karafka
219
222
  # @param manual_seek [Boolean] Flag to differentiate between user seek and system/strategy
220
223
  # based seek. User seek operations should take precedence over system actions, hence we need
221
224
  # to know who invoked it.
225
+ # @param reset_offset [Boolean] should we reset offset when seeking backwards. It is false by
226
+ # default to prevent marking in the offset that was earlier than the highest marked offset
227
+ # for given consumer group. It can be set to true if we want to reprocess data once again and
228
+ # want to make sure that the marking starts from where we moved to.
222
229
  # @note Please note, that if you are seeking to a time offset, getting the offset is blocking
223
- def seek(offset, manual_seek = true)
230
+ def seek(offset, manual_seek = true, reset_offset: false)
224
231
  coordinator.manual_seek if manual_seek
232
+ coordinator.seek_offset = nil if reset_offset
225
233
 
226
234
  client.seek(
227
235
  Karafka::Messages::Seek.new(
@@ -101,7 +101,7 @@ module Karafka
101
101
 
102
102
  # @return [Array<String>] names and aliases for command matching
103
103
  def names
104
- ((@aliases || []) << name).flatten.map(&:to_s)
104
+ ((@aliases || []) << name).flatten.map(&:to_s).uniq
105
105
  end
106
106
  end
107
107
  end