Current section

113 Versions

Jump to

Compare versions

30 files changed
+1855 additions
-2865 deletions
  @@ -1,42 +1,17 @@
1 + KAFKA_VERSION ?= 1.1
1 2 PROJECT = brod
2 3 PROJECT_DESCRIPTION = Kafka client library in Erlang
3 - PROJECT_VERSION = 3.5.2
4 + PROJECT_VERSION = 3.6.0
4 5
5 6 DEPS = supervisor3 kafka_protocol
6 - TEST_DEPS = docopt jsone meck proper
7 - REL_DEPS = docopt jsone
8 7
9 - ERLC_OPTS = -Werror +warn_unused_vars +warn_shadow_vars +warn_unused_import +warn_obsolete_guard +debug_info
10 - TEST_ERLC_OPTS = -Werror +warn_unused_vars +warn_shadow_vars +warn_unused_import +warn_obsolete_guard +debug_info
8 + ERLC_OPTS = -Werror +warn_unused_vars +warn_shadow_vars +warn_unused_import +warn_obsolete_guard +debug_info -Dbuild_brod_cli
11 9
12 - dep_supervisor3_commit = 1.1.5
13 - dep_kafka_protocol_commit = 1.1.2
14 - dep_docopt = git https://github.com/zmstone/docopt-erl.git 0.1.3
10 + dep_supervisor3_commit = 1.1.7
11 + dep_kafka_protocol_commit = 2.1.1
12 + dep_kafka_protocol = git https://github.com/klarna/kafka_protocol.git $(dep_kafka_protocol_commit)
15 13
16 - ERTS_VSN = $(shell erl -noshell -eval 'io:put_chars(erlang:system_info(version)), halt()')
17 - ESCRIPT_FILE = scripts/brod_cli
18 - ESCRIPT_EMU_ARGS = -sname brod_cli
19 -
20 - COVER = true
21 -
22 - EUNIT_OPTS = verbose
23 -
24 - CT_OPTS = -ct_use_short_names true
25 -
26 - ERL_LIBS := $(ERL_LIBS):$(CURDIR)
27 -
28 - ifeq ($(MAKECMDGOALS),)
29 - export BROD_CLI=true
30 - else ifneq ($(filter rel,$(MAKECMDGOALS)),)
31 - export BROD_CLI=true
32 - else ifneq ($(filter escript,$(MAKECMDGOALS)),)
33 - export BROD_CLI=true
34 - endif
35 -
36 - ifeq ($(BROD_CLI),true)
37 - ERLC_OPTS += -DBROD_CLI
38 - TEST_ERLC_OPTS += -DBROD_CLI
39 - endif
14 + EDOC_OPTS = preprocess, {macros, [{build_brod_cli, true}]}
40 15
41 16 ## Make app the default target
42 17 ## To avoid building a release when brod is used as a erlang.mk project's dependency
  @@ -44,20 +19,50 @@ app::
