rdkafka 0.29.2 → 0.30.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 +4 -4
- data/CHANGELOG.md +28 -14
- data/README.md +1 -0
- data/dist/{librdkafka-2.14.2.tar.gz → librdkafka-2.15.0.tar.gz} +0 -0
- data/lib/rdkafka/admin/alter_consumer_group_offsets_handle.rb +31 -0
- data/lib/rdkafka/admin/alter_consumer_group_offsets_report.rb +50 -0
- data/lib/rdkafka/admin/delete_consumer_group_offsets_handle.rb +31 -0
- data/lib/rdkafka/admin/delete_consumer_group_offsets_report.rb +50 -0
- data/lib/rdkafka/admin.rb +120 -0
- data/lib/rdkafka/bindings.rb +45 -2
- data/lib/rdkafka/callbacks/alter_consumer_group_offsets_handler.rb +65 -0
- data/lib/rdkafka/callbacks/delete_consumer_group_offsets_handler.rb +65 -0
- data/lib/rdkafka/callbacks.rb +14 -16
- data/lib/rdkafka/config.rb +34 -0
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +6 -0
- metadata +9 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9a5ff1b8b0535c2a9781c7a629907b034e372fd69707895be94867aacdf70c69
|
|
4
|
+
data.tar.gz: 8594c653516b17b414ff6c1e02709d1f00e776caa497980c699cb2ac8ea131d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88d5515df49496899ecbb474ed379b2405b4aacbf8a7cd2c10b9356276bdeb862091a450b87713dca495d4101e585717b459a96b2a1bdffb55ef80caf948165e
|
|
7
|
+
data.tar.gz: 17743522771d227ad2f729a87a6c6976322908221cbebb74b5af7a46d7218cf7e2775bda7b031ace347ceccad1f20d7035c486b23cc6158c1d5ed29e2ecee56e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
# Rdkafka Changelog
|
|
2
2
|
|
|
3
|
+
## 0.30.0 (2026-09-25)
|
|
4
|
+
- [Feature] Add `Admin#alter_consumer_group_offsets` and `Admin#delete_consumer_group_offsets` to set or clear a consumer group's committed offsets from the admin client.
|
|
5
|
+
- [Enhancement] Bump the bundled zlib to `1.3.2`.
|
|
6
|
+
- [Enhancement] Bump librdkafka to `2.15.0`.
|
|
7
|
+
- [Enhancement] Bump the bundled MIT Kerberos (krb5) to `1.22.2`.
|
|
8
|
+
- [Enhancement] Add `Rdkafka::Config.partitioner_key_uses_bytesize` to hash partition keys by byte length, matching other Kafka clients for multibyte keys. Defaults to `false`.
|
|
9
|
+
- [Maintenance] Derive the zlib `CHECKSUMS` entry from `ZLIB_VERSION`.
|
|
10
|
+
- [Maintenance] Drop the unused `dist/openssl-3.0.16.tar.gz` build cache.
|
|
11
|
+
- [Fix] Honor the `isolation_level:` argument to `Admin#list_offsets`, which was silently ignored.
|
|
12
|
+
- [Fix] Return correct results for every item of a multi-item topic, partition, group or ACL admin request, not just the first.
|
|
13
|
+
- [Maintenance] Fix a use-after-free in the multi-item admin integration test that read result-name pointers after librdkafka had destroyed the background event, which made it flaky on newer glibc (e.g. Debian trixie).
|
|
14
|
+
- [Maintenance] Stabilize consumer specs on slow CI runners: wait longer for a partition assignment, raise the `TestTopics.create` admin timeout (a timeout there also tripped the leaked-handle guard), and let the long-running consumption spec drain its backlog instead of stopping at a fixed 60s.
|
|
15
|
+
- [Maintenance] Raise the `TestTopics.create` admin timeout to 30s so a loaded CI runner no longer hits `create topic timed out` (which also tripped the leaked-handle guard).
|
|
16
|
+
|
|
3
17
|
## 0.29.2 (2026-09-11)
|
|
4
18
|
- [Fix] Close live clients from an `at_exit` hook before Ruby's shutdown finalization, so librdkafka is no longer `dlclose`d while its native threads are still running (which could segfault on exit).
|
|
5
19
|
- [Fix] Make client construction exception-safe and destroy the native handle when setup fails after `rd_kafka_new`, so a later error no longer orphans the native client.
|
|
6
|
-
- [Fix]
|
|
7
|
-
- [Fix] Free
|
|
8
|
-
- [Fix] Raise
|
|
20
|
+
- [Fix] Fix a double-free in `Consumer#poll_batch`/`#poll_batch_nb` that could abort the process when building a message raised a non-`RdkafkaError`.
|
|
21
|
+
- [Fix] Free native resources when `Admin#describe_configs`/`#incremental_alter_configs` raise while building their request (e.g. a non-String resource name).
|
|
22
|
+
- [Fix] Raise `ConfigError` instead of segfaulting when `Admin#describe_configs`/`#incremental_alter_configs` get an empty resource name or a negative resource type.
|
|
9
23
|
|
|
10
24
|
## 0.29.1 (2026-09-04)
|
|
11
25
|
- [Enhancement] Add `Admin#delete_records` to delete all messages in a partition up to a given offset.
|
|
@@ -19,8 +33,8 @@
|
|
|
19
33
|
|
|
20
34
|
## 0.29.0 (2026-07-10)
|
|
21
35
|
- [Enhancement] Bump librdkafka to `2.14.2`
|
|
22
|
-
- [Enhancement] Add `Consumer#metadata` and `Producer#metadata`, mirroring `Admin#metadata`,
|
|
23
|
-
- [Enhancement] Support offset-commit metadata
|
|
36
|
+
- [Enhancement] Add `Consumer#metadata` and `Producer#metadata`, mirroring `Admin#metadata`, to fetch cluster metadata without a separate admin connection.
|
|
37
|
+
- [Enhancement] Support offset-commit metadata via `Consumer#store_offset(message, metadata)`, readable through `Consumer::Partition#metadata` and `Consumer#committed`.
|
|
24
38
|
- [Enhancement] Expose `replicas` and `isrs` (in-sync replica broker ids) on each partition in topic metadata; both were previously dropped from the `Metadata#topics` partition hashes.
|
|
25
39
|
- [Enhancement] Extract the admin background-event result handlers into one class per operation under `lib/rdkafka/callbacks/`. Internal reorganization with no API or behavior change.
|
|
26
40
|
- [Enhancement] Reuse per-thread scratch pointers in `Consumer::Headers.from_native`, removing the per-message native allocations from the consumer hot path.
|
|
@@ -28,32 +42,32 @@
|
|
|
28
42
|
- [Fix] Cache the partition count for a missing topic, so `produce` with a `partition_key` to a missing topic no longer re-runs a blocking metadata query on every message.
|
|
29
43
|
- [Fix] Let `PartitionsCountCache` adopt a lower partition count once the cached entry has expired, so a topic recreated with fewer partitions no longer fails `produce` until process restart.
|
|
30
44
|
- [Fix] Surface per-message build errors inline in `Consumer#poll_batch`/`#poll_batch_nb` instead of discarding the batch, preserving the messages that built successfully.
|
|
31
|
-
- [Fix] Bound the `Metadata` retry loop
|
|
45
|
+
- [Fix] Bound the `Metadata` retry loop to about 5 seconds, so a synchronous metadata fetch can no longer block for minutes.
|
|
32
46
|
- [Fix] Synchronize `AbstractHandle::REGISTRY` mutations with a mutex, which could otherwise lose a write on JRuby and leave a handle unregistered or leaked.
|
|
33
|
-
- [Fix]
|
|
47
|
+
- [Fix] Raise `ConfigError` instead of `NameError` in `Admin#delete_group`, `#delete_acl` and `#describe_acl` when the background queue is unavailable.
|
|
34
48
|
- [Fix] Actually populate `ConfigBindingResult#synonyms`. The synonym loop built the synonym binding objects and discarded them, so `#synonyms` was always an empty array; they are now appended.
|
|
35
49
|
- [Fix] Stop leaking the native `rd_kafka_topic_conf_t` in `Producer#set_topic_config` when a per-topic config value is rejected.
|
|
36
|
-
- [Fix]
|
|
50
|
+
- [Fix] Raise `ClosedConsumerError` from `Consumer#position` on a closed consumer, like the other consumer methods.
|
|
37
51
|
- [Fix] Guard the OAuthBearer token refresh callback against a NULL client pointer before calling `rd_kafka_name` on it.
|
|
38
|
-
- [Fix]
|
|
52
|
+
- [Fix] Fully close a consumer collected without an explicit `close`, preventing a hang or leak.
|
|
39
53
|
- [Fix] Free the librdkafka-allocated string in `Consumer#cluster_id` and `Consumer#member_id`, and fix the `rd_kafka_clusterid` arity. `Consumer#cluster_id` now accepts a `timeout_ms`.
|
|
40
54
|
- [Fix] Attach `rd_kafka_query_watermark_offsets` with `blocking: true` so it releases the GVL; it previously froze every other Ruby thread for up to `timeout_ms`.
|
|
41
55
|
- [Fix] Stop leaking the native `rd_kafka_conf_t` when client creation fails, a multi-KB leak per failed attempt for supervisors retrying on transient SASL/SSL misconfiguration.
|
|
42
56
|
- [Fix] Stop `Metadata` from leaking the native metadata struct on every retried fetch; each attempt now frees its own native resources.
|
|
43
57
|
- [Fix] Stop `Producer#produce` from orphaning the delivery handle in the process-global registry when it fails after registering it.
|
|
44
58
|
- [Fix] Guard the message delivery callback so a raising user `delivery_callback` can no longer leave the handle locked or crash the producer; exceptions are now logged and swallowed.
|
|
45
|
-
- [Fix] Stop `describe_configs`, `incremental_alter_configs` and `list_offsets` from leaking
|
|
46
|
-
- [Fix]
|
|
59
|
+
- [Fix] Stop `describe_configs`, `incremental_alter_configs` and `list_offsets` from leaking native resources when their arguments are rejected.
|
|
60
|
+
- [Fix] Stop `TopicPartitionList#to_native_tpl` from leaking the native list when building it fails partway.
|
|
47
61
|
- [Fix] Raise instead of silently dropping a rejected `incremental_alter_configs` entry, which previously left the alter request reporting success.
|
|
48
62
|
- [Fix] Allocate the admin result-count out-parameter as `:size_t` instead of `:int32`, fixing a 4-byte overflow on every admin result parse.
|
|
49
63
|
- [Fix] Stabilize the flaky `Consumer#lag` "calculates the consumer lag" spec on overloaded CI.
|
|
50
|
-
- [Fix]
|
|
51
|
-
- [Fix]
|
|
64
|
+
- [Fix] Return the real error from an admin operation that fails at the operation level (e.g. brokers unreachable) instead of blocking until `wait` times out.
|
|
65
|
+
- [Fix] Stop every admin operation from leaking its result event. The internal FFI struct fields on admin handles are removed; use `handle.wait` and the returned report objects, which are unchanged.
|
|
52
66
|
|
|
53
67
|
## 0.28.0 (2026-06-03)
|
|
54
68
|
- [Enhancement] Bump librdkafka to `2.14.1`
|
|
55
69
|
- [Enhancement] Replace version-gated `Warning[:performance]` with dynamic `Warning.categories` opt-in in spec helper so new Ruby warning categories are automatically enabled without manual updates.
|
|
56
|
-
- [Enhancement] `poll_batch` and `poll_batch_nb` now return
|
|
70
|
+
- [Enhancement] `poll_batch` and `poll_batch_nb` now return errors inline as `RdkafkaError` objects instead of raising on the first one. The return type is `Array<Message, RdkafkaError>`, so callers must handle errors in the result.
|
|
57
71
|
|
|
58
72
|
## 0.27.0 (2026-05-07)
|
|
59
73
|
- [Feature] Add `Consumer#poll_batch(timeout_ms, max_items:)` and `Consumer#poll_batch_nb(timeout_ms, max_items:)` for batch message polling via `rd_kafka_consume_batch_queue`.
|
data/README.md
CHANGED
|
@@ -163,6 +163,7 @@ bundle exec rake produce_messages
|
|
|
163
163
|
|
|
164
164
|
| rdkafka-ruby | librdkafka | patches |
|
|
165
165
|
|-|-|-|
|
|
166
|
+
| 0.30.x (2026-09-25) | 2.15.0 (2026-06-30) | yes |
|
|
166
167
|
| 0.29.x (2026-07-10) | 2.14.2 (2026-06-03) | yes |
|
|
167
168
|
| 0.28.x (2026-06-03) | 2.14.1 (2026-04-15) | yes |
|
|
168
169
|
| 0.27.x (2026-05-07) | 2.14.0 (2026-04-01) | yes |
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
class Admin
|
|
5
|
+
# Handle for alter consumer group offsets operation
|
|
6
|
+
class AlterConsumerGroupOffsetsHandle < AbstractHandle
|
|
7
|
+
layout :pending, :bool,
|
|
8
|
+
:response, :int
|
|
9
|
+
|
|
10
|
+
# @return [String] the name of the operation
|
|
11
|
+
def operation_name
|
|
12
|
+
"alter consumer group offsets"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Creates the result report
|
|
16
|
+
# @return [AlterConsumerGroupOffsetsReport]
|
|
17
|
+
def create_result
|
|
18
|
+
prepared_result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Raises an error if the operation failed
|
|
22
|
+
# @raise [RdkafkaError]
|
|
23
|
+
def raise_error
|
|
24
|
+
raise RdkafkaError.new(
|
|
25
|
+
self[:response],
|
|
26
|
+
broker_message: broker_message
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
class Admin
|
|
5
|
+
# Report for alter consumer group offsets operation result
|
|
6
|
+
class AlterConsumerGroupOffsetsReport
|
|
7
|
+
# @return [String, nil] the group the operation ran against
|
|
8
|
+
attr_reader :group_name
|
|
9
|
+
|
|
10
|
+
# @return [String, nil] group level error message, if any
|
|
11
|
+
attr_reader :error_string
|
|
12
|
+
|
|
13
|
+
# Per partition outcomes, each with `:topic`, `:partition`, `:offset` and `:error`
|
|
14
|
+
# (an `RdkafkaError` or nil). Partitions are reported individually because Kafka can
|
|
15
|
+
# fail some and accept others within a single request.
|
|
16
|
+
# @return [Array<Hash>]
|
|
17
|
+
attr_reader :partitions
|
|
18
|
+
|
|
19
|
+
# @param error_string [FFI::Pointer] pointer to the group level error string
|
|
20
|
+
# @param result_name [FFI::Pointer] pointer to the group name
|
|
21
|
+
# @param partitions_ptr [FFI::Pointer] pointer to the per partition result list
|
|
22
|
+
def initialize(error_string, result_name, partitions_ptr = FFI::Pointer::NULL)
|
|
23
|
+
@error_string = error_string.read_string if error_string != FFI::Pointer::NULL
|
|
24
|
+
@group_name = result_name.read_string if result_name != FFI::Pointer::NULL
|
|
25
|
+
@partitions = extract_partitions(partitions_ptr)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# @param partitions_ptr [FFI::Pointer] pointer to a native topic partition list
|
|
31
|
+
# @return [Array<Hash>]
|
|
32
|
+
def extract_partitions(partitions_ptr)
|
|
33
|
+
return [] if partitions_ptr.nil? || partitions_ptr.null?
|
|
34
|
+
|
|
35
|
+
native = Bindings::TopicPartitionList.new(partitions_ptr)
|
|
36
|
+
|
|
37
|
+
Array.new(native[:cnt]) do |i|
|
|
38
|
+
tp = Bindings::TopicPartition.new(native[:elems] + (i * Bindings::TopicPartition.size))
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
topic: tp[:topic],
|
|
42
|
+
partition: tp[:partition],
|
|
43
|
+
offset: tp[:offset],
|
|
44
|
+
error: tp[:err].zero? ? nil : RdkafkaError.new(tp[:err])
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
class Admin
|
|
5
|
+
# Handle for delete consumer group offsets operation
|
|
6
|
+
class DeleteConsumerGroupOffsetsHandle < AbstractHandle
|
|
7
|
+
layout :pending, :bool,
|
|
8
|
+
:response, :int
|
|
9
|
+
|
|
10
|
+
# @return [String] the name of the operation
|
|
11
|
+
def operation_name
|
|
12
|
+
"delete consumer group offsets"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Creates the result report
|
|
16
|
+
# @return [DeleteConsumerGroupOffsetsReport]
|
|
17
|
+
def create_result
|
|
18
|
+
prepared_result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Raises an error if the operation failed
|
|
22
|
+
# @raise [RdkafkaError]
|
|
23
|
+
def raise_error
|
|
24
|
+
raise RdkafkaError.new(
|
|
25
|
+
self[:response],
|
|
26
|
+
broker_message: broker_message
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
class Admin
|
|
5
|
+
# Report for delete consumer group offsets operation result
|
|
6
|
+
class DeleteConsumerGroupOffsetsReport
|
|
7
|
+
# @return [String, nil] the group the operation ran against
|
|
8
|
+
attr_reader :group_name
|
|
9
|
+
|
|
10
|
+
# @return [String, nil] group level error message, if any
|
|
11
|
+
attr_reader :error_string
|
|
12
|
+
|
|
13
|
+
# Per partition outcomes, each with `:topic`, `:partition`, `:offset` and `:error`
|
|
14
|
+
# (an `RdkafkaError` or nil). Partitions are reported individually because Kafka can
|
|
15
|
+
# fail some and accept others within a single request.
|
|
16
|
+
# @return [Array<Hash>]
|
|
17
|
+
attr_reader :partitions
|
|
18
|
+
|
|
19
|
+
# @param error_string [FFI::Pointer] pointer to the group level error string
|
|
20
|
+
# @param result_name [FFI::Pointer] pointer to the group name
|
|
21
|
+
# @param partitions_ptr [FFI::Pointer] pointer to the per partition result list
|
|
22
|
+
def initialize(error_string, result_name, partitions_ptr = FFI::Pointer::NULL)
|
|
23
|
+
@error_string = error_string.read_string if error_string != FFI::Pointer::NULL
|
|
24
|
+
@group_name = result_name.read_string if result_name != FFI::Pointer::NULL
|
|
25
|
+
@partitions = extract_partitions(partitions_ptr)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# @param partitions_ptr [FFI::Pointer] pointer to a native topic partition list
|
|
31
|
+
# @return [Array<Hash>]
|
|
32
|
+
def extract_partitions(partitions_ptr)
|
|
33
|
+
return [] if partitions_ptr.nil? || partitions_ptr.null?
|
|
34
|
+
|
|
35
|
+
native = Bindings::TopicPartitionList.new(partitions_ptr)
|
|
36
|
+
|
|
37
|
+
Array.new(native[:cnt]) do |i|
|
|
38
|
+
tp = Bindings::TopicPartition.new(native[:elems] + (i * Bindings::TopicPartition.size))
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
topic: tp[:topic],
|
|
42
|
+
partition: tp[:partition],
|
|
43
|
+
offset: tp[:offset],
|
|
44
|
+
error: tp[:err].zero? ? nil : RdkafkaError.new(tp[:err])
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/rdkafka/admin.rb
CHANGED
|
@@ -224,6 +224,78 @@ module Rdkafka
|
|
|
224
224
|
create_topic_handle
|
|
225
225
|
end
|
|
226
226
|
|
|
227
|
+
# Sets the committed offsets of a consumer group from outside the group.
|
|
228
|
+
#
|
|
229
|
+
# Kafka requires the group to be empty (no active members) for this to be accepted; when it
|
|
230
|
+
# is not, the broker rejects the request and the handle raises with `group_not_empty` rather
|
|
231
|
+
# than reporting success.
|
|
232
|
+
#
|
|
233
|
+
# @param group_id [String] the group whose offsets we want to set
|
|
234
|
+
# @param topic_partition_list [TopicPartitionList] partitions with the offsets to commit
|
|
235
|
+
# @return [AlterConsumerGroupOffsetsHandle] handle that can be used to wait for the result
|
|
236
|
+
# @raise [RdkafkaError] when altering the offsets fails
|
|
237
|
+
def alter_consumer_group_offsets(group_id, topic_partition_list)
|
|
238
|
+
closed_admin_check(__method__)
|
|
239
|
+
|
|
240
|
+
native_tpl = topic_partition_list.to_native_tpl
|
|
241
|
+
|
|
242
|
+
begin
|
|
243
|
+
alter_ptr = Rdkafka::Bindings.rd_kafka_AlterConsumerGroupOffsets_new(
|
|
244
|
+
FFI::MemoryPointer.from_string(group_id),
|
|
245
|
+
native_tpl
|
|
246
|
+
)
|
|
247
|
+
rescue Exception
|
|
248
|
+
Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(native_tpl)
|
|
249
|
+
raise
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# librdkafka copies the list into the request object, so ours is no longer needed
|
|
253
|
+
Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(native_tpl)
|
|
254
|
+
|
|
255
|
+
enqueue_group_offsets_op(
|
|
256
|
+
request_ptr: alter_ptr,
|
|
257
|
+
handle: AlterConsumerGroupOffsetsHandle.new,
|
|
258
|
+
admin_op: Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_ALTERCONSUMERGROUPOFFSETS,
|
|
259
|
+
destroy: Rdkafka::Bindings.method(:rd_kafka_AlterConsumerGroupOffsets_destroy),
|
|
260
|
+
enqueue: Rdkafka::Bindings.method(:rd_kafka_AlterConsumerGroupOffsets)
|
|
261
|
+
)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Deletes the committed offsets of specific partitions of a consumer group, leaving the
|
|
265
|
+
# group and its remaining offsets in place.
|
|
266
|
+
#
|
|
267
|
+
# This is the partition scoped counterpart of {#delete_group}, which removes the whole group.
|
|
268
|
+
#
|
|
269
|
+
# @param group_id [String] the group whose offsets we want to delete
|
|
270
|
+
# @param topic_partition_list [TopicPartitionList] partitions whose offsets to delete
|
|
271
|
+
# @return [DeleteConsumerGroupOffsetsHandle] handle that can be used to wait for the result
|
|
272
|
+
# @raise [RdkafkaError] when deleting the offsets fails
|
|
273
|
+
def delete_consumer_group_offsets(group_id, topic_partition_list)
|
|
274
|
+
closed_admin_check(__method__)
|
|
275
|
+
|
|
276
|
+
native_tpl = topic_partition_list.to_native_tpl
|
|
277
|
+
|
|
278
|
+
begin
|
|
279
|
+
delete_ptr = Rdkafka::Bindings.rd_kafka_DeleteConsumerGroupOffsets_new(
|
|
280
|
+
FFI::MemoryPointer.from_string(group_id),
|
|
281
|
+
native_tpl
|
|
282
|
+
)
|
|
283
|
+
rescue Exception
|
|
284
|
+
Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(native_tpl)
|
|
285
|
+
raise
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(native_tpl)
|
|
289
|
+
|
|
290
|
+
enqueue_group_offsets_op(
|
|
291
|
+
request_ptr: delete_ptr,
|
|
292
|
+
handle: DeleteConsumerGroupOffsetsHandle.new,
|
|
293
|
+
admin_op: Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_DELETECONSUMERGROUPOFFSETS,
|
|
294
|
+
destroy: Rdkafka::Bindings.method(:rd_kafka_DeleteConsumerGroupOffsets_destroy),
|
|
295
|
+
enqueue: Rdkafka::Bindings.method(:rd_kafka_DeleteConsumerGroupOffsets)
|
|
296
|
+
)
|
|
297
|
+
end
|
|
298
|
+
|
|
227
299
|
# Deletes a consumer group
|
|
228
300
|
#
|
|
229
301
|
# @param group_id [String] the group id to delete
|
|
@@ -1139,6 +1211,54 @@ module Rdkafka
|
|
|
1139
1211
|
|
|
1140
1212
|
private
|
|
1141
1213
|
|
|
1214
|
+
# Shared enqueue path for the two consumer group offset admin operations. They differ only
|
|
1215
|
+
# in their C entry points, so keeping one body avoids two near identical copies of the
|
|
1216
|
+
# queue/handle/options dance and its cleanup.
|
|
1217
|
+
#
|
|
1218
|
+
# @param request_ptr [FFI::Pointer] the op specific request object
|
|
1219
|
+
# @param handle [AbstractHandle] the handle to register and return
|
|
1220
|
+
# @param admin_op [Integer] the RD_KAFKA_ADMIN_OP_* constant for this operation
|
|
1221
|
+
# @param destroy [Method] bound function used to free the request object
|
|
1222
|
+
# @param enqueue [Method] bound function used to enqueue the request
|
|
1223
|
+
# @return [AbstractHandle] the registered handle
|
|
1224
|
+
def enqueue_group_offsets_op(request_ptr:, handle:, admin_op:, destroy:, enqueue:)
|
|
1225
|
+
array_ptr = FFI::MemoryPointer.new(:pointer)
|
|
1226
|
+
array_ptr.write_array_of_pointer([request_ptr])
|
|
1227
|
+
|
|
1228
|
+
queue_ptr = @native_kafka.with_inner do |inner|
|
|
1229
|
+
Rdkafka::Bindings.rd_kafka_queue_get_background(inner)
|
|
1230
|
+
end
|
|
1231
|
+
|
|
1232
|
+
if queue_ptr.null?
|
|
1233
|
+
destroy.call(request_ptr)
|
|
1234
|
+
raise Rdkafka::Config::ConfigError.new("rd_kafka_queue_get_background was NULL")
|
|
1235
|
+
end
|
|
1236
|
+
|
|
1237
|
+
handle[:pending] = true
|
|
1238
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_PARTITION_UA
|
|
1239
|
+
handle.class.register(handle)
|
|
1240
|
+
|
|
1241
|
+
admin_options_ptr = @native_kafka.with_inner do |inner|
|
|
1242
|
+
Rdkafka::Bindings.rd_kafka_AdminOptions_new(inner, admin_op)
|
|
1243
|
+
end
|
|
1244
|
+
Rdkafka::Bindings.rd_kafka_AdminOptions_set_opaque(admin_options_ptr, handle.to_ptr)
|
|
1245
|
+
|
|
1246
|
+
begin
|
|
1247
|
+
@native_kafka.with_inner do |inner|
|
|
1248
|
+
enqueue.call(inner, array_ptr, 1, admin_options_ptr, queue_ptr)
|
|
1249
|
+
end
|
|
1250
|
+
rescue Exception
|
|
1251
|
+
handle.class.remove(handle.to_ptr.address)
|
|
1252
|
+
raise
|
|
1253
|
+
ensure
|
|
1254
|
+
Rdkafka::Bindings.rd_kafka_AdminOptions_destroy(admin_options_ptr)
|
|
1255
|
+
Rdkafka::Bindings.rd_kafka_queue_destroy(queue_ptr)
|
|
1256
|
+
destroy.call(request_ptr)
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1259
|
+
handle
|
|
1260
|
+
end
|
|
1261
|
+
|
|
1142
1262
|
# Checks if the admin is closed and raises an error if so
|
|
1143
1263
|
# @param method [Symbol] name of the calling method for error context
|
|
1144
1264
|
# @raise [ClosedAdminError] when the admin is closed
|
data/lib/rdkafka/bindings.rb
CHANGED
|
@@ -192,7 +192,7 @@ module Rdkafka
|
|
|
192
192
|
RD_KAFKA_ALTER_CONFIG_OP_TYPE_SUBTRACT = 3
|
|
193
193
|
|
|
194
194
|
# List Offsets
|
|
195
|
-
RD_KAFKA_ADMIN_OP_LISTOFFSETS =
|
|
195
|
+
RD_KAFKA_ADMIN_OP_LISTOFFSETS = 21
|
|
196
196
|
RD_KAFKA_EVENT_LISTOFFSETS_RESULT = 0x400000
|
|
197
197
|
|
|
198
198
|
# rd_kafka_IsolationLevel_t
|
|
@@ -503,9 +503,31 @@ module Rdkafka
|
|
|
503
503
|
raise Rdkafka::Config::ConfigError.new("Unknown partitioner: #{partitioner}")
|
|
504
504
|
end
|
|
505
505
|
|
|
506
|
-
public_send(method_name, topic_ptr, str_ptr, str
|
|
506
|
+
public_send(method_name, topic_ptr, str_ptr, partition_key_length(str), partition_count, nil, nil)
|
|
507
507
|
end
|
|
508
508
|
|
|
509
|
+
# Partition key length as the character count (legacy default).
|
|
510
|
+
#
|
|
511
|
+
# @param str [String] the partition key string
|
|
512
|
+
# @return [Integer]
|
|
513
|
+
def self.partition_key_size(str)
|
|
514
|
+
str.size
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
# Partition key length as the byte count, which is what librdkafka hashes (UTF-8 bytes copied
|
|
518
|
+
# into the key pointer) and what other Kafka clients use.
|
|
519
|
+
#
|
|
520
|
+
# @param str [String] the partition key string
|
|
521
|
+
# @return [Integer]
|
|
522
|
+
def self.partition_key_bytesize(str)
|
|
523
|
+
str.bytesize
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# Length of the partition key passed to librdkafka. Aliased to one of the methods above by
|
|
527
|
+
# `Rdkafka::Config.partitioner_key_uses_bytesize=`, so the per-message path does not check the
|
|
528
|
+
# setting on every call.
|
|
529
|
+
singleton_class.alias_method :partition_key_length, :partition_key_size
|
|
530
|
+
|
|
509
531
|
# Create Topics
|
|
510
532
|
RD_KAFKA_ADMIN_OP_CREATETOPICS = 1 # rd_kafka_admin_op_t
|
|
511
533
|
RD_KAFKA_EVENT_CREATETOPICS_RESULT = 100 # rd_kafka_event_type_t
|
|
@@ -547,6 +569,26 @@ module Rdkafka
|
|
|
547
569
|
attach_function :rd_kafka_event_DeleteGroups_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteGroups_result_t*
|
|
548
570
|
attach_function :rd_kafka_DeleteGroups_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteGroups_result_t*, size_t* => rd_kafka_group_result_t**
|
|
549
571
|
|
|
572
|
+
# Alter Consumer Group Offsets
|
|
573
|
+
RD_KAFKA_ADMIN_OP_ALTERCONSUMERGROUPOFFSETS = 15 # rd_kafka_admin_op_t
|
|
574
|
+
RD_KAFKA_EVENT_ALTERCONSUMERGROUPOFFSETS_RESULT = 0x10000 # rd_kafka_event_type_t
|
|
575
|
+
|
|
576
|
+
attach_function :rd_kafka_AlterConsumerGroupOffsets, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
|
|
577
|
+
attach_function :rd_kafka_AlterConsumerGroupOffsets_new, [:pointer, :pointer], :pointer, blocking: true # const char*, const rd_kafka_topic_partition_list_t* => rd_kafka_AlterConsumerGroupOffsets_t*
|
|
578
|
+
attach_function :rd_kafka_AlterConsumerGroupOffsets_destroy, [:pointer], :void, blocking: true
|
|
579
|
+
attach_function :rd_kafka_event_AlterConsumerGroupOffsets_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_AlterConsumerGroupOffsets_result_t*
|
|
580
|
+
attach_function :rd_kafka_AlterConsumerGroupOffsets_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_AlterConsumerGroupOffsets_result_t*, size_t* => rd_kafka_group_result_t**
|
|
581
|
+
|
|
582
|
+
# Delete Consumer Group Offsets
|
|
583
|
+
RD_KAFKA_ADMIN_OP_DELETECONSUMERGROUPOFFSETS = 8 # rd_kafka_admin_op_t
|
|
584
|
+
RD_KAFKA_EVENT_DELETECONSUMERGROUPOFFSETS_RESULT = 107 # rd_kafka_event_type_t
|
|
585
|
+
|
|
586
|
+
attach_function :rd_kafka_DeleteConsumerGroupOffsets, [:pointer, :pointer, :size_t, :pointer, :pointer], :void, blocking: true
|
|
587
|
+
attach_function :rd_kafka_DeleteConsumerGroupOffsets_new, [:pointer, :pointer], :pointer, blocking: true # const char*, const rd_kafka_topic_partition_list_t* => rd_kafka_DeleteConsumerGroupOffsets_t*
|
|
588
|
+
attach_function :rd_kafka_DeleteConsumerGroupOffsets_destroy, [:pointer], :void, blocking: true
|
|
589
|
+
attach_function :rd_kafka_event_DeleteConsumerGroupOffsets_result, [:pointer], :pointer, blocking: true # rd_kafka_event_t* => rd_kafka_DeleteConsumerGroupOffsets_result_t*
|
|
590
|
+
attach_function :rd_kafka_DeleteConsumerGroupOffsets_result_groups, [:pointer, :pointer], :pointer, blocking: true # rd_kafka_DeleteConsumerGroupOffsets_result_t*, size_t* => rd_kafka_group_result_t**
|
|
591
|
+
|
|
550
592
|
# Delete Records
|
|
551
593
|
RD_KAFKA_ADMIN_OP_DELETERECORDS = 6 # rd_kafka_admin_op_t
|
|
552
594
|
RD_KAFKA_EVENT_DELETERECORDS_RESULT = 105 # rd_kafka_event_type_t
|
|
@@ -696,5 +738,6 @@ module Rdkafka
|
|
|
696
738
|
|
|
697
739
|
attach_function :rd_kafka_group_result_error, [:pointer], NativeError.by_ref # rd_kafka_group_result_t* => rd_kafka_error_t*
|
|
698
740
|
attach_function :rd_kafka_group_result_name, [:pointer], :pointer
|
|
741
|
+
attach_function :rd_kafka_group_result_partitions, [:pointer], :pointer # rd_kafka_group_result_t* => rd_kafka_topic_partition_list_t*
|
|
699
742
|
end
|
|
700
743
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_ALTERCONSUMERGROUPOFFSETS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class AlterConsumerGroupOffsetsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the alter consumer group offsets handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
result = Rdkafka::Bindings.rd_kafka_event_AlterConsumerGroupOffsets_result(event_ptr)
|
|
14
|
+
|
|
15
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
16
|
+
group_result_array = Rdkafka::Bindings.rd_kafka_AlterConsumerGroupOffsets_result_groups(result, pointer_to_size_t)
|
|
17
|
+
group_results = GroupResult.create_group_results_from_array(pointer_to_size_t.read_int, group_result_array)
|
|
18
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
19
|
+
|
|
20
|
+
if (handle = Rdkafka::Admin::AlterConsumerGroupOffsetsHandle.remove(handle_ptr.address))
|
|
21
|
+
unless resolve_operation_error(event_ptr, handle)
|
|
22
|
+
group_result = group_results[0]
|
|
23
|
+
|
|
24
|
+
# librdkafka only supports one group per invocation, so a missing group result
|
|
25
|
+
# means the broker returned nothing to act on rather than a partial success.
|
|
26
|
+
if group_result.nil?
|
|
27
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
28
|
+
handle.result = Rdkafka::Admin::AlterConsumerGroupOffsetsReport.new(
|
|
29
|
+
FFI::Pointer::NULL,
|
|
30
|
+
FFI::Pointer::NULL
|
|
31
|
+
)
|
|
32
|
+
else
|
|
33
|
+
report = Rdkafka::Admin::AlterConsumerGroupOffsetsReport.new(
|
|
34
|
+
group_result.error_string,
|
|
35
|
+
group_result.result_name,
|
|
36
|
+
Rdkafka::Bindings.rd_kafka_group_result_partitions(group_result_array.read_pointer)
|
|
37
|
+
)
|
|
38
|
+
handle.result = report
|
|
39
|
+
|
|
40
|
+
# Kafka reports a rejected offset change per partition, leaving the group level
|
|
41
|
+
# error unset - a group with live members comes back with the group error NULL
|
|
42
|
+
# and `unknown_member_id` on each partition. Resolving on the group error alone
|
|
43
|
+
# would hand back a report that looks like success, so any failed partition has
|
|
44
|
+
# to fail the handle too.
|
|
45
|
+
failed = report.partitions.find { |partition| partition[:error] }
|
|
46
|
+
|
|
47
|
+
if !group_result.result_error.zero?
|
|
48
|
+
handle[:response] = group_result.result_error
|
|
49
|
+
handle.broker_message = report.error_string
|
|
50
|
+
elsif failed
|
|
51
|
+
handle[:response] = failed[:error].rdkafka_response
|
|
52
|
+
handle.broker_message = "Failed for partition #{failed[:partition]} of '#{failed[:topic]}'"
|
|
53
|
+
else
|
|
54
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
handle.unlock
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rdkafka
|
|
4
|
+
module Callbacks
|
|
5
|
+
# Handles `RD_KAFKA_EVENT_DELETECONSUMERGROUPOFFSETS_RESULT` events
|
|
6
|
+
# @private
|
|
7
|
+
class DeleteConsumerGroupOffsetsHandler < BaseHandler
|
|
8
|
+
class << self
|
|
9
|
+
# Resolves the delete consumer group offsets handle from its result event
|
|
10
|
+
# @param event_ptr [FFI::Pointer] pointer to the event
|
|
11
|
+
# @return [void]
|
|
12
|
+
def call(event_ptr)
|
|
13
|
+
result = Rdkafka::Bindings.rd_kafka_event_DeleteConsumerGroupOffsets_result(event_ptr)
|
|
14
|
+
|
|
15
|
+
pointer_to_size_t = FFI::MemoryPointer.new(:size_t)
|
|
16
|
+
group_result_array = Rdkafka::Bindings.rd_kafka_DeleteConsumerGroupOffsets_result_groups(result, pointer_to_size_t)
|
|
17
|
+
group_results = GroupResult.create_group_results_from_array(pointer_to_size_t.read_int, group_result_array)
|
|
18
|
+
handle_ptr = Rdkafka::Bindings.rd_kafka_event_opaque(event_ptr)
|
|
19
|
+
|
|
20
|
+
if (handle = Rdkafka::Admin::DeleteConsumerGroupOffsetsHandle.remove(handle_ptr.address))
|
|
21
|
+
unless resolve_operation_error(event_ptr, handle)
|
|
22
|
+
group_result = group_results[0]
|
|
23
|
+
|
|
24
|
+
# librdkafka only supports one group per invocation, so a missing group result
|
|
25
|
+
# means the broker returned nothing to act on rather than a partial success.
|
|
26
|
+
if group_result.nil?
|
|
27
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
28
|
+
handle.result = Rdkafka::Admin::DeleteConsumerGroupOffsetsReport.new(
|
|
29
|
+
FFI::Pointer::NULL,
|
|
30
|
+
FFI::Pointer::NULL
|
|
31
|
+
)
|
|
32
|
+
else
|
|
33
|
+
report = Rdkafka::Admin::DeleteConsumerGroupOffsetsReport.new(
|
|
34
|
+
group_result.error_string,
|
|
35
|
+
group_result.result_name,
|
|
36
|
+
Rdkafka::Bindings.rd_kafka_group_result_partitions(group_result_array.read_pointer)
|
|
37
|
+
)
|
|
38
|
+
handle.result = report
|
|
39
|
+
|
|
40
|
+
# Kafka reports a rejected offset change per partition, leaving the group level
|
|
41
|
+
# error unset - a group with live members comes back with the group error NULL
|
|
42
|
+
# and `unknown_member_id` on each partition. Resolving on the group error alone
|
|
43
|
+
# would hand back a report that looks like success, so any failed partition has
|
|
44
|
+
# to fail the handle too.
|
|
45
|
+
failed = report.partitions.find { |partition| partition[:error] }
|
|
46
|
+
|
|
47
|
+
if !group_result.result_error.zero?
|
|
48
|
+
handle[:response] = group_result.result_error
|
|
49
|
+
handle.broker_message = report.error_string
|
|
50
|
+
elsif failed
|
|
51
|
+
handle[:response] = failed[:error].rdkafka_response
|
|
52
|
+
handle.broker_message = "Failed for partition #{failed[:partition]} of '#{failed[:topic]}'"
|
|
53
|
+
else
|
|
54
|
+
handle[:response] = Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
handle.unlock
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/rdkafka/callbacks.rb
CHANGED
|
@@ -21,10 +21,9 @@ module Rdkafka
|
|
|
21
21
|
# @param array_pointer [FFI::Pointer] pointer to the results array
|
|
22
22
|
# @return [Array<TopicResult>] array of topic results
|
|
23
23
|
def self.create_topic_results_from_array(count, array_pointer)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
24
|
+
return [] if count.zero?
|
|
25
|
+
|
|
26
|
+
array_pointer.read_array_of_pointer(count).map { |result_pointer| new(result_pointer) }
|
|
28
27
|
end
|
|
29
28
|
end
|
|
30
29
|
|
|
@@ -53,10 +52,9 @@ module Rdkafka
|
|
|
53
52
|
# @param array_pointer [FFI::Pointer] pointer to the results array
|
|
54
53
|
# @return [Array<GroupResult>] array of group results
|
|
55
54
|
def self.create_group_results_from_array(count, array_pointer)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
end
|
|
55
|
+
return [] if count.zero?
|
|
56
|
+
|
|
57
|
+
array_pointer.read_array_of_pointer(count).map { |result_pointer| new(result_pointer) }
|
|
60
58
|
end
|
|
61
59
|
end
|
|
62
60
|
|
|
@@ -77,10 +75,9 @@ module Rdkafka
|
|
|
77
75
|
# @param array_pointer [FFI::Pointer] pointer to the results array
|
|
78
76
|
# @return [Array<CreateAclResult>] array of ACL results
|
|
79
77
|
def self.create_acl_results_from_array(count, array_pointer)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
end
|
|
78
|
+
return [] if count.zero?
|
|
79
|
+
|
|
80
|
+
array_pointer.read_array_of_pointer(count).map { |result_pointer| new(result_pointer) }
|
|
84
81
|
end
|
|
85
82
|
end
|
|
86
83
|
|
|
@@ -108,10 +105,9 @@ module Rdkafka
|
|
|
108
105
|
# @param array_pointer [FFI::Pointer] pointer to the results array
|
|
109
106
|
# @return [Array<DeleteAclResult>] array of delete ACL results
|
|
110
107
|
def self.delete_acl_results_from_array(count, array_pointer)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
end
|
|
108
|
+
return [] if count.zero?
|
|
109
|
+
|
|
110
|
+
array_pointer.read_array_of_pointer(count).map { |result_pointer| new(result_pointer) }
|
|
115
111
|
end
|
|
116
112
|
end
|
|
117
113
|
|
|
@@ -213,6 +209,8 @@ module Rdkafka
|
|
|
213
209
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETETOPICS_RESULT then DeleteTopicHandler
|
|
214
210
|
when Rdkafka::Bindings::RD_KAFKA_ADMIN_OP_CREATEPARTITIONS_RESULT then CreatePartitionsHandler
|
|
215
211
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEGROUPS_RESULT then DeleteGroupsHandler
|
|
212
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_ALTERCONSUMERGROUPOFFSETS_RESULT then AlterConsumerGroupOffsetsHandler
|
|
213
|
+
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETECONSUMERGROUPOFFSETS_RESULT then DeleteConsumerGroupOffsetsHandler
|
|
216
214
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETERECORDS_RESULT then DeleteRecordsHandler
|
|
217
215
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_CREATEACLS_RESULT then CreateAclHandler
|
|
218
216
|
when Rdkafka::Bindings::RD_KAFKA_EVENT_DELETEACLS_RESULT then DeleteAclHandler
|
data/lib/rdkafka/config.rb
CHANGED
|
@@ -22,6 +22,12 @@ module Rdkafka
|
|
|
22
22
|
@@log_mutex = Mutex.new
|
|
23
23
|
# @!visibility private
|
|
24
24
|
@@oauthbearer_token_refresh_callback = nil
|
|
25
|
+
# @!visibility private
|
|
26
|
+
# Whether the partition key length passed to the partitioner is the byte length (`bytesize`)
|
|
27
|
+
# rather than the character length (`size`). `false` (character length) is the legacy default
|
|
28
|
+
# to avoid changing partition assignment for existing multibyte/binary keys; set to `true` to
|
|
29
|
+
# opt into the correct, other-client-consistent byte-length hashing.
|
|
30
|
+
@@partitioner_key_uses_bytesize = false
|
|
25
31
|
|
|
26
32
|
# Returns the current logger, by default this is a logger to stdout.
|
|
27
33
|
#
|
|
@@ -122,6 +128,34 @@ module Rdkafka
|
|
|
122
128
|
@@oauthbearer_token_refresh_callback
|
|
123
129
|
end
|
|
124
130
|
|
|
131
|
+
# Whether the partitioner hashes the partition key by its byte length instead of its character
|
|
132
|
+
# length. Defaults to `false` (character length) to preserve existing partition assignment for
|
|
133
|
+
# multibyte/binary keys. Passing the byte length is the correct, other-client-consistent
|
|
134
|
+
# behavior; enable it (and be aware it can move such keys to a different partition) with
|
|
135
|
+
# `Rdkafka::Config.partitioner_key_uses_bytesize = true`. This default is expected to change in
|
|
136
|
+
# a future major version.
|
|
137
|
+
#
|
|
138
|
+
# @return [Boolean]
|
|
139
|
+
def self.partitioner_key_uses_bytesize
|
|
140
|
+
@@partitioner_key_uses_bytesize
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Sets whether the partitioner hashes the partition key by its byte length rather than its
|
|
144
|
+
# character length. The key length method is resolved here once rather than on every produced
|
|
145
|
+
# message, and each call re-resolves it, so changing the setting at runtime takes effect
|
|
146
|
+
# immediately.
|
|
147
|
+
#
|
|
148
|
+
# @param value [Boolean] true to hash by byte length, false (default) for character length
|
|
149
|
+
# @return [void]
|
|
150
|
+
def self.partitioner_key_uses_bytesize=(value)
|
|
151
|
+
@@partitioner_key_uses_bytesize = value
|
|
152
|
+
|
|
153
|
+
Rdkafka::Bindings.singleton_class.alias_method(
|
|
154
|
+
:partition_key_length,
|
|
155
|
+
value ? :partition_key_bytesize : :partition_key_size
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
|
|
125
159
|
# @private
|
|
126
160
|
def self.opaques
|
|
127
161
|
@@opaques
|
data/lib/rdkafka/version.rb
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Rdkafka
|
|
4
4
|
# Current rdkafka-ruby gem version
|
|
5
|
-
VERSION = "0.
|
|
5
|
+
VERSION = "0.30.0"
|
|
6
6
|
# Target librdkafka version to be used
|
|
7
|
-
LIBRDKAFKA_VERSION = "2.
|
|
7
|
+
LIBRDKAFKA_VERSION = "2.15.0"
|
|
8
8
|
# SHA256 hash of the librdkafka source tarball for verification
|
|
9
|
-
LIBRDKAFKA_SOURCE_SHA256 = "
|
|
9
|
+
LIBRDKAFKA_SOURCE_SHA256 = "259015220cdca708afe838b5aa79ebf1a5fb710fb4179cf918d390aed85d5dbc"
|
|
10
10
|
end
|
data/lib/rdkafka.rb
CHANGED
|
@@ -13,6 +13,10 @@ require "rdkafka/helpers/list_offsets"
|
|
|
13
13
|
require "rdkafka/defaults"
|
|
14
14
|
require "rdkafka/abstract_handle"
|
|
15
15
|
require "rdkafka/admin"
|
|
16
|
+
require "rdkafka/admin/alter_consumer_group_offsets_handle"
|
|
17
|
+
require "rdkafka/admin/alter_consumer_group_offsets_report"
|
|
18
|
+
require "rdkafka/admin/delete_consumer_group_offsets_handle"
|
|
19
|
+
require "rdkafka/admin/delete_consumer_group_offsets_report"
|
|
16
20
|
require "rdkafka/admin/create_topic_handle"
|
|
17
21
|
require "rdkafka/admin/create_topic_report"
|
|
18
22
|
require "rdkafka/admin/delete_groups_handle"
|
|
@@ -46,6 +50,8 @@ require "rdkafka/callbacks/base_handler"
|
|
|
46
50
|
require "rdkafka/callbacks/create_topic_handler"
|
|
47
51
|
require "rdkafka/callbacks/delete_topic_handler"
|
|
48
52
|
require "rdkafka/callbacks/create_partitions_handler"
|
|
53
|
+
require "rdkafka/callbacks/alter_consumer_group_offsets_handler"
|
|
54
|
+
require "rdkafka/callbacks/delete_consumer_group_offsets_handler"
|
|
49
55
|
require "rdkafka/callbacks/delete_groups_handler"
|
|
50
56
|
require "rdkafka/callbacks/delete_records_handler"
|
|
51
57
|
require "rdkafka/callbacks/create_acl_handler"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rdkafka
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.30.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Thijs Cadier
|
|
@@ -93,7 +93,7 @@ files:
|
|
|
93
93
|
- README.md
|
|
94
94
|
- Rakefile
|
|
95
95
|
- bin/verify_kafka_warnings
|
|
96
|
-
- dist/librdkafka-2.
|
|
96
|
+
- dist/librdkafka-2.15.0.tar.gz
|
|
97
97
|
- dist/patches/rdkafka_global_init.patch
|
|
98
98
|
- docker-compose-ssl.yml
|
|
99
99
|
- docker-compose.yml
|
|
@@ -102,6 +102,8 @@ files:
|
|
|
102
102
|
- lib/rdkafka/abstract_handle.rb
|
|
103
103
|
- lib/rdkafka/admin.rb
|
|
104
104
|
- lib/rdkafka/admin/acl_binding_result.rb
|
|
105
|
+
- lib/rdkafka/admin/alter_consumer_group_offsets_handle.rb
|
|
106
|
+
- lib/rdkafka/admin/alter_consumer_group_offsets_report.rb
|
|
105
107
|
- lib/rdkafka/admin/config_binding_result.rb
|
|
106
108
|
- lib/rdkafka/admin/config_resource_binding_result.rb
|
|
107
109
|
- lib/rdkafka/admin/create_acl_handle.rb
|
|
@@ -112,6 +114,8 @@ files:
|
|
|
112
114
|
- lib/rdkafka/admin/create_topic_report.rb
|
|
113
115
|
- lib/rdkafka/admin/delete_acl_handle.rb
|
|
114
116
|
- lib/rdkafka/admin/delete_acl_report.rb
|
|
117
|
+
- lib/rdkafka/admin/delete_consumer_group_offsets_handle.rb
|
|
118
|
+
- lib/rdkafka/admin/delete_consumer_group_offsets_report.rb
|
|
115
119
|
- lib/rdkafka/admin/delete_groups_handle.rb
|
|
116
120
|
- lib/rdkafka/admin/delete_groups_report.rb
|
|
117
121
|
- lib/rdkafka/admin/delete_records_handle.rb
|
|
@@ -130,11 +134,13 @@ files:
|
|
|
130
134
|
- lib/rdkafka/admin/list_offsets_report.rb
|
|
131
135
|
- lib/rdkafka/bindings.rb
|
|
132
136
|
- lib/rdkafka/callbacks.rb
|
|
137
|
+
- lib/rdkafka/callbacks/alter_consumer_group_offsets_handler.rb
|
|
133
138
|
- lib/rdkafka/callbacks/base_handler.rb
|
|
134
139
|
- lib/rdkafka/callbacks/create_acl_handler.rb
|
|
135
140
|
- lib/rdkafka/callbacks/create_partitions_handler.rb
|
|
136
141
|
- lib/rdkafka/callbacks/create_topic_handler.rb
|
|
137
142
|
- lib/rdkafka/callbacks/delete_acl_handler.rb
|
|
143
|
+
- lib/rdkafka/callbacks/delete_consumer_group_offsets_handler.rb
|
|
138
144
|
- lib/rdkafka/callbacks/delete_groups_handler.rb
|
|
139
145
|
- lib/rdkafka/callbacks/delete_records_handler.rb
|
|
140
146
|
- lib/rdkafka/callbacks/delete_topic_handler.rb
|
|
@@ -192,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
192
198
|
- !ruby/object:Gem::Version
|
|
193
199
|
version: '0'
|
|
194
200
|
requirements: []
|
|
195
|
-
rubygems_version: 4.0.
|
|
201
|
+
rubygems_version: 4.0.20
|
|
196
202
|
specification_version: 4
|
|
197
203
|
summary: The rdkafka gem is a modern Kafka client library for Ruby based on librdkafka.
|
|
198
204
|
It wraps the production-ready C client using the ffi gem and targets Kafka 1.0+
|