Skip to content

Conversation

@injae-kim
Copy link
Contributor

Closes gh-31256

Motivation

// users want to handle error like this on various cases!
    @Override
    public <T> Mono<T> inConnection(Function<Connection, Mono<T>> action) throws DataAccessException {
        return super.inConnection(con -> action.apply(con)
                .onErrorResume(e -> {
                    handleError(e, con); // here
                    return Mono.error(e);
                }));
    }

    @Override
    public <T> Flux<T> inConnectionMany(Function<Connection, Flux<T>> action) throws DataAccessException {
        return super.inConnectionMany(con -> action.apply(con)
                .onErrorResume(e -> {
                    handleError(e, con); // here
                    return Mono.error(e);
                }));
    }
  • We found that users want to handle error by user's custom error handling logic on DatabaseClient, but currently impossible

Modification

DatabaseClient.builder()
    .handleInConnectionError((t, conn) -> { /* error handling logic */})
    .build()
  • Add error handling function on R2DBC DatabaseClient and it's builder

Result

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 3, 2024
@jhoeller jhoeller self-assigned this Jan 3, 2024
@jhoeller jhoeller added in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 3, 2024
@jhoeller jhoeller added this to the 6.2.x milestone Jan 3, 2024
@jhoeller
Copy link
Contributor

jhoeller commented Jan 3, 2024

Thanks for the pull request! From a quick first glance, this looks pretty good to me :-)

A code-style note: Please do not use star imports such as io.r2dbc.spi.*; we always list all imported classes explicitly. You may run the check build target instead of test, including our Checkstyle task as well which checks for such common code style issues.

A naming note: handleInConnectionError is descriptive but sounds like a protected template method rather than a callback. Maybe onConnectionError with an event-style on prefix instead? The specific semantics of being called for exceptions that come up within the inConnection method could be put into a javadoc, still making it descriptive enough.

@injae-kim
Copy link
Contributor Author

oh thanks a lot for detailed review @jhoeller !

  • Fix import * to import all classes explicitly
  • Fix naming handleInConnectionError to onConnectionError
  • Run checkStyle and build and check success

✅ I updated PR like above based on your suggestion. thanks!

@sbrannen sbrannen changed the title Add error handling function on R2DBC DatabaseClient Jan 4, 2024
Copy link
Member

@sbrannen sbrannen left a comment

Choose a reason for hiding this comment

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

Please rename instances of the BiConsumer to errorHandler (or perhaps connectionErrorHandler).

Thanks

@jhoeller
Copy link
Contributor

jhoeller commented Jan 4, 2024

@sbrannen @injae-kim indeed, what we register via onConnectionError is an error handler function, terminology-wise, and that should be reflected in the argument name.

@mp911de does the overall arrangement look sensible to you?

@mp911de
Copy link
Member

mp911de commented Jan 4, 2024

Taking a step back, I wonder what we actually want to achieve. Generally, connections are released (closed) upon an exception and the error signal is dispatched to the subscriber.

DatabaseClient has a concept of functions (ExecuteFunction, StatementFilterFunction) so I'm wondering whether it would rather make sense to have ConnectionFilterFunction that acts as hook for all inConnection[Many] invocations. inConnection was built with the intent to serve as customization hook. Introducing a filter function that can serve this purpose would take the error handler into consideration and provide customization beyond just error handling.

@injae-kim
Copy link
Contributor Author

injae-kim commented Jan 4, 2024

Taking a step back, I wonder what we actually want to achieve.

I just simply want to make user can handleError with connection like handleError(t, conn) on inConnection[Many]!
e.g. user can leave log or open circuit breaker with connection info and error by using handleError(t, conn)

Currently it's impossible cause connection is only used inside of inConnection[Many].

I'm wondering whether it would rather make sense to have ConnectionFilterFunction that acts as hook for all inConnection[Many] invocations.

@mp911de , thanks a lot for your suggestion!
Can you share some example code about ConnectionFilterFunction usage?
(it's my first PR on spring-r2dbc so I'm hard to imagine how ConnectionFilterFunction works like 😅 )

@injae-kim
Copy link
Contributor Author

injae-kim commented Jan 4, 2024

(@mp911de) Introducing a ConnectionFilterFunction that can serve this purpose would take the error handler into consideration and provide customization beyond just error handling.

Hi @@sbrannen, @jhoeller what do you think about above suggestion?

If you agree with this, please share to me~! I'll update this PR with this way!
(introducing ConnectionFilterFunction instead of BiConsumer<> errorHandler)

I also agree that ConnectionFilterFunction can provide customization beyond just error handling, but for now user may only need BiFunction<> errorHandler and it's simpler. waiting your opinion! 😄

@injae-kim injae-kim force-pushed the add-errorHandler-r2dbc-databaseClient branch from d8c5942 to 6554c16 Compare January 8, 2024 15:16
@injae-kim
Copy link
Contributor Author

Rebase to upstream/main to resolve conflict on test~!

@jhoeller jhoeller removed their assignment Jan 11, 2024
@snicoll snicoll self-assigned this Jan 15, 2024
@snicoll snicoll modified the milestones: 6.2.x, 6.2.0-M1 Jan 15, 2024
@snicoll snicoll removed their assignment Jan 15, 2024
@snicoll
Copy link
Member

snicoll commented Jan 15, 2024

Looking at the latest state of this PR, I don't really see how the consumer is related to "connection error". The function that uses the connection may also lead to an error, and if closing the connection fails, it is not invoked. Looking at the javadoc of onConnectionError I don't believe it matches what the algorithm does.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Jan 15, 2024
@injae-kim
Copy link
Contributor Author

injae-kim commented Jan 15, 2024

public interface ConnectionAccessor {
/**
* Execute a callback {@link Function} within a {@link Connection} scope.
* The function is responsible for creating a {@link Mono}. The connection

/**
 * Handle an exception thrown from {@link ConnectionAccessor#inConnection}
 * or {@link ConnectionAccessor#inConnectionMany} 👉 (new) during executing a callback {@link Function} within a {@link Connection} scope.
 * @param errorHandler a {@code BiConsumer} that handles the connection error
 * @since 6.2
 */
Builder onConnectionError(BiConsumer<? super Throwable, ? super Connection> errorHandler)

onConnectionError actually consumes error thrown during action.apply(connection).
And "action is a callback function within a connection scope", based on ConnectionAccessor.inConnection* comment.

So it's good to enhance onConnectionError javadoc like above? matching with what it really does.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 15, 2024
@snicoll
Copy link
Member

snicoll commented Jan 22, 2024

So it's good to enhance onConnectionError javadoc like above? matching with what it really does.

I don't think so and I am not sure that is where we want to go anyway. Brainstorming with @mp911de, we'd like to take a step back and resume the conversation on the issue. Specifically by sharing a representative sample of what that would achieve. It's unclear if you're affected by that issue as well or if you're trying to help based on the original report. Either way, let's continue chatting on the issue. Thanks for the PR, in any case!

@snicoll snicoll closed this Jan 22, 2024
@snicoll snicoll removed this from the 6.2.x milestone Jan 22, 2024
@snicoll snicoll added status: declined A suggestion or change that we don't feel we should currently apply and removed status: feedback-provided Feedback has been provided labels Jan 22, 2024
@injae-kim
Copy link
Contributor Author

Either way, let's continue chatting on the issue.

aha I got it! let's continue to discuss on issue~ thanks a lot for review 🙇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: data Issues in data modules (jdbc, orm, oxm, tx) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

6 participants