44 19
45 20 include erlang.mk
46 21
47 - rel:: escript
48 - @cp scripts/brod _rel/brod/bin/brod
49 - @cp $(ESCRIPT_FILE) _rel/brod/bin/brod_cli
50 - @ln -sf erts-$(ERTS_VSN) _rel/brod/erts
51 - @tar -pczf _rel/brod.tar.gz -C _rel brod
22 + compile:
23 + @rebar3 compile
52 24
53 25 test-env:
54 - ./scripts/setup-test-env.sh
26 + @./scripts/setup-test-env.sh
55 27
56 - t: eunit ct
57 - ./scripts/cover-summary.escript eunit.coverdata ct.coverdata
28 + ut:
29 + @rebar3 eunit -v --cover_export_name ut-$(KAFKA_VERSION)
30 +
31 + # version check, eunit and all common tests
32 + t: vsn-check ut
33 + @rebar3 ct -v --cover_export_name ct-$(KAFKA_VERSION)
58 34
59 35 vsn-check:
60 - $(verbose) ./scripts/vsn-check.sh $(PROJECT_VERSION)
36 + @./scripts/vsn-check.sh $(PROJECT_VERSION)
37 +
38 + distclean:: rebar-clean
39 +
40 + rebar-clean:
41 + @rebar3 clean
42 + @rm -rf _build
43 + @rm -rf doc
44 + @rm -f pipe.testdata
61 45
62 46 hex-publish: distclean
63 - $(verbose) rebar3 hex publish
47 + @rebar3 hex publish
48 +
49 + ## tests that require kafka running at localhost
50 + INTEGRATION_CTS = brod_cg_commits brod_client brod_compression brod_consumer brod_producer brod_group_subscriber brod_topic_subscriber
51 +
52 + ## integration tests
53 + it: ut $(INTEGRATION_CTS:%=it-%)
54 +
55 + $(INTEGRATION_CTS:%=it-%):
56 + @rebar3 ct -v --suite=test/$(subst it-,,$@)_SUITE --cover_export_name $@-$(KAFKA_VERSION)
57 +
58 + ## build escript and a releas, and copy escript to release bin dir
59 + brod-cli:
60 + @rebar3 as brod_cli escriptize
61 + @rebar3 as brod_cli release
62 + @cp _build/brod_cli/bin/brod_cli _build/brod_cli/rel/brod/bin/
63 +
64 + cover:
65 + @rebar3 cover -v
66 +
67 + coveralls:
68 + @rebar3 coveralls send
  @@ -1,8 +1,8 @@
