12
12
import tech .ydb .yoj .repository .db .exception .OptimisticLockException ;
13
13
import tech .ydb .yoj .repository .db .exception .QueryCancelledException ;
14
14
import tech .ydb .yoj .repository .ydb .exception .BadSessionException ;
15
- import tech .ydb .yoj .repository .ydb .exception .YdbClientInternalException ;
16
15
import tech .ydb .yoj .repository .ydb .exception .YdbComponentUnavailableException ;
16
+ import tech .ydb .yoj .repository .ydb .exception .YdbConditionallyRetryableException ;
17
17
import tech .ydb .yoj .repository .ydb .exception .YdbOverloadedException ;
18
18
import tech .ydb .yoj .repository .ydb .exception .YdbRepositoryException ;
19
19
import tech .ydb .yoj .repository .ydb .exception .YdbSchemaException ;
@@ -39,63 +39,75 @@ public static void validate(String request, StatusCode statusCode, String respon
39
39
}
40
40
41
41
// 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
+ }
46
47
47
48
// Transaction locks invalidated: somebody touched the same rows that we've read and/or changed in a SERIALIZABLE-level transaction.
48
49
// Retry immediately
49
50
case ABORTED -> throw new OptimisticLockException (response );
50
51
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
+
51
62
// 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
63
65
checkGrpcContextStatus (response , null );
64
66
65
- // The result of the request is unknown; it might have been cancelled... or it executed successfully!
66
67
log .warn ("""
67
68
Database is overloaded, but we still got a reply from the DB
68
69
Request: {}
69
70
Response: {}""" , request , response );
70
71
throw new YdbOverloadedException (request , response );
71
72
}
72
73
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
77
86
checkGrpcContextStatus (response , null );
78
87
79
88
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
81
90
Request: {}
82
91
Response: {}""" , request , response );
83
- throw new YdbClientInternalException (request , response );
92
+ throw new YdbComponentUnavailableException (request , response );
84
93
}
85
94
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
94
101
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
96
103
Request: {}
97
104
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
+ );
99
111
}
100
112
101
113
// 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
124
136
125
137
// Serious internal error. No retries
126
138
case CLIENT_CALL_UNIMPLEMENTED ,
139
+ CLIENT_GRPC_ERROR ,
127
140
BAD_REQUEST ,
128
141
UNSUPPORTED ,
129
142
INTERNAL_ERROR ,
130
143
GENERIC_ERROR ,
131
144
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!
134
146
log .error ("""
135
147
Bad response status
136
148
Request: {}
0 commit comments