Skip to content

Commit ddbb132

Browse files
authored
Ship all grpc error codes (#200)
* Ship all grpc error codes These are useful for influencing http responses. Our users may not import grpc, and shouldn't need to know about grpc. * Document codes * Split out restate error codes so they aren't mistakenly used protocol_violation might tempt people to use, and this would be a problem. * Fix import in tests
1 parent 26ad194 commit ddbb132

File tree

3 files changed

+145
-5
lines changed

3 files changed

+145
-5
lines changed

src/restate_context_impl.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { SideEffectEntryMessage } from "./generated/proto/javascript";
4141
import { AsyncLocalStorage } from "async_hooks";
4242
import {
4343
ErrorCodes,
44+
RestateErrorCodes,
4445
RestateError,
4546
RetryableError,
4647
TerminalError,
@@ -443,7 +444,7 @@ async function executeWithRetries<T>(
443444
// - they are not retried within the service, because they will never succeed within this service,
444445
// but can only succeed within a new invocation going to service with fixed code
445446
// we hence break the retries here similar to terminal errors
446-
if (e instanceof RestateError && e.code == ErrorCodes.JOURNAL_MISMATCH) {
447+
if (e instanceof RestateError && e.code == RestateErrorCodes.JOURNAL_MISMATCH) {
447448
throw e;
448449
}
449450

src/types/errors.ts

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,147 @@ import { JournalEntry } from "../journal";
1818
import { FailureWithTerminal } from "../generated/proto/javascript";
1919

2020
export enum ErrorCodes {
21+
/**
22+
* Not an error; returned on success.
23+
* HTTP 200
24+
*/
25+
OK = 0,
26+
/**
27+
* The operation was cancelled, typically by the caller.
28+
* HTTP 408
29+
*/
30+
CANCELLED = 1,
31+
/**
32+
* Unknown error. For example, this error may be returned when a
33+
* Status value received from another address space belongs to an error
34+
* space that is not known in this address space. Also errors raised by APIs
35+
* that do not return enough error information may be converted to this
36+
* error.
37+
* HTTP 500
38+
*/
2139
UNKNOWN = 2,
40+
/**
41+
* The client specified an invalid argument. Note that
42+
* this differs from FAILED_PRECONDITION. INVALID_ARGUMENT indicates
43+
* arguments that are problematic regardless of the state of the system
44+
* (e.g., a malformed file name).
45+
* HTTP 400
46+
*/
47+
INVALID_ARGUMENT = 3,
48+
/**
49+
* The deadline expired before the operation could
50+
* complete. For operations that change the state of the system, this error
51+
* may be returned even if the operation has completed successfully. For
52+
* example, a successful response from a server could have been delayed
53+
* long.
54+
* HTTP 408
55+
*/
56+
DEADLINE_EXCEEDED = 4,
57+
/**
58+
* Some requested entity (e.g., file or directory) was not
59+
* found. Note to server developers: if a request is denied for an entire
60+
* class of users, such as gradual feature rollout or undocumented
61+
* allowlist, NOT_FOUND may be used. If a request is denied for some users
62+
* within a class of users, such as user-based access control,
63+
* PERMISSION_DENIED must be used.
64+
* HTTP 404
65+
*/
66+
NOT_FOUND = 5,
67+
/**
68+
* The entity that a client attempted to create (e.g., file
69+
* or directory) already exists.
70+
* HTTP 409
71+
*/
72+
ALREADY_EXISTS = 6,
73+
/**
74+
* The caller does not have permission to execute the
75+
* specified operation. PERMISSION_DENIED must not be used for rejections
76+
* caused by exhausting some resource (use RESOURCE_EXHAUSTED instead for
77+
* those errors). PERMISSION_DENIED must not be used if the caller can not
78+
* be identified (use UNAUTHENTICATED instead for those errors). This error
79+
* code does not imply the request is valid or the requested entity exists
80+
* or satisfies other pre-conditions.
81+
* HTTP 403
82+
*/
83+
PERMISSION_DENIED = 7,
84+
/**
85+
* Some resource has been exhausted, perhaps a per-user
86+
* quota, or perhaps the entire file system is out of space.
87+
* HTTP 413
88+
*/
89+
RESOURCE_EXHAUSTED = 8,
90+
/**
91+
* The operation was rejected because the system is
92+
* not in a state required for the operation's execution. For example, the
93+
* directory to be deleted is non-empty, an rmdir operation is applied to a
94+
* non-directory, etc. Service implementors can use the following guidelines
95+
* to decide between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: (a) Use
96+
* UNAVAILABLE if the client can retry just the failing call. (b) Use
97+
* ABORTED if the client should retry at a higher level (e.g., when a
98+
* client-specified test-and-set fails, indicating the client should restart
99+
* a read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client
100+
* should not retry until the system state has been explicitly fixed. E.g.,
101+
* if an "rmdir" fails because the directory is non-empty,
102+
* FAILED_PRECONDITION should be returned since the client should not retry
103+
* unless the files are deleted from the directory.
104+
* HTTP 412
105+
*/
106+
FAILED_PRECONDITION = 9,
107+
/**
108+
* The operation was aborted, typically due to a concurrency issue
109+
* such as a sequencer check failure or transaction abort. See the
110+
* guidelines above for deciding between FAILED_PRECONDITION, ABORTED, and
111+
* UNAVAILABLE.
112+
* HTTP 409
113+
*/
114+
ABORTED = 10,
115+
/**
116+
* The operation was attempted past the valid range. E.g.,
117+
* seeking or reading past end-of-file. Unlike INVALID_ARGUMENT, this error
118+
* indicates a problem that may be fixed if the system state changes. For
119+
* example, a 32-bit file system will generate INVALID_ARGUMENT if asked to
120+
* read at an offset that is not in the range [0,2^32-1], but it will
121+
* generate OUT_OF_RANGE if asked to read from an offset past the current
122+
* file size. There is a fair bit of overlap between FAILED_PRECONDITION and
123+
* OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
124+
* when it applies so that callers who are iterating through a space can
125+
* easily look for an OUT_OF_RANGE error to detect when they are done.
126+
* HTTP 400
127+
*/
128+
OUT_OF_RANGE = 11,
129+
/**
130+
* The operation is not implemented or is not
131+
* supported/enabled in this service.
132+
* HTTP 501
133+
*/
134+
UNIMPLEMENTED = 12,
135+
/**
136+
* Internal errors. This means that some invariants expected by
137+
* the underlying system have been broken. This error code is reserved for
138+
* serious errors.
139+
* HTTP 500
140+
*/
22141
INTERNAL = 13,
142+
/**
143+
* The service is currently unavailable. This is most likely a
144+
* transient condition, which can be corrected by retrying with a backoff.
145+
* Note that it is not always safe to retry non-idempotent operations.
146+
* HTTP 503
147+
*/
148+
UNAVAILABLE = 14,
149+
/**
150+
* Unrecoverable data loss or corruption.
151+
* HTTP 500
152+
*/
153+
DATA_LOSS = 15,
154+
/**
155+
* The request does not have valid authentication
156+
* credentials for the operation.
157+
* HTTP 401
158+
*/
159+
UNAUTHENTICATED = 16,
160+
}
161+
export enum RestateErrorCodes {
23162
JOURNAL_MISMATCH = 32,
24163
PROTOCOL_VIOLATION = 33,
25164
}
@@ -86,12 +225,12 @@ export class RetryableError extends RestateError {
86225
- In the replayed messages: type: ${
87226
replayMessage.messageType
88227
}, message: ${printMessageAsJson(replayMessage.message)}`;
89-
return new RetryableError(msg, { errorCode: ErrorCodes.JOURNAL_MISMATCH });
228+
return new RetryableError(msg, { errorCode: RestateErrorCodes.JOURNAL_MISMATCH });
90229
}
91230

92231
public static protocolViolation(message: string) {
93232
return new RetryableError(message, {
94-
errorCode: ErrorCodes.PROTOCOL_VIOLATION,
233+
errorCode: RestateErrorCodes.PROTOCOL_VIOLATION,
95234
});
96235
}
97236

test/protoutils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import {
5555
import { expect } from "@jest/globals";
5656
import { jsonSerialize, printMessageAsJson } from "../src/utils/utils";
5757
import { rlog } from "../src/utils/logger";
58-
import { ErrorCodes } from "../src/types/errors";
58+
import {ErrorCodes, RestateErrorCodes} from "../src/types/errors";
5959

6060
export function startMessage(
6161
knownEntries?: number,
@@ -426,7 +426,7 @@ export function checkError(
426426
export function checkJournalMismatchError(outputMsg: Message) {
427427
expect(outputMsg.messageType).toEqual(ERROR_MESSAGE_TYPE);
428428
expect((outputMsg.message as ErrorMessage).code).toStrictEqual(
429-
ErrorCodes.JOURNAL_MISMATCH
429+
RestateErrorCodes.JOURNAL_MISMATCH
430430
);
431431
expect((outputMsg.message as ErrorMessage).message).toContain(
432432
"Journal mismatch: Replayed journal entries did not correspond to the user code. The user code has to be deterministic!"

0 commit comments

Comments
 (0)