1 - # Brod - Apache Kafka Erlang client library
1 + [![Build Status](https://travis-ci.org/klarna/brod.svg)](https://travis-ci.org/klarna/brod) [![Coverage Status](https://coveralls.io/repos/github/klarna/brod/badge.svg?branch=master)](https://coveralls.io/github/klarna/brod?branch=master)
2 2
3 - Brod is an erlang implementation of the Apache Kafka protocol, providing support for both producers and consumers.
3 + # Brod - Apache Kafka Client for Erlang/Elixir
4 4
5 - [![Build Status](https://travis-ci.org/klarna/brod.svg)](https://travis-ci.org/klarna/brod)
5 + Brod is an Erlang implementation of the Apache Kafka protocol, providing support for both producers and consumers.
6 6
7 7 Why "brod"? [http://en.wikipedia.org/wiki/Max_Brod](http://en.wikipedia.org/wiki/Max_Brod)
8 8
  @@ -11,23 +11,20 @@ Why "brod"? [http://en.wikipedia.org/wiki/Max_Brod](http://en.wikipedia.org/wiki
11 11 * Supports Apache Kafka v0.8+
12 12 * Robust producer implementation supporting in-flight requests and asynchronous acknowledgements
13 13 * Both consumer and producer handle leader re-election and other cluster disturbances internally
14 - * Opens max 1 tcp connection to a broker per "brod_client", one can create more clients if needed
14 + * Opens max 1 tcp connection to a broker per `brod_client`, one can create more clients if needed
15 15 * Producer: will start to batch automatically when number of unacknowledged (in flight) requests exceeds configurable maximum
16 16 * Producer: will try to re-send buffered messages on common errors like "Not a leader for partition", errors are resolved automatically by refreshing metadata
17 17 * Simple consumer: The poller, has a configurable "prefetch count" - it will continue sending fetch requests as long as total number of unprocessed messages (not message-sets) is less than "prefetch count"
18 18 * Group subscriber: Support for consumer groups with options to have Kafka as offset storage or a custom one
19 19 * Topic subscriber: Subscribe on messages from all or selected topic partitions without using consumer groups
20 20 * Pick latest supported version when sending requests to kafka.
21 -
22 - # Missing features
23 -
24 - * lz4 compression & decompression
25 - * new 0.10.1.0 create/delete topic api
21 + * Direct APIs for message send/fetch and cluster inspection/management without having to start clients/producers/consumers.
22 + * A escriptized command-line tool for message send/fetch and cluster inspection/management.
26 23
27 24 # Building and testing
28 25
29 - make
30 - make test-env t # requires docker-composer in place
26 + make compile
27 + make test-env t # requires docker-compose in place
31 28
32 29 # Working With Kafka 0.9.x or Earlier
33 30
  @@ -48,45 +45,46 @@ e.g. in sys.config:
48 45
49 46 # Quick Demo
50 47
51 - Assuming kafka is running at `localhost:9092`
52 - and there is a topic named `brod-test`.
48 + Assuming kafka is running at `localhost:9092` and there is a topic named `test-topic`.
53 49
54 - Below code snippet is copied from Erlang shell
55 - with some non-important printouts trimmed.
50 + Start Erlang shell by `make compile; erl -pa _build/default/lib/*/ebin`, then paste lines below into shell:
56 51
57 52 ```erlang
58 - > rr(brod).
59 - > {ok, _} = application:ensure_all_started(brod).
60 - > KafkaBootstrapEndpoints = [{"localhost", 9092}].
61 - > Topic = <<"brod-test">>.
62 - > Partition = 0.
63 - > ok = brod:start_client(KafkaBootstrapEndpoints, client1).
64 - > ok = brod:start_producer(client1, Topic, _ProducerConfig = []).
65 - > ok = brod:produce_sync(client1, Topic, Partition, <<"key1">>, <<"value1">>).
66 - > ok = brod:produce_sync(client1, Topic, Partition, <<"key2">>, <<"value2">>).
67 - > SubscriberCallbackFun =
68 - fun(Partition, Msg, ShellPid = CallbackState) ->
69 - ShellPid ! Msg,
70 - {ok, ack, CallbackState}
71 - end.
72 - > Receive = fun() -> receive Msg -> Msg after 1000 -> timeout end end.
73 - > brod_topic_subscriber:start_link(client1, Topic, Partitions=[Partition],
74 - _ConsumerConfig=[{begin_offset, earliest}],
75 - _CommittdOffsets=[], message, SubscriberCallbackFun,
76 - _CallbackState=self()).
77 - > Receive().
78 - #kafka_message{offset = 0,magic_byte = 0,attributes = 0,
79 - key = <<"key1">>,value = <<"value1">>,crc = 1978725405}
80 - > Receive().
81 - #kafka_message{offset = 1,magic_byte = 0,attributes = 0,
82 - key = <<"key2">>,value = <<"value2">>,crc = 1964753830}
83 - > {ok, CallRef} = brod:produce(client1, Topic, Partition, <<"key3">>, <<"value3">>).
84 - > #brod_produce_reply{ call_ref = CallRef,
85 - result = brod_produce_req_acked
86 - } = Receive().
87 - > Receive().
88 - #kafka_message{offset = 2,magic_byte = 0,attributes = 0,
89 - key = <<"key3">>,value = <<"value3">>,crc = -1013830416}
53 + rr(brod),
54 + {ok, _} = application:ensure_all_started(brod),
55 + KafkaBootstrapEndpoints = [{"localhost", 9092}],
56 + Topic = <<"test-topic">>,
57 + Partition = 0,
58 + ok = brod:start_client(KafkaBootstrapEndpoints, client1),
59 + ok = brod:start_producer(client1, Topic, _ProducerConfig = []),
60 + {ok, FirstOffset} = brod:produce_sync_offset(client1, Topic, Partition, <<"key1">>, <<"value1">>),
61 + ok = brod:produce_sync(client1, Topic, Partition, <<"key2">>, <<"value2">>),
62 + SubscriberCallbackFun = fun(Partition, Msg, ShellPid = CallbackState) -> ShellPid ! Msg, {ok, ack, CallbackState} end,
63 + Receive = fun() -> receive Msg -> Msg after 1000 -> timeout end end,
64 + brod_topic_subscriber:start_link(client1, Topic, Partitions=[Partition],
65 + _ConsumerConfig=[{begin_offset, FirstOffset}],
66 + _CommittdOffsets=[], message, SubscriberCallbackFun,
67 + _CallbackState=self()),
68 + AckCb = fun(Partition, BaseOffset) -> io:format(user, "\nProduced to partition ~p at base-offset ~p\n", [Partition, BaseOffset]) end,
69 + ok = brod:produce_cb(client1, Topic, Partition, <<>>, [{<<"key3">>, <<"value3">>}], AckCb).
70 + Receive().
71 + Receive().
72 + {ok, {_, [Msg]}} = brod:fetch(KafkaBootstrapEndpoints, Topic, Partition, FirstOffset + 2), Msg.
73 + ```
74 +
75 + Example outputs:
76 +
77 + ```erlang
78 + #kafka_message{offset = 0,key = <<"key1">>,
79 + value = <<"value1">>,ts_type = create,ts = 1531995555085,
80 + headers = []}
81 + #kafka_message{offset = 1,key = <<"key2">>,
82 + value = <<"value2">>,ts_type = create,ts = 1531995555107,
83 + headers = []}
84 + Produced to partition 0 at base-offset 406
85 + #kafka_message{offset = 2,key = <<"key3">>,
86 + value = <<"value3">>,ts_type = create,ts = 1531995555129,
87 + headers = []}
90 88 ```
91 89
92 90 # Overview
  @@ -154,7 +152,7 @@ Put below configs to client config in sys.config or app env:
154 152 {default_producer_config, []}
155 153 ```
156 154
157 - ## Start a producer on demand
155 + ## Start a Producer on Demand
158 156
159 157 ```erlang
160 158 brod:start_producer(_Client = brod_client_1,
  @@ -162,30 +160,41 @@ brod:start_producer(_Client = brod_client_1,
162 160 _ProducerConfig = []).
163 161 ```
164 162
165 - ## Produce to a known topic-partition:
163 + ## Supported Message Input Format
164 +
165 + Brod supports below produce APIs:
166 +
167 + - `brod:produce`: Async produce with ack message sent back to caller.
168 + - `brod:produce_cb`: Async produce with a callback evaluated when ack is received.
169 + - `brod:produce_sync`: Sync produce returns `ok`.
170 + - `brod:produce_sync_offset`: Sync produce returns `{ok, BaseOffset}`.
171 +
172 + The `Value` arg in these APIs can be:
173 +
174 + - `binary()`: One single message
175 + - `{brod:msg_ts(), binary()}`: One single message with its create-time timestamp
176 + - `#{ts => brod:msg_ts(), value => binary(), headers => [{_, _}]}`:
177 + One single message. If this map does not have a `key` field, the `Key` argument is used.
178 + - `[{K, V} | {T, K, V}]`: A batch, where `V` could be a nested list of such representation.
179 + - `[#{key => K, value => V, ts => T, headers => [{_, _}]}]`: A batch.
180 +
181 + When `Value` is a batch, the `Key` argument is only used as partitioner input.
182 + All messages are unified into a batch format of below spec:
183 + `[#{key => K, value => V, ts => T, headers => [{_, _}]}]`.
184 + `ts` field is dropped for kafka prior to version `0.10`
185 + `headers` field is dropped for kafka prior to version `0.11`
186 +
187 + ## Synchronized Produce API
166 188
167 189 ```erlang
168 - {ok, CallRef} =
169 - brod:produce(_Client = brod_client_1,
170 - _Topic = <<"brod-test-topic-1">>,
171 - _Partition = 0
172 - _Key = <<"some-key">>
173 - _Value = <<"some-value">>),
174 -
175 - %% just to illustrate what message to expect
176 - receive
177 - #brod_produce_reply{ call_ref = CallRef
178 - , result = brod_produce_req_acked
179 - } ->
180 - ok
181 - after 5000 ->
182 - erlang:exit(timeout)
183 - end.
190 + brod:produce_sync(_Client = brod_client_1,
191 + _Topic = <<"brod-test-topic-1">>,
192 + _Partition = 0
193 + _Key = <<"some-key">>
194 + _Value = <<"some-value">>).
184 195 ```
185 196
186 - ## Synchronized produce request
187 -
188 - Block calling process until Kafka confirmed the message:
197 + Or block calling process until Kafka confirmed the message:
189 198
190 199 ```erlang
191 200 {ok, CallRef} =
  @@ -197,17 +206,15 @@ Block calling process until Kafka confirmed the message:
197 206 brod:sync_produce_request(CallRef).
198 207 ```
199 208
200 - or the same in one call:
209 + ## Produce One Message and Receive Its Offset in Kafka
201 210
202 211 ```erlang
203 - brod:produce_sync(_Client = brod_client_1,
204 - _Topic = <<"brod-test-topic-1">>,
205 - _Partition = 0
206 - _Key = <<"some-key">>
207 - _Value = <<"some-value">>).
212 + Client = brod_client_1,
213 + Topic = <<"brod-test-topic-1">>,
214 + {ok, Offset} = brod:produce_sync_offset(Client, Topic, 0, <<>>, <<"value">>).
208 215 ```
209 216
210 - ## Produce with random partitioner
217 + ## Produce with Random Partitioner
211 218
212 219 ```erlang
213 220 Client = brod_client_1,
  @@ -215,60 +222,54 @@ Topic = <<"brod-test-topic-1">>,
215 222 PartitionFun = fun(_Topic, PartitionsCount, _Key, _Value) ->
216 223 {ok, crypto:rand_uniform(0, PartitionsCount)}
217 224 end,
218 - {ok, CallRef} = brod:produce(Client, Topic, PartitionFun, Key, Value).
225 + ok = brod:produce_sync(Client, Topic, PartitionFun, Key, Value).
219 226 ```
220 227
221 - ## Produce a batch of (maybe nested) Key-Value list
228 + ## Produce a Batch
222 229
223 230 ```erlang
224 - %% The top-level key is used for partitioning
225 - %% and nested keys are discarded.
226 - %% Nested messages are serialized into a message set to the same partition.
227 231 brod:produce(_Client = brod_client_1,
228 232 _Topic = <<"brod-test-topic-1">>,
229 233 _Partition = MyPartitionerFun
230 234 _Key = KeyUsedForPartitioning
231 - _Value = [ {<<"k1", <<"v1">>}
232 - , {<<"k2", <<"v2">>}
233 - , { _KeyDiscarded = <<>>
234 - , [ {<<"k3">>, <<"v3">>}
235 - , {<<"k4">>, <<"v4">>}
236 - ]}
235 + _Value = [ #{key => "k1" value => "v1", headers = [{"foo", "bar"}]}
236 + , #{key => "k2" value => "v2"}
237 237 ]).
238 238 ```
239 239
240 - ## Produce message create time.
240 + ## Handle Acks from Kafka as Messages
241 241
242 - ```erlang
243 - brod:produce(Client, Topic, Partition, _Key = <<>>,
244 - _Value = [{Ts1, Key1, Value1}, {Ts2, Key2, Value2}]).
245 - ```
246 -
247 - ## Handle acks from kafka
248 -
249 - Unless brod:produce_sync was called, callers of brod:produce should
250 - expect a message of below pattern for each produce call.
251 - Add `-include_lib("brod/include/brod.hrl").` to use the record.
242 + For async produce APIs `brod:produce/3` and `brod:produce/5`,
243 + the caller should expect a message of below pattern for each produce call.
252 244
253 245 ```erlang
254 246 #brod_produce_reply{ call_ref = CallRef %% returned from brod:produce
255 247 , result = brod_produce_req_acked
256 248 }
257 249 ```
250 + Add `-include_lib("brod/include/brod.hrl").` to use the record.
258 251
259 - NOTE: If required_acks is set to 0 in producer config,
260 - kafka will NOT ack the requests, and the reply message is sent back
261 - to caller immediately after the message has been sent to the socket process.
262 -
263 - In case the brod:produce caller is a process like gen_server which
252 + In case the `brod:produce` caller is a process like `gen_server` which
264 253 receives ALL messages, the callers should keep the call references in its
265 254 looping state and match the replies against them when received.
266 - Otherwise brod:sync_produce_request/1 can be used to block-wait for acks.
255 + Otherwise `brod:sync_produce_request/1` can be used to block-wait for acks.
256 +
257 + NOTE: If `required_acks` is set to `none` in producer config,
258 + kafka will NOT ack the requests, and the reply message is sent back
259 + to caller immediately after the message has been sent to the socket process.
267 260
268 261 NOTE: The replies are only strictly ordered per-partition.
269 262 i.e. if the caller is producing to two or more partitions,
270 263 it may receive replies ordered differently than in which order
271 - brod:produce API was called.
264 + `brod:produce` API was called.
265 +
266 + ## Handle Acks from Kafka in Callback Function
267 +
268 + Async APIs `brod:produce_cb/4` and `brod:produce_cb/6` allow callers to
269 + provided a callback function to handle acknowledgements from kafka.
270 + In this case, the caller may want to monitor the producer process because
271 + then they know that the callbacks will not be evaluated if the producer is 'DOWN',
272 + and there is perhaps a need for retry.
272 273
273 274 # Consumers
274 275
  @@ -371,9 +372,13 @@ start(ClientId) ->
371 372
372 373 # Authentication support
373 374
374 - brod supports SASL PLAIN authentication mechanism out of the box. To use it
375 - add `{sasl, {plain, Username, Password}}` to client config. Also, brod has authentication
376 - plugins support. Authentication callback module should implement `brod_auth_backend` behaviour.
375 + brod supports SASL `PLAIN`, `SCRAM-SHA-256` and `SCRAM-SHA-512` authentication mechanisms out of the box.
376 + To use it, add `{sasl, {Mechanism, Username, Password}}` or `{sasl, {Mechanism, File}}` to client config.
377 + Where `Mechanism` is `plain | scram_sha_256 | scram_sha_512`, and `File` is the path to a text file
378 + which contains two lines, first line for username and second line for password
379 +
380 + Also, brod has authentication plugins support with `{sasl, {callback, Module, Opts}}` in client config.
381 + Authentication callback module should implement `brod_auth_backend` behaviour.
377 382 Auth function spec:
378 383
379 384 ```erlang
  @@ -403,7 +408,6 @@ Partition = 0.
403 408 brod:get_metadata(Hosts).
404 409 brod:get_metadata(Hosts, [Topic]).
405 410 brod:resolve_offset(Hosts, Topic, Partition).
406 - brod:fetch(Hosts, Topic, Partition, 1).
407 411 ```
408 412
409 413 # brod-cli: A command line tool to interact with Kafka
  @@ -411,38 +415,32 @@ brod:fetch(Hosts, Topic, Partition, 1).
411 415 This will build a self-contained binary with brod application
412 416
413 417 ```bash
414 - make rel
415 - ./_rel/brod/bin/brod --help
418 + make brod-cli
419 + _build/brod_cli/rel/brod/bin/brod -h
416 420 ```
417 421
418 422 Disclaimer: This script is NOT designed for use cases where fault-tolerance is a hard requirement.
419 423 As it may crash when e.g. kafka cluster is temporarily unreachable,
420 424 or (for fetch command) when the parition leader migrates to another broker in the cluster.
421 425
422 - Start an Erlang shell with brod started
423 -
424 - ```bash
425 - ./_rel/brod/bin/brod-i
426 - ```
427 -
428 - ## brod-cli examples:
426 + ## brod-cli examples (with `alias brod=_build/brod_cli/rel/brod/bin/brod`):
429 427
430 428 ### Fetch and print metadata
431 429 ```
432 - ./scripts/brod meta -b localhost
430 + brod meta -b localhost
433 431 ```
434 432
435 433 ### Produce a Message
436 434
437 435 ```
438 - ./scripts/brod send -b localhost -t test-topic -p 0 -k "key" -v "value"
436 + brod send -b localhost -t test-topic -p 0 -k "key" -v "value"
439 437
440 438 ```
441 439
442 440 ### Fetch a Message
443 441
444 442 ```
445 - ./scripts/brod fetch -b localhost -t test-topic -p 0 --fmt 'io:format("offset=~p, ts=~p, key=~s, value=~s\n", [Offset, Ts, Key, Value])'
443 + brod fetch -b localhost -t test-topic -p 0 --fmt 'io:format("offset=~p, ts=~p, key=~s, value=~s\n", [Offset, Ts, Key, Value])'
446 444 ```
447 445
448 446 Bound variables to be used in `--fmt` expression:
  @@ -450,7 +448,6 @@ Bound variables to be used in `--fmt` expression:
450 448 - `Offset`: Message offset
451 449 - `Key`: Kafka key
452 450 - `Value`: Kafka Value
453 - - `CRC`: Message CRC
454 451 - `TsType`: Timestamp type either `create` or `append`
455 452 - `Ts`: Timestamp, `-1` as no value
456 453
  @@ -458,33 +455,33 @@ Bound variables to be used in `--fmt` expression:
458 455
459 456 Send `README.md` to kafka one line per kafka message
460 457 ```
461 - ./scripts/brod pipe -b localhost:9092 -t test-topic -p 0 -s @./README.md
458 + brod pipe -b localhost:9092 -t test-topic -p 0 -s @./README.md
462 459 ```
463 460
464 461 ### Resolve Offset
465 462
466 463 ```
467 - ./scripts/brod offset -b localhost:9092 -t test-topic -p 0
464 + brod offset -b localhost:9092 -t test-topic -p 0
468 465 ```
469 466
470 467 ### List or Describe Groups
471 468
472 469 ```
473 470 # List all groups
474 - ./scripts/brod groups -b localhost:9092
471 + brod groups -b localhost:9092
475 472
476 473 # Describe groups
477 - ./scripts/brod groups -b localhost:9092 --ids group-1,group-2
474 + brod groups -b localhost:9092 --ids group-1,group-2
478 475 ```
479 476
480 477 ### Display Committed Offsets
481 478
482 479 ```
483 480 # all topics
484 - ./scripts/brod commits -b localhost:9092 --id the-group-id --describe
481 + brod commits -b localhost:9092 --id the-group-id --describe
485 482
486 483 # a specific topic
487 - ./scripts/brod commits -b localhost:9092 --id the-group-id --describe --topic topic-name
484 + brod commits -b localhost:9092 --id the-group-id --describe --topic topic-name
488 485 ```
489 486
490 487 ### Commit Offsets
  @@ -493,15 +490,23 @@ NOTE: This feature is designed for force overwriting commits, not for regular us
493 490
494 491 ```
495 492 # Commit 'latest' offsets of all partitions with 2 days retention
496 - ./scripts/brod commits -b localhost:9092 --id the-group-id --topic topic-name --offsets latest --retention 2d
493 + brod commits -b localhost:9092 --id the-group-id --topic topic-name --offsets latest --retention 2d
497 494
498 495 # Commit offset=100 for partition 0 and 200 for partition 1
499 - ./scripts/brod commits -b localhost:9092 --id the-group-id --topic topic-name --offsets "0:100,1:200"
496 + brod commits -b localhost:9092 --id the-group-id --topic topic-name --offsets "0:100,1:200"
500 497
501 498 # Use --retention 0 to delete commits (may linger in kafka before cleaner does its job)
502 - ./scripts/brod commits -b localhost:9092 --id the-group-id --topic topic-name --offsets latest --retention 0
499 + brod commits -b localhost:9092 --id the-group-id --topic topic-name --offsets latest --retention 0
503 500
504 501 # Try join an active consumer group using 'range' protocol and steal one partition assignment then commit offset=10000
505 - ./scripts/brod commits -b localhost:9092 -i the-group-id -t topic-name -o "0:10000" --protocol range
502 + brod commits -b localhost:9092 -i the-group-id -t topic-name -o "0:10000" --protocol range
506 503 ```
507 504
505 + ## TODOs
506 +
507 + * HTML tagged EDoc
508 + * Support scram-sasl in brod-cli
509 + * lz4 compression & decompression
510 + * Create/delete topic APIs
511 + * Transactional produce APIs
512 +
unknownerlang.mk
File is too large to be displayed (100 KB limit).
  @@ -1,12 +1,12 @@
1 1 {<<"name">>,<<"brod">>}.
2 - {<<"version">>,<<"3.5.2">>}.
2 + {<<"version">>,<<"3.6.0">>}.
3 3 {<<"requirements">>,
4 4 #{<<"kafka_protocol">> =>
5 5 #{<<"app">> => <<"kafka_protocol">>,<<"optional">> => false,
6 - <<"requirement">> => <<"1.1.2">>},
6 + <<"requirement">> => <<"2.1.1">>},
7 7 <<"supervisor3">> =>
8 8 #{<<"app">> => <<"supervisor3">>,<<"optional">> => false,
9 - <<"requirement">> => <<"1.1.5">>}}}.
9 + <<"requirement">> => <<"1.1.7">>}}}.
10 10 {<<"app">>,<<"brod">>}.
11 11 {<<"maintainers">>,[<<"Ivan Dyachkov">>,<<"Zaiming Shi">>]}.
12 12 {<<"precompiled">>,false}.
  @@ -15,15 +15,13 @@
