Skip to content

Commit 67806b6

Browse files
committed
Associate client exceptions with SQL state and ErrorDetails
We now provide error details for client-side exceptions for easier handling of failures. [resolves #538] Signed-off-by: Mark Paluch <[email protected]>
1 parent e224fc5 commit 67806b6

File tree

4 files changed

+90
-15
lines changed

4 files changed

+90
-15
lines changed

src/main/java/io/r2dbc/postgresql/PostgresqlConnectionFactory.java

+15-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import io.netty.buffer.ByteBufAllocator;
2020
import io.netty.channel.unix.DomainSocketAddress;
21+
import io.r2dbc.postgresql.api.ErrorDetails;
22+
import io.r2dbc.postgresql.api.PostgresqlException;
2123
import io.r2dbc.postgresql.authentication.AuthenticationHandler;
2224
import io.r2dbc.postgresql.authentication.PasswordAuthenticationHandler;
2325
import io.r2dbc.postgresql.authentication.SASLAuthenticationHandler;
@@ -262,10 +264,20 @@ private Mono<IsolationLevel> getIsolationLevel(io.r2dbc.postgresql.api.Postgresq
262264
})).defaultIfEmpty(IsolationLevel.READ_COMMITTED).last();
263265
}
264266

265-
static class PostgresConnectionException extends R2dbcNonTransientResourceException {
267+
static class PostgresConnectionException extends R2dbcNonTransientResourceException implements PostgresqlException {
266268

267-
public PostgresConnectionException(String msg, @Nullable Throwable cause) {
268-
super(msg, cause);
269+
private static final String CONNECTION_DOES_NOT_EXIST = "08003";
270+
271+
private final ErrorDetails errorDetails;
272+
273+
public PostgresConnectionException(String reason, @Nullable Throwable cause) {
274+
super(reason, CONNECTION_DOES_NOT_EXIST, 0, null, cause);
275+
this.errorDetails = ErrorDetails.fromCodeAndMessage(CONNECTION_DOES_NOT_EXIST, reason);
276+
}
277+
278+
@Override
279+
public ErrorDetails getErrorDetails() {
280+
return this.errorDetails;
269281
}
270282

271283
}

src/main/java/io/r2dbc/postgresql/api/ErrorDetails.java

+17
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import java.util.Collections;
2525
import java.util.HashMap;
26+
import java.util.LinkedHashMap;
2627
import java.util.List;
2728
import java.util.Map;
2829
import java.util.Objects;
@@ -130,6 +131,22 @@ public static ErrorDetails fromMessage(String message) {
130131
return new ErrorDetails(Collections.singletonMap(MESSAGE, message));
131132
}
132133

134+
/**
135+
* Create a new {@link ErrorDetails}
136+
*
137+
* @param code the error code
138+
* @param message the error message
139+
* @return the {@link ErrorDetails} object
140+
*/
141+
public static ErrorDetails fromCodeAndMessage(String code, String message) {
142+
143+
Map<FieldType, String> details = new LinkedHashMap<>(2);
144+
details.put(CODE, code);
145+
details.put(MESSAGE, message);
146+
147+
return new ErrorDetails(details);
148+
}
149+
133150
@Override
134151
public boolean equals(Object o) {
135152
if (this == o) {

src/main/java/io/r2dbc/postgresql/client/AbstractPostgresSSLHandlerAdapter.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import io.netty.handler.ssl.SslHandler;
2323
import io.netty.util.concurrent.Future;
2424
import io.netty.util.concurrent.GenericFutureListener;
25+
import io.r2dbc.postgresql.api.ErrorDetails;
26+
import io.r2dbc.postgresql.api.PostgresqlException;
2527
import io.r2dbc.spi.R2dbcPermissionDeniedException;
2628
import reactor.core.publisher.Mono;
2729

@@ -86,10 +88,18 @@ SslHandler getSslHandler() {
8688
/**
8789
* Postgres-specific {@link R2dbcPermissionDeniedException}.
8890
*/
89-
static final class PostgresqlSslException extends R2dbcPermissionDeniedException {
91+
static final class PostgresqlSslException extends R2dbcPermissionDeniedException implements PostgresqlException {
9092

91-
PostgresqlSslException(String msg) {
92-
super(msg);
93+
private final ErrorDetails errorDetails;
94+
95+
PostgresqlSslException(String reason) {
96+
super(reason, ReactorNettyClient.CONNECTION_FAILURE, 0, (String) null);
97+
this.errorDetails = ErrorDetails.fromCodeAndMessage(ReactorNettyClient.CONNECTION_FAILURE, reason);
98+
}
99+
100+
@Override
101+
public ErrorDetails getErrorDetails() {
102+
return this.errorDetails;
93103
}
94104

95105
}

src/main/java/io/r2dbc/postgresql/client/ReactorNettyClient.java

+45-9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import io.netty.util.ReferenceCountUtil;
2929
import io.netty.util.internal.logging.InternalLogger;
3030
import io.netty.util.internal.logging.InternalLoggerFactory;
31+
import io.r2dbc.postgresql.api.ErrorDetails;
32+
import io.r2dbc.postgresql.api.PostgresqlException;
3133
import io.r2dbc.postgresql.message.backend.BackendKeyData;
3234
import io.r2dbc.postgresql.message.backend.BackendMessage;
3335
import io.r2dbc.postgresql.message.backend.BackendMessageDecoder;
@@ -88,6 +90,8 @@
8890
*/
8991
public final class ReactorNettyClient implements Client {
9092

93+
static final String CONNECTION_FAILURE = "08006";
94+
9195
private static final Logger logger = Loggers.getLogger(ReactorNettyClient.class);
9296

9397
private static final boolean DEBUG_ENABLED = logger.isDebugEnabled();
@@ -535,38 +539,70 @@ public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
535539

536540
}
537541

538-
static class PostgresConnectionClosedException extends R2dbcNonTransientResourceException {
542+
static class PostgresConnectionClosedException extends R2dbcNonTransientResourceException implements PostgresqlException {
543+
544+
private final ErrorDetails errorDetails;
539545

540546
public PostgresConnectionClosedException(String reason) {
541-
super(reason);
547+
super(reason, CONNECTION_FAILURE, 0, (String) null);
548+
this.errorDetails = ErrorDetails.fromCodeAndMessage(CONNECTION_FAILURE, reason);
542549
}
543550

544551
public PostgresConnectionClosedException(String reason, @Nullable Throwable cause) {
545-
super(reason, cause);
552+
super(reason, CONNECTION_FAILURE, 0, null, cause);
553+
this.errorDetails = ErrorDetails.fromCodeAndMessage(CONNECTION_FAILURE, reason);
554+
}
555+
556+
@Override
557+
public ErrorDetails getErrorDetails() {
558+
return this.errorDetails;
546559
}
547560

548561
}
549562

550-
static class PostgresConnectionException extends R2dbcNonTransientResourceException {
563+
static class PostgresConnectionException extends R2dbcNonTransientResourceException implements PostgresqlException {
564+
565+
private final static ErrorDetails ERROR_DETAILS = ErrorDetails.fromCodeAndMessage(CONNECTION_FAILURE, "An I/O error occurred while sending to the backend or receiving from the backend");
551566

552567
public PostgresConnectionException(Throwable cause) {
553-
super(cause);
568+
super(ERROR_DETAILS.getMessage(), ERROR_DETAILS.getCode(), 0, null, cause);
569+
}
570+
571+
@Override
572+
public ErrorDetails getErrorDetails() {
573+
return ERROR_DETAILS;
554574
}
555575

556576
}
557577

558-
static class RequestQueueException extends R2dbcTransientResourceException {
578+
static class RequestQueueException extends R2dbcTransientResourceException implements PostgresqlException {
579+
580+
private final ErrorDetails errorDetails;
559581

560582
public RequestQueueException(String message) {
561-
super(message);
583+
super(message, CONNECTION_FAILURE, 0, (String) null);
584+
this.errorDetails = ErrorDetails.fromCodeAndMessage(CONNECTION_FAILURE, message);
585+
}
586+
587+
@Override
588+
public ErrorDetails getErrorDetails() {
589+
return this.errorDetails;
562590
}
563591

564592
}
565593

566-
static class ResponseQueueException extends R2dbcNonTransientResourceException {
594+
static class ResponseQueueException extends R2dbcNonTransientResourceException implements PostgresqlException {
595+
596+
private final ErrorDetails errorDetails;
567597

568598
public ResponseQueueException(String message) {
569-
super(message);
599+
super(message, CONNECTION_FAILURE, 0, (String) null);
600+
this.errorDetails = ErrorDetails.fromCodeAndMessage(CONNECTION_FAILURE, message);
601+
}
602+
603+
@Override
604+
public ErrorDetails getErrorDetails() {
605+
return this.errorDetails;
570606
}
571607

572608
}

0 commit comments

Comments
 (0)