1212import tech .ydb .yoj .repository .db .exception .OptimisticLockException ;
1313import tech .ydb .yoj .repository .db .exception .QueryCancelledException ;
1414import tech .ydb .yoj .repository .ydb .exception .BadSessionException ;
15- import tech .ydb .yoj .repository .ydb .exception .YdbClientInternalException ;
1615import tech .ydb .yoj .repository .ydb .exception .YdbComponentUnavailableException ;
16+ import tech .ydb .yoj .repository .ydb .exception .YdbConditionallyRetryableException ;
1717import tech .ydb .yoj .repository .ydb .exception .YdbOverloadedException ;
1818import tech .ydb .yoj .repository .ydb .exception .YdbRepositoryException ;
1919import tech .ydb .yoj .repository .ydb .exception .YdbSchemaException ;
@@ -39,63 +39,75 @@ public static void validate(String request, StatusCode statusCode, String respon
3939 }
4040
4141 // Current session can no longer be used. Retry immediately by creating a new session
42- case BAD_SESSION ,
43- SESSION_EXPIRED ,
44- // Prepared statement or transaction was not found
45- NOT_FOUND -> throw new BadSessionException (response );
42+ case BAD_SESSION , // This session is no longer available. Create a new session
43+ SESSION_EXPIRED , // The session has already expired. Create a new session
44+ NOT_FOUND -> { // Prepared statement or transaction was not found in current session. Create a new session
45+ throw new BadSessionException (response );
46+ }
4647
4748 // Transaction locks invalidated: somebody touched the same rows that we've read and/or changed in a SERIALIZABLE-level transaction.
4849 // Retry immediately
4950 case ABORTED -> throw new OptimisticLockException (response );
5051
52+ // The request was cancelled because the request timeout (CancelAfter) has expired. The request has been cancelled on the server.
53+ // Non-retryable
54+ case CANCELLED -> throw new QueryCancelledException (response );
55+
56+ // Client query timeouts. Non-retryable
57+ case CLIENT_DEADLINE_EXPIRED , // Deadline expired before the request was sent to the server
58+ CLIENT_DEADLINE_EXCEEDED -> { // Client could not get response from the server in time
59+ throw new DeadlineExceededException (response );
60+ }
61+
5162 // DB overloaded and similar conditions. Slow retry with exponential backoff
52- case OVERLOADED ,
53- // DB took too long to respond
54- TIMEOUT ,
55- // The request was cancelled because the request timeout (CancelAfter) has expired. The request has been cancelled on the server
56- CANCELLED ,
57- // Not enough resources to process the request
58- CLIENT_RESOURCE_EXHAUSTED ,
59- // Deadline expired before the request was sent to the server
60- CLIENT_DEADLINE_EXPIRED ,
61- // The request was cancelled on the client, at the transport level (because the GRPC deadline expired)
62- CLIENT_DEADLINE_EXCEEDED -> {
63+ case OVERLOADED , // A part of the system is overloaded. Retry the last action (query) and reduce the query rate.
64+ CLIENT_RESOURCE_EXHAUSTED -> { // Not enough resources to process the request
6365 checkGrpcContextStatus (response , null );
6466
65- // The result of the request is unknown; it might have been cancelled... or it executed successfully!
6667 log .warn ("""
6768 Database is overloaded, but we still got a reply from the DB
6869 Request: {}
6970 Response: {}""" , request , response );
7071 throw new YdbOverloadedException (request , response );
7172 }
7273
73- // Unknown error on the client side (most often at the transport level). Fast retry with fixed interval
74- case CLIENT_CANCELLED ,
75- CLIENT_GRPC_ERROR ,
76- CLIENT_INTERNAL_ERROR -> {
74+ // The query cannot be executed in the current state. Non-retryable
75+ //
76+ // NB: Primary key/UNIQUE index violations are checked by YdbValidator.validatePkConstraint() separately,
77+ // before YdbValidator.validate() is called!
78+ // And all other, unknown "failed preconditions" are considered to be non-retryable.
79+ case PRECONDITION_FAILED -> throw new YdbRepositoryException (request , response );
80+
81+ // DB, one of its components, or the transport is temporarily unavailable. Fast retry with fixed interval
82+ case UNAVAILABLE , // DB responded that it or some of its subsystems are unavailable
83+ CLIENT_DISCOVERY_FAILED , // Error occurred while retrieving the list of endpoints
84+ CLIENT_LIMITS_REACHED , // Client-side session limit reached
85+ SESSION_BUSY -> { // Another query is being executed in this session, should retry with a new session
7786 checkGrpcContextStatus (response , null );
7887
7988 log .warn ("""
80- YDB SDK internal error or cancellation
89+ Some database components are not available, but we still got a reply from the DB
8190 Request: {}
8291 Response: {}""" , request , response );
83- throw new YdbClientInternalException (request , response );
92+ throw new YdbComponentUnavailableException (request , response );
8493 }
8594
86- // DB, one of its components, or the transport is temporarily unavailable. Fast retry with fixed interval
87- case UNAVAILABLE , // DB responded that it or some of its subsystems are unavailable
88- TRANSPORT_UNAVAILABLE , // Network connectivity issues
89- CLIENT_DISCOVERY_FAILED , // Error occurred while retrieving the list of endpoints
90- CLIENT_LIMITS_REACHED , // Client-side session limit reached
91- UNDETERMINED ,
92- SESSION_BUSY , // Another query is being executed in this session, should retry with a new session
93- PRECONDITION_FAILED -> {
95+ // The result of the request is unknown; it might have never reached the server, have been cancelled... or executed successfully!
96+ case TIMEOUT , // Query timeout expired. If the query is conditionally retryable, retry it
97+ UNDETERMINED , // Unknown transaction state. We don't know if it has been committed or not
98+ CLIENT_CANCELLED , // GRPC call to the server has been cancelled. We don't know if the server performed the request or not
99+ TRANSPORT_UNAVAILABLE , // Network connectivity issues. We don't know if the server performed the request or not
100+ CLIENT_INTERNAL_ERROR -> { // Internal YDB SDK error, assumed to be transient
94101 log .warn ("""
95- Some database components are not available, but we still got a reply from the DB
102+ Indeterminate request state: it's not known whether the request reached the DB and was performed
96103 Request: {}
97104 Response: {}""" , request , response );
98- throw new YdbComponentUnavailableException (request , response );
105+ throw new YdbConditionallyRetryableException (
106+ "Indeterminate request state: it's not known whether the request reached the DB and was performed" ,
107+ statusCode ,
108+ request ,
109+ response
110+ );
99111 }
100112
101113 // GRPC client reports that the request was not authenticated properly. Retry immediately.
@@ -124,13 +136,13 @@ public static void validate(String request, StatusCode statusCode, String respon
124136
125137 // Serious internal error. No retries
126138 case CLIENT_CALL_UNIMPLEMENTED ,
139+ CLIENT_GRPC_ERROR ,
127140 BAD_REQUEST ,
128141 UNSUPPORTED ,
129142 INTERNAL_ERROR ,
130143 GENERIC_ERROR ,
131144 UNUSED_STATUS ,
132- // This status is used by other YDB services (not the {Table,Query}Service). This is *NOT* a form of PRECONDITION_FAILED!
133- ALREADY_EXISTS -> {
145+ ALREADY_EXISTS -> { // Used by other YDB services (not the {Table,Query}Service). This is *NOT* a form of PRECONDITION_FAILED!
134146 log .error ("""
135147 Bad response status
136148 Request: {}
0 commit comments