15 15 [<<"src/brod.app.src">>,<<"LICENSE">>,<<"Makefile">>,<<"NOTICE">>,
16 16 <<"README.md">>,<<"erlang.mk">>,<<"include/brod.hrl">>,
17 17 <<"include/brod_int.hrl">>,<<"rebar.config">>,<<"rebar.config.script">>,
18 - <<"src/brod.erl">>,<<"src/brod_auth_backend.erl">>,
19 - <<"src/brod_cg_commits.erl">>,<<"src/brod_cli.erl">>,
18 + <<"src/brod.erl">>,<<"src/brod_cg_commits.erl">>,<<"src/brod_cli.erl">>,
20 19 <<"src/brod_cli_pipe.erl">>,<<"src/brod_client.erl">>,
21 20 <<"src/brod_consumer.erl">>,<<"src/brod_consumers_sup.erl">>,
22 21 <<"src/brod_group_coordinator.erl">>,<<"src/brod_group_member.erl">>,
23 22 <<"src/brod_group_subscriber.erl">>,<<"src/brod_kafka_apis.erl">>,
24 - <<"src/brod_kafka_request.erl">>,<<"src/brod_kafka_requests.erl">>,
25 - <<"src/brod_producer.erl">>,<<"src/brod_producer_buffer.erl">>,
26 - <<"src/brod_producers_sup.erl">>,<<"src/brod_sock.erl">>,
23 + <<"src/brod_kafka_request.erl">>,<<"src/brod_producer.erl">>,
24 + <<"src/brod_producer_buffer.erl">>,<<"src/brod_producers_sup.erl">>,
27 25 <<"src/brod_sup.erl">>,<<"src/brod_topic_subscriber.erl">>,
28 26 <<"src/brod_utils.erl">>]}.
29 27 {<<"licenses">>,[<<"Apache License 2.0">>]}.
  @@ -1,5 +1,5 @@
