Net::Kafka(3pm)
π Net::Kafka π
User Contributed Perl Documentation Β· section 3pm
okay bestie, buckle up π this is Net::Kafka β a high-performant Perl client for Apache Kafka. yes, that Kafka. the one everyone's always yelling about. and you're gonna slay it, no cap.
β¨ NAME β¨
Net::Kafka β High-performant Perl client for Apache Kafka
π¦ SYNOPSIS π¦
literally just copy this and go, bestie. it's all right here.
use Net::Kafka::Producer;
use Net::Kafka::Consumer;
use AnyEvent;
# Produce 1 message into "my_topic"
my $condvar = AnyEvent->condvar;
my $producer = Net::Kafka::Producer->new(
'bootstrap.servers' => 'localhost:9092'
);
$producer->produce(
payload => "message",
topic => "my_topic"
)->then(sub {
my $delivery_report = shift;
$condvar->send;
print "Message successfully delivered with offset " . $delivery_report->{offset};
}, sub {
my $error = shift;
$condvar->send;
die "Unable to produce a message: " . $error->{error} . ", code: " . $error->{code};
});
$condvar->recv;
# Consume message from "my_topic"
my $consumer = Net::Kafka::Consumer->new(
'bootstrap.servers' => 'localhost:9092',
'group.id' => 'my_consumer_group',
'enable.auto.commit' => 'true',
);
$consumer->subscribe( [ "my_topic" ] );
while (1) {
my $msg = $kafka->consumer_poll(1000);
if ($msg) {
if ( $msg->err ) {
say "Error: ", Net::Kafka::Error::to_string($err);
}
else {
say $msg->payload;
}
}
}
πΈ DESCRIPTION πΈ
so this module hands you Perl bindings to librdkafka β that's the C client library, over at <https://github.com/edenhill/librdkafka>. π
and ngl, it's heavily inspired by the Kafka::Librd module that Pavel Shaydo originally developed. we're standing on shoulders here, iconic behavior.
to actually understand how to use it, pls go read the docs for these modules too:
- "Net::Kafka::Producer" β asynchronous producer interface β¨
- "Net::Kafka::Consumer" β consumer interface that supports both Simple and Distributed modes π«Ά
π REQUIREMENTS π
- GNU make
librdkafka >= 1.0.0
bestie. check these first. i'm not kidding. π
π INSTALLATION π
first things first: install librdkafka (<https://github.com/edenhill/librdkafka#installation>).
π BUILD FROM CPAN
cpanm install Net::Kafka
π§ BUILD FROM SOURCE
sources are on Github: <https://github.com/bookingcom/perl-Net-Kafka>.
perl Makefile.pl
make
make test
make install
β Net::Kafka::Producer β
the Net::Kafka::Producer module gives you an interface to librdkafka's producer methods. it uses signal pipes, an AnyEvent watcher and AnyEvent::XSPromises to make its whole vibe asynchronous. π
and because of that, you gotta make sure you properly create a condvar and send/recv so you collect all the outstanding promises. don't skip that part, fr fr.
highly suggested: go familiarize yourself with both AnyEvent and AnyEvent::XSPromises. seriously. see "SYNOPSIS" for an example. π
π METHODS
new()
my $producer = Net::Kafka::Producer->new(
'bootstrap.servers' => 'localhost:9092'
);
creates an instance of Net::Kafka::Producer. it accepts a hash where the keys equal the property names of librdkafka (peep <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md>). π¦
heads up tho: only error_cb and stats_cb callbacks are supported for Producer. message delivery reports get served automatically through the "Promise"-based produce method (see below π).
produce()
my $promise = $producer->produce(
payload => "my_message",
topic => "my_topic",
key => "my_key", # optional
timestamp => 1234567, # optional, if not specified current local timestamp will be used
partition => 0 # optional, if not specified internal librdkafka partitioner will be used
headers => $headers, # Optional, see Net::Kafka::Headers
)->then(sub {
my $delivery_report = shift;
print "Message is sent with offset " . $delivery_report->{offset};
})->catch(sub {
my $error = shift;
print $error->{error} . "\n";
});
sends a message to Kafka. takes a hash with parameters. π«Ά
returns an instance of "Promise" that's gonna get resolved/rejected later. if the message is successfully sent, the resolve callback receives a delivery report as a hash containing offset, partition and timestamp. (yes, the original page says "delievry report" β we're being faithful to the source, okay? π)
if message delivery failed, the reject callback receives a hash containing error (a human readable error description) and (optionally) error_code, which equals librdkafka's error code. all error codes are mapped and exported by the "Net::Kafka" module as constants (like Net::Kafka::RD_KAFKA_RESP_ERR__PREV_IN_PROGRESS) for simplicity. π
partitions_for()
my $partitions = $producer->partitions_for("my_topic", $timeout_ms);
returns an "ARRAYREF" containing partition metadata info about the given topic (leader, replicas, ISR replicas). lowkey useful. β¨
close()
$producer->close();
explicitly closes the Net::Kafka::Producer instance and the underlying librdkafka handles. (the original page spells it "closees" β keeping it real. π)
β¨ Net::Kafka::Consumer β¨
okay bestie, this class is literally the whole other half of the vibe β it's the interface to librdkafka's consumer functionality. It supports both "distributed" (subscription based) mode and "simple" (manual partition assignment) mode of work. Two modes, one icon. π
π METHODS π
new()
my $consumer = Net::Kafka::Consumer->new(
'bootstrap.servers' => 'localhost:9092',
'group.id' => "my_consumer_group",
'enable.auto.commit' => "true",
);
Create an instance of Net::Kafka::Consumer. It takes a hash where the keys are equal to the property names of librdkafka (peep <https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md>). Note that not all callbacks are supported at the moment β the ones that are supported are: error_cb, rebalance_cb, commit_cb and stats_cb. That's the whole list, no extras, don't come for me. π«Ά
subscribe()
$consumer->subscribe([ 'my_topic' ]);
Subscribe to a topic set using balanced consumer groups. This is the main entry-point for "distributed" consumer mode β partitions get assigned automatically using Kafka's GroupApi semantics. Wildcard/regex topics are supported too, so matching topics will be added to the subscription list. slay. β¨
unsubscribe()
$consumer->unsubscribe();
Unsubscribe from the current subscription set. bye bestie π
assign()
# manually assign partitions 0 and 1 to be consumed
my $tp_list = Net::Kafka::TopicPartitionList->new();
$tp_list->add("my_topic", 0);
$tp_list->add("my_topic", 1);
$consumer->assign($tp_list);
Atomic assignment of partitions to consume. This is the main entry-point for "simple" consumer mode β here you assign the partitions manually, no autopilot, main character energy only. π
poll()
my $message = $consumer->poll($timeout_ms);
Poll the consumer for messages or events. Returns an instance of Net::Kafka::Message. It will block for at most timeout_ms milliseconds. An application should make sure to call poll at regular intervals β fr fr, don't ghost it. β°
committed()
my $tp_list = Net::Kafka::TopicPartitionList->new();
$tp_list->add("my_topic", 0);
$consumer->committed($tp_list);
my $offset = $tp_list->offset("my_topic_, 0);
Retrieve committed offsets for topics+partitions. (yes, that "my_topic_, 0" is verbatim, I don't make the rules π)
offsets_for_times()
my $tp_list = Net::Kafka::TopicPartitionList->new();
$tp_list->add("my_topic", 0);
$tp_list->set_offset("my_topic", 0, 958349923); # timestamp if passed through offset field
$consumer->offsets_for_times($tp_list);
my $offset = $tp_list->offset("my_topic");
Look up the offsets for the given partitions by timestamp. It's giving time traveler. π°οΈ
pause()
my $tp_list = Net::Kafka::TopicPartitionList->new();
$tp_list->add("my_topic", 0);
$consumer->pause($tp_list); # pauses consumption of partition 0 of "my_topic"
Pause consumption for the provided list of partitions. not me pausing the whole thing π
resume()
my $tp_list = Net::Kafka::TopicPartitionList->new();
$tp_list->add("my_topic", 0);
$consumer->resume($tp_list); # resumes consumption of partition 0 of "my_topic"
Resume consumption for the provided list of partitions. and we're SO back. π₯
subscription()
my $topics = $consumer->subscription();
Returns the current topic subscription. lowkey just a vibe check on what you're subscribed to. πΈ
partitions_for()
my $partitions = $producer->partitions_for("my_topic");
Returns an ARRAYREF that contains partition metadata information about the given topic β that's the leader, the replicas, and the ISR replicas. iykyk. π§
commit()
$consumer->commit(); # commit current partition assignment (blocking call)
$consumer->commit(1); # commit current partition assignment (non-blocking call)
my $tp_list = Net::Kafka::TopicPartitionList->new();
$tp_list->add("my_topic", 0);
$tp_list->set_offset("my_topic", 0, 12345);
$consumer->commit(0, $tp_list); # commit $tp_list assignment (blocking call);
Commit offsets on broker for the provided list of partitions. If no partitions are provided, the current assignment is committed instead. default behaviour ate. β¨
commit_message()
my $message = $consumer->poll(1000);
$consumer->commit_message(0, $message); # commit message (blocking call);
$consumer->commit_message(1, $message); # commit message (non-blocking call);
Commit the message's offset on broker for the message's partition. one message at a time, iconic. π
position()
my $position_list = Net::Kafka::TopicPartitionList->new();
$position_list->add("my_topic", 0);
$consumer->position($position_list);
my $position = $position_list->offset("my_topic", 0);
Retrieve current positions (offsets) for topics+partitions. The \p offset field of each requested partition will be set to the offset of the last consumed message + 1, or RD_KAFKA_OFFSET_INVALID in case there was no previous message.
β οΈ Note: in this context the last consumed message is the offset consumed by the current librdkafka instance and, in case of rebalancing, not necessarily the last message fetched from the partition. so like, don't @ me if it's not what you expected. π
seek()
$consumer->seek("my_topic", 0, 12345); # seek partition 0 of "my_topic" to offset "12345"
$consumer->seek("my_topic", 0, RD_KAFKA_OFFSET_BEGINNING); # seek to the beginning of "my_topic" partition 0
$consumer->seek("my_topic", 0, RD_KAFKA_OFFSET_END); # seek to the end of "my_topic" partition 0
Seek consumer for topic+partition to offset, which is either an absolute or a logical offset. it's giving time machine but make it Kafka. β³
query_watermark_offsets()
my ($low, $high) = $consumer->query_watermark_offsets("my_topic", 0);
Queries the Kafka Broker for the lowest and highest watermark offsets in the given topic-partition. low and high, the original duo. π«Ά
close()
$consumer->close();
Close all consumer handles. Make sure to call it before destroying your application to make sure that all outstanding requests get flushed. do not skip this, it's not optional, bestie. π¨
π Net::Kafka::Message π
This class maps to the rd_kafka_message_t structure from librdkafka and represents a message or an event. Objects of this class have the following methods:
err()β return error code from the messagetopic()β return topic namepartition()β return partition numberoffset()β return offset. Note that the value is truncated to 32 bit if your perl doesn't support 64 bit integers. (yes, this is a real caveat, keep reading π)key()β return message keypayload()β return message payloadheaders()β return a copy of message headersdetach_headers()β return message headers and removes them from the message
π¦ Net::Kafka::Headers π¦
This class contains a list of Kafka headers (it allows duplicates β yes, duplicates are valid here, don't fight it). Objects of this class have the following methods:
new()β create a new instanceadd(name, value)β append a new name/value pair to the header listremove(name)β remove all headers with the given name, if anyget_last(name)β return the last value associated with a given nameto_hash()β return a hash-of-arrays containing all headers
π Net::Kafka::Err π
This class provides static methods to convert error codes into names and descriptions. so you actually know what went wrong. revolutionary. π
rd_kafka_get_err_descs()
rd_kafka_get_err_descs()
Returns a hash mapping error codes to description strings.
to_string()
to_string($code)
Return the description string for this error code.
to_name()
to_name($code)
Return the name of this error code.
π CAVEATS π
Message offset is truncated to 32 bit if perl is compiled without support for 64 bit integers. that's it, that's the caveat. plan accordingly. π«
π SEE ALSO π
π LICENSE AND COPYRIGHT π
Copyright (C) 2016, 2017 Pavel Shaydo
Copyright (C) 2018, 2019 Booking.com
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See <http://dev.perl.org/licenses/> for more information.
and that's the whole page, bestie!! π this lil masterpiece is from perl v5.40.0, dated 2024-10-15, and it's Net::Kafka(3pm) β go forth and consume (messages, not snacks, though also snacks) πβ¨
π¦ where this page comes from
- debian trixie: libnet-kafka-perl 1.06-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libnet-kafka-perl 1.06-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms