@restatedev/restate-sdk 0.7.3-worker → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +29 -51
  3. package/dist/clients/workflow_client.d.ts +77 -0
  4. package/dist/clients/workflow_client.d.ts.map +1 -0
  5. package/dist/clients/workflow_client.js +172 -0
  6. package/dist/clients/workflow_client.js.map +1 -0
  7. package/dist/connection/buffered_connection.js +44 -0
  8. package/dist/connection/buffered_connection.js.map +1 -0
  9. package/dist/connection/connection.js +13 -0
  10. package/dist/connection/connection.js.map +1 -0
  11. package/dist/connection/embedded_connection.js +59 -0
  12. package/dist/connection/embedded_connection.js.map +1 -0
  13. package/dist/connection/http_connection.js +203 -0
  14. package/dist/connection/http_connection.js.map +1 -0
  15. package/dist/connection/lambda_connection.js +58 -0
  16. package/dist/connection/lambda_connection.js.map +1 -0
  17. package/dist/{restate_context.d.ts → context.d.ts} +239 -170
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +113 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/{restate_context_impl.d.ts → context_impl.d.ts} +26 -30
  22. package/dist/context_impl.d.ts.map +1 -0
  23. package/dist/context_impl.js +439 -0
  24. package/dist/context_impl.js.map +1 -0
  25. package/dist/embedded/api.d.ts +2 -2
  26. package/dist/embedded/api.d.ts.map +1 -1
  27. package/dist/embedded/api.js +35 -0
  28. package/dist/embedded/api.js.map +1 -0
  29. package/dist/embedded/handler.d.ts +2 -2
  30. package/dist/embedded/handler.d.ts.map +1 -1
  31. package/dist/embedded/handler.js +26 -0
  32. package/dist/embedded/handler.js.map +1 -0
  33. package/dist/embedded/http2_remote.js +91 -0
  34. package/dist/embedded/http2_remote.js.map +1 -0
  35. package/dist/embedded/invocation.d.ts.map +1 -1
  36. package/dist/embedded/invocation.js +94 -0
  37. package/dist/embedded/invocation.js.map +1 -0
  38. package/dist/endpoint/endpoint_impl.d.ts +35 -0
  39. package/dist/endpoint/endpoint_impl.d.ts.map +1 -0
  40. package/dist/endpoint/endpoint_impl.js +405 -0
  41. package/dist/endpoint/endpoint_impl.js.map +1 -0
  42. package/dist/endpoint/http2_handler.d.ts +11 -0
  43. package/dist/endpoint/http2_handler.d.ts.map +1 -0
  44. package/dist/endpoint/http2_handler.js +119 -0
  45. package/dist/endpoint/http2_handler.js.map +1 -0
  46. package/dist/endpoint/lambda_handler.d.ts +15 -0
  47. package/dist/endpoint/lambda_handler.d.ts.map +1 -0
  48. package/dist/endpoint/lambda_handler.js +144 -0
  49. package/dist/endpoint/lambda_handler.js.map +1 -0
  50. package/dist/endpoint.d.ts +161 -0
  51. package/dist/endpoint.d.ts.map +1 -0
  52. package/dist/endpoint.js +22 -0
  53. package/dist/endpoint.js.map +1 -0
  54. package/dist/generated/dev/restate/events.js +371 -0
  55. package/dist/generated/dev/restate/events.js.map +1 -0
  56. package/dist/generated/dev/restate/ext.js +215 -0
  57. package/dist/generated/dev/restate/ext.js.map +1 -0
  58. package/dist/generated/google/protobuf/descriptor.js +6676 -0
  59. package/dist/generated/google/protobuf/descriptor.js.map +1 -0
  60. package/dist/generated/google/protobuf/empty.js +107 -0
  61. package/dist/generated/google/protobuf/empty.js.map +1 -0
  62. package/dist/generated/google/protobuf/struct.js +754 -0
  63. package/dist/generated/google/protobuf/struct.js.map +1 -0
  64. package/dist/generated/proto/discovery.js +364 -0
  65. package/dist/generated/proto/discovery.js.map +1 -0
  66. package/dist/generated/proto/dynrpc.js +668 -0
  67. package/dist/generated/proto/dynrpc.js.map +1 -0
  68. package/dist/generated/proto/javascript.d.ts +13 -0
  69. package/dist/generated/proto/javascript.d.ts.map +1 -1
  70. package/dist/generated/proto/javascript.js +416 -0
  71. package/dist/generated/proto/javascript.js.map +1 -0
  72. package/dist/generated/proto/protocol.d.ts +43 -0
  73. package/dist/generated/proto/protocol.d.ts.map +1 -1
  74. package/dist/generated/proto/protocol.js +2641 -0
  75. package/dist/generated/proto/protocol.js.map +1 -0
  76. package/dist/generated/proto/services.js +1535 -0
  77. package/dist/generated/proto/services.js.map +1 -0
  78. package/dist/generated/proto/test.js +321 -0
  79. package/dist/generated/proto/test.js.map +1 -0
  80. package/dist/invocation.d.ts +4 -1
  81. package/dist/invocation.d.ts.map +1 -1
  82. package/dist/invocation.js +157 -0
  83. package/dist/invocation.js.map +1 -0
  84. package/dist/io/decoder.d.ts +1 -0
  85. package/dist/io/decoder.d.ts.map +1 -1
  86. package/dist/io/decoder.js +140 -0
  87. package/dist/io/decoder.js.map +1 -0
  88. package/dist/io/encoder.d.ts +1 -2
  89. package/dist/io/encoder.d.ts.map +1 -1
  90. package/dist/io/encoder.js +68 -0
  91. package/dist/io/encoder.js.map +1 -0
  92. package/dist/journal.d.ts +13 -4
  93. package/dist/journal.d.ts.map +1 -1
  94. package/dist/journal.js +405 -0
  95. package/dist/journal.js.map +1 -0
  96. package/dist/local_state_store.d.ts +5 -3
  97. package/dist/local_state_store.d.ts.map +1 -1
  98. package/dist/local_state_store.js +82 -0
  99. package/dist/local_state_store.js.map +1 -0
  100. package/dist/logger.d.ts +19 -0
  101. package/dist/logger.d.ts.map +1 -0
  102. package/dist/logger.js +90 -0
  103. package/dist/logger.js.map +1 -0
  104. package/dist/promise_combinator_tracker.d.ts +29 -0
  105. package/dist/promise_combinator_tracker.d.ts.map +1 -0
  106. package/dist/promise_combinator_tracker.js +128 -0
  107. package/dist/promise_combinator_tracker.js.map +1 -0
  108. package/dist/public_api.d.ts +5 -5
  109. package/dist/public_api.d.ts.map +1 -1
  110. package/dist/public_api.js +60 -0
  111. package/dist/public_api.js.map +1 -0
  112. package/dist/state_machine.d.ts +19 -12
  113. package/dist/state_machine.d.ts.map +1 -1
  114. package/dist/state_machine.js +437 -0
  115. package/dist/state_machine.js.map +1 -0
  116. package/dist/types/errors.d.ts +12 -3
  117. package/dist/types/errors.d.ts.map +1 -1
  118. package/dist/types/errors.js +273 -0
  119. package/dist/types/errors.js.map +1 -0
  120. package/dist/types/grpc.d.ts +6 -4
  121. package/dist/types/grpc.d.ts.map +1 -1
  122. package/dist/types/grpc.js +81 -0
  123. package/dist/types/grpc.js.map +1 -0
  124. package/dist/types/protocol.d.ts +9 -5
  125. package/dist/types/protocol.d.ts.map +1 -1
  126. package/dist/types/protocol.js +147 -0
  127. package/dist/types/protocol.js.map +1 -0
  128. package/dist/types/router.d.ts +8 -8
  129. package/dist/types/router.d.ts.map +1 -1
  130. package/dist/types/router.js +36 -0
  131. package/dist/types/router.js.map +1 -0
  132. package/dist/types/types.d.ts +1 -0
  133. package/dist/types/types.d.ts.map +1 -1
  134. package/dist/types/types.js +138 -0
  135. package/dist/types/types.js.map +1 -0
  136. package/dist/utils/{assumpsions.d.ts → assumptions.d.ts} +1 -1
  137. package/dist/utils/{assumpsions.d.ts.map → assumptions.d.ts.map} +1 -1
  138. package/dist/utils/assumptions.js +101 -0
  139. package/dist/utils/assumptions.js.map +1 -0
  140. package/dist/utils/message_logger.d.ts +28 -0
  141. package/dist/utils/message_logger.d.ts.map +1 -0
  142. package/dist/utils/message_logger.js +88 -0
  143. package/dist/utils/message_logger.js.map +1 -0
  144. package/dist/utils/promises.d.ts +15 -0
  145. package/dist/utils/promises.d.ts.map +1 -0
  146. package/dist/utils/promises.js +67 -0
  147. package/dist/utils/promises.js.map +1 -0
  148. package/dist/utils/public_utils.js +49 -0
  149. package/dist/utils/public_utils.js.map +1 -0
  150. package/dist/utils/rand.d.ts +1 -1
  151. package/dist/utils/rand.d.ts.map +1 -1
  152. package/dist/utils/rand.js +114 -0
  153. package/dist/utils/rand.js.map +1 -0
  154. package/dist/utils/utils.d.ts +1 -10
  155. package/dist/utils/utils.d.ts.map +1 -1
  156. package/dist/utils/utils.js +122 -0
  157. package/dist/utils/utils.js.map +1 -0
  158. package/dist/workflows/workflow.d.ts +101 -0
  159. package/dist/workflows/workflow.d.ts.map +1 -0
  160. package/dist/workflows/workflow.js +80 -0
  161. package/dist/workflows/workflow.js.map +1 -0
  162. package/dist/workflows/workflow_state_service.d.ts +35 -0
  163. package/dist/workflows/workflow_state_service.d.ts.map +1 -0
  164. package/dist/workflows/workflow_state_service.js +201 -0
  165. package/dist/workflows/workflow_state_service.js.map +1 -0
  166. package/dist/workflows/workflow_wrapper_service.d.ts +10 -0
  167. package/dist/workflows/workflow_wrapper_service.d.ts.map +1 -0
  168. package/dist/workflows/workflow_wrapper_service.js +264 -0
  169. package/dist/workflows/workflow_wrapper_service.js.map +1 -0
  170. package/package.json +38 -39
  171. package/src/clients/workflow_client.ts +290 -0
  172. package/src/connection/buffered_connection.ts +47 -0
  173. package/src/connection/connection.ts +34 -0
  174. package/src/connection/embedded_connection.ts +62 -0
  175. package/src/connection/http_connection.ts +228 -0
  176. package/src/connection/lambda_connection.ts +69 -0
  177. package/src/context.ts +633 -0
  178. package/src/context_impl.ts +721 -0
  179. package/src/embedded/api.ts +57 -0
  180. package/src/embedded/handler.ts +36 -0
  181. package/src/embedded/http2_remote.ts +103 -0
  182. package/src/embedded/invocation.ts +126 -0
  183. package/src/endpoint/endpoint_impl.ts +623 -0
  184. package/src/endpoint/http2_handler.ts +151 -0
  185. package/src/endpoint/lambda_handler.ts +181 -0
  186. package/src/endpoint.ts +187 -0
  187. package/src/generated/dev/restate/events.ts +430 -0
  188. package/src/generated/dev/restate/ext.ts +238 -0
  189. package/src/generated/google/protobuf/descriptor.ts +7889 -0
  190. package/src/generated/google/protobuf/empty.ts +150 -0
  191. package/src/generated/google/protobuf/struct.ts +878 -0
  192. package/src/generated/proto/discovery.ts +423 -0
  193. package/src/generated/proto/dynrpc.ts +768 -0
  194. package/src/generated/proto/javascript.ts +488 -0
  195. package/src/generated/proto/protocol.ts +3091 -0
  196. package/src/generated/proto/services.ts +1834 -0
  197. package/src/generated/proto/test.ts +387 -0
  198. package/src/invocation.ts +212 -0
  199. package/src/io/decoder.ts +171 -0
  200. package/src/io/encoder.ts +72 -0
  201. package/src/journal.ts +537 -0
  202. package/src/local_state_store.ts +94 -0
  203. package/src/logger.ts +121 -0
  204. package/src/promise_combinator_tracker.ts +191 -0
  205. package/src/public_api.ts +53 -0
  206. package/src/state_machine.ts +635 -0
  207. package/src/types/errors.ts +297 -0
  208. package/src/types/grpc.ts +97 -0
  209. package/src/types/protocol.ts +201 -0
  210. package/src/types/router.ts +118 -0
  211. package/src/types/types.ts +160 -0
  212. package/src/utils/assumptions.ts +131 -0
  213. package/src/utils/message_logger.ts +112 -0
  214. package/src/utils/promises.ts +118 -0
  215. package/src/utils/public_utils.ts +91 -0
  216. package/src/utils/rand.ts +142 -0
  217. package/src/utils/utils.ts +178 -0
  218. package/src/workflows/workflow.ts +178 -0
  219. package/src/workflows/workflow_state_service.ts +299 -0
  220. package/src/workflows/workflow_wrapper_service.ts +314 -0
  221. package/dist/cloudflare_bundle.js +0 -27387
  222. package/dist/restate_context.d.ts.map +0 -1
  223. package/dist/restate_context_impl.d.ts.map +0 -1
  224. package/dist/server/base_restate_server.d.ts +0 -32
  225. package/dist/server/base_restate_server.d.ts.map +0 -1
  226. package/dist/server/restate_lambda_handler.d.ts +0 -104
  227. package/dist/server/restate_lambda_handler.d.ts.map +0 -1
  228. package/dist/server/restate_server.d.ts +0 -97
  229. package/dist/server/restate_server.d.ts.map +0 -1
  230. package/dist/utils/logger.d.ts +0 -60
  231. package/dist/utils/logger.d.ts.map +0 -1
