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
Introduced top-level ConsumerGroup construct #277
Conversation
This is a lower-level API that unlocks use cases such as consuming each assigned partition using a separate Reader or to overwrite offsets for a group. Refactored logic out of Reader and into ConsumerGroup so that Reader uses the ConsumerGroup when GroupID is set.
This change is in support of #263. It is largely a lift-and-shift, pulling logic out of Tests are currently failing, and more tests are forthcoming, but this PR currently captures the spirit of what we're trying to do. The way the
It could also be used to overwrite group offsets with code like:
|
I haven't dug into the details of the code yet, but some high-level thoughts: In your example, the readers are closed twice. Is this a bug? In your example, I don't see offsets being marked on the group/generation. Is this a bug? Would you need to also pass the Will the goroutines be required to share a Is This is a good example of why having constructors like You might consider moving low-level stuff to a subpackage. Looks pretty good though. I was confused at first, but I had to remind myself this is a low-level API. I expect I'll need to wrap this in a higher-level API, but I think all the pieces are there to do that. |
Great feedback...thanks! The example code I wrote was kind of off-the-cuff, so not surprised you found some bugs in there. 😄 I updated the example snippet to pass the generation and call
At the moment, yes. This is a carry-over from how they're currently handled. This strategy reduces round trips. Can you think of any cases where it would be bad to have the shared commit queue?
Again, this is an artifact from the way we currently handle offsets. The code in
Great point. We hadn't yet captured that on the wish list in #150, but it's there now! It's possible to avoid the panic with a bit of care since it's only hit if the config is invalid, but generally speaking, it's concerning. We'll have to fix that at some point...
I'll talk to the other folks to see what our long-term plans are...we eventually want to export many more of the lower-level operations, so this may be a good forcing function for us to consider how all that should look. |
In the case of synchronous commits, wouldn't it essentially synchronize all the readers? Also, I just noticed that the config says Otherwise, I think the reader threads will be sharing a single lock on the underlying offsets map. But, honestly I can't say for certain how that would impact performance without testing. Possibly the locking could be replaced by buffered channel or sync.Map, if necessary.
It does feel a bit awkward, but not sure how the example code would work without |
Ah, the docs on Good call re: the synchronous commit. The current Thinking a bit more about the commit loop, one could argue that the partition watcher falls into the same camp--it's logic that someone implementing consumer group code may very well want, but strictly speaking, it's not actually a part of the group. That said, I think there's a better case for including the partition watcher since it is involved in group mechanics, i.e. rebalancing. Tracking and managing offsets to commit has nothing to do with the mechanics of the group. I think all this discussion is pointing towards removing the |
…ches sometimes in CI
… two batches sometimes in CI" This reverts commit 4b21b1f.
also moved the r.offsetStash into local vars b/c they shouldn't be preserved across generations and because it was potentially racy to have it as a member var on the reader.
an exported channel on the ConsumerGroup struct. also added backoff on rejoin after error.
I've done some refactoring that I think makes the consumer group a little more idiomatic by removing the exported I added some example code as well. I think that's probably the best place to start if looking over this code as it shows how a caller would interact with the consumer group. The next best place to look is the reader code to see how it's been refactored. I'm still thinking that it might be nice to provide commit loop functionality but as a separate type that works with a consumer group generation. I think the primary use folks will have for this code is the parallel reader example, so it would be nice to provide commit management code. Still working through what that will look like, though. Also, such a change can come later since it would be new code and would not break b/w compatibility. |
Can this PR be merged as my use case is to reset offset for consumer group. |
Hi @vgvineet4. I'm finishing up some test cases now and hope to merge this soon. As I've been refactoring the code, I've discovered a lot of edge cases and error conditions that weren't properly handled. Once I get the tests ironed out, we'll be good to merge this. I think the API is locked down at this point, so if you'd like to pull this branch as a pre-release, I don't anticipate any breaking changes with subsequent commits. |
…reader and into CG
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.
Really nice work here! Let's get this merged 👍
Is this feature available? |
@cuiyuan yes, we release v0.3.1 which includes the work that was merged in this PR |
Awesome! This feature should be documented. Also the |
You raise an excellent point! 😁 #347 |
Previously, the batch read functions returned io.EOF to signal the end of the batch. However, this caused ambiguity because there are valid io.EOF errors from other sources (e.g. a connection that is closed by the broker). Because io.EOF can leave the conection in an unusable state, we are closing the connection and logging it. However, this also means that we're closing the connection after every single fetch request, which is not desirable. This PR also fixes an accidental line deletion of deadline management that was introduced in #277. Fixes #258
The Batch read functions return io.EOF to signal the end of the batch. However, there was ambiguity because io.EOF errors could also surface for other reasons (e.g. a connection closed by the broker). Due to this ambiguity, the Reader would treat io.EOF as an error. In turn, this would result in an error message being logged and the connection being closed after every single fetch request. Such behavior is undesirable from a performance perpsective because the connection could be re-used. It is also misleading because it increases error stats and logs stats when there is really no error. This PR fixes the handling of the io.EOF in the Reader to be an expected condition meanwhile ensuring that the Batch maps any underlying io.EOF errors to io.ErrUnexpectedEOF. This PR also fixes an accidental line deletion of deadline management that was introduced in #277. Fixes #258
@stevevls I tried to use this feature. But I found cannot use kafka-consumer-groups to list the CURRENT-OFFSET of the groupId. Does it has something to do with this feature? |
This is a lower-level API that unlocks use cases such as consuming
each assigned partition using a separate Reader or to overwrite
offsets for a group.
Refactored logic out of Reader and into ConsumerGroup so that
Reader uses the ConsumerGroup when GroupID is set.