1
+ //! Types exposing Restate functionalities to service handlers.
2
+
1
3
use crate :: endpoint:: { ContextInternal , InputMetadata } ;
2
4
use crate :: errors:: { HandlerResult , TerminalError } ;
3
5
use crate :: serde:: { Deserialize , Serialize } ;
@@ -11,6 +13,7 @@ pub use request::{Request, RequestTarget};
11
13
pub use run:: RunClosure ;
12
14
pub type HeaderMap = http:: HeaderMap < String > ;
13
15
16
+ /// Service handler context.
14
17
pub struct Context < ' ctx > {
15
18
random_seed : u64 ,
16
19
#[ cfg( feature = "rand" ) ]
@@ -20,10 +23,12 @@ pub struct Context<'ctx> {
20
23
}
21
24
22
25
impl < ' ctx > Context < ' ctx > {
26
+ /// Get request headers.
23
27
pub fn headers ( & self ) -> & HeaderMap {
24
28
& self . headers
25
29
}
26
30
31
+ /// Get request headers.
27
32
pub fn headers_mut ( & mut self ) -> & HeaderMap {
28
33
& mut self . headers
29
34
}
@@ -41,6 +46,7 @@ impl<'ctx> From<(&'ctx ContextInternal, InputMetadata)> for Context<'ctx> {
41
46
}
42
47
}
43
48
49
+ /// Object shared handler context.
44
50
pub struct SharedObjectContext < ' ctx > {
45
51
key : String ,
46
52
random_seed : u64 ,
@@ -51,14 +57,17 @@ pub struct SharedObjectContext<'ctx> {
51
57
}
52
58
53
59
impl < ' ctx > SharedObjectContext < ' ctx > {
60
+ /// Get object key.
54
61
pub fn key ( & self ) -> & str {
55
62
& self . key
56
63
}
57
64
65
+ /// Get request headers.
58
66
pub fn headers ( & self ) -> & HeaderMap {
59
67
& self . headers
60
68
}
61
69
70
+ /// Get request headers.
62
71
pub fn headers_mut ( & mut self ) -> & HeaderMap {
63
72
& mut self . headers
64
73
}
@@ -77,6 +86,7 @@ impl<'ctx> From<(&'ctx ContextInternal, InputMetadata)> for SharedObjectContext<
77
86
}
78
87
}
79
88
89
+ /// Object handler context.
80
90
pub struct ObjectContext < ' ctx > {
81
91
key : String ,
82
92
random_seed : u64 ,
@@ -87,14 +97,17 @@ pub struct ObjectContext<'ctx> {
87
97
}
88
98
89
99
impl < ' ctx > ObjectContext < ' ctx > {
100
+ /// Get object key.
90
101
pub fn key ( & self ) -> & str {
91
102
& self . key
92
103
}
93
104
105
+ /// Get request headers.
94
106
pub fn headers ( & self ) -> & HeaderMap {
95
107
& self . headers
96
108
}
97
109
110
+ /// Get request headers.
98
111
pub fn headers_mut ( & mut self ) -> & HeaderMap {
99
112
& mut self . headers
100
113
}
@@ -113,6 +126,7 @@ impl<'ctx> From<(&'ctx ContextInternal, InputMetadata)> for ObjectContext<'ctx>
113
126
}
114
127
}
115
128
129
+ /// Workflow shared handler context.
116
130
pub struct SharedWorkflowContext < ' ctx > {
117
131
key : String ,
118
132
random_seed : u64 ,
@@ -136,19 +150,23 @@ impl<'ctx> From<(&'ctx ContextInternal, InputMetadata)> for SharedWorkflowContex
136
150
}
137
151
138
152
impl < ' ctx > SharedWorkflowContext < ' ctx > {
153
+ /// Get workflow key.
139
154
pub fn key ( & self ) -> & str {
140
155
& self . key
141
156
}
142
157
158
+ /// Get request headers.
143
159
pub fn headers ( & self ) -> & HeaderMap {
144
160
& self . headers
145
161
}
146
162
163
+ /// Get request headers.
147
164
pub fn headers_mut ( & mut self ) -> & HeaderMap {
148
165
& mut self . headers
149
166
}
150
167
}
151
168
169
+ /// Workflow handler context.
152
170
pub struct WorkflowContext < ' ctx > {
153
171
key : String ,
154
172
random_seed : u64 ,
@@ -172,19 +190,23 @@ impl<'ctx> From<(&'ctx ContextInternal, InputMetadata)> for WorkflowContext<'ctx
172
190
}
173
191
174
192
impl < ' ctx > WorkflowContext < ' ctx > {
193
+ /// Get workflow key.
175
194
pub fn key ( & self ) -> & str {
176
195
& self . key
177
196
}
178
197
198
+ /// Get request headers.
179
199
pub fn headers ( & self ) -> & HeaderMap {
180
200
& self . headers
181
201
}
182
202
203
+ /// Get request headers.
183
204
pub fn headers_mut ( & mut self ) -> & HeaderMap {
184
205
& mut self . headers
185
206
}
186
207
}
187
208
209
+ /// Trait exposing Restate timers functionalities.
188
210
pub trait ContextTimers < ' ctx > : private:: SealedContext < ' ctx > {
189
211
/// Sleep using Restate
190
212
fn sleep ( & self , duration : Duration ) -> impl Future < Output = Result < ( ) , TerminalError > > + ' ctx {
@@ -194,7 +216,9 @@ pub trait ContextTimers<'ctx>: private::SealedContext<'ctx> {
194
216
195
217
impl < ' ctx , CTX : private:: SealedContext < ' ctx > > ContextTimers < ' ctx > for CTX { }
196
218
219
+ /// Trait exposing Restate service to service communication functionalities.
197
220
pub trait ContextClient < ' ctx > : private:: SealedContext < ' ctx > {
221
+ /// Create a [`Request`].
198
222
fn request < Req , Res > (
199
223
& self ,
200
224
request_target : RequestTarget ,
@@ -203,20 +227,95 @@ pub trait ContextClient<'ctx>: private::SealedContext<'ctx> {
203
227
Request :: new ( self . inner_context ( ) , request_target, req)
204
228
}
205
229
230
+ /// Create a service client. The service client is generated by the [`restate_sdk_macros::service`] macro with the same name of the trait suffixed with `Client`.
231
+ ///
232
+ /// ```rust
233
+ /// # use std::time::Duration;
234
+ /// # use restate_sdk::prelude::*;
235
+ ///
236
+ /// #[restate_sdk::service]
237
+ /// trait MyService {
238
+ /// fn handle() -> HandlerResult<()>;
239
+ /// }
240
+ ///
241
+ /// # async fn handler(ctx: Context<'_>) {
242
+ /// let client = ctx.service_client::<MyServiceClient>();
243
+ ///
244
+ /// // Do request
245
+ /// let result = client.handle().call().await;
246
+ ///
247
+ /// // Just send the request, don't wait the response
248
+ /// client.handle().send();
249
+ ///
250
+ /// // Schedule the request to be executed later
251
+ /// client.handle().send_with_delay(Duration::from_secs(60));
252
+ /// }
253
+ ///
254
+ /// ```
206
255
fn service_client < C > ( & self ) -> C
207
256
where
208
257
C : IntoServiceClient < ' ctx > ,
209
258
{
210
259
C :: create_client ( self . inner_context ( ) )
211
260
}
212
261
262
+ /// Create an object client. The object client is generated by the [`restate_sdk_macros::object`] macro with the same name of the trait suffixed with `Client`.
263
+ ///
264
+ /// ```rust
265
+ /// # use std::time::Duration;
266
+ /// # use restate_sdk::prelude::*;
267
+ ///
268
+ /// #[restate_sdk::object]
269
+ /// trait MyObject {
270
+ /// fn handle() -> HandlerResult<()>;
271
+ /// }
272
+ ///
273
+ /// # async fn handler(ctx: Context<'_>) {
274
+ /// let client = ctx.object_client::<MyObjectClient>("my-key");
275
+ ///
276
+ /// // Do request
277
+ /// let result = client.handle().call().await;
278
+ ///
279
+ /// // Just send the request, don't wait the response
280
+ /// client.handle().send();
281
+ ///
282
+ /// // Schedule the request to be executed later
283
+ /// client.handle().send_with_delay(Duration::from_secs(60));
284
+ /// }
285
+ ///
286
+ /// ```
213
287
fn object_client < C > ( & self , key : impl Into < String > ) -> C
214
288
where
215
289
C : IntoObjectClient < ' ctx > ,
216
290
{
217
291
C :: create_client ( self . inner_context ( ) , key. into ( ) )
218
292
}
219
293
294
+ /// Create an workflow client. The workflow client is generated by the [`restate_sdk_macros::workflow`] macro with the same name of the trait suffixed with `Client`.
295
+ ///
296
+ /// ```rust
297
+ /// # use std::time::Duration;
298
+ /// # use restate_sdk::prelude::*;
299
+ ///
300
+ /// #[restate_sdk::workflow]
301
+ /// trait MyWorkflow {
302
+ /// fn handle() -> HandlerResult<()>;
303
+ /// }
304
+ ///
305
+ /// # async fn handler(ctx: Context<'_>) {
306
+ /// let client = ctx.workflow_client::<MyWorkflowClient>("my-key");
307
+ ///
308
+ /// // Do request
309
+ /// let result = client.handle().call().await;
310
+ ///
311
+ /// // Just send the request, don't wait the response
312
+ /// client.handle().send();
313
+ ///
314
+ /// // Schedule the request to be executed later
315
+ /// client.handle().send_with_delay(Duration::from_secs(60));
316
+ /// }
317
+ ///
318
+ /// ```
220
319
fn workflow_client < C > ( & self , key : impl Into < String > ) -> C
221
320
where
222
321
C : IntoWorkflowClient < ' ctx > ,
@@ -225,20 +324,29 @@ pub trait ContextClient<'ctx>: private::SealedContext<'ctx> {
225
324
}
226
325
}
227
326
327
+ /// Trait used by codegen to create the service client.
228
328
pub trait IntoServiceClient < ' ctx > : Sized {
229
329
fn create_client ( ctx : & ' ctx ContextInternal ) -> Self ;
230
330
}
231
331
332
+ /// Trait used by codegen to use the object client.
232
333
pub trait IntoObjectClient < ' ctx > : Sized {
233
334
fn create_client ( ctx : & ' ctx ContextInternal , key : String ) -> Self ;
234
335
}
235
336
337
+ /// Trait used by codegen to use the workflow client.
236
338
pub trait IntoWorkflowClient < ' ctx > : Sized {
237
339
fn create_client ( ctx : & ' ctx ContextInternal , key : String ) -> Self ;
238
340
}
239
341
240
342
impl < ' ctx , CTX : private:: SealedContext < ' ctx > > ContextClient < ' ctx > for CTX { }
241
343
344
+ /// Trait exposing Restate awakeables functionalities.
345
+ ///
346
+ /// Awakeables can be used to implement external asynchronous systems interactions,
347
+ /// for example you can send a Kafka record including the awakeable id returned by [`ContextAwakeables::awakeable`],
348
+ /// and then let another service consume from Kafka the responses of given external system interaction by using
349
+ /// [`ContextAwakeables::resolve_awakeable`] or [`ContextAwakeables::reject_awakeable`].
242
350
pub trait ContextAwakeables < ' ctx > : private:: SealedContext < ' ctx > {
243
351
/// Create an awakeable
244
352
fn awakeable < T : Deserialize + ' static > (
@@ -263,8 +371,10 @@ pub trait ContextAwakeables<'ctx>: private::SealedContext<'ctx> {
263
371
264
372
impl < ' ctx , CTX : private:: SealedContext < ' ctx > > ContextAwakeables < ' ctx > for CTX { }
265
373
374
+ /// Trait exposing Restate functionalities to deal with non-deterministic operations.
266
375
pub trait ContextSideEffects < ' ctx > : private:: SealedContext < ' ctx > {
267
- /// Run a non-deterministic operation
376
+ /// Run a non-deterministic operation and record its result.
377
+ ///
268
378
fn run < R , F , T > (
269
379
& self ,
270
380
name : & ' ctx str ,
@@ -278,15 +388,23 @@ pub trait ContextSideEffects<'ctx>: private::SealedContext<'ctx> {
278
388
self . inner_context ( ) . run ( name, run_closure)
279
389
}
280
390
391
+ /// Return a random seed inherently predictable, based on the invocation id, which is not secret.
392
+ ///
393
+ /// This value is stable during the invocation lifecycle, thus across retries.
281
394
fn random_seed ( & self ) -> u64 {
282
395
private:: SealedContext :: random_seed ( self )
283
396
}
284
397
398
+ /// Return a [`rand::Rng`] instance inherently predictable, seeded with [`ContextSideEffects::random_seed`].
399
+ ///
400
+ /// This instance is useful to generate identifiers, idempotency keys, and for uniform sampling from a set of options.
401
+ /// If a cryptographically secure value is needed, please generate that externally using [`ContextSideEffects::run`].
285
402
#[ cfg( feature = "rand" ) ]
286
403
fn rand ( & mut self ) -> & mut rand:: prelude:: StdRng {
287
404
private:: SealedContext :: rand ( self )
288
405
}
289
406
407
+ /// Return a random [`uuid::Uuid`], generated using [`ContextSideEffects::rand`].
290
408
#[ cfg( all( feature = "rand" , feature = "uuid" ) ) ]
291
409
fn rand_uuid ( & mut self ) -> uuid:: Uuid {
292
410
let rand = private:: SealedContext :: rand ( self ) ;
@@ -296,6 +414,7 @@ pub trait ContextSideEffects<'ctx>: private::SealedContext<'ctx> {
296
414
297
415
impl < ' ctx , CTX : private:: SealedContext < ' ctx > > ContextSideEffects < ' ctx > for CTX { }
298
416
417
+ /// Trait exposing Restate K/V read functionalities.
299
418
pub trait ContextReadState < ' ctx > : private:: SealedContext < ' ctx > {
300
419
/// Get state
301
420
fn get < T : Deserialize + ' static > (
@@ -316,6 +435,7 @@ impl<'ctx, CTX: private::SealedContext<'ctx> + private::SealedCanReadState> Cont
316
435
{
317
436
}
318
437
438
+ /// Trait exposing Restate K/V write functionalities.
319
439
pub trait ContextWriteState < ' ctx > : private:: SealedContext < ' ctx > {
320
440
/// Set state
321
441
fn set < T : Serialize + ' static > ( & self , key : & str , t : T ) {
@@ -338,6 +458,13 @@ impl<'ctx, CTX: private::SealedContext<'ctx> + private::SealedCanWriteState> Con
338
458
{
339
459
}
340
460
461
+ /// Trait exposing Restate promise functionalities.
462
+ ///
463
+ /// A promise is a durable, distributed version of a Rust oneshot channel.
464
+ /// Restate keeps track of the promises across restarts/failures.
465
+ ///
466
+ /// You can use this feature to implement interaction between different workflow handlers, e.g. to
467
+ /// send a signal from a shared handler to the workflow handler.
341
468
pub trait ContextPromises < ' ctx > : private:: SealedContext < ' ctx > {
342
469
/// Create a promise
343
470
fn promise < T : Deserialize + ' static > (
0 commit comments