karafka-rdkafka 0.14.2 → 0.14.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/lib/rdkafka/admin/acl_binding_result.rb +38 -24
- data/lib/rdkafka/bindings.rb +6 -1
- data/lib/rdkafka/consumer.rb +28 -14
- data/lib/rdkafka/producer.rb +29 -2
- data/lib/rdkafka/version.rb +1 -1
- data/spec/rdkafka/admin/delete_acl_report_spec.rb +1 -0
- data/spec/rdkafka/admin/describe_acl_report_spec.rb +1 -0
- data/spec/rdkafka/consumer_spec.rb +18 -1
- data/spec/rdkafka/producer_spec.rb +25 -0
- data/spec/spec_helper.rb +0 -4
- data.tar.gz.sig +0 -0
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d22e33d93f77f138063f03111b25386c08e1667012b6ab4c8449fef61754ad44
|
4
|
+
data.tar.gz: b8cc0557cbb945e5d7b7e025198a292a7cf601ce9decef97cb5102fd25af742b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfc9af0e70030f513c4c34b00f9b94b6b3b9c828add2ac6cd742ebe2eb308a1e1a5489bf4c4280c34a98d2f0118d741608918314fa8f267b7cf98b22b3d8782d
|
7
|
+
data.tar.gz: 315b552a77691b62e5a30fd5eaec1bf89efd8ec5789f9f0deeadf3997eeca9dc83bb6466ee8365e40e53d2e09707d3d68a57278b3637b170ad027b5080838519
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.github/workflows/ci.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Rdkafka Changelog
|
2
2
|
|
3
|
+
## 0.14.4 (2023-12-19)
|
4
|
+
- [Enhancement] Add ability to store offsets in a transaction (mensfeld)
|
5
|
+
|
6
|
+
## 0.14.3 (2023-12-17)
|
7
|
+
- [Enhancement] Replace `rd_kafka_offset_store` with `rd_kafka_offsets_store` (mensfeld)
|
8
|
+
- [Fix] Missing ACL `RD_KAFKA_RESOURCE_BROKER` constant reference (mensfeld)
|
9
|
+
- [Change] Rename `matching_acl_pattern_type` to `matching_acl_resource_pattern_type` to align the whole API (mensfeld)
|
10
|
+
|
3
11
|
## 0.14.2 (2023-12-11)
|
4
12
|
- [Enhancement] Alias `topic_name` as `topic` in the delivery report (mensfeld)
|
5
13
|
- [Fix] Fix return type on `#rd_kafka_poll` (mensfeld)
|
@@ -2,36 +2,50 @@
|
|
2
2
|
|
3
3
|
module Rdkafka
|
4
4
|
class Admin
|
5
|
-
|
6
5
|
# Extracts attributes of rd_kafka_AclBinding_t
|
7
6
|
#
|
8
7
|
class AclBindingResult
|
9
|
-
attr_reader :result_error, :error_string, :matching_acl_resource_type,
|
8
|
+
attr_reader :result_error, :error_string, :matching_acl_resource_type,
|
9
|
+
:matching_acl_resource_name, :matching_acl_resource_pattern_type,
|
10
|
+
:matching_acl_principal, :matching_acl_host, :matching_acl_operation,
|
11
|
+
:matching_acl_permission_type
|
12
|
+
|
13
|
+
# This attribute was initially released under the name that is now an alias
|
14
|
+
# We keep it for backwards compatibility but it was changed for the consistency
|
15
|
+
alias matching_acl_pattern_type matching_acl_resource_pattern_type
|
10
16
|
|
11
17
|
def initialize(matching_acl)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@matching_acl_resource_type = Rdkafka::Bindings.rd_kafka_AclBinding_restype(matching_acl)
|
19
|
-
matching_acl_resource_name = Rdkafka::Bindings.rd_kafka_AclBinding_name(matching_acl)
|
20
|
-
if matching_acl_resource_name != FFI::Pointer::NULL
|
21
|
-
@matching_acl_resource_name = matching_acl_resource_name.read_string
|
22
|
-
end
|
23
|
-
@matching_acl_pattern_type = Rdkafka::Bindings.rd_kafka_AclBinding_resource_pattern_type(matching_acl)
|
24
|
-
matching_acl_principal = Rdkafka::Bindings.rd_kafka_AclBinding_principal(matching_acl)
|
25
|
-
if matching_acl_principal != FFI::Pointer::NULL
|
26
|
-
@matching_acl_principal = matching_acl_principal.read_string
|
27
|
-
end
|
28
|
-
matching_acl_host = Rdkafka::Bindings.rd_kafka_AclBinding_host(matching_acl)
|
29
|
-
if matching_acl_host != FFI::Pointer::NULL
|
30
|
-
@matching_acl_host = matching_acl_host.read_string
|
31
|
-
end
|
32
|
-
@matching_acl_operation = Rdkafka::Bindings.rd_kafka_AclBinding_operation(matching_acl)
|
33
|
-
@matching_acl_permission_type = Rdkafka::Bindings.rd_kafka_AclBinding_permission_type(matching_acl)
|
18
|
+
rd_kafka_error_pointer = Rdkafka::Bindings.rd_kafka_AclBinding_error(matching_acl)
|
19
|
+
@result_error = Rdkafka::Bindings.rd_kafka_error_code(rd_kafka_error_pointer)
|
20
|
+
error_string = Rdkafka::Bindings.rd_kafka_error_string(rd_kafka_error_pointer)
|
21
|
+
|
22
|
+
if error_string != FFI::Pointer::NULL
|
23
|
+
@error_string = error_string.read_string
|
34
24
|
end
|
25
|
+
|
26
|
+
@matching_acl_resource_type = Rdkafka::Bindings.rd_kafka_AclBinding_restype(matching_acl)
|
27
|
+
matching_acl_resource_name = Rdkafka::Bindings.rd_kafka_AclBinding_name(matching_acl)
|
28
|
+
|
29
|
+
if matching_acl_resource_name != FFI::Pointer::NULL
|
30
|
+
@matching_acl_resource_name = matching_acl_resource_name.read_string
|
31
|
+
end
|
32
|
+
|
33
|
+
@matching_acl_resource_pattern_type = Rdkafka::Bindings.rd_kafka_AclBinding_resource_pattern_type(matching_acl)
|
34
|
+
matching_acl_principal = Rdkafka::Bindings.rd_kafka_AclBinding_principal(matching_acl)
|
35
|
+
|
36
|
+
if matching_acl_principal != FFI::Pointer::NULL
|
37
|
+
@matching_acl_principal = matching_acl_principal.read_string
|
38
|
+
end
|
39
|
+
|
40
|
+
matching_acl_host = Rdkafka::Bindings.rd_kafka_AclBinding_host(matching_acl)
|
41
|
+
|
42
|
+
if matching_acl_host != FFI::Pointer::NULL
|
43
|
+
@matching_acl_host = matching_acl_host.read_string
|
44
|
+
end
|
45
|
+
|
46
|
+
@matching_acl_operation = Rdkafka::Bindings.rd_kafka_AclBinding_operation(matching_acl)
|
47
|
+
@matching_acl_permission_type = Rdkafka::Bindings.rd_kafka_AclBinding_permission_type(matching_acl)
|
35
48
|
end
|
49
|
+
end
|
36
50
|
end
|
37
51
|
end
|
data/lib/rdkafka/bindings.rb
CHANGED
@@ -199,12 +199,15 @@ module Rdkafka
|
|
199
199
|
attach_function :rd_kafka_poll_set_consumer, [:pointer], :void, blocking: true
|
200
200
|
attach_function :rd_kafka_consumer_poll, [:pointer, :int], :pointer, blocking: true
|
201
201
|
attach_function :rd_kafka_consumer_close, [:pointer], :void, blocking: true
|
202
|
-
attach_function :
|
202
|
+
attach_function :rd_kafka_offsets_store, [:pointer, :pointer], :int, blocking: true
|
203
203
|
attach_function :rd_kafka_pause_partitions, [:pointer, :pointer], :int, blocking: true
|
204
204
|
attach_function :rd_kafka_resume_partitions, [:pointer, :pointer], :int, blocking: true
|
205
205
|
attach_function :rd_kafka_seek, [:pointer, :int32, :int64, :int], :int, blocking: true
|
206
206
|
attach_function :rd_kafka_offsets_for_times, [:pointer, :pointer, :int], :int, blocking: true
|
207
207
|
attach_function :rd_kafka_position, [:pointer, :pointer], :int, blocking: true
|
208
|
+
# those two are used for eos support
|
209
|
+
attach_function :rd_kafka_consumer_group_metadata, [:pointer], :pointer, blocking: true
|
210
|
+
attach_function :rd_kafka_consumer_group_metadata_destroy, [:pointer], :void, blocking: true
|
208
211
|
|
209
212
|
# Headers
|
210
213
|
attach_function :rd_kafka_header_get_all, [:pointer, :size_t, :pointer, :pointer, SizePtr], :int
|
@@ -276,6 +279,7 @@ module Rdkafka
|
|
276
279
|
callback :delivery_cb, [:pointer, :pointer, :pointer], :void
|
277
280
|
attach_function :rd_kafka_conf_set_dr_msg_cb, [:pointer, :delivery_cb], :void
|
278
281
|
attach_function :rd_kafka_init_transactions, [:pointer, :int], :pointer, blocking: true
|
282
|
+
attach_function :rd_kafka_send_offsets_to_transaction, [:pointer, :pointer, :pointer, :int], :pointer, blocking: true
|
279
283
|
attach_function :rd_kafka_begin_transaction, [:pointer], :pointer, blocking: true
|
280
284
|
attach_function :rd_kafka_abort_transaction, [:pointer, :int], :pointer, blocking: true
|
281
285
|
attach_function :rd_kafka_commit_transaction, [:pointer, :int], :pointer, blocking: true
|
@@ -412,6 +416,7 @@ module Rdkafka
|
|
412
416
|
RD_KAFKA_RESOURCE_ANY = 1
|
413
417
|
RD_KAFKA_RESOURCE_TOPIC = 2
|
414
418
|
RD_KAFKA_RESOURCE_GROUP = 3
|
419
|
+
RD_KAFKA_RESOURCE_BROKER = 4
|
415
420
|
|
416
421
|
# rd_kafka_ResourcePatternType_t - https://github.com/confluentinc/librdkafka/blob/292d2a66b9921b783f08147807992e603c7af059/src/rdkafka.h#L7320
|
417
422
|
|
data/lib/rdkafka/consumer.rb
CHANGED
@@ -388,28 +388,26 @@ module Rdkafka
|
|
388
388
|
def store_offset(message)
|
389
389
|
closed_consumer_check(__method__)
|
390
390
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
391
|
+
list = TopicPartitionList.new
|
392
|
+
list.add_topic_and_partitions_with_offsets(
|
393
|
+
message.topic,
|
394
|
+
message.partition => message.offset + 1
|
395
|
+
)
|
396
|
+
|
397
|
+
tpl = list.to_native_tpl
|
398
|
+
|
399
|
+
response = @native_kafka.with_inner do |inner|
|
400
|
+
Rdkafka::Bindings.rd_kafka_offsets_store(
|
395
401
|
inner,
|
396
|
-
|
397
|
-
nil
|
402
|
+
tpl
|
398
403
|
)
|
399
404
|
end
|
400
|
-
response = Rdkafka::Bindings.rd_kafka_offset_store(
|
401
|
-
native_topic,
|
402
|
-
message.partition,
|
403
|
-
message.offset
|
404
|
-
)
|
405
405
|
|
406
406
|
Rdkafka::RdkafkaError.validate!(response)
|
407
407
|
|
408
408
|
nil
|
409
409
|
ensure
|
410
|
-
if
|
411
|
-
Rdkafka::Bindings.rd_kafka_topic_destroy(native_topic)
|
412
|
-
end
|
410
|
+
Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(tpl) if tpl
|
413
411
|
end
|
414
412
|
|
415
413
|
# Seek to a particular message. The next poll on the topic/partition will return the
|
@@ -673,6 +671,22 @@ module Rdkafka
|
|
673
671
|
end
|
674
672
|
end
|
675
673
|
|
674
|
+
# Returns pointer to the consumer group metadata. It is used only in the context of
|
675
|
+
# exactly-once-semantics in transactions, this is why it is never remapped to Ruby
|
676
|
+
#
|
677
|
+
# This API is **not** usable by itself from Ruby
|
678
|
+
#
|
679
|
+
# @note This pointer **needs** to be removed with `#rd_kafka_consumer_group_metadata_destroy`
|
680
|
+
#
|
681
|
+
# @private
|
682
|
+
def consumer_group_metadata_pointer
|
683
|
+
closed_consumer_check(__method__)
|
684
|
+
|
685
|
+
@native_kafka.with_inner do |inner|
|
686
|
+
Bindings.rd_kafka_consumer_group_metadata(inner)
|
687
|
+
end
|
688
|
+
end
|
689
|
+
|
676
690
|
private
|
677
691
|
|
678
692
|
def closed_consumer_check(method)
|
data/lib/rdkafka/producer.rb
CHANGED
@@ -81,7 +81,7 @@ module Rdkafka
|
|
81
81
|
@native_kafka.with_inner do |inner|
|
82
82
|
response_ptr = Rdkafka::Bindings.rd_kafka_begin_transaction(inner)
|
83
83
|
|
84
|
-
Rdkafka::RdkafkaError.validate!(response_ptr)
|
84
|
+
Rdkafka::RdkafkaError.validate!(response_ptr) || true
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -91,7 +91,7 @@ module Rdkafka
|
|
91
91
|
@native_kafka.with_inner do |inner|
|
92
92
|
response_ptr = Rdkafka::Bindings.rd_kafka_commit_transaction(inner, timeout_ms)
|
93
93
|
|
94
|
-
Rdkafka::RdkafkaError.validate!(response_ptr)
|
94
|
+
Rdkafka::RdkafkaError.validate!(response_ptr) || true
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
@@ -100,8 +100,35 @@ module Rdkafka
|
|
100
100
|
|
101
101
|
@native_kafka.with_inner do |inner|
|
102
102
|
response_ptr = Rdkafka::Bindings.rd_kafka_abort_transaction(inner, timeout_ms)
|
103
|
+
Rdkafka::RdkafkaError.validate!(response_ptr) || true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Sends provided offsets of a consumer to the transaction for collective commit
|
108
|
+
#
|
109
|
+
# @param consumer [Consumer] consumer that owns the given tpls
|
110
|
+
# @param tpl [Consumer::TopicPartitionList]
|
111
|
+
# @param timeout_ms [Integer] offsets send timeout
|
112
|
+
# @note Use **only** in the context of an active transaction
|
113
|
+
def send_offsets_to_transaction(consumer, tpl, timeout_ms = 5_000)
|
114
|
+
closed_producer_check(__method__)
|
115
|
+
|
116
|
+
return if tpl.empty?
|
117
|
+
|
118
|
+
cgmetadata = consumer.consumer_group_metadata_pointer
|
119
|
+
native_tpl = tpl.to_native_tpl
|
120
|
+
|
121
|
+
@native_kafka.with_inner do |inner|
|
122
|
+
response_ptr = Bindings.rd_kafka_send_offsets_to_transaction(inner, native_tpl, cgmetadata, timeout_ms)
|
123
|
+
|
103
124
|
Rdkafka::RdkafkaError.validate!(response_ptr)
|
104
125
|
end
|
126
|
+
ensure
|
127
|
+
if cgmetadata && !cgmetadata.null?
|
128
|
+
Bindings.rd_kafka_consumer_group_metadata_destroy(cgmetadata)
|
129
|
+
end
|
130
|
+
|
131
|
+
Rdkafka::Bindings.rd_kafka_topic_partition_list_destroy(native_tpl) unless native_tpl.nil?
|
105
132
|
end
|
106
133
|
|
107
134
|
# Close this producer and wait for the internal poll queue to empty.
|
data/lib/rdkafka/version.rb
CHANGED
@@ -50,6 +50,7 @@ describe Rdkafka::Admin::DeleteAclReport do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should get deleted acl resource pattern type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL" do
|
53
|
+
expect(subject.deleted_acls[0].matching_acl_resource_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
|
53
54
|
expect(subject.deleted_acls[0].matching_acl_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
|
54
55
|
end
|
55
56
|
|
@@ -51,6 +51,7 @@ describe Rdkafka::Admin::DescribeAclReport do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should get matching acl resource pattern type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL" do
|
54
|
+
expect(subject.acls[0].matching_acl_resource_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
|
54
55
|
expect(subject.acls[0].matching_acl_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
|
55
56
|
end
|
56
57
|
|
@@ -360,7 +360,6 @@ describe Rdkafka::Consumer do
|
|
360
360
|
end
|
361
361
|
end
|
362
362
|
|
363
|
-
|
364
363
|
describe "#position, #commit, #committed and #store_offset" do
|
365
364
|
# Make sure there are messages to work with
|
366
365
|
let!(:report) do
|
@@ -480,6 +479,8 @@ describe Rdkafka::Consumer do
|
|
480
479
|
end
|
481
480
|
|
482
481
|
describe "#store_offset" do
|
482
|
+
let(:consumer) { rdkafka_consumer_config('enable.auto.offset.store': false).consumer }
|
483
|
+
|
483
484
|
before do
|
484
485
|
config = {}
|
485
486
|
config[:'enable.auto.offset.store'] = false
|
@@ -542,6 +543,14 @@ describe Rdkafka::Consumer do
|
|
542
543
|
}.to raise_error(Rdkafka::RdkafkaError)
|
543
544
|
end
|
544
545
|
end
|
546
|
+
|
547
|
+
context "when trying to use with enable.auto.offset.store set to true" do
|
548
|
+
let(:consumer) { rdkafka_consumer_config('enable.auto.offset.store': true).consumer }
|
549
|
+
|
550
|
+
it "expect to raise invalid configuration error" do
|
551
|
+
expect { consumer.store_offset(message) }.to raise_error(Rdkafka::RdkafkaError, /invalid_arg/)
|
552
|
+
end
|
553
|
+
end
|
545
554
|
end
|
546
555
|
end
|
547
556
|
end
|
@@ -1132,6 +1141,14 @@ describe Rdkafka::Consumer do
|
|
1132
1141
|
end
|
1133
1142
|
end
|
1134
1143
|
|
1144
|
+
describe '#consumer_group_metadata_pointer' do
|
1145
|
+
it 'expect to yield pointer' do
|
1146
|
+
consumer.consumer_group_metadata_pointer do |pointer|
|
1147
|
+
expect(pointer).to be_a(FFI::Pointer)
|
1148
|
+
end
|
1149
|
+
end
|
1150
|
+
end
|
1151
|
+
|
1135
1152
|
describe "a rebalance listener" do
|
1136
1153
|
let(:consumer) do
|
1137
1154
|
config = rdkafka_consumer_config
|
@@ -883,5 +883,30 @@ describe Rdkafka::Producer do
|
|
883
883
|
expect { producer2.commit_transaction }.not_to raise_error
|
884
884
|
end
|
885
885
|
end
|
886
|
+
|
887
|
+
context 'when having a consumer with tpls for exactly once semantics' do
|
888
|
+
let(:tpl) do
|
889
|
+
producer.produce(topic: 'consume_test_topic', payload: 'data1', partition: 0).wait
|
890
|
+
result = producer.produce(topic: 'consume_test_topic', payload: 'data1', partition: 0).wait
|
891
|
+
|
892
|
+
Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
893
|
+
list.add_topic_and_partitions_with_offsets("consume_test_topic", 0 => result.offset + 1)
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
before do
|
898
|
+
consumer.subscribe("consume_test_topic")
|
899
|
+
wait_for_assignment(consumer)
|
900
|
+
producer.init_transactions
|
901
|
+
producer.begin_transaction
|
902
|
+
end
|
903
|
+
|
904
|
+
after { consumer.unsubscribe }
|
905
|
+
|
906
|
+
it 'expect to store offsets and not crash' do
|
907
|
+
producer.send_offsets_to_transaction(consumer, tpl)
|
908
|
+
producer.commit_transaction
|
909
|
+
end
|
910
|
+
end
|
886
911
|
end
|
887
912
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -107,10 +107,6 @@ def wait_for_unassignment(consumer)
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
def objects_of_type_count(type)
|
111
|
-
ObjectSpace.each_object(type).count
|
112
|
-
end
|
113
|
-
|
114
110
|
def notify_listener(listener, &block)
|
115
111
|
# 1. subscribe and poll
|
116
112
|
consumer.subscribe("consume_test_topic")
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: karafka-rdkafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thijs Cadier
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
|
36
36
|
msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2023-12-
|
38
|
+
date: 2023-12-19 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: ffi
|
metadata.gz.sig
CHANGED
Binary file
|