Skip to content

Commit 437cbcb

Browse files
committed
Docs
1 parent 1136f2b commit 437cbcb

1 file changed

Lines changed: 64 additions & 22 deletions

File tree

doc/integrations/kafka.md

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ Dependency:
77
```
88

99
`Flow`s which read from a Kafka topic, mapping stages and drains which publish to Kafka topics are available through
10-
the `KafkaFlow`, `KafkaStage` and `KafkaDrain` objects. In all cases either a manually constructed instance of a
11-
`KafkaProducer` / `KafkaConsumer` is needed, or `ProducerSettings` / `ConsumerSetttings` need to be provided with the
12-
bootstrap servers, consumer group id, key / value serializers, etc.
10+
the `KafkaFlow`, `KafkaStage` and `KafkaDrain` objects.
11+
12+
In all cases kafka producers and consumers can be provided:
13+
* by manually creating (and closing) an instance of a `KafkaProducer` / `KafkaConsumer`
14+
* through a `ProducerSettings` / `ConsumerSettings`, with the bootstrap servers, consumer group id, key/value
15+
serializers, etc. The lifetime is then managed by the flow operators.
16+
* through a thread-safe wrapper on a consumer (`ActorRef[KafkaConsumerWrapper[K, V]]`), for which the lifetime is bound
17+
to the current concurrency scope
18+
19+
## Reading from Kafka
1320

1421
To read from a Kafka topic, use:
1522

@@ -25,6 +32,8 @@ val source = KafkaFlow.subscribe(settings, topic)
2532
.runForeach { (msg: ReceivedMessage[String, String]) => ??? }
2633
```
2734

35+
## Publishing to Kafka
36+
2837
To publish data to a Kafka topic:
2938

3039
```scala mdoc:compile-only
@@ -40,6 +49,25 @@ Flow
4049
.pipe(KafkaDrain.runPublish(settings))
4150
```
4251

52+
To publish data as a mapping stage:
53+
54+
```scala mdoc:compile-only
55+
import ox.flow.Flow
56+
import ox.kafka.ProducerSettings
57+
import ox.kafka.KafkaStage.*
58+
import org.apache.kafka.clients.producer.{ProducerRecord, RecordMetadata}
59+
60+
val settings = ProducerSettings.default.bootstrapServers("localhost:9092")
61+
val metadatas: Flow[RecordMetadata] = Flow
62+
.fromIterable(List("a", "b", "c"))
63+
.map(msg => ProducerRecord[String, String]("my_topic", msg))
64+
.mapPublish(settings)
65+
66+
// process & run the metadatas flow further
67+
```
68+
69+
## Reading & publishing to Kafka with offset commits
70+
4371
Quite often data to be published to a topic (`topic1`) is computed basing on data received from another topic
4472
(`topic2`). In such a case, it's possible to commit messages from `topic2`, after the messages to `topic1` are
4573
successfully published.
@@ -63,7 +91,7 @@ computed. For example:
6391
```scala mdoc:compile-only
6492
import ox.kafka.{ConsumerSettings, KafkaDrain, KafkaFlow, ProducerSettings, SendPacket}
6593
import ox.kafka.ConsumerSettings.AutoOffsetReset
66-
import ox.pipe
94+
import ox.*
6795
import org.apache.kafka.clients.producer.ProducerRecord
6896

6997
val consumerSettings = ConsumerSettings.default("my_group")
@@ -72,29 +100,43 @@ val producerSettings = ProducerSettings.default.bootstrapServers("localhost:9092
72100
val sourceTopic = "source_topic"
73101
val destTopic = "dest_topic"
74102

75-
KafkaFlow
76-
.subscribe(consumerSettings, sourceTopic)
77-
.map(in => (in.value.toLong * 2, in))
78-
.map((value, original) =>
79-
SendPacket(ProducerRecord[String, String](destTopic, value.toString), original))
80-
.pipe(KafkaDrain.runPublishAndCommit(producerSettings))
103+
supervised:
104+
// the consumer is shared between the subscribe & offset stages
105+
// its lifetime is bound to the current concurrency scope
106+
val consumer = consumerSettings.toThreadSafeConsumerWrapper
107+
KafkaFlow
108+
.subscribe(consumer, sourceTopic)
109+
.map(in => (in.value.toLong * 2, in))
110+
.map((value, original) =>
111+
SendPacket(ProducerRecord[String, String](destTopic, value.toString), original))
112+
.pipe(KafkaDrain.runPublishAndCommit(producerSettings, consumer))
81113
```
82114

83115
The offsets are committed every second in a background process.
84116

85-
To publish data as a mapping stage:
117+
## Reading from Kafka, processing data & committing offsets
118+
119+
Offsets can also be committed after the data has been processed, without producing any records to write to a topic.
120+
For that, we can use the `runCommit` drain, or the `mapCommit` stage, both of which work with a `Flow[CommitPacket]`:
86121

87122
```scala mdoc:compile-only
88-
import ox.flow.Flow
89-
import ox.kafka.ProducerSettings
90-
import ox.kafka.KafkaStage.*
91-
import org.apache.kafka.clients.producer.{ProducerRecord, RecordMetadata}
123+
import ox.kafka.{ConsumerSettings, KafkaDrain, KafkaFlow, CommitPacket}
124+
import ox.kafka.ConsumerSettings.AutoOffsetReset
125+
import ox.*
92126

93-
val settings = ProducerSettings.default.bootstrapServers("localhost:9092")
94-
val metadatas: Flow[RecordMetadata] = Flow
95-
.fromIterable(List("a", "b", "c"))
96-
.map(msg => ProducerRecord[String, String]("my_topic", msg))
97-
.mapPublish(settings)
127+
val consumerSettings = ConsumerSettings.default("my_group")
128+
.bootstrapServers("localhost:9092").autoOffsetReset(AutoOffsetReset.Earliest)
129+
val sourceTopic = "source_topic"
98130

99-
// process & run the metadatas flow further
100-
```
131+
supervised:
132+
// the consumer is shared between the subscribe & offset stages
133+
// its lifetime is bound to the current concurrency scope
134+
val consumer = consumerSettings.toThreadSafeConsumerWrapper
135+
KafkaFlow
136+
.subscribe(consumer, sourceTopic)
137+
.mapPar(10) { in =>
138+
// process the message, e.g. send an HTTP request
139+
CommitPacket(in)
140+
}
141+
.pipe(KafkaDrain.runCommit(consumer))
142+
```

0 commit comments

Comments
 (0)