@@ -0,0 +1,297 @@
1
+ /*
2
+ * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH
3
+ *
4
+ * This file is part of the Restate SDK for Node.js/TypeScript,
5
+ * which is released under the MIT license.
6
+ *
7
+ * You can find a copy of the license in file LICENSE in the root
8
+ * directory of this repository or package, or at
9
+ * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
10
+ */
11
+
12
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
+
14
+ import { ErrorMessage, Failure } from "../generated/proto/protocol";
15
+ import { formatMessageAsJson } from "../utils/utils";
16
+ import { FailureWithTerminal } from "../generated/proto/javascript";
17
+ import * as p from "./protocol";
18
+
19
+ export enum ErrorCodes {
20
+ /**
21
+ * Not an error; returned on success.
22
+ * HTTP 200
23
+ */
24
+ OK = 0,
25
+ /**
26
+ * The operation was cancelled, typically by the caller.
27
+ * HTTP 408
28
+ */
29
+ CANCELLED = 1,
30
+ /**
31
+ * Unknown error. For example, this error may be returned when a
32
+ * Status value received from another address space belongs to an error
33
+ * space that is not known in this address space. Also errors raised by APIs
34
+ * that do not return enough error information may be converted to this
35
+ * error.
36
+ * HTTP 500
37
+ */
38
+ UNKNOWN = 2,
39
+ /**
40
+ * The client specified an invalid argument. Note that
41
+ * this differs from FAILED_PRECONDITION. INVALID_ARGUMENT indicates
42
+ * arguments that are problematic regardless of the state of the system
43
+ * (e.g., a malformed file name).
44
+ * HTTP 400
45
+ */
46
+ INVALID_ARGUMENT = 3,
47
+ /**
48
+ * The deadline expired before the operation could
49
+ * complete. For operations that change the state of the system, this error
50
+ * may be returned even if the operation has completed successfully. For
51
+ * example, a successful response from a server could have been delayed
52
+ * long.
53
+ * HTTP 408
54
+ */
55
+ DEADLINE_EXCEEDED = 4,
56
+ /**
57
+ * Some requested entity (e.g., file or directory) was not
58
+ * found. Note to server developers: if a request is denied for an entire
59
+ * class of users, such as gradual feature rollout or undocumented
60
+ * allowlist, NOT_FOUND may be used. If a request is denied for some users
61
+ * within a class of users, such as user-based access control,
62
+ * PERMISSION_DENIED must be used.
63
+ * HTTP 404
64
+ */
65
+ NOT_FOUND = 5,
66
+ /**
67
+ * The entity that a client attempted to create (e.g., file
68
+ * or directory) already exists.
69
+ * HTTP 409
70
+ */
71
+ ALREADY_EXISTS = 6,
72
+ /**
73
+ * The caller does not have permission to execute the
74
+ * specified operation. PERMISSION_DENIED must not be used for rejections
75
+ * caused by exhausting some resource (use RESOURCE_EXHAUSTED instead for
76
+ * those errors). PERMISSION_DENIED must not be used if the caller can not
77
+ * be identified (use UNAUTHENTICATED instead for those errors). This error
78
+ * code does not imply the request is valid or the requested entity exists
79
+ * or satisfies other pre-conditions.
80
+ * HTTP 403
81
+ */
82
+ PERMISSION_DENIED = 7,
83
+ /**
84
+ * Some resource has been exhausted, perhaps a per-user
85
+ * quota, or perhaps the entire file system is out of space.
86
+ * HTTP 413
87
+ */
88
+ RESOURCE_EXHAUSTED = 8,
89
+ /**
90
+ * The operation was rejected because the system is
91
+ * not in a state required for the operation's execution. For example, the
92
+ * directory to be deleted is non-empty, an rmdir operation is applied to a
93
+ * non-directory, etc. Service implementors can use the following guidelines
94
+ * to decide between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: (a) Use
95
+ * UNAVAILABLE if the client can retry just the failing call. (b) Use
96
+ * ABORTED if the client should retry at a higher level (e.g., when a
97
+ * client-specified test-and-set fails, indicating the client should restart
98
+ * a read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client
99
+ * should not retry until the system state has been explicitly fixed. E.g.,
100
+ * if an "rmdir" fails because the directory is non-empty,
101
+ * FAILED_PRECONDITION should be returned since the client should not retry
102
+ * unless the files are deleted from the directory.
103
+ * HTTP 412
104
+ */
105
+ FAILED_PRECONDITION = 9,
106
+ /**
107
+ * The operation was aborted, typically due to a concurrency issue
108
+ * such as a sequencer check failure or transaction abort. See the
109
+ * guidelines above for deciding between FAILED_PRECONDITION, ABORTED, and
110
+ * UNAVAILABLE.
111
+ * HTTP 409
112
+ */
113
+ ABORTED = 10,
114
+ /**
115
+ * The operation was attempted past the valid range. E.g.,
116
+ * seeking or reading past end-of-file. Unlike INVALID_ARGUMENT, this error
117
+ * indicates a problem that may be fixed if the system state changes. For
118
+ * example, a 32-bit file system will generate INVALID_ARGUMENT if asked to
119
+ * read at an offset that is not in the range [0,2^32-1], but it will
120
+ * generate OUT_OF_RANGE if asked to read from an offset past the current
121
+ * file size. There is a fair bit of overlap between FAILED_PRECONDITION and
122
+ * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
123
+ * when it applies so that callers who are iterating through a space can
124
+ * easily look for an OUT_OF_RANGE error to detect when they are done.
125
+ * HTTP 400
126
+ */
127
+ OUT_OF_RANGE = 11,
128
+ /**
129
+ * The operation is not implemented or is not
130
+ * supported/enabled in this service.
131
+ * HTTP 501
132
+ */
133
+ UNIMPLEMENTED = 12,
134
+ /**
135
+ * Internal errors. This means that some invariants expected by
136
+ * the underlying system have been broken. This error code is reserved for
137
+ * serious errors.
138
+ * HTTP 500
139
+ */
140
+ INTERNAL = 13,
141
+ /**
142
+ * The service is currently unavailable. This is most likely a
143
+ * transient condition, which can be corrected by retrying with a backoff.
144
+ * Note that it is not always safe to retry non-idempotent operations.
145
+ * HTTP 503
146
+ */
147
+ UNAVAILABLE = 14,
148
+ /**
149
+ * Unrecoverable data loss or corruption.
150
+ * HTTP 500
151
+ */
152
+ DATA_LOSS = 15,
153
+ /**
154
+ * The request does not have valid authentication
155
+ * credentials for the operation.
156
+ * HTTP 401
157
+ */
158
+ UNAUTHENTICATED = 16,
159
+ }
160
+ export enum RestateErrorCodes {
161
+ JOURNAL_MISMATCH = 32,
162
+ PROTOCOL_VIOLATION = 33,
163
+ }
164
+
165
+ export function ensureError(e: unknown): Error {
166
+ if (e instanceof Error) {
167
+ return e;
168
+ }
169
+
170
+ let msg;
171
+ try {
172
+ msg = JSON.stringify(e);
173
+ } catch (x) {
174
+ msg = "(no JSON representation)";
175
+ }
176
+
177
+ return new Error("Non-Error value: " + msg);
178
+ }
179
+
180
+ export class RestateError extends Error {
181
+ public readonly code: number;
182
+
183
+ constructor(message: string, options?: { errorCode?: number; cause?: any }) {
184
+ super(message, { cause: options?.cause });
185
+ this.code = options?.errorCode ?? ErrorCodes.INTERNAL;
186
+ }
187
+
188
+ public toFailure(): Failure {
189
+ return Failure.create({
190
+ code: this.code,
191
+ message: this.message,
192
+ });
193
+ }
194
+ }
195
+
196
+ // Does not lead to Restate retries
197
+ // Leads to an output message with a failure defined
198
+ export class TerminalError extends RestateError {
199
+ constructor(message: string, options?: { errorCode?: number; cause?: any }) {
200
+ super(message, options);
201
+ }
202
+ }
203
+
204
+ export class TimeoutError extends TerminalError {
205
+ constructor() {
206
+ super("Timeout occurred", { errorCode: ErrorCodes.DEADLINE_EXCEEDED });
207
+ }
208
+ }
209
+
210
+ // Leads to Restate retries
211
+ export class RetryableError extends RestateError {
212
+ constructor(message: string, options?: { errorCode?: number; cause?: any }) {
213
+ super(message, options);
214
+ }
215
+
216
+ public static internal(message: string) {
217
+ return new RetryableError(message);
218
+ }
219
+
220
+ public static journalMismatch(
221
+ journalIndex: number,
222
+ actualEntry: {
223
+ messageType: bigint;
224
+ message: p.ProtocolMessage | Uint8Array;
225
+ },
226
+ expectedEntry: {
227
+ messageType: bigint;
228
+ message: p.ProtocolMessage | Uint8Array;
229
+ }
230
+ ) {
231
+ const msg = `Journal mismatch: Replayed journal entries did not correspond to the user code. The user code has to be deterministic!
232
+ The journal entry at position ${journalIndex} was:
233
+ - In the user code: type: ${
234
+ expectedEntry.messageType
235
+ }, message:${formatMessageAsJson(expectedEntry.message)}
236
+ - In the replayed messages: type: ${
237
+ actualEntry.messageType
238
+ }, message: ${formatMessageAsJson(actualEntry.message)}`;
239
+ return new RetryableError(msg, {
240
+ errorCode: RestateErrorCodes.JOURNAL_MISMATCH,
241
+ });
242
+ }
243
+
244
+ public static protocolViolation(message: string) {
245
+ return new RetryableError(message, {
246
+ errorCode: RestateErrorCodes.PROTOCOL_VIOLATION,
247
+ });
248
+ }
249
+
250
+ public static apiViolation(message: string) {
251
+ return new RetryableError(`API violation: ${message}`, {
252
+ errorCode: ErrorCodes.INTERNAL,
253
+ });
254
+ }
255
+ }
256
+
257
+ export function errorToFailure(err: Error): Failure {
258
+ return err instanceof RestateError
259
+ ? err.toFailure()
260
+ : Failure.create({
261
+ code: ErrorCodes.INTERNAL,
262
+ message: err.message,
263
+ });
264
+ }
265
+
266
+ export function errorToFailureWithTerminal(err: Error): FailureWithTerminal {
267
+ const failure = errorToFailure(err);
268
+ return FailureWithTerminal.create({
269
+ failure,
270
+ terminal: err instanceof TerminalError,
271
+ });
272
+ }
273
+
274
+ export function failureToTerminalError(failure: Failure): TerminalError {
275
+ return failureToError(failure, true) as TerminalError;
276
+ }
277
+
278
+ export function failureToError(
279
+ failure: Failure,
280
+ terminalError: boolean
281
+ ): Error {
282
+ const errorMessage = failure.message ?? "(missing error message)";
283
+ const errorCode = failure.code ?? ErrorCodes.INTERNAL;
284
+
285
+ return terminalError
286
+ ? new TerminalError(errorMessage, { errorCode })
287
+ : new RestateError(errorMessage, { errorCode });
288
+ }
289
+
290
+ export function errorToErrorMessage(err: Error): ErrorMessage {
291
+ const code = err instanceof RestateError ? err.code : ErrorCodes.INTERNAL;
292
+
293
+ return ErrorMessage.create({
294
+ code: code,
295
+ message: err.message,
296
+ });
297
+ }
@@ -0,0 +1,97 @@
1
+ /*
2
+ * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH
3
+ *
4
+ * This file is part of the Restate SDK for Node.js/TypeScript,
5
+ * which is released under the MIT license.
6
+ *
7
+ * You can find a copy of the license in file LICENSE in the root
8
+ * directory of this repository or package, or at
9
+ * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
10
+ */
11
+
12
+ import { Context } from "../context";
13
+ import { FileDescriptorProto } from "ts-proto-descriptors";
14
+
15
+ export class GrpcServiceMethod<I, O> {
16
+ constructor(
17
+ readonly name: string, // the gRPC name as defined in the .proto file
18
+ readonly localName: string, // the method name as defined in the class.
19
+ readonly keyedContext: boolean, // If the method expects a keyed context
20
+ readonly localFn: (instance: unknown, input: I) => Promise<O>, // the actual function
21
+ readonly inputDecoder: (buf: Uint8Array) => I, // the protobuf decoder
22
+ readonly outputEncoder: (output: O) => Uint8Array // protobuf encoder
23
+ ) {}
24
+ }
25
+
26
+ export class GrpcService {
27
+ constructor(
28
+ readonly name: string,
29
+ readonly packge: string,
30
+ readonly impl: object,
31
+ readonly methods: Array<GrpcServiceMethod<unknown, unknown>>
32
+ ) {}
33
+ }
34
+
35
+ export class HostedGrpcServiceMethod<I, O> {
36
+ constructor(
37
+ readonly instance: unknown,
38
+ readonly pkg: string,
39
+ readonly service: string,
40
+ readonly method: GrpcServiceMethod<I, O>
41
+ ) {}
42
+
43
+ // The end of an invoke is either a response (Uint8Array) or a SuspensionMessage
44
+ async invoke(context: Context, inBytes: Uint8Array): Promise<Uint8Array> {
45
+ const instanceWithContext = setContext(this.instance, context);
46
+ const input = this.method.inputDecoder(inBytes);
47
+ const result: O = await this.method.localFn(instanceWithContext, input);
48
+ return this.method.outputEncoder(result);
49
+ }
50
+ }
51
+
52
+ function setContext<T>(instance: T, context: Context): T {
53
+ // creates a *new*, per call object that shares all the properties that @instance has
54
+ // except '$$restate' which is a unique, per call pointer to a restate context.
55
+ //
56
+ // The following line create a new object, that its prototype is @instance.
57
+ // and that object has a $$restate property.
58
+ const wrapper = Object.create(instance as object, {
59
+ $$restate: { value: context },
60
+ });
61
+ return wrapper as T;
62
+ }
63
+
64
+ //
65
+ // The following definitions are equivalent to the ones
66
+ // generated by the protoc ts plugin.
67
+ // we use them to traverse the FileDescriptor
68
+ //
69
+ /* eslint-disable @typescript-eslint/no-explicit-any */
70
+ type ProtoMetaMessageOptions = {
71
+ options?: { [key: string]: any };
72
+ fields?: { [key: string]: { [key: string]: any } };
73
+ oneof?: { [key: string]: { [key: string]: any } };
74
+ nested?: { [key: string]: ProtoMetaMessageOptions };
75
+ };
76
+
77
+ export interface ProtoMetadata {
78
+ fileDescriptor: FileDescriptorProto;
79
+ references: { [key: string]: any };
80
+ dependencies?: ProtoMetadata[];
81
+ options?: {
82
+ options?: { [key: string]: any };
83
+ services?: {
84
+ [key: string]: {
85
+ options?: { [key: string]: any };
86
+ methods?: { [key: string]: { [key: string]: any } };
87
+ };
88
+ };
89
+ messages?: { [key: string]: ProtoMetaMessageOptions };
90
+ enums?: {
91
+ [key: string]: {
92
+ options?: { [key: string]: any };
93
+ values?: { [key: string]: { [key: string]: any } };
94
+ };
95
+ };
96
+ };
97
+ }
@@ -0,0 +1,201 @@
1
+ /*
2
+ * Copyright (c) 2023-2024 - Restate Software, Inc., Restate GmbH
3
+ *
4
+ * This file is part of the Restate SDK for Node.js/TypeScript,
5
+ * which is released under the MIT license.
6
+ *
7
+ * You can find a copy of the license in file LICENSE in the root
8
+ * directory of this repository or package, or at
9
+ * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
10
+ */
11
+
12
+ import {
13
+ SideEffectEntryMessage,
14
+ CombinatorEntryMessage,
15
+ } from "../generated/proto/javascript";
16
+ import {
17
+ AwakeableEntryMessage,
18
+ BackgroundInvokeEntryMessage,
19
+ ClearStateEntryMessage,
20
+ ClearAllStateEntryMessage,
21
+ CompleteAwakeableEntryMessage,
22
+ CompletionMessage,
23
+ EntryAckMessage,
24
+ ErrorMessage,
25
+ EndMessage,
26
+ GetStateEntryMessage,
27
+ GetStateKeysEntryMessage,
28
+ InvokeEntryMessage,
29
+ OutputStreamEntryMessage,
30
+ PollInputStreamEntryMessage,
31
+ SetStateEntryMessage,
32
+ SleepEntryMessage,
33
+ StartMessage,
34
+ SuspensionMessage,
35
+ } from "../generated/proto/protocol";
36
+
37
+ // Re-export the protobuf messages.
38
+ export {
39
+ AwakeableEntryMessage,
40
+ BackgroundInvokeEntryMessage,
41
+ ClearStateEntryMessage,
42
+ ClearAllStateEntryMessage,
43
+ CompleteAwakeableEntryMessage,
44
+ CompletionMessage,
45
+ ErrorMessage,
46
+ EndMessage,
47
+ GetStateEntryMessage,
48
+ GetStateKeysEntryMessage,
49
+ InvokeEntryMessage,
50
+ OutputStreamEntryMessage,
51
+ PollInputStreamEntryMessage,
52
+ SetStateEntryMessage,
53
+ SleepEntryMessage,
54
+ StartMessage,
55
+ SuspensionMessage,
56
+ EntryAckMessage,
57
+ } from "../generated/proto/protocol";
58
+
59
+ // Export the protocol message types as defined by the restate protocol.
60
+ export const START_MESSAGE_TYPE = 0x0000n;
61
+ export const COMPLETION_MESSAGE_TYPE = 0x0001n;
62
+ export const SUSPENSION_MESSAGE_TYPE = 0x0002n;
63
+ export const ERROR_MESSAGE_TYPE = 0x0003n;
64
+ export const ENTRY_ACK_MESSAGE_TYPE = 0x0004n;
65
+ export const END_MESSAGE_TYPE = 0x0005n;
66
+ export const POLL_INPUT_STREAM_ENTRY_MESSAGE_TYPE = 0x0400n;
67
+ export const OUTPUT_STREAM_ENTRY_MESSAGE_TYPE = 0x0401n;
68
+ export const GET_STATE_ENTRY_MESSAGE_TYPE = 0x0800n;
69
+ export const SET_STATE_ENTRY_MESSAGE_TYPE = 0x0801n;
70
+ export const CLEAR_STATE_ENTRY_MESSAGE_TYPE = 0x0802n;
71
+ export const CLEAR_ALL_STATE_ENTRY_MESSAGE_TYPE = 0x0803n;
72
+ export const GET_STATE_KEYS_ENTRY_MESSAGE_TYPE = 0x0804n;
73
+ export const SLEEP_ENTRY_MESSAGE_TYPE = 0x0c00n;
74
+ export const INVOKE_ENTRY_MESSAGE_TYPE = 0x0c01n;
75
+ export const BACKGROUND_INVOKE_ENTRY_MESSAGE_TYPE = 0x0c02n;
76
+ export const AWAKEABLE_ENTRY_MESSAGE_TYPE = 0x0c03n;
77
+ export const COMPLETE_AWAKEABLE_ENTRY_MESSAGE_TYPE = 0x0c04n;
78
+
79
+ export const AWAKEABLE_IDENTIFIER_PREFIX = "prom_1";
80
+
81
+ // Export the custom message types
82
+ // Side effects are custom messages because the runtime does not need to inspect them
83
+ export const SIDE_EFFECT_ENTRY_MESSAGE_TYPE = 0xfc01n;
84
+ export const COMBINATOR_ENTRY_MESSAGE = 0xfc02n;
85
+
86
+ // Restate DuplexStream
87
+
88
+ // Message types in the protocol.
89
+ // Custom message types (per SDK) such as side effect entry message should not be included here.
90
+ export const KNOWN_MESSAGE_TYPES = new Set([
91
+ START_MESSAGE_TYPE,
92
+ COMPLETION_MESSAGE_TYPE,
93
+ SUSPENSION_MESSAGE_TYPE,
94
+ ERROR_MESSAGE_TYPE,
95
+ ENTRY_ACK_MESSAGE_TYPE,
96
+ END_MESSAGE_TYPE,
97
+ POLL_INPUT_STREAM_ENTRY_MESSAGE_TYPE,
98
+ OUTPUT_STREAM_ENTRY_MESSAGE_TYPE,
99
+ GET_STATE_ENTRY_MESSAGE_TYPE,
100
+ GET_STATE_KEYS_ENTRY_MESSAGE_TYPE,
101
+ SET_STATE_ENTRY_MESSAGE_TYPE,
102
+ CLEAR_STATE_ENTRY_MESSAGE_TYPE,
103
+ CLEAR_ALL_STATE_ENTRY_MESSAGE_TYPE,
104
+ SLEEP_ENTRY_MESSAGE_TYPE,
105
+ INVOKE_ENTRY_MESSAGE_TYPE,
106
+ BACKGROUND_INVOKE_ENTRY_MESSAGE_TYPE,
107
+ AWAKEABLE_ENTRY_MESSAGE_TYPE,
108
+ COMPLETE_AWAKEABLE_ENTRY_MESSAGE_TYPE,
109
+ SIDE_EFFECT_ENTRY_MESSAGE_TYPE,
110
+ COMBINATOR_ENTRY_MESSAGE,
111
+ ]);
112
+
113
+ const PROTOBUF_MESSAGE_NAME_BY_TYPE = new Map<bigint, string>([
114
+ [START_MESSAGE_TYPE, "StartMessage"],
115
+ [COMPLETION_MESSAGE_TYPE, "CompletionMessage"],
116
+ [SUSPENSION_MESSAGE_TYPE, "SuspensionMessage"],
117
+ [ERROR_MESSAGE_TYPE, "ErrorMessage"],
118
+ [ENTRY_ACK_MESSAGE_TYPE, "EntryAckMessage"],
119
+ [END_MESSAGE_TYPE, "EndMessage"],
120
+ [POLL_INPUT_STREAM_ENTRY_MESSAGE_TYPE, "PollInputStreamEntryMessage"],
121
+ [OUTPUT_STREAM_ENTRY_MESSAGE_TYPE, "OutputStreamEntryMessage"],
122
+ [GET_STATE_ENTRY_MESSAGE_TYPE, "GetStateEntryMessage"],
123
+ [GET_STATE_KEYS_ENTRY_MESSAGE_TYPE, "GetStateKeysEntryMessage"],
124
+ [SET_STATE_ENTRY_MESSAGE_TYPE, "SetStateEntryMessage"],
125
+ [CLEAR_STATE_ENTRY_MESSAGE_TYPE, "ClearStateEntryMessage"],
126
+ [CLEAR_ALL_STATE_ENTRY_MESSAGE_TYPE, "ClearAllStateEntryMessage"],
127
+ [SLEEP_ENTRY_MESSAGE_TYPE, "SleepEntryMessage"],
128
+ [INVOKE_ENTRY_MESSAGE_TYPE, "InvokeEntryMessage"],
129
+ [BACKGROUND_INVOKE_ENTRY_MESSAGE_TYPE, "BackgroundInvokeEntryMessage"],
130
+ [AWAKEABLE_ENTRY_MESSAGE_TYPE, "AwakeableEntryMessage"],
131
+ [COMPLETE_AWAKEABLE_ENTRY_MESSAGE_TYPE, "CompleteAwakeableEntryMessage"],
132
+ [SIDE_EFFECT_ENTRY_MESSAGE_TYPE, "SideEffectEntryMessage"],
133
+ [COMBINATOR_ENTRY_MESSAGE, "CombinatorEntryMessage"],
134
+ ]);
135
+
136
+ export function formatMessageType(messageType: bigint) {
137
+ return (
138
+ PROTOBUF_MESSAGE_NAME_BY_TYPE.get(messageType) || messageType.toString()
139
+ );
140
+ }
141
+
142
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
143
+ const PROTOBUF_MESSAGES: Array<[bigint, any]> = [
144
+ [START_MESSAGE_TYPE, StartMessage],
145
+ [COMPLETION_MESSAGE_TYPE, CompletionMessage],
146
+ [SUSPENSION_MESSAGE_TYPE, SuspensionMessage],
147
+ [ERROR_MESSAGE_TYPE, ErrorMessage],
148
+ [ENTRY_ACK_MESSAGE_TYPE, EntryAckMessage],
149
+ [END_MESSAGE_TYPE, EndMessage],
150
+ [POLL_INPUT_STREAM_ENTRY_MESSAGE_TYPE, PollInputStreamEntryMessage],
151
+ [OUTPUT_STREAM_ENTRY_MESSAGE_TYPE, OutputStreamEntryMessage],
152
+ [GET_STATE_ENTRY_MESSAGE_TYPE, GetStateEntryMessage],
153
+ [GET_STATE_KEYS_ENTRY_MESSAGE_TYPE, GetStateKeysEntryMessage],
154
+ [SET_STATE_ENTRY_MESSAGE_TYPE, SetStateEntryMessage],
155
+ [CLEAR_STATE_ENTRY_MESSAGE_TYPE, ClearStateEntryMessage],
156
+ [CLEAR_ALL_STATE_ENTRY_MESSAGE_TYPE, ClearAllStateEntryMessage],
157
+ [SLEEP_ENTRY_MESSAGE_TYPE, SleepEntryMessage],
158
+ [INVOKE_ENTRY_MESSAGE_TYPE, InvokeEntryMessage],
159
+ [BACKGROUND_INVOKE_ENTRY_MESSAGE_TYPE, BackgroundInvokeEntryMessage],
160
+ [AWAKEABLE_ENTRY_MESSAGE_TYPE, AwakeableEntryMessage],
161
+ [COMPLETE_AWAKEABLE_ENTRY_MESSAGE_TYPE, CompleteAwakeableEntryMessage],
162
+ [SIDE_EFFECT_ENTRY_MESSAGE_TYPE, SideEffectEntryMessage],
163
+ [COMBINATOR_ENTRY_MESSAGE, CombinatorEntryMessage],
164
+ ];
165
+
166
+ export const PROTOBUF_MESSAGE_BY_TYPE = new Map(PROTOBUF_MESSAGES);
167
+
168
+ export type ProtocolMessage =
169
+ | StartMessage
170
+ | CompletionMessage
171
+ | SuspensionMessage
172
+ | ErrorMessage
173
+ | EntryAckMessage
174
+ | EndMessage
175
+ | PollInputStreamEntryMessage
176
+ | OutputStreamEntryMessage
177
+ | GetStateEntryMessage
178
+ | GetStateKeysEntryMessage
179
+ | SetStateEntryMessage
180
+ | ClearStateEntryMessage
181
+ | ClearAllStateEntryMessage
182
+ | SleepEntryMessage
183
+ | InvokeEntryMessage
184
+ | BackgroundInvokeEntryMessage
185
+ | AwakeableEntryMessage
186
+ | CompleteAwakeableEntryMessage
187
+ | SideEffectEntryMessage
188
+ | CombinatorEntryMessage;
189
+
190
+ // These message types will trigger sending a suspension message from the runtime
191
+ // for each of the protocol modes
192
+ export const SUSPENSION_TRIGGERS: bigint[] = [
193
+ INVOKE_ENTRY_MESSAGE_TYPE,
194
+ GET_STATE_ENTRY_MESSAGE_TYPE,
195
+ GET_STATE_KEYS_ENTRY_MESSAGE_TYPE,
196
+ AWAKEABLE_ENTRY_MESSAGE_TYPE,
197
+ SLEEP_ENTRY_MESSAGE_TYPE,
198
+ COMBINATOR_ENTRY_MESSAGE,
199
+ // We need it because of the ack
200
+ SIDE_EFFECT_ENTRY_MESSAGE_TYPE,
201
+ ];