22
22
import com .google .cloud .spanner .SpannerException .DoNotConstructDirectly ;
23
23
import com .google .common .base .MoreObjects ;
24
24
import com .google .common .base .Predicate ;
25
+ import com .google .rpc .ErrorInfo ;
25
26
import com .google .rpc .ResourceInfo ;
26
27
import io .grpc .Context ;
27
28
import io .grpc .Metadata ;
@@ -46,6 +47,8 @@ public final class SpannerExceptionFactory {
46
47
"type.googleapis.com/google.spanner.admin.instance.v1.Instance" ;
47
48
private static final Metadata .Key <ResourceInfo > KEY_RESOURCE_INFO =
48
49
ProtoUtils .keyForProto (ResourceInfo .getDefaultInstance ());
50
+ private static final Metadata .Key <ErrorInfo > KEY_ERROR_INFO =
51
+ ProtoUtils .keyForProto (ErrorInfo .getDefaultInstance ());
49
52
50
53
public static SpannerException newSpannerException (ErrorCode code , @ Nullable String message ) {
51
54
return newSpannerException (code , message , null );
@@ -213,13 +216,33 @@ private static ResourceInfo extractResourceInfo(Throwable cause) {
213
216
return null ;
214
217
}
215
218
219
+ private static ErrorInfo extractErrorInfo (Throwable cause ) {
220
+ if (cause != null ) {
221
+ Metadata trailers = Status .trailersFromThrowable (cause );
222
+ if (trailers != null ) {
223
+ return trailers .get (KEY_ERROR_INFO );
224
+ }
225
+ }
226
+ return null ;
227
+ }
228
+
216
229
static SpannerException newSpannerExceptionPreformatted (
217
230
ErrorCode code , @ Nullable String message , @ Nullable Throwable cause ) {
218
231
// This is the one place in the codebase that is allowed to call constructors directly.
219
232
DoNotConstructDirectly token = DoNotConstructDirectly .ALLOWED ;
220
233
switch (code ) {
221
234
case ABORTED :
222
235
return new AbortedException (token , message , cause );
236
+ case RESOURCE_EXHAUSTED :
237
+ ErrorInfo info = extractErrorInfo (cause );
238
+ if (info != null
239
+ && info .getMetadataMap ()
240
+ .containsKey (AdminRequestsPerMinuteExceededException .ADMIN_REQUESTS_LIMIT_KEY )
241
+ && AdminRequestsPerMinuteExceededException .ADMIN_REQUESTS_LIMIT_VALUE .equals (
242
+ info .getMetadataMap ()
243
+ .get (AdminRequestsPerMinuteExceededException .ADMIN_REQUESTS_LIMIT_KEY ))) {
244
+ return new AdminRequestsPerMinuteExceededException (token , message , cause );
245
+ }
223
246
case NOT_FOUND :
224
247
ResourceInfo resourceInfo = extractResourceInfo (cause );
225
248
if (resourceInfo != null ) {
0 commit comments