-
Notifications
You must be signed in to change notification settings - Fork 5
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
Moved connections to the source reader from the split reader #29
base: main
Are you sure you want to change the base?
Conversation
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.
I have not completed this review. I need code to reproduce the original problem. Please add a code snipped to our slack chat.
src/main/java/io/synadia/flink/v0/source/NatsJetStreamSource.java
Outdated
Show resolved
Hide resolved
// close all connections | ||
for (ConnectionContext ctx : connections.values()) { | ||
ctx.connection.close(); | ||
} |
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.
I previously commented that I don't think it's appropriate for this to manage connections passed in to it. Is there another way to do this? Can the factory still be used here? I mean if this object is being closed before an ack, maybe there is a lifecycle problem.
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.
I believe we need to maintain a map since a split reader can handle multiple splits, with each split connection represented as a key-value pair. Additionally, there should be one map per source reader instance. These maps will remain active even if the fetcher thread pulling messages stops and new threads are created.
Perhaps we could maintain these maps within the connection factory itself? However, these maps are currently tied to the source reader’s context and do not exist outside it.
If moving them to the connection factory is something you’re considering, I can make the necessary changes to accommodate that. Let me know your thoughts!
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.
Why are you closing all the connections when one reader closes? Each reader should have it's own connection anyway.
src/main/java/io/synadia/flink/v0/source/reader/NatsJetStreamSourceReader.java
Outdated
Show resolved
Hide resolved
src/main/java/io/synadia/flink/v0/source/reader/NatsJetStreamSourceReader.java
Outdated
Show resolved
Hide resolved
src/main/java/io/synadia/flink/v0/source/reader/NatsSourceFetcherManager.java
Outdated
Show resolved
Hide resolved
src/main/java/io/synadia/flink/v0/source/reader/NatsSubjectSplitReader.java
Outdated
Show resolved
Hide resolved
src/test/java/io/synadia/io/synadia/flink/v0/NatsSubjectSplitReaderTest.java
Outdated
Show resolved
Hide resolved
I will share a code snippet with you. |
You can reproduce the issue by re-running the Why does this happen?Flink initializes multiple source reader instances, each of which is responsible for managing its own fetcher manager. The fetcher manager oversees fetcher threads, and each fetcher thread contains a split reader. Here’s what happens:
Please let me know if you need any additional information or input from my side. |
Signed-off-by: Tilak Raj <tilak.raj94@gmail.com>
Signed-off-by: Tilak Raj <tilak.raj94@gmail.com>
c86ecea
to
64172ab
Compare
Signed-off-by: Tilak Raj <tilak.raj94@gmail.com>
ConnectionFactory connectionFactory, | ||
NatsJetStreamSourceConfiguration sourceConfiguration) { | ||
private final Map<String, ConnectionContext> connections; | ||
private JetStreamSubscription subscription; |
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.
Please revert this variable back to jetStreamSubscription
elementsQueue, | ||
fetcherManager, | ||
sourceConfiguration, connectionFactory, payloadDeserializer, | ||
readerContext); |
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.
I think this whole section did not need to be refactored. It's clear what's going on and everything is inline and readable.
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.
One thing I do if I do make a change like this, is I do a review myself and comment so other reviewers can see why the change was made.
NatsSubjectSplitReader splitReader = | ||
(NatsSubjectSplitReader) splitFetcher.getSplitReader(); | ||
splitReader.notifyCheckpointComplete(partition, messages); | ||
private void triggerAcknowledge(SplitFetcher<Message, NatsSubjectSplit> splitFetcher, String splitId, List<Message> messages) throws Exception { //TODO Change to nats specific exception |
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.
Do you have any idea about this todo?
Connections are currently established in the fetch method of the split reader. This method operates in a separate thread, and the connections are terminated when the split reader is closed.
However, acknowledgments (acks) are processed with a slight delay. By the time an acknowledgment is triggered, the split reader might already have been closed. Since message acknowledgments (Message.Ack) rely on the same connection that was used to receive the message, closing the connection prematurely causes the acknowledgment to fail.
To resolve this, connections need to remain active beyond the lifecycle of the split reader. They should only be closed when the source reader itself is closed to ensure all acknowledgments are successfully processed.
This behavior can be observed by running the testJsSourceBounded test case.
Test Case Observations:
The output log below demonstrates the issue:
Here, the test fails because the connection was closed as soon as the split reader shut down.
This PR moves the connections back to the source reader and get closed only when source reader closes.