Skip to content

Commit 0ebd017

Browse files
committed
eval protocol exception retry
1 parent 55043e4 commit 0ebd017

File tree

7 files changed

+702
-571
lines changed

7 files changed

+702
-571
lines changed

eval_protocol/exceptions.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
"""
2+
Custom exceptions for Eval Protocol that map to gRPC Status codes.
3+
4+
These exceptions provide a clean way to handle errors and map them to appropriate
5+
Status objects following the AIP-193 standard.
6+
"""
7+
8+
from typing import Optional
9+
10+
11+
class EvalProtocolError(Exception):
12+
"""
13+
Base exception for all Eval Protocol specific errors.
14+
15+
Maps to Status.Code and can be converted to Status objects for structured logging.
16+
"""
17+
18+
pass
19+
20+
21+
# Standard gRPC status code exceptions
22+
class CancelledError(EvalProtocolError):
23+
"""Operation was cancelled (Status.Code.CANCELLED = 1)"""
24+
25+
status_code = 1
26+
27+
28+
class UnknownError(EvalProtocolError):
29+
"""Unknown error occurred (Status.Code.UNKNOWN = 2)"""
30+
31+
status_code = 2
32+
33+
34+
class InvalidArgumentError(EvalProtocolError):
35+
"""Invalid argument provided (Status.Code.INVALID_ARGUMENT = 3)"""
36+
37+
status_code = 3
38+
39+
40+
class DeadlineExceededError(EvalProtocolError):
41+
"""Deadline exceeded (Status.Code.DEADLINE_EXCEEDED = 4)"""
42+
43+
status_code = 4
44+
45+
46+
class NotFoundError(EvalProtocolError):
47+
"""Resource not found (Status.Code.NOT_FOUND = 5)"""
48+
49+
status_code = 5
50+
51+
52+
class AlreadyExistsError(EvalProtocolError):
53+
"""Resource already exists (Status.Code.ALREADY_EXISTS = 6)"""
54+
55+
status_code = 6
56+
57+
58+
class PermissionDeniedError(EvalProtocolError):
59+
"""Permission denied (Status.Code.PERMISSION_DENIED = 7)"""
60+
61+
status_code = 7
62+
63+
64+
class ResourceExhaustedError(EvalProtocolError):
65+
"""Resource exhausted (Status.Code.RESOURCE_EXHAUSTED = 8)"""
66+
67+
status_code = 8
68+
69+
70+
class FailedPreconditionError(EvalProtocolError):
71+
"""Failed precondition (Status.Code.FAILED_PRECONDITION = 9)"""
72+
73+
status_code = 9
74+
75+
76+
class AbortedError(EvalProtocolError):
77+
"""Operation was aborted (Status.Code.ABORTED = 10)"""
78+
79+
status_code = 10
80+
81+
82+
class OutOfRangeError(EvalProtocolError):
83+
"""Value out of range (Status.Code.OUT_OF_RANGE = 11)"""
84+
85+
status_code = 11
86+
87+
88+
class UnimplementedError(EvalProtocolError):
89+
"""Operation is not implemented (Status.Code.UNIMPLEMENTED = 12)"""
90+
91+
status_code = 12
92+
93+
94+
class InternalError(EvalProtocolError):
95+
"""Internal server error (Status.Code.INTERNAL = 13)"""
96+
97+
status_code = 13
98+
99+
100+
class UnavailableError(EvalProtocolError):
101+
"""Service unavailable (Status.Code.UNAVAILABLE = 14)"""
102+
103+
status_code = 14
104+
105+
106+
class DataLossError(EvalProtocolError):
107+
"""Unrecoverable data loss (Status.Code.DATA_LOSS = 15)"""
108+
109+
status_code = 15
110+
111+
112+
class UnauthenticatedError(EvalProtocolError):
113+
"""Request lacks valid authentication (Status.Code.UNAUTHENTICATED = 16)"""
114+
115+
status_code = 16
116+
117+
118+
# Custom EP exceptions
119+
class RolloutFinishedError(EvalProtocolError):
120+
"""Rollout completed successfully (Status.Code.FINISHED = 100)"""
121+
122+
status_code = 100
123+
124+
125+
class RolloutRunningError(EvalProtocolError):
126+
"""Rollout is still running (Status.Code.RUNNING = 101)"""
127+
128+
status_code = 101
129+
130+
131+
class ScoreInvalidError(EvalProtocolError):
132+
"""Score is invalid (Status.Code.SCORE_INVALID = 102)"""
133+
134+
status_code = 102
135+
136+
137+
# Convenience mapping from status codes to exception classes
138+
# Only actual error conditions should raise exceptions
139+
STATUS_CODE_TO_EXCEPTION = {
140+
0: None, # OK - success, no exception
141+
1: CancelledError,
142+
2: UnknownError,
143+
3: InvalidArgumentError,
144+
4: DeadlineExceededError,
145+
5: NotFoundError,
146+
6: AlreadyExistsError,
147+
7: PermissionDeniedError,
148+
8: ResourceExhaustedError,
149+
9: FailedPreconditionError,
150+
10: AbortedError,
151+
11: OutOfRangeError,
152+
12: UnimplementedError,
153+
13: InternalError,
154+
14: UnavailableError,
155+
15: DataLossError,
156+
16: UnauthenticatedError,
157+
100: None, # FINISHED - success, no exception
158+
101: None, # RUNNING - in progress, no exception
159+
102: None, # SCORE_INVALID - success, no exception
160+
}
161+
162+
163+
def exception_for_status_code(code: int) -> Optional[EvalProtocolError]:
164+
"""
165+
Create an exception instance for a given status code.
166+
167+
Args:
168+
code: Status code from Status.Code enum
169+
170+
Returns:
171+
Exception instance or None if code is OK (0)
172+
"""
173+
exception_class = STATUS_CODE_TO_EXCEPTION.get(code)
174+
if exception_class is None:
175+
return None
176+
return exception_class()

0 commit comments

Comments
 (0)