@@ -108,6 +108,16 @@ class CPPKAFKA_API BufferedProducer {
108
108
* \param builder The builder that contains the message to be produced
109
109
*/
110
110
void produce (const MessageBuilder& builder);
111
+
112
+ /* *
113
+ * \brief Produces a message without buffering it
114
+ *
115
+ * The message will still be tracked so that a call to flush or wait_for_acks will actually
116
+ * wait for it to be acknowledged.
117
+ *
118
+ * \param message The message to be produced
119
+ */
120
+ void produce (const Message& message);
111
121
112
122
/* *
113
123
* \brief Flushes the buffered messages.
@@ -126,6 +136,34 @@ class CPPKAFKA_API BufferedProducer {
126
136
* Clears any buffered messages
127
137
*/
128
138
void clear ();
139
+
140
+ /* *
141
+ * \brief Sets the maximum amount of messages to be enqueued in the buffer.
142
+ *
143
+ * After 'max_buffer_size' is reached, flush() will be called automatically.
144
+ *
145
+ * \param size The max size of the internal buffer. Allowed values are:
146
+ * -1 : Unlimited buffer size. Must be flushed manually (default value)
147
+ * 0 : Don't buffer anything. add_message() behaves like produce()
148
+ * > 0 : Max number of messages before flush() is called.
149
+ *
150
+ * \remark add_message() will block when 'max_buffer_size' is reached due to flush()
151
+ */
152
+ void set_max_buffer_size (ssize_t max_buffer_size);
153
+
154
+ /* *
155
+ * \brief Return the maximum allowed buffer size.
156
+ *
157
+ * \return The max buffer size. A value of -1 indicates an unbounded buffer.
158
+ */
159
+ ssize_t get_max_buffer_size () const ;
160
+
161
+ /* *
162
+ * \brief Get the number of messages in the buffer
163
+ *
164
+ * \return The number of messages
165
+ */
166
+ size_t get_buffer_size () const ;
129
167
130
168
/* *
131
169
* Gets the Producer object
@@ -157,20 +195,25 @@ class CPPKAFKA_API BufferedProducer {
157
195
158
196
template <typename BuilderType>
159
197
void do_add_message (BuilderType&& builder);
160
- void produce_message (const MessageBuilder& message);
198
+ template <typename MessageType>
199
+ void produce_message (const MessageType& message);
161
200
Configuration prepare_configuration (Configuration config);
162
201
void on_delivery_report (const Message& message);
163
202
203
+
204
+ Configuration::DeliveryReportCallback delivery_report_callback_;
164
205
Producer producer_;
165
206
QueueType messages_;
166
207
ProduceFailureCallback produce_failure_callback_;
167
208
size_t expected_acks_{0 };
168
209
size_t messages_acked_{0 };
210
+ ssize_t max_buffer_size_{-1 };
169
211
};
170
212
171
213
template <typename BufferType>
172
214
BufferedProducer<BufferType>::BufferedProducer(Configuration config)
173
- : producer_(prepare_configuration(std::move(config))) {
215
+ : delivery_report_callback_(config.get_delivery_report_callback()),
216
+ producer_ (prepare_configuration(std::move(config))) {
174
217
175
218
}
176
219
@@ -190,13 +233,18 @@ void BufferedProducer<BufferType>::produce(const MessageBuilder& builder) {
190
233
expected_acks_++;
191
234
}
192
235
236
+ template <typename BufferType>
237
+ void BufferedProducer<BufferType>::produce(const Message& message) {
238
+ produce_message (message);
239
+ expected_acks_++;
240
+ }
241
+
193
242
template <typename BufferType>
194
243
void BufferedProducer<BufferType>::flush() {
195
244
while (!messages_.empty ()) {
196
245
produce_message (messages_.front ());
197
246
messages_.pop ();
198
247
}
199
-
200
248
wait_for_acks ();
201
249
}
202
250
@@ -228,11 +276,32 @@ void BufferedProducer<BufferType>::clear() {
228
276
messages_acked_ = 0 ;
229
277
}
230
278
279
+ template <typename BufferType>
280
+ void BufferedProducer<BufferType>::set_max_buffer_size(ssize_t max_buffer_size) {
281
+ if (max_buffer_size < -1 ) {
282
+ throw Exception (" Invalid buffer size." );
283
+ }
284
+ max_buffer_size_ = max_buffer_size;
285
+ }
286
+
287
+ template <typename BufferType>
288
+ ssize_t BufferedProducer<BufferType>::get_max_buffer_size() const {
289
+ return max_buffer_size_;
290
+ }
291
+
292
+ template <typename BufferType>
293
+ size_t BufferedProducer<BufferType>::get_buffer_size() const {
294
+ return messages_.size ();
295
+ }
296
+
231
297
template <typename BufferType>
232
298
template <typename BuilderType>
233
299
void BufferedProducer<BufferType>::do_add_message(BuilderType&& builder) {
234
300
expected_acks_++;
235
- messages_.push (std::move (builder));
301
+ messages_.push (std::forward<BuilderType>(builder));
302
+ if ((max_buffer_size_ >= 0 ) && (max_buffer_size_ <= (ssize_t )messages_.size ())) {
303
+ flush ();
304
+ }
236
305
}
237
306
238
307
template <typename BufferType>
@@ -257,11 +326,12 @@ void BufferedProducer<BufferType>::set_produce_failure_callback(ProduceFailureCa
257
326
}
258
327
259
328
template <typename BufferType>
260
- void BufferedProducer<BufferType>::produce_message(const MessageBuilder& builder) {
329
+ template <typename MessageType>
330
+ void BufferedProducer<BufferType>::produce_message(const MessageType& message) {
261
331
bool sent = false ;
262
332
while (!sent) {
263
333
try {
264
- producer_.produce (builder );
334
+ producer_.produce (message );
265
335
sent = true ;
266
336
}
267
337
catch (const HandleException& ex) {
@@ -287,22 +357,16 @@ Configuration BufferedProducer<BufferType>::prepare_configuration(Configuration
287
357
288
358
template <typename BufferType>
289
359
void BufferedProducer<BufferType>::on_delivery_report(const Message& message) {
290
- // We should produce this message again if it has an error and we either don't have a
360
+ // Call the user-supplied delivery report callback if any
361
+ if (delivery_report_callback_) {
362
+ delivery_report_callback_ (producer_, message);
363
+ }
364
+ // We should produce this message again if it has an error and we either don't have a
291
365
// produce failure callback or we have one but it returns true
292
366
bool should_produce = message.get_error () &&
293
367
(!produce_failure_callback_ || produce_failure_callback_ (message));
294
368
if (should_produce) {
295
- MessageBuilder builder (message.get_topic ());
296
- const auto & key = message.get_key ();
297
- const auto & payload = message.get_payload ();
298
- builder.partition (message.get_partition ())
299
- .key (Buffer (key.get_data (), key.get_size ()))
300
- .payload (Buffer (payload.get_data (), payload.get_size ()))
301
- .user_data (message.get_user_data ());
302
- if (message.get_timestamp ()) {
303
- builder.timestamp (message.get_timestamp ()->get_timestamp ());
304
- }
305
- produce_message (builder);
369
+ produce_message (message);
306
370
return ;
307
371
}
308
372
// If production was successful or the produce failure callback returned false, then
0 commit comments