@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,69 @@
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 { Connection } from "./connection";
13
+ import { encodeMessage } from "../io/encoder";
14
+ import {
15
+ ERROR_MESSAGE_TYPE,
16
+ OUTPUT_STREAM_ENTRY_MESSAGE_TYPE,
17
+ SUSPENSION_MESSAGE_TYPE,
18
+ } from "../types/protocol";
19
+ import { Message } from "../types/types";
20
+ import { rlog } from "../logger";
21
+
22
+ const RESOLVED: Promise<void> = Promise.resolve();
23
+
24
+ export class LambdaConnection implements Connection {
25
+ // Empty buffer to store journal output messages
26
+ private outputBuffer: Buffer = Buffer.alloc(0);
27
+
28
+ // Callback to resolve the invocation promise of the Lambda handler when the response is ready
29
+ private readonly completionPromise: Promise<Buffer>;
30
+ private resolveOnCompleted!: (value: Buffer | PromiseLike<Buffer>) => void;
31
+
32
+ constructor(private suspendedOrCompleted = false) {
33
+ // Promise that signals when the invocation is over, to then flush the messages
34
+ this.completionPromise = new Promise<Buffer>((resolve) => {
35
+ this.resolveOnCompleted = resolve;
36
+ });
37
+ }
38
+
39
+ // Send a message back to the runtime
40
+ send(msg: Message): Promise<void> {
41
+ // Add the header and the body to buffer and add to the output buffer
42
+ const msgBuffer = encodeMessage(msg);
43
+ this.outputBuffer = Buffer.concat([this.outputBuffer, msgBuffer]);
44
+
45
+ // An output message, suspension message or error message is the end of a Lambda invocation
46
+ if (
47
+ msg.messageType === OUTPUT_STREAM_ENTRY_MESSAGE_TYPE ||
48
+ msg.messageType === SUSPENSION_MESSAGE_TYPE ||
49
+ msg.messageType === ERROR_MESSAGE_TYPE
50
+ ) {
51
+ this.suspendedOrCompleted = true;
52
+ }
53
+
54
+ return RESOLVED;
55
+ }
56
+
57
+ getResult(): Promise<Buffer> {
58
+ return this.completionPromise;
59
+ }
60
+
61
+ end(): Promise<void> {
62
+ if (this.suspendedOrCompleted) {
63
+ rlog.debug("Flushing output buffer...");
64
+ this.resolveOnCompleted(this.outputBuffer);
65
+ }
66
+ this.outputBuffer = Buffer.alloc(0);
67
+ return RESOLVED;
68
+ }
69
+ }
package/src/context.ts ADDED
@@ -0,0 +1,633 @@
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 { RetrySettings } from "./utils/public_utils";
13
+ import { Client, SendClient } from "./types/router";
14
+ import { ContextImpl } from "./context_impl";
15
+
16
+ /**
17
+ * Key value store operations. Only keyed services have an attached key-value store.
18
+ */
19
+ export interface KeyValueStore {
20
+ /**
21
+ * Get/retrieve state from the Restate runtime.
22
+ * Note that state objects are serialized with `Buffer.from(JSON.stringify(theObject))`
23
+ * and deserialized with `JSON.parse(value.toString()) as T`.
24
+ *
25
+ * @param name key of the state to retrieve
26
+ * @returns a Promise that is resolved with the value of the state key
27
+ *
28
+ * @example
29
+ * const ctx = restate.useContext(this);
30
+ * const state = await ctx.get<string>("STATE");
31
+ */
32
+ get<T>(name: string): Promise<T | null>;
33
+
34
+ stateKeys(): Promise<Array<string>>;
35
+
36
+ /**
37
+ * Set/store state in the Restate runtime.
38
+ * Note that state objects are serialized with `Buffer.from(JSON.stringify(theObject))`
39
+ * and deserialized with `JSON.parse(value.toString()) as T`.
40
+ *
41
+ * @param name key of the state to set
42
+ * @param value value to set
43
+ *
44
+ * @example
45
+ * const ctx = restate.useContext(this);
46
+ * ctx.set("STATE", "Hello");
47
+ */
48
+ set<T>(name: string, value: T): void;
49
+
50
+ /**
51
+ * Clear/delete state in the Restate runtime.
52
+ * @param name key of the state to delete
53
+ *
54
+ * @example
55
+ * const ctx = restate.useContext(this);
56
+ * ctx.clear("STATE");
57
+ */
58
+ clear(name: string): void;
59
+
60
+ /**
61
+ * Clear/delete all the state entries in the Restate runtime.
62
+ *
63
+ * @example
64
+ * const ctx = restate.useContext(this);
65
+ * ctx.clearAll();
66
+ */
67
+ clearAll(): void;
68
+ }
69
+
70
+ /**
71
+ * The context that gives access to all Restate-backed operations, for example
72
+ * - sending reliable messages / RPC through Restate
73
+ * - side effects
74
+ * - sleeps and delayed calls
75
+ * - awakeables
76
+ * - ...
77
+ *
78
+ * Keyed services can also access their key-value store using the {@link KeyedContext}.
79
+ *
80
+ * In gRPC-based API, to access this context, use {@link useContext}.
81
+ */
82
+ export interface Context {
83
+ /**
84
+ * The unique id that identifies the current function invocation. This id is guaranteed to be
85
+ * unique across invocations, but constant across reties and suspensions.
86
+ */
87
+ id: Buffer;
88
+
89
+ /**
90
+ * Name of the service.
91
+ */
92
+ serviceName: string;
93
+
94
+ /**
95
+ * Deterministic random methods; these are inherently predictable (seeded on the invocation ID, which is not secret)
96
+ * and so should not be used for any cryptographic purposes. They are useful for identifiers, idempotency keys,
97
+ * and for uniform sampling from a set of options. If a cryptographically secure value is needed, please generate that
98
+ * externally and capture the result with a side effect.
99
+ *
100
+ * Calls to these methods from inside side effects are disallowed and will fail - side effects must be idempotent, and
101
+ * these calls are not.
102
+ */
103
+ rand: Rand;
104
+
105
+ /**
106
+ * Console to use for logging. It attaches to each log message some contextual information,
107
+ * such as invoked service method and invocation id, and automatically excludes logs during replay.
108
+ */
109
+ console: Console;
110
+
111
+ /**
112
+ * Execute a side effect and store the result in Restate. The side effect will thus not
113
+ * be re-executed during a later replay, but take the durable result from Restate.
114
+ *
115
+ * Side effects let you capture potentially non-deterministic computation and interaction
116
+ * with external systems in a safe way.
117
+ *
118
+ * Failure semantics of side effects are:
119
+ * - If a side effect executed and persisted before, the result (value or Error) will be
120
+ * taken from the Restate journal.
121
+ * - There is a small window where a side effect may be re-executed twice, if a failure
122
+ * occurred between execution and persisting the result.
123
+ * - No second side effect will be executed while a previous side effect's result is not
124
+ * yet durable. That way, side effects that build on top of each other can assume
125
+ * deterministic results from previous effects, and at most one side effect will be
126
+ * re-executed on replay (the latest, if the failure happened in the small windows
127
+ * described above).
128
+ *
129
+ * This function takes an optional retry policy, that determines what happens if the
130
+ * side effect throws an error. The default retry policy retries infinitely, with exponential
131
+ * backoff and uses suspending sleep for the wait times between retries.
132
+ *
133
+ * @example
134
+ * const ctx = restate.useContext(this);
135
+ * const result = await ctx.sideEffect(async () => someExternalAction() )
136
+ *
137
+ * @example
138
+ * const paymentAction = async () => {
139
+ * const result = await paymentClient.call(txId, methodIdentifier, amount);
140
+ * if (result.error) {
141
+ * throw result.error;
142
+ * } else {
143
+ * return result.payment_accepted;
144
+ * }
145
+ * }
146
+ * const paymentAccepted: boolean =
147
+ * await ctx.sideEffect(paymentAction, { maxRetries: 10});
148
+ *
149
+ * @param fn The function to run as a side effect.
150
+ * @param retryPolicy The optional policy describing how retries happen.
151
+ */
152
+ sideEffect<T>(fn: () => Promise<T>, retryPolicy?: RetrySettings): Promise<T>;
153
+
154
+ /**
155
+ * Register an awakeable and pause the processing until the awakeable ID (and optional payload) have been returned to the service
156
+ * (via ctx.completeAwakeable(...)). The SDK deserializes the payload with `JSON.parse(result.toString()) as T`.
157
+ * @returns
158
+ * - id: the string ID that has to be used to complete the awakaeble by some external service
159
+ * - promise: the Promise that needs to be awaited and that is resolved with the payload that was supplied by the service which completed the awakeable
160
+ *
161
+ * @example
162
+ * const ctx = restate.useContext(this);
163
+ * const awakeable = ctx.awakeable<string>();
164
+ *
165
+ * // send the awakeable ID to some external service that will wake this one back up
166
+ * // The ID can be retrieved by:
167
+ * const id = awakeable.id;
168
+ *
169
+ * // ... send to external service ...
170
+ *
171
+ * // Wait for the external service to wake this service back up
172
+ * const result = await awakeable.promise;
173
+ */
174
+ awakeable<T>(): { id: string; promise: CombineablePromise<T> };
175
+
176
+ /**
177
+ * Resolve an awakeable of another service.
178
+ * @param id the string ID of the awakeable.
179
+ * This is supplied by the service that needs to be woken up.
180
+ * @param payload the payload to pass to the service that is woken up.
181
+ * The SDK serializes the payload with `Buffer.from(JSON.stringify(payload))`
182
+ * and deserializes it in the receiving service with `JSON.parse(result.toString()) as T`.
183
+ *
184
+ * @example
185
+ * const ctx = restate.useContext(this);
186
+ * // The sleeping service should have sent the awakeableIdentifier string to this service.
187
+ * ctx.resolveAwakeable(awakeableIdentifier, "hello");
188
+ */
189
+ resolveAwakeable<T>(id: string, payload?: T): void;
190
+
191
+ /**
192
+ * Reject an awakeable of another service. When rejecting, the service waiting on this awakeable will be woken up with a terminal error with the provided reason.
193
+ * @param id the string ID of the awakeable.
194
+ * This is supplied by the service that needs to be woken up.
195
+ * @param reason the reason of the rejection.
196
+ *
197
+ * @example
198
+ * const ctx = restate.useContext(this);
199
+ * // The sleeping service should have sent the awakeableIdentifier string to this service.
200
+ * ctx.rejectAwakeable(awakeableIdentifier, "super bad error");
201
+ */
202
+ rejectAwakeable(id: string, reason: string): void;
203
+
204
+ /**
205
+ * Sleep until a timeout has passed.
206
+ * @param millis duration of the sleep in millis.
207
+ * This is a lower-bound.
208
+ *
209
+ * @example
210
+ * const ctx = restate.useContext(this);
211
+ * await ctx.sleep(1000);
212
+ */
213
+ sleep(millis: number): CombineablePromise<void>;
214
+
215
+ /**
216
+ * Makes a type-safe request/response RPC to the specified target service.
217
+ *
218
+ * The RPC goes through Restate and is guaranteed to be reliably delivered. The RPC is also
219
+ * journaled for durable execution and will thus not be duplicated when the handler is re-invoked
220
+ * for retries or after suspending.
221
+ *
222
+ * This call will return the result produced by the target handler, or the Error, if the target
223
+ * handler finishes with a Terminal Error.
224
+ *
225
+ * This call is a suspension point: The handler might suspend while awaiting the response and
226
+ * resume once the response is available.
227
+ *
228
+ * @example
229
+ * *Service Side:*
230
+ * ```ts
231
+ * const router = restate.router({
232
+ * someAction: async(ctx: restate.RpcContext, req: string) => { ... },
233
+ * anotherAction: async(ctx: restate.RpcContext, count: number) => { ... }
234
+ * });
235
+ *
236
+ * // option 1: export only the type signature of the router
237
+ * export type myApiType = typeof router;
238
+ *
239
+ * // option 2: export the API definition with type and name (path)
240
+ * export const myApi: restate.ServiceApi<typeof router> = { path : "myservice" };
241
+ *
242
+ * restate.createServer().bindRouter("myservice", router).listen(9080);
243
+ * ```
244
+ * **Client side:**
245
+ * ```ts
246
+ * // option 1: use only types and supply service name separately
247
+ * const result1 = await ctx.rpc<myApiType>({path: "myservice"}).someAction("hello!");
248
+ *
249
+ * // option 2: use full API spec
250
+ * const result2 = await ctx.rpc(myApi).anotherAction(1337);
251
+ * ```
252
+ */
253
+ rpc<M>(opts: ServiceApi<M>): Client<M>;
254
+
255
+ /**
256
+ * Makes a type-safe one-way RPC to the specified target service. This method effectively behaves
257
+ * like enqueuing the message in a message queue.
258
+ *
259
+ * The message goes through Restate and is guaranteed to be reliably delivered. The RPC is also
260
+ * journaled for durable execution and will thus not be duplicated when the handler is re-invoked
261
+ * for retries or after suspending.
262
+ *
263
+ * This call will return immediately; the message sending happens asynchronously in the background.
264
+ * Despite that, the message is guaranteed to be sent, because the completion of the invocation that
265
+ * triggers the send (calls this function) happens logically after the sending. That means that any
266
+ * failure where the message does not reach Restate also cannot complete this invocation, and will
267
+ * hence recover this handler and (through the durable execution) recover the message to be sent.
268
+ *
269
+ * @example
270
+ * *Service Side:*
271
+ * ```ts
272
+ * const router = restate.router({
273
+ * someAction: async(ctx: restate.RpcContext, req: string) => { ... },
274
+ * anotherAction: async(ctx: restate.RpcContext, count: number) => { ... }
275
+ * });
276
+ *
277
+ * // option 1: export only the type signature of the router
278
+ * export type myApiType = typeof router;
279
+ *
280
+ * // option 2: export the API definition with type and name (path)
281
+ * export const myApi: restate.ServiceApi<typeof router> = { path : "myservice" };
282
+ *
283
+ * restate.createServer().bindRouter("myservice", router).listen(9080);
284
+ * ```
285
+ * **Client side:**
286
+ * ```ts
287
+ * // option 1: use only types and supply service name separately
288
+ * ctx.send<myApiType>({path: "myservice"}).someAction("hello!");
289
+ *
290
+ * // option 2: use full API spec
291
+ * ctx.send(myApi).anotherAction(1337);
292
+ * ```
293
+ */
294
+ send<M>(opts: ServiceApi<M>): SendClient<M>;
295
+
296
+ /**
297
+ * Makes a type-safe one-way RPC to the specified target service, after a delay specified by the
298
+ * milliseconds' argument.
299
+ * This method is like stetting up a fault-tolerant cron job that enqueues the message in a
300
+ * message queue.
301
+ * The handler calling this function does not have to stay active for the delay time.
302
+ *
303
+ * Both the delay timer and the message are durably stored in Restate and guaranteed to be reliably
304
+ * delivered. The delivery happens no earlier than specified through the delay, but may happen
305
+ * later, if the target service is down, or backpressuring the system.
306
+ *
307
+ * The delay message is journaled for durable execution and will thus not be duplicated when the
308
+ * handler is re-invoked for retries or after suspending.
309
+ *
310
+ * This call will return immediately; the message sending happens asynchronously in the background.
311
+ * Despite that, the message is guaranteed to be sent, because the completion of the invocation that
312
+ * triggers the send (calls this function) happens logically after the sending. That means that any
313
+ * failure where the message does not reach Restate also cannot complete this invocation, and will
314
+ * hence recover this handler and (through the durable execution) recover the message to be sent.
315
+ *
316
+ * @example
317
+ * *Service Side:*
318
+ * ```ts
319
+ * const router = restate.router({
320
+ * someAction: async(ctx: restate.RpcContext, req: string) => { ... },
321
+ * anotherAction: async(ctx: restate.RpcContext, count: number) => { ... }
322
+ * });
323
+ *
324
+ * // option 1: export only the type signature of the router
325
+ * export type myApiType = typeof router;
326
+ *
327
+ * // option 2: export the API definition with type and name (path)
328
+ * export const myApi: restate.ServiceApi<typeof router> = { path : "myservice" };
329
+ *
330
+ * restate.createServer().bindRouter("myservice", router).listen(9080);
331
+ * ```
332
+ * **Client side:**
333
+ * ```ts
334
+ * // option 1: use only types and supply service name separately
335
+ * ctx.sendDelayed<myApiType>({path: "myservice"}, 60_000).someAction("hello!");
336
+ *
337
+ * // option 2: use full API spec
338
+ * ctx.sendDelayed(myApi, 60_000).anotherAction(1337);
339
+ * ```
340
+ */
341
+ sendDelayed<M>(opts: ServiceApi<M>, delay: number): SendClient<M>;
342
+
343
+ /**
344
+ * Get the {@link RestateGrpcChannel} to invoke gRPC based services.
345
+ */
346
+ grpcChannel(): RestateGrpcChannel;
347
+ }
348
+
349
+ /**
350
+ * The context that gives access to all Restate-backed operations, for example
351
+ * - sending reliable messages / RPC through Restate
352
+ * - access/update state
353
+ * - side effects
354
+ * - sleeps and delayed calls
355
+ * - awakeables
356
+ * - ...
357
+ *
358
+ * This context can be used only within keyed services/routers.
359
+ *
360
+ * In gRPC-based API, to access this context, use {@link useKeyedContext}.
361
+ */
362
+ export interface KeyedContext extends Context, KeyValueStore {}
363
+
364
+ export interface Rand {
365
+ /**
366
+ * Equivalent of JS `Math.random()` but deterministic; seeded by the invocation ID of the current invocation,
367
+ * each call will return a new pseudorandom float within the range [0,1)
368
+ */
369
+ random(): number;
370
+
371
+ /**
372
+ * Using the same random source and seed as random(), produce a UUID version 4 string. This is inherently predictable
373
+ * based on the invocation ID and should not be used in cryptographic contexts
374
+ */
375
+ uuidv4(): string;
376
+ }
377
+
378
+ /**
379
+ * A promise that can be combined using Promise combinators in RestateContext.
380
+ */
381
+ export type CombineablePromise<T> = Promise<T> & {
382
+ __restate_context: Context;
383
+
384
+ /**
385
+ * Creates a promise that awaits for the current promise up to the specified timeout duration.
386
+ * If the timeout is fired, this Promise will be rejected with a {@link TimeoutError}.
387
+ *
388
+ * @param millis duration of the sleep in millis.
389
+ * This is a lower-bound.
390
+ */
391
+ orTimeout(millis: number): Promise<T>;
392
+ };
393
+
394
+ export const CombineablePromise = {
395
+ /**
396
+ * Creates a Promise that is resolved with an array of results when all of the provided Promises
397
+ * resolve, or rejected when any Promise is rejected.
398
+ *
399
+ * See {@link Promise.all} for more details.
400
+ *
401
+ * @param values An iterable of Promises.
402
+ * @returns A new Promise.
403
+ */
404
+ all<T extends readonly CombineablePromise<unknown>[] | []>(
405
+ values: T
406
+ ): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }> {
407
+ if (values.length == 0) {
408
+ return Promise.all(values);
409
+ }
410
+
411
+ return (values[0].__restate_context as ContextImpl).createCombinator(
412
+ Promise.all.bind(Promise),
413
+ values
414
+ ) as Promise<{
415
+ -readonly [P in keyof T]: Awaited<T[P]>;
416
+ }>;
417
+ },
418
+
419
+ /**
420
+ * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
421
+ * or rejected.
422
+ *
423
+ * See {@link Promise.race} for more details.
424
+ *
425
+ * @param values An iterable of Promises.
426
+ * @returns A new Promise.
427
+ */
428
+ race<T extends readonly CombineablePromise<unknown>[] | []>(
429
+ values: T
430
+ ): Promise<Awaited<T[number]>> {
431
+ if (values.length == 0) {
432
+ return Promise.race(values);
433
+ }
434
+
435
+ return (values[0].__restate_context as ContextImpl).createCombinator(
436
+ Promise.race.bind(Promise),
437
+ values
438
+ ) as Promise<Awaited<T[number]>>;
439
+ },
440
+
441
+ /**
442
+ * Creates a promise that fulfills when any of the input's promises fulfills, with this first fulfillment value.
443
+ * It rejects when all the input's promises reject (including when an empty iterable is passed),
444
+ * with an AggregateError containing an array of rejection reasons.
445
+ *
446
+ * See {@link Promise.any} for more details.
447
+ *
448
+ * @param values An iterable of Promises.
449
+ * @returns A new Promise.
450
+ */
451
+ any<T extends readonly CombineablePromise<unknown>[] | []>(
452
+ values: T
453
+ ): Promise<Awaited<T[number]>> {
454
+ if (values.length == 0) {
455
+ return Promise.any(values);
456
+ }
457
+
458
+ return (values[0].__restate_context as ContextImpl).createCombinator(
459
+ Promise.any.bind(Promise),
460
+ values
461
+ ) as Promise<Awaited<T[number]>>;
462
+ },
463
+
464
+ /**
465
+ * Creates a promise that fulfills when all the input's promises settle (including when an empty iterable is passed),
466
+ * with an array of objects that describe the outcome of each promise.
467
+ *
468
+ * See {@link Promise.allSettled} for more details.
469
+ *
470
+ * @param values An iterable of Promises.
471
+ * @returns A new Promise.
472
+ */
473
+ allSettled<T extends readonly CombineablePromise<unknown>[] | []>(
474
+ values: T
475
+ ): Promise<{
476
+ -readonly [P in keyof T]: PromiseSettledResult<Awaited<T[P]>>;
477
+ }> {
478
+ if (values.length == 0) {
479
+ return Promise.allSettled(values);
480
+ }
481
+
482
+ return (values[0].__restate_context as ContextImpl).createCombinator(
483
+ Promise.allSettled.bind(Promise),
484
+ values
485
+ ) as Promise<{
486
+ -readonly [P in keyof T]: PromiseSettledResult<Awaited<T[P]>>;
487
+ }>;
488
+ },
489
+ };
490
+
491
+ // ----------------------------------------------------------------------------
492
+ // types and functions for the gRPC-based API
493
+ // ----------------------------------------------------------------------------
494
+
495
+ /**
496
+ * Interface to interact with **gRPC** based services. You can use this interface to instantiate a gRPC generated client.
497
+ */
498
+ export interface RestateGrpcChannel {
499
+ /**
500
+ * Unidirectional call to other Restate services ( = in background / async / not waiting on response).
501
+ * To do this, wrap the call via the proto-ts client with oneWayCall, as shown in the example.
502
+ *
503
+ * NOTE: this returns a Promise because we override the gRPC clients provided by proto-ts.
504
+ * So we are required to return a Promise.
505
+ *
506
+ * @param call Invoke another service by using the generated proto-ts client.
507
+ * @example
508
+ * const ctx = restate.useContext(this);
509
+ * const client = new GreeterClientImpl(ctx);
510
+ * await ctx.oneWayCall(() =>
511
+ * client.greet(Request.create({ name: "Peter" }))
512
+ * )
513
+ */
514
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
515
+ oneWayCall(call: () => Promise<any>): Promise<void>;
516
+
517
+ /**
518
+ * Delayed unidirectional call to other Restate services ( = in background / async / not waiting on response).
519
+ * To do this, wrap the call via the proto-ts client with delayedCall, as shown in the example.
520
+ * Add the delay in millis as the second parameter.
521
+ *
522
+ * NOTE: this returns a Promise because we override the gRPC clients provided by proto-ts.
523
+ * So we are required to return a Promise.
524
+ *
525
+ * @param call Invoke another service by using the generated proto-ts client.
526
+ * @param delayMillis millisecond delay duration to delay the execution of the call
527
+ * @example
528
+ * const ctx = restate.useContext(this);
529
+ * const client = new GreeterClientImpl(ctx);
530
+ * await ctx.delayedCall(() =>
531
+ * client.greet(Request.create({ name: "Peter" })),
532
+ * 5000
533
+ * )
534
+ */
535
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
536
+ delayedCall(call: () => Promise<any>, delayMillis?: number): Promise<void>;
537
+
538
+ /**
539
+ * Call another Restate service and await the response.
540
+ *
541
+ * This function is not recommended to be called directly. Instead, use the generated gRPC client
542
+ * that was generated based on the Protobuf service definitions (which internally use this method):
543
+ *
544
+ * @example
545
+ * ```
546
+ * const ctx = restate.useContext(this);
547
+ * const client = new GreeterClientImpl(ctx);
548
+ * client.greet(Request.create({ name: "Peter" }))
549
+ * ```
550
+ *
551
+ * @param service name of the service to call
552
+ * @param method name of the method to call
553
+ * @param data payload as Uint8Array
554
+ * @returns a Promise that is resolved with the response of the called service
555
+ */
556
+ request(
557
+ service: string,
558
+ method: string,
559
+ data: Uint8Array
560
+ ): Promise<Uint8Array>;
561
+ }
562
+
563
+ /**
564
+ * @deprecated use {@link KeyedContext}.
565
+ */
566
+ export type RestateContext = KeyedContext;
567
+
568
+ /**
569
+ * Returns the {@link Context} which is the entrypoint for all interaction with Restate.
570
+ * Use this from within a method to retrieve the {@link Context}.
571
+ * The context is bounded to a single invocation.
572
+ *
573
+ * @example
574
+ * const ctx = restate.useContext(this);
575
+ *
576
+ */
577
+ export function useContext<T>(instance: T): Context {
578
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
579
+ const wrapper = instance as any;
580
+ if (wrapper.$$restate === undefined || wrapper.$$restate === null) {
581
+ throw new Error(`not running within a Restate call.`);
582
+ }
583
+ return wrapper.$$restate;
584
+ }
585
+
586
+ /**
587
+ * Returns the {@link KeyedContext} which is the entrypoint for all interaction with Restate.
588
+ * Use this from within a method of a keyed service to retrieve the {@link KeyedContext}.
589
+ * The context is bounded to a single invocation.
590
+ *
591
+ * @example
592
+ * const ctx = restate.useKeyedContext(this);
593
+ *
594
+ */
595
+ export function useKeyedContext<T>(instance: T): KeyedContext {
596
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
597
+ const wrapper = instance as any;
598
+ if (wrapper.$$restate === undefined || wrapper.$$restate === null) {
599
+ throw new Error(`not running within a Restate call.`);
600
+ }
601
+ return wrapper.$$restate;
602
+ }
603
+
604
+ // ----------------------------------------------------------------------------
605
+ // types for the rpc-handler-based API
606
+ // ----------------------------------------------------------------------------
607
+
608
+ /* eslint-disable @typescript-eslint/no-unused-vars */
609
+
610
+ /**
611
+ * ServiceApi captures the type and parameters to make RPC calls and send messages to
612
+ * a set of RPC handlers in a router.
613
+ *
614
+ * @example
615
+ * **Service Side:**
616
+ * ```ts
617
+ * const router = restate.router({
618
+ * someAction: async(ctx: restate.RpcContext, req: string) => { ... },
619
+ * anotherAction: async(ctx: restate.RpcContext, count: number) => { ... }
620
+ * });
621
+ *
622
+ * export const myApi: restate.ServiceApi<typeof router> = { path : "myservice" };
623
+ *
624
+ * restate.createServer().bindRouter("myservice", router).listen(9080);
625
+ * ```
626
+ * **Client side:**
627
+ * ```ts
628
+ * ctx.rpc(myApi).someAction("hello!");
629
+ * ```
630
+ */
631
+ export type ServiceApi<_M = unknown> = {
632
+ path: string;
633
+ };