You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/modules/ROOT/pages/pipes/plugins/kafka.adoc
+64-10Lines changed: 64 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,11 @@
21
21
22
22
The Apache Kafka plugin (`tika-pipes-kafka`) provides an emitter (publishes parsed documents to a Kafka topic) and an iterator (consumes fetch requests from a Kafka topic).
23
23
24
+
The two halves have different standing. The *emitter* is a plain producer and a good fit: Tika
25
+
parses, results stream to a topic for downstream indexing. The *iterator* is a worked example
26
+
whose suitability depends on your parse latency -- see <<iterator-caveats>> before building on
27
+
it.
28
+
24
29
[cols="2,1,3"]
25
30
|===
26
31
|Interface |Component name |Class
@@ -146,12 +151,47 @@ applies. The Default column below is therefore the Kafka client's default.
146
151
[#kafka-iterator]
147
152
== Kafka Iterator (`kafka-pipes-iterator`)
148
153
149
-
Consumes fetch-request messages from a Kafka topic and emits one `FetchEmitTuple` per message. Useful for building event-driven pipelines where some upstream system pushes work to a queue.
150
-
151
-
[source,json]
152
-
----
153
-
include::example$pipes-kafka-iterator.json[]
154
-
----
154
+
[WARNING]
155
+
.Reference example -- check that your parse latency suits it
156
+
====
157
+
Kafka's consumer model assumes bounded, roughly uniform per-message processing time, so how
158
+
well this component works depends on *how long your documents take to parse*. Short, predictable
159
+
parses fit that assumption. Long-running parses do not: pairing Kafka with documents that take
160
+
minutes to an hour -- OCR'd PDFs, large archives, anything near the one-hour default total-task
161
+
timeout -- works against the grain of the offset model, and the caveats below stop being
162
+
theoretical.
163
+
164
+
It is kept as a worked example rather than a supported production integration. If your workload
165
+
has a long latency tail, consider driving tika-server or tika-grpc from your own consumer, where
166
+
you control acknowledgement and retry, and use the <<kafka-emitter,Kafka emitter>> to publish
167
+
results.
168
+
====
169
+
170
+
[#iterator-caveats]
171
+
=== Things to know before building on it
172
+
173
+
*Head-of-line blocking, in proportion to your latency spread.* A partition is consumed in order
174
+
by one member of the group. Even with `numClients` workers parsing in parallel, correct offset
175
+
handling can only advance the commit watermark to the lowest un-acknowledged offset, so one slow
176
+
document holds up its partition's progress. With short, uniform parses this is barely
177
+
noticeable; with a long tail, one document can stall a partition for as long as it parses.
178
+
This follows from Kafka's offset model rather than from a setting.
179
+
180
+
*At-most-once delivery.* `enable.auto.commit` is left at Kafka's default of `true`, so offsets
181
+
are committed on a timer as soon as records are *polled* -- before Tika has parsed or emitted
182
+
them. A crash, OOM or failed emit in between loses those documents silently. Committing after a
183
+
successful emit is not currently possible: the iterator pushes tuples onto a queue and receives
184
+
no completion signal back.
185
+
186
+
*It drains and exits; it does not stream.* The iterator enqueues what is on the topic and then
187
+
finishes, because tika-pipes' iterator contract is finite. A quiet period ends the run (see
188
+
`drainIdleMs`). It suits a periodic batch drain, not a long-running consumer.
189
+
190
+
*Give the consumer room to join.* A stock Kafka broker applies
191
+
`group.initial.rebalance.delay.ms` (default 3000) to the first member joining an *empty* group.
192
+
A deployment that runs back-to-back, or keeps another member in the group, never pays this; one
193
+
that starts cold pays it every run. The iterator waits for a partition assignment up to
194
+
`assignmentTimeoutMs` rather than mistaking a not-yet-assigned consumer for an empty topic.
155
195
156
196
=== Configuration
157
197
@@ -183,21 +223,35 @@ In addition to the required `fetcherId` / `emitterId` (see xref:pipes/iterators.
183
223
184
224
|`pollDelayMs`
185
225
|`100`
186
-
|Sleep between `poll()` calls when the topic is idle.
226
+
|Timeout passed to each `poll()` call.
187
227
188
228
|`emitMax`
189
229
|`-1`
190
230
|Maximum tuples to emit. `-1` means unbounded.
191
231
232
+
|`assignmentTimeoutMs`
233
+
|`30000`
234
+
|How long to wait for the consumer to be assigned a partition before failing. A newly
235
+
subscribed consumer returns empty polls while it joins the group; the iterator waits for an
236
+
assignment so it cannot mistake that for an empty topic.
237
+
238
+
|`drainIdleMs`
239
+
|`1000`
240
+
|How long the topic must stay quiet (no records, after assignment) before it is treated as
241
+
drained and the iterator finishes. A duration rather than a poll count, so it holds however
242
+
short `pollDelayMs` is.
243
+
192
244
|`groupInitialRebalanceDelayMs`
193
245
|`3000`
194
-
|Initial rebalance delay for the consumer group.
246
+
|*Deprecated and ignored.* This is a broker setting, not a consumer one, so Kafka never
247
+
applied it. Use `assignmentTimeoutMs` instead. Still accepted so existing configs start;
248
+
scheduled for removal.
195
249
|===
196
250
197
251
[#kafka-pipeline]
198
252
== Complete Pipeline Example
199
253
200
-
A Kafka iterator (consuming fetch requests), a filesystem fetcher, and a Kafka emitter (publishing parsed results) — the stream-processing shape.
254
+
A Kafka iterator (consuming fetch requests), a filesystem fetcher, and a Kafka emitter (publishing parsed results). This end-to-end shape is the reference example; see <<iterator-caveats>> before relying on the iterator half.
* The Kafka plugin uses the official `kafka-clients` SDK.
211
265
* The emitter is fire-and-forget at the Tika level; durability is determined by Kafka's `acks` and broker replication factor, not by Tika.
212
266
* For exactly-once semantics, set `enableIdempotence: true` (and ensure `acks: all`); for transactional semantics, also set `transactionalId`.
213
-
* The iterator's `groupId` controls partition assignment. Set it explicitly in production — without one, the consumer receives a transient assignment that resets on restart.
267
+
* The iterator's `groupId` controls partition assignment. Set it explicitly — without one, the consumer receives a transient assignment that resets on restart.
Copy file name to clipboardExpand all lines: tika-integration-tests/tika-pipes-kafka-integration-tests/src/test/java/org/apache/tika/pipes/kafka/tests/TikaPipesKafkaTest.java
Copy file name to clipboardExpand all lines: tika-pipes/tika-pipes-plugins/tika-pipes-kafka/src/main/java/org/apache/tika/pipes/iterator/kafka/KafkaPipesIterator.java
Copy file name to clipboardExpand all lines: tika-pipes/tika-pipes-plugins/tika-pipes-kafka/src/main/java/org/apache/tika/pipes/iterator/kafka/KafkaPipesIteratorConfig.java
+21Lines changed: 21 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -47,7 +47,15 @@ public static KafkaPipesIteratorConfig load(final String json)
47
47
privateStringautoOffsetReset = "earliest";
48
48
privateintpollDelayMs = 100;
49
49
privateintemitMax = -1;
50
+
/**
51
+
* @deprecated inert -- this is a broker setting, never a consumer one, so Kafka has always
52
+
* ignored it ("supplied but not used yet"). Kept only so existing configs still start;
53
+
* remove in 4.1.0. Use assignmentTimeoutMs to bound waiting for a partition assignment.
54
+
*/
55
+
@Deprecated
50
56
privateintgroupInitialRebalanceDelayMs = 3000;
57
+
privateintassignmentTimeoutMs = 30000;
58
+
privateintdrainIdleMs = 1000;
51
59
52
60
publicStringgetTopic() {
53
61
returntopic;
@@ -81,10 +89,19 @@ public int getEmitMax() {
81
89
returnemitMax;
82
90
}
83
91
92
+
@Deprecated
84
93
publicintgetGroupInitialRebalanceDelayMs() {
85
94
returngroupInitialRebalanceDelayMs;
86
95
}
87
96
97
+
publicintgetAssignmentTimeoutMs() {
98
+
returnassignmentTimeoutMs;
99
+
}
100
+
101
+
publicintgetDrainIdleMs() {
102
+
returndrainIdleMs;
103
+
}
104
+
88
105
@Override
89
106
publicbooleanequals(Objecto) {
90
107
if (!(oinstanceofKafkaPipesIteratorConfigthat)) {
@@ -96,6 +113,8 @@ public boolean equals(Object o) {
0 commit comments