Skip to content

Commit 43357e6

Browse files
committed
Feedback
1 parent 10cda09 commit 43357e6

File tree

3 files changed

+103
-111
lines changed

3 files changed

+103
-111
lines changed

src/context/mod.rs

Lines changed: 91 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,14 @@ impl<'ctx> WorkflowContext<'ctx> {
232232
/// # }
233233
/// ```
234234
///
235-
/// **Tip: Cost savings on FaaS**:
235+
/// **Cost savings on FaaS**:
236236
/// Restate suspends the handler while it is sleeping, to free up resources.
237237
/// This is beneficial for AWS Lambda deployments, since you don't pay for the time the handler is sleeping.
238238
///
239-
/// **Info: Sleeping in Virtual Objects**:
239+
/// **Sleeping in Virtual Objects**:
240240
/// Virtual Objects only process a single invocation at a time, so the Virtual Object will be blocked while sleeping.
241241
///
242-
/// <details className="grey-details">
242+
/// <details>
243243
/// <summary>Clock synchronization Restate Server vs. SDK</summary>
244244
///
245245
/// The Restate SDK calculates the wake-up time based on the delay you specify.
@@ -309,21 +309,9 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextTimers<'ctx> for CTX {}
309309
/// 2. **Specify the handler** you want to call and supply the request.
310310
/// 3. **Await** the call to retrieve the response.
311311
///
312-
/// **Tip: No need for manual retry logic**:
313-
/// These calls are proxied by Restate, and get logged in the journal.
314-
/// In case of failures, Restate takes care of retries.
315-
///
316-
/// **Note: Workflow retention time**:
317-
/// Once the `run` handler of the workflow has finished, the other handlers can still be called up to the retention time of the workflow, by default 24 hours.
318-
/// This can be configured via the [Admin API](https://docs.restate.dev/references/admin-api/#tag/service/operation/modify_service) per Workflow definition by setting `workflow_completion_retention`.
319-
///
320-
/// **Caution: Deadlocks with Virtual Objects**:
321-
/// Request-response calls to Virtual Objects can lead to deadlocks, in which the Virtual Object remains locked and can't process any more requests.
322-
/// Some example cases:
323-
/// - Cross deadlock between Virtual Object A and B: A calls B, and B calls A, both using same keys.
324-
/// - Cyclical deadlock: A calls B, and B calls C, and C calls A again.
325-
///
326-
/// In this situation, you can use the CLI to unblock the Virtual Object manually by [cancelling invocations](https://docs.restate.dev/operate/invocation#cancelling-invocations).
312+
/// **No need for manual retry logic**:
313+
/// Restate proxies all the calls and logs them in the journal.
314+
/// In case of failures, Restate takes care of retries, so you don't need to implement this yourself here.
327315
///
328316
/// ## Sending messages
329317
///
@@ -359,7 +347,7 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextTimers<'ctx> for CTX {}
359347
/// # }
360348
/// ```
361349
///
362-
/// **Tip: No need for message queues**:
350+
/// **No need for message queues**:
363351
/// Without Restate, you would usually put a message queue in between the two services, to guarantee the message delivery.
364352
/// Restate eliminates the need for a message queue because Restate durably logs the request and makes sure it gets executed.
365353
///
@@ -400,11 +388,10 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextTimers<'ctx> for CTX {}
400388
/// # }
401389
/// ```
402390
///
403-
/// **Tip: Scheduling async tasks**:
404391
/// You can also use this functionality to schedule async tasks.
405392
/// Restate will make sure the task gets executed at the desired time.
406393
///
407-
/// **Note: Ordering guarantees in Virtual Objects**:
394+
/// ### Ordering guarantees in Virtual Objects
408395
/// Invocations to a Virtual Object are executed serially.
409396
/// Invocations will execute in the same order in which they arrive at Restate.
410397
/// For example, assume a handler calls the same Virtual Object twice:
@@ -427,6 +414,15 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextTimers<'ctx> for CTX {}
427414
///
428415
/// It is guaranteed that call A will execute before call B.
429416
/// It is not guaranteed though that call B will be executed immediately after call A, as invocations coming from other handlers/sources, could interleave these two calls.
417+
///
418+
/// ### Deadlocks with Virtual Objects
419+
/// Request-response calls to Virtual Objects can lead to deadlocks, in which the Virtual Object remains locked and can't process any more requests.
420+
/// Some example cases:
421+
/// - Cross deadlock between Virtual Object A and B: A calls B, and B calls A, both using same keys.
422+
/// - Cyclical deadlock: A calls B, and B calls C, and C calls A again.
423+
///
424+
/// In this situation, you can use the CLI to unblock the Virtual Object manually by [cancelling invocations](https://docs.restate.dev/operate/invocation#cancelling-invocations).
425+
///
430426
pub trait ContextClient<'ctx>: private::SealedContext<'ctx> {
431427
/// Create a [`Request`].
432428
fn request<Req, Res>(
@@ -619,12 +615,12 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextClient<'ctx> for CTX {}
619615
/// # }
620616
/// ```
621617
///
622-
/// **Note**: You can return any payload that implements the `serde::Serialize` and `serde::Deserialize` traits ([see serialization docs][crate::serde]).
618+
/// You can return any payload that implements the `serde::Serialize` and `serde::Deserialize` traits ([see serialization docs][crate::serde]).
623619
///
624-
/// **Note**: When running on Function-as-a-Service platforms, such as AWS Lambda, Restate suspends the handler while waiting for the awakeable to be completed.
620+
/// When running on Function-as-a-Service platforms, such as AWS Lambda, Restate suspends the handler while waiting for the awakeable to be completed.
625621
/// Since you only pay for the time that the handler is actually running, you don't pay while waiting for the external process to return.
626622
///
627-
/// **Warning**: Virtual Objects only process a single invocation at a time, so the Virtual Object will be blocked while waiting on the awakeable to be resolved.
623+
/// **Be aware**: Virtual Objects only process a single invocation at a time, so the Virtual Object will be blocked while waiting on the awakeable to be resolved.
628624
pub trait ContextAwakeables<'ctx>: private::SealedContext<'ctx> {
629625
/// Create an awakeable
630626
fn awakeable<T: Deserialize + 'static>(
@@ -655,67 +651,36 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextAwakeables<'ctx> for CTX {}
655651
/// This means that non-deterministic results (e.g. database responses, UUID generation) need to be stored in the execution log.
656652
/// The SDK offers some functionalities to help you with this:
657653
/// 1. **[Journaled actions][crate::context::ContextSideEffects#journaled-actions]**: Run any block of code and store the result in Restate. Restate replays the result instead of re-executing the block on retries.
658-
/// 3. **[Random generators][crate::context::ContextSideEffects#generating-randoms]**: Built-in helpers for generating stable UUIDs and random numbers.
659-
///
660-
/// ## Journaled actions
661-
/// You can store the result of a (non-deterministic) operation in the Restate execution log (e.g. database requests, HTTP calls, etc).
662-
/// Restate replays the result instead of re-executing the operation on retries.
663-
///
664-
/// Here is an example of a database request for which the string response is stored in Restate:
665-
/// ```rust,no_run
666-
/// # use restate_sdk::prelude::*;
667-
/// # async fn handle(ctx: Context<'_>) -> Result<(), HandlerError> {
668-
/// let response = ctx.run(|| do_db_request()).await?;
669-
/// # Ok(())
670-
/// # }
671-
/// # async fn do_db_request() -> Result<String, HandlerError>{
672-
/// # Ok("Hello".to_string())
673-
/// # }
674-
/// ```
675-
///
676-
/// You cannot use the Restate context within `ctx.run`.
677-
/// This includes actions such as getting state, calling another service, and nesting other journaled actions.
678-
///
679-
/// You can store any result value that implements the `Serialize` and `Deserialize` trait ([see serialization docs][crate::serde]).
680-
///
681-
/// **Caution: Immediately await journaled actions:**
682-
/// Always immediately await `ctx.run`, before doing any other context calls.
683-
/// If not, you might bump into non-determinism errors during replay,
684-
/// because the journaled result can get interleaved with the other context calls in the journal in a non-deterministic way.
685-
///
654+
/// 2. **[UUID generator][crate::context::ContextSideEffects#generating-uuids]**: Built-in helpers for generating stable UUIDs. Restate seeds the random number generator with the invocation ID, so it always returns the same value on retries.
655+
/// 3. **[Random generator][crate::context::ContextSideEffects#generating-random-numbers]**: Built-in helpers for generating randoms. Restate seeds the random number generator with the invocation ID, so it always returns the same value on retries.
686656
///
687-
/// ## Generating randoms
688-
/// The SDK provides helper functions for the deterministic generation of UUIDs and random numbers. Restate seeds the random number generator with the invocation ID, so it always returns the same value on retries.
689-
///
690-
/// ### Generating UUIDs
691-
///
692-
/// You can use these UUIDs to generate stable idempotency keys, to deduplicate operations. For example, you can use this to let a payment service avoid duplicate payments during retries.
693-
///
694-
/// Do not use this in cryptographic contexts.
695-
///
696-
/// ```rust,no_run
697-
/// # use restate_sdk::prelude::*;
698-
/// # use uuid::Uuid;
699-
/// # async fn uuid_generate(mut ctx: Context<'_>) {
700-
/// let uuid: Uuid = ctx.rand_uuid();
701-
/// # }
702-
/// ```
703-
///
704-
///
705-
/// ### Generating random numbers
706-
///
707-
/// This returns a new pseudorandom float within the range `[0,1]`.
708-
/// This is the equivalent of JS `Math.random()` but deterministically replayable.
709-
///
710-
/// ```rust,no_run
711-
/// # use restate_sdk::prelude::*;
712-
/// # use rand::Rng;
713-
/// async fn rand_generate(mut ctx: Context<'_>) {
714-
/// let x: u32 = ctx.rand().gen();
715-
/// # }
716-
/// ```
717657
pub trait ContextSideEffects<'ctx>: private::SealedContext<'ctx> {
718-
/// Run a non-deterministic operation and record its result.
658+
/// ## Journaled actions
659+
/// You can store the result of a (non-deterministic) operation in the Restate execution log (e.g. database requests, HTTP calls, etc).
660+
/// Restate replays the result instead of re-executing the operation on retries.
661+
///
662+
/// Here is an example of a database request for which the string response is stored in Restate:
663+
/// ```rust,no_run
664+
/// # use restate_sdk::prelude::*;
665+
/// # async fn handle(ctx: Context<'_>) -> Result<(), HandlerError> {
666+
/// let response = ctx.run(|| do_db_request()).await?;
667+
/// # Ok(())
668+
/// # }
669+
/// # async fn do_db_request() -> Result<String, HandlerError>{
670+
/// # Ok("Hello".to_string())
671+
/// # }
672+
/// ```
673+
///
674+
/// You cannot use the Restate context within `ctx.run`.
675+
/// This includes actions such as getting state, calling another service, and nesting other journaled actions.
676+
///
677+
/// You can store any result value that implements the `Serialize` and `Deserialize` trait ([see serialization docs][crate::serde]).
678+
///
679+
/// **Caution: Immediately await journaled actions:**
680+
/// Always immediately await `ctx.run`, before doing any other context calls.
681+
/// If not, you might bump into non-determinism errors during replay,
682+
/// because the journaled result can get interleaved with the other context calls in the journal in a non-deterministic way.
683+
///
719684
#[must_use]
720685
fn run<R, F, T>(&self, run_closure: R) -> impl RunFuture<Result<T, TerminalError>> + 'ctx
721686
where
@@ -733,16 +698,41 @@ pub trait ContextSideEffects<'ctx>: private::SealedContext<'ctx> {
733698
private::SealedContext::random_seed(self)
734699
}
735700

701+
/// ### Generating random numbers
702+
///
736703
/// Return a [`rand::Rng`] instance inherently predictable, seeded with [`ContextSideEffects::random_seed`].
737704
///
705+
/// For example, you can use this to generate a random number:
706+
///
707+
/// ```rust,no_run
708+
/// # use restate_sdk::prelude::*;
709+
/// # use rand::Rng;
710+
/// async fn rand_generate(mut ctx: Context<'_>) {
711+
/// let x: u32 = ctx.rand().gen();
712+
/// # }
713+
/// ```
714+
///
738715
/// This instance is useful to generate identifiers, idempotency keys, and for uniform sampling from a set of options.
739716
/// If a cryptographically secure value is needed, please generate that externally using [`ContextSideEffects::run`].
740717
#[cfg(feature = "rand")]
741718
fn rand(&mut self) -> &mut rand::prelude::StdRng {
742719
private::SealedContext::rand(self)
743720
}
744-
745-
/// Return a random [`uuid::Uuid`], generated using [`ContextSideEffects::rand`].
721+
/// ### Generating UUIDs
722+
///
723+
/// Returns a random [`uuid::Uuid`], generated using [`ContextSideEffects::rand`].
724+
///
725+
/// You can use these UUIDs to generate stable idempotency keys, to deduplicate operations. For example, you can use this to let a payment service avoid duplicate payments during retries.
726+
///
727+
/// Do not use this in cryptographic contexts.
728+
///
729+
/// ```rust,no_run
730+
/// # use restate_sdk::prelude::*;
731+
/// # use uuid::Uuid;
732+
/// # async fn uuid_generate(mut ctx: Context<'_>) {
733+
/// let uuid: Uuid = ctx.rand_uuid();
734+
/// # }
735+
/// ```
746736
#[cfg(all(feature = "rand", feature = "uuid"))]
747737
fn rand_uuid(&mut self) -> uuid::Uuid {
748738
let rand = private::SealedContext::rand(self);
@@ -752,21 +742,14 @@ pub trait ContextSideEffects<'ctx>: private::SealedContext<'ctx> {
752742

753743
impl<'ctx, CTX: private::SealedContext<'ctx>> ContextSideEffects<'ctx> for CTX {}
754744

755-
/// # State
745+
/// # Reading state
756746
/// You can store key-value state in Restate.
757747
/// Restate makes sure the state is consistent with the processing of the code execution.
758748
///
759749
/// **This feature is only available for Virtual Objects and Workflows:**
760750
/// - For **Virtual Objects**, the state is isolated per Virtual Object and lives forever (across invocations for that object).
761751
/// - For **Workflows**, you can think of it as if every workflow execution is a new object. So the state is isolated to a single workflow execution. The state can only be mutated by the `run` handler of the workflow. The other handlers can only read the state.
762752
///
763-
/// **Info: Command-line introspection**:
764-
/// You can inspect and edit the K/V state stored in Restate via `psql` and the CLI.
765-
/// Have a look at the [introspection docs](https://docs.restate.dev//operate/introspection#inspecting-application-state) for more information.
766-
///
767-
/// **Info: Serializing state**:
768-
/// You can store any type of value that that implements the `serde::Serialize` and `serde::Deserialize` traits ([see serialization docs][crate::serde]).
769-
///
770753
/// ```rust,no_run
771754
/// # use restate_sdk::prelude::*;
772755
/// #
@@ -795,6 +778,13 @@ impl<'ctx, CTX: private::SealedContext<'ctx>> ContextSideEffects<'ctx> for CTX {
795778
/// # }
796779
/// ```
797780
///
781+
/// ### Command-line introspection
782+
/// You can inspect and edit the K/V state stored in Restate via `psql` and the CLI.
783+
/// Have a look at the [introspection docs](https://docs.restate.dev//operate/introspection#inspecting-application-state) for more information.
784+
///
785+
/// ### Serializing state
786+
/// You can store any type of value that that implements the `serde::Serialize` and `serde::Deserialize` traits ([see serialization docs][crate::serde]).
787+
///
798788
pub trait ContextReadState<'ctx>: private::SealedContext<'ctx> {
799789
/// Get state
800790
fn get<T: Deserialize + 'static>(
@@ -815,21 +805,14 @@ impl<'ctx, CTX: private::SealedContext<'ctx> + private::SealedCanReadState> Cont
815805
{
816806
}
817807

818-
/// # State
808+
/// # Writing State
819809
/// You can store key-value state in Restate.
820810
/// Restate makes sure the state is consistent with the processing of the code execution.
821811
///
822812
/// **This feature is only available for Virtual Objects and Workflows:**
823813
/// - For **Virtual Objects**, the state is isolated per Virtual Object and lives forever (across invocations for that object).
824814
/// - For **Workflows**, you can think of it as if every workflow execution is a new object. So the state is isolated to a single workflow execution. The state can only be mutated by the `run` handler of the workflow. The other handlers can only read the state.
825815
///
826-
/// **Info: Command-line introspection**:
827-
/// You can inspect and edit the K/V state stored in Restate via `psql` and the CLI.
828-
/// Have a look at the [introspection docs](https://docs.restate.dev//operate/introspection#inspecting-application-state) for more information.
829-
///
830-
/// **Info: Serializing state**:
831-
/// You can store any type of value that that implements the `serde::Serialize` and `serde::Deserialize` traits ([see serialization docs][crate::serde]).
832-
///
833816
/// ```rust,no_run
834817
/// # use restate_sdk::prelude::*;
835818
/// #
@@ -858,6 +841,13 @@ impl<'ctx, CTX: private::SealedContext<'ctx> + private::SealedCanReadState> Cont
858841
/// # }
859842
/// ```
860843
///
844+
/// ## Command-line introspection
845+
/// You can inspect and edit the K/V state stored in Restate via `psql` and the CLI.
846+
/// Have a look at the [introspection docs](https://docs.restate.dev//operate/introspection#inspecting-application-state) for more information.
847+
///
848+
/// ### Serializing state
849+
/// You can store any type of value that that implements the `serde::Serialize` and `serde::Deserialize` traits ([see serialization docs][crate::serde]).
850+
///
861851
pub trait ContextWriteState<'ctx>: private::SealedContext<'ctx> {
862852
/// Set state
863853
fn set<T: Serialize + 'static>(&self, key: &str, t: T) {

src/http_server.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
//!
1818
//! #[tokio::main]
1919
//! async fn main() {
20-
//! tracing_subscriber::fmt::init();
2120
//! HttpServer::new(
2221
//! Endpoint::builder()
2322
//! .bind(MyServiceImpl.serve())
@@ -46,7 +45,6 @@
4645
//! #
4746
//! # #[tokio::main]
4847
//! # async fn main() {
49-
//! # tracing_subscriber::fmt::init();
5048
//! HttpServer::new(
5149
//! Endpoint::builder()
5250
//! .bind(MyServiceImpl.serve())

0 commit comments

Comments
 (0)