Skip to content
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

Allow to commit offset in case of deserialization errors #761

Merged

Conversation

giamo
Copy link
Contributor

@giamo giamo commented Jul 7, 2023

Problem

When a consumed message cannnot be deserialized (e.g. when using the Avro deserializer and receiving a JSON) the DefaultKafkaListenerExceptionHandler has an option to skip the message with a seek() and keep consuming the next message, but it doesn’t commit the message offset. This means that until a “good” message is processed and committed, the consumer group will show a lag and it will try reprocessing the bad message in case of restart or group rebalancing. This issue especially impacts low-traffic topics.

Proposed solution

Add a flag commitRecordOnDeserializationFailure to indicate if the default error handler should also commit the offset in addition to doing the seek(). The flag is set to false by default, so the handler will continue with the current behavior unless the flag is set explicitly by the user.

Copy link
Contributor

@sdelamo sdelamo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would need a test if we wanted to go with this approach.

Copy link
Contributor

@jeremyg484 jeremyg484 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logically I think this option makes sense overall. I'd potentially like to see more fine-grained error handling as mentioned, and as @sdelamo said, it needs tests.

Copy link
Contributor

@guillermocalvo guillermocalvo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM except for the lack of tests.

As an altenative approach, we could have merged those two boolean flags into a single configurable property onDeserializationFailure or deserializationFailureStrategy that could be populated with an enum type like this:

public enum DeserializationFailureStrategy {
    /** Does nothing. */
    DO_NOTHING,

    /** Seeks past the offending record. */
    SKIP,

    /** Skips and commits offending record. */
    COMMIT
}

But I admit the current approach is more backward compatible.

@giamo
Copy link
Contributor Author

giamo commented Jul 12, 2023

LGTM except for the lack of tests.

As an altenative approach, we could have merged those two boolean flags into a single configurable property onDeserializationFailure or deserializationFailureStrategy that could be populated with an enum type like this:

public enum DeserializationFailureStrategy {
    /** Does nothing. */
    DO_NOTHING,

    /** Seeks past the offending record. */
    SKIP,

    /** Skips and commits offending record. */
    COMMIT
}

But I admit the current approach is more backward compatible.

Then enum would make sense but I suppose it’s better to be backward compatible and not change the interface and the behavior for people already using the handler.

I will try to add the test one of these days!

@giamo giamo force-pushed the commit-on-deserialization-error branch 4 times, most recently from f5c52a7 to 4d7688a Compare July 16, 2023 11:33
@giamo
Copy link
Contributor Author

giamo commented Jul 16, 2023

@sdelamo @jeremyg484 @guillermocalvo added a test and a separate try/catch for the commit operation

@sdelamo
Copy link
Contributor

sdelamo commented Jul 17, 2023

Then enum would make sense but I suppose it’s better to be backward compatible and not change the interface and the behavior for people already using the handler.

Yes, we cannot introduce a breaking change.

@giamo giamo force-pushed the commit-on-deserialization-error branch from 4d7688a to d5881ac Compare July 18, 2023 10:38
@sdelamo sdelamo added the type: improvement A minor improvement to an existing feature label Jul 19, 2023
Copy link
Contributor

@sdelamo sdelamo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will people discover this new setting? I think we have to add docs.

Previous behavior was buggy. It was fixed by:
micronaut-projects#771

then: "The message is skipped, but not committed"
conditions.eventually {
consumer.currentPosition > 0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guillermocalvo it's strange that this test passes, the DoNothingOnDeserializationErrorConsumer explicitly sets the skipRecordOnDeserializationFailure to false so I'd expect the offset not to be advanced... or am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@giamo Previous behavior was fixed by: #771

@sdelamo sdelamo merged commit 1281d47 into micronaut-projects:master Aug 18, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: improvement A minor improvement to an existing feature
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants