-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KafkaProducer: Expose run()
method
#63
KafkaProducer: Expose run()
method
#63
Conversation
70f32cd
to
9fd97e2
Compare
/// Task that polls the Kafka cluster for updates periodically. | ||
private var pollTask: Task<Void, Never>! | ||
/// Variable that indicates if our poll loop should be running. | ||
private var polling = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this property. We can use the state for this started
indicates that we are polling
Motivation: * Our current implementation of polling `librdkafka` for new message acknowledgements in `KafkaProducer` did not support backpressure. Also, it made use of some `weak` references which we generally want to avoid due to performance reasons. Modifications: * fix typo in `SwiftKafkaTests` * upgrade minimum OS versions to support the `Duration` type * move conversion of `rd_kafka_message_t` to `KafkaAcknowledgementResult` to `RDKafkaConfig` so that we can pass the `KafkaAcknowledgementResult` type as early as possible and don't have to bother with `UnsafePointer<rd_kafka_message_t>` in all our delivery callback logic * expose KafkaProducer.run() method * `README`: use `TaskGroup` in `KafkaProducer` example * add comments to task groups in `README` * refactor all tests into using task groups (structured concurrency) Have two factory methods creating KafkaProducer Motivation: We want to have a `KafkaProducer` that is not consuming any acknowledgements. This means it is initialized without a `deliveryReportCallback` which in turn means that `librdkafka` will not queue any incoming acknowledgements which prevents us from running out of memory in that case. Modifications: * add two new factory methods for creating `KafkaProducer`: * `KafkaProducer.newProducer` * `KafkaProducer.newProducerWithAcknowledgements` * update README
9fd97e2
to
28c9e6f
Compare
public nonisolated let acknowledgements: AcknowledgedMessagesAsyncSequence | ||
nonisolated let acknowlegdementsSource: AcknowledgedMessagesAsyncSequence.WrappedSequence.Source | ||
private typealias Acknowledgement = Result<KafkaAcknowledgedMessage, KafkaAcknowledgedMessageError> | ||
private let client: KafkaClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we create a ticket to try to internalise all of the properties here into our state where it makes sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// - Parameter logger: A logger. | ||
/// - Returns: The newly created ``KafkaProducer``. | ||
/// - Throws: A ``KafkaError`` if initializing the producer failed. | ||
public static func newProducer( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static func newProducer( | |
public static func makeProducer( |
/// Initialize a new ``KafkaProducer`` that ignores incoming message acknowledgements. | ||
/// - Parameter config: The ``KafkaProducerConfig`` for configuring the ``KafkaProducer``. | ||
/// - Parameter topicConfig: The ``KafkaTopicConfig`` used for newly created topics. | ||
/// - Parameter logger: A logger. | ||
/// - Returns: The newly created ``KafkaProducer``. | ||
/// - Throws: A ``KafkaError`` if initializing the producer failed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Initialize a new ``KafkaProducer`` that ignores incoming message acknowledgements. | |
/// - Parameter config: The ``KafkaProducerConfig`` for configuring the ``KafkaProducer``. | |
/// - Parameter topicConfig: The ``KafkaTopicConfig`` used for newly created topics. | |
/// - Parameter logger: A logger. | |
/// - Returns: The newly created ``KafkaProducer``. | |
/// - Throws: A ``KafkaError`` if initializing the producer failed. | |
/// Initialize a new ``KafkaProducer``. | |
/// | |
/// This factory method creates a producer without message acknowledgements. | |
/// | |
/// - Parameter configuration: The ``KafkaProducerConfig`` for configuring the ``KafkaProducer``. | |
/// - Parameter topicConfiguration: The ``KafkaTopicConfig`` used for newly created topics. | |
/// - Parameter logger: A logger. | |
/// - Returns: The newly created ``KafkaProducer``. | |
/// - Throws: A ``KafkaError`` if initializing the producer failed. |
Can we also create a radar to rename the config structs to spell out configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Initialize a new ``KafkaProducer`` alongside a ``KafkaMessageAcknowledgements`` `AsyncSequence` that can be used | ||
/// to receive message acknowlegements. | ||
/// - Parameter config: The ``KafkaProducerConfig`` for configuring the ``KafkaProducer``. | ||
/// - Parameter topicConfig: The ``KafkaTopicConfig`` used for newly created topics. | ||
/// - Parameter logger: A logger. | ||
/// - Returns: A tuple containing the created ``KafkaProducer`` and the ``KafkaMessageAcknowledgements`` | ||
/// `AsyncSequence` used for receiving message acknowledgements. | ||
/// - Throws: A ``KafkaError`` if initializing the producer failed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Initialize a new ``KafkaProducer`` alongside a ``KafkaMessageAcknowledgements`` `AsyncSequence` that can be used | |
/// to receive message acknowlegements. | |
/// - Parameter config: The ``KafkaProducerConfig`` for configuring the ``KafkaProducer``. | |
/// - Parameter topicConfig: The ``KafkaTopicConfig`` used for newly created topics. | |
/// - Parameter logger: A logger. | |
/// - Returns: A tuple containing the created ``KafkaProducer`` and the ``KafkaMessageAcknowledgements`` | |
/// `AsyncSequence` used for receiving message acknowledgements. | |
/// - Throws: A ``KafkaError`` if initializing the producer failed. | |
/// Initialize a new ``KafkaProducer`` and a ``KafkaMessageAcknowledgements`` asynchronous sequence. | |
/// | |
/// Use the asynchronous sequence to consume message acknowledgements. | |
/// | |
/// - Important: When the asynchronous sequence is deinited the producer will be shutdown. | |
/// | |
/// - Parameter config: The ``KafkaProducerConfig`` for configuring the ``KafkaProducer``. | |
/// - Parameter topicConfig: The ``KafkaTopicConfig`` used for newly created topics. | |
/// - Parameter logger: A logger. | |
/// - Returns: A tuple containing the created ``KafkaProducer`` and the ``KafkaMessageAcknowledgements`` | |
/// `AsyncSequence` used for receiving message acknowledgements. | |
/// - Throws: A ``KafkaError`` if initializing the producer failed. |
return | ||
} | ||
|
||
_ = source.yield(messageResult) // Ignore YieldResult |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add why we ignore this result i.e. due to no back pressure support.
self.client.withKafkaHandlePointer { handle in | ||
rd_kafka_poll(handle, 0) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this a method on the KafkaClient
which does the withHandle
stuff?
Modifications: * rename `KafkaProducer.newProducer*` to `KafkaProducer.makeProducer*` * update docc documentation for `KafkaProducer.newProducer*` methods * create new method `KafkaClient.poll(timeout:)`
Motivation: Given that we don't support backpressure for our `KafkaProducer`, we can replace the `NIOAsyncSequence` with a `AsyncStream` for the acknowledgements. Furthermore we want to shut down the producer once our stream has terminated. Modifications: * `KafkaProducer`: replace `NIOAsyncSequence` with `AsyncStream` * `KafkaProducerTests.testNoMemoryLeakAfterShutdown` make sure to kill stream otherwise we have a memory leak
66c57ef
to
84a67d5
Compare
Modifications
SwiftKafkaTests
Duration
typerd_kafka_message_t
toKafkaAcknowledgementResult
toRDKafkaConfig
so that we can pass theKafkaAcknowledgementResult
type as early as possible and don't have to bother withUnsafePointer<rd_kafka_message_t>
in all our delivery callback logicREADME
: useTaskGroup
inKafkaProducer
exampleREADME
Have two factory methods creating KafkaProducer
Motivation
We want to have a
KafkaProducer
that is not consuming any acknowledgements. This means it is initialized without adeliveryReportCallback
which in turn means thatlibrdkafka
will not queue any incoming acknowledgements which prevents us from running out of memory in that case.Modifications
KafkaProducer
: *KafkaProducer.newProducer
*KafkaProducer.newProducerWithAcknowledgements