1 1 %%%
2 - %%% Copyright (c) 2014-2017, Klarna AB
2 + %%% Copyright (c) 2014-2018, Klarna Bank AB (publ)
3 3 %%%
4 4 %%% Licensed under the Apache License, Version 2.0 (the "License");
5 5 %%% you may not use this file except in compliance with the License.
  @@ -28,26 +28,26 @@
28 28 , partition :: brod:partition()
29 29 , high_wm_offset :: integer() %% max offset of the partition
30 30 , messages :: [brod:message()] %% exposed to brod user
31 - | kpro:incomplete_message() %% this union member
32 - %% is internal only
31 + | kpro:incomplete_batch() %% this union member
32 + %% is internal only
33 33 }).
34 34
35 35 -record(kafka_fetch_error,
36 36 { topic :: brod:topic()
37 37 , partition :: brod:partition()
38 38 , error_code :: brod:error_code()
39 - , error_desc :: binary()
39 + , error_desc = ""
40 40 }).
41 41
42 - -record(brod_call_ref, { caller :: pid()
43 - , callee :: pid()
44 - , ref :: reference()
42 + -record(brod_call_ref, { caller :: undefined | pid()
43 + , callee :: undefined | pid()
44 + , ref :: undefined | reference()
45 45 }).
46 46
47 47 -define(BROD_PRODUCE_UNKNOWN_OFFSET, -1).
48 48
49 49 -record(brod_produce_reply, { call_ref :: brod:call_ref()
50 - , base_offset :: brod:offset()
50 + , base_offset :: undefined | brod:offset()
51 51 , result :: brod:produce_result()
52 52 }).
Loading more files…