Skip to content

Commit

Permalink
Quickstart rewrites (#482)
Browse files Browse the repository at this point in the history
  • Loading branch information
gvdongen authored Nov 22, 2024
1 parent aa51260 commit d43b789
Show file tree
Hide file tree
Showing 31 changed files with 3,052 additions and 774 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import dev.restate.sdk.annotation.Shared;
import dev.restate.sdk.annotation.Workflow;
import dev.restate.sdk.common.DurablePromiseKey;
import dev.restate.sdk.http.vertx.RestateHttpEndpointBuilder;
import dev.restate.sdk.serde.jackson.JacksonSerdes;
import develop.workflows.Email;
import usecases.utils.URL;
Expand All @@ -32,5 +33,9 @@ public void resultAsEmail(SharedWorkflowContext ctx, Email email) {
URL url = ctx.promise(URL_PROMISE).awaitable().await();
ctx.run(() -> sendEmail(url, email));
}

public static void main(String[] args) {
RestateHttpEndpointBuilder.builder().bind(new DataPreparationService()).buildAndListen();
}
}
// <end_here>
3 changes: 2 additions & 1 deletion code_snippets/ts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions code_snippets/ts/src/concepts/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
*/

import * as restate from "@restatedev/restate-sdk";
import {
emailClnt,
paymentClnt,
} from "./utils";
import { emailClnt, paymentClnt } from "./utils";

/**
* Order processing workflow Gets called for each Kafka event that is published to the order topic.
Expand Down
2 changes: 1 addition & 1 deletion code_snippets/ts/src/develop/awakeable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const service = restate.service({
greet: async (ctx: restate.Context, name: string) => {
// <start_here>
// <mark_1>
const {id, promise} = ctx.awakeable<string>();
const { id, promise } = ctx.awakeable<string>();
// </mark_1>

// <mark_2>
Expand Down
52 changes: 28 additions & 24 deletions code_snippets/ts/src/develop/serialization.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
import * as restate from "@restatedev/restate-sdk";
import {Context, WorkflowContext} from "@restatedev/restate-sdk";
import { Context, WorkflowContext } from "@restatedev/restate-sdk";

// <start_service_definition>
const myService = restate.service({
name: "MyService",
handlers: {
myHandler: restate.handlers.handler({
// Set the input serde here
input: restate.serde.binary,
// Set the output serde here
output: restate.serde.binary
}, async (ctx: Context, data: Uint8Array): Promise<Uint8Array> => {
// Process the request
return data;
}),
},
name: "MyService",
handlers: {
myHandler: restate.handlers.handler(
{
// Set the input serde here
input: restate.serde.binary,
// Set the output serde here
output: restate.serde.binary,
},
async (ctx: Context, data: Uint8Array): Promise<Uint8Array> => {
// Process the request
return data;
}
),
},
});
// <end_service_definition>

let ctx: WorkflowContext = undefined as unknown as WorkflowContext;
let input = new Uint8Array();

// <start_client>
ctx.serviceClient(myService)
.myHandler(
input,
restate.rpc.opts({
input: restate.serde.binary,
output: restate.serde.binary
})
);
ctx.serviceClient(myService).myHandler(
input,
restate.rpc.opts({
input: restate.serde.binary,
output: restate.serde.binary,
})
);
// <end_client>

// <start_state>
Expand All @@ -38,9 +40,11 @@ ctx.set("my-binary-data", new Uint8Array(), restate.serde.binary);
// <end_state>

// <start_awakeable>
ctx.awakeable(restate.serde.binary)
ctx.awakeable(restate.serde.binary);
// <end_awakeable>

// <start_run>
ctx.run("my-side-effect", () => new Uint8Array(), { serde: restate.serde.binary });
// <end_run>
ctx.run("my-side-effect", () => new Uint8Array(), {
serde: restate.serde.binary,
});
// <end_run>
4 changes: 3 additions & 1 deletion code_snippets/ts/src/develop/service_communication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const service = restate.service({
// <end_one_way_object>

// <start_delayed_service>
ctx.serviceSendClient(MyService).myHandler("Hi", restate.rpc.sendOpts({ delay: 5000 }));
ctx
.serviceSendClient(MyService)
.myHandler("Hi", restate.rpc.sendOpts({ delay: 5000 }));
// <end_delayed_service>

// <start_delayed_object>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const eventEnricher = restate.object({
ctx.set("user", event);
// </mark_1>
// <mark_3>
ctx.objectSendClient(EventEnricher, ctx.key).emit(restate.rpc.sendOpts({ delay: 1000 }));
ctx
.objectSendClient(EventEnricher, ctx.key)
.emit(restate.rpc.sendOpts({ delay: 1000 }));
// </mark_3>
},

Expand All @@ -43,7 +45,7 @@ const eventEnricher = restate.object({
emit: async (ctx: ObjectContext) => {
// </mark_2>
// <mark_1>
const user = await ctx.get<UserProfile>("user")
const user = await ctx.get<UserProfile>("user");
// </mark_1>
send(ctx.key, user);
// <mark_1>
Expand Down
37 changes: 10 additions & 27 deletions docs/develop/go/awakeables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,16 @@ This pattern is also known as the callback (task token) pattern.

## Creating awakeables

<Scrollycoding>

## !!steps
1. The handler **creates an awakeable**. This contains a String identifier and a handle on the future result.

```go !
CODE_LOAD::go/develop/awakeable.go?1
```

## !!steps
2. The handler **triggers a task/process** and attaches the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `restate.Run` to avoid re-triggering the task on retries.

```go !
CODE_LOAD::go/develop/awakeable.go?2
```

## !!steps
3. The handler **waits** until the other process has executed the task.
The handler **receives the payload and resumes**.

```go !
CODE_LOAD::go/develop/awakeable.go?3
```

</Scrollycoding>
1. **Create an awakeable**. This contains a String identifier and a handle on the future result.
2. **Trigger a task/process** and attach the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `restate.Run` to avoid re-triggering the task on retries.
3. **Wait** until the other process has executed the task.
The handler **receives the payload and resumes**.

```go
CODE_LOAD::go/develop/awakeable.go
```

## Completing awakeables

Expand Down
78 changes: 22 additions & 56 deletions docs/develop/java/awakeables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,63 +19,29 @@ This pattern is also known as the callback (task token) pattern.
## Creating awakeables
<Tabs groupId="sdk" queryString>
<TabItem value="java" label="Java">
<Scrollycoding>

# !!steps
1. The handler **creates an awakeable**. This contains a String identifier and a Promise/Awaitable.

```java !
CODE_LOAD::java/src/main/java/develop/Awakeables.java?1
```

# !!steps
2. The handler **triggers a task/process** and attaches the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `ctx.run` to avoid re-triggering the task on retries.

```java !
CODE_LOAD::java/src/main/java/develop/Awakeables.java?2
```

# !!steps
3. The handler **waits** until the other process has executed the task.
The handler **receives the payload and resumes**.

```java !
CODE_LOAD::java/src/main/java/develop/Awakeables.java?3
```

</Scrollycoding>

</TabItem>
<TabItem value="kotlin" label="Kotlin">
<Scrollycoding>

# !!steps
1. The handler **creates an awakeable**. This contains a String identifier and a Promise/Awaitable.

```kotlin !
CODE_LOAD::kotlin/src/main/kotlin/develop/Awakeables.kt?1
```

# !!steps
2. The handler **triggers a task/process** and attaches the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `ctx.runBlock` to avoid re-triggering the task on retries.

```kotlin !
CODE_LOAD::kotlin/src/main/kotlin/develop/Awakeables.kt?2
```

# !!steps
3. The handler **waits** until the other process has executed the task.
The handler **receives the payload and resumes**.

```kotlin !
CODE_LOAD::kotlin/src/main/kotlin/develop/Awakeables.kt?3
```
1. **Create an awakeable**. This contains a String identifier and a Promise/Awaitable.
2. **Trigger a task/process** and attach the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `ctx.run` to avoid re-triggering the task on retries.
3. **Wait** until the other process has executed the task.
The handler **receives the payload and resumes**.

```java
CODE_LOAD::java/src/main/java/develop/Awakeables.java
```

</Scrollycoding>
</TabItem>
<TabItem value="kotlin" label="Kotlin">
1. **Create an awakeable**. This contains a String identifier and a Promise/Awaitable.
2. **Trigger a task/process** and attach the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `ctx.runBlock` to avoid re-triggering the task on retries.
3. **Wait** until the other process has executed the task.
The handler **receives the payload and resumes**.

```kotlin
CODE_LOAD::kotlin/src/main/kotlin/develop/Awakeables.kt
```
</TabItem>
</Tabs>

Expand Down
21 changes: 14 additions & 7 deletions docs/develop/java/workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Admonition from '@theme/Admonition';
import {TextAndCode} from "../../../src/components/code/code/text-and-code";
import {Scrollycoding} from "../../../src/components/code/scrollycoding";

# Workflows

Expand All @@ -31,8 +32,7 @@ Have a look at the code example to get a better understanding of how workflows a
<TabItem value="java" label="Java">
<Scrollycoding>


### !!steps The `run` handler
### !!steps The run handler

Every workflow needs a `run` handler.
This handler has access to the same SDK features as Service and Virtual Object handlers.
Expand All @@ -59,8 +59,12 @@ Have a look at the code example to get a better understanding of how workflows a
These promises are durable and distributed, meaning they survive crashes and can be resolved or rejected by any handler in the workflow.

Do the following:
1. Create a promise in your `run` handler that is durable and distributed
2. Resolve or reject the promise in any other handler in the workflow. This can be done at most one time.
1. Create a promise that is durable and distributed in the `run` handler.
2. Resolve or reject the promise in another handler in the workflow. This can be done at most one time.

You can also use this pattern in reverse and let the `run` handler resolve promises that other handlers are waiting on.
For example, the `run` handler could resolve a promise when it finishes a step of the workflow, so that other handlers can request whether this step has been completed.


```java !
CODE_LOAD::java/src/main/java/develop/workflows/SignupWorkflow.java?3
Expand All @@ -80,7 +84,7 @@ Have a look at the code example to get a better understanding of how workflows a
<TabItem value="kotlin" label="Kotlin">
<Scrollycoding>

### !!steps The `run` handler
### !!steps The run handler

Every workflow needs a `run` handler.
This handler has access to the same SDK features as Service and Virtual Object handlers.
Expand All @@ -107,8 +111,11 @@ Have a look at the code example to get a better understanding of how workflows a
These promises are durable and distributed, meaning they survive crashes and can be resolved or rejected by any handler in the workflow.

Do the following:
1. Create a promise in your `run` handler that is durable and distributed
2. Resolve or reject the promise in any other handler in the workflow. This can be done at most one time.
1. Create a promise that is durable and distributed in the `run` handler.
2. Resolve or reject the promise in another handler in the workflow. This can be done at most one time.

You can also use this pattern in reverse and let the `run` handler resolve promises that other handlers are waiting on.
For example, the `run` handler could resolve a promise when it finishes a step of the workflow, so that other handlers can request whether this step has been completed.

```kotlin !
CODE_LOAD::kotlin/src/main/kotlin/develop/workflows/SignupWorkflow.kt?3
Expand Down
35 changes: 9 additions & 26 deletions docs/develop/python/awakeables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ description: "Pause invocations while waiting for an external task completion."
---

import Admonition from '@theme/Admonition';
import {Scrollycoding} from "../../../src/components/code/scrollycoding";
import {TextAndCode} from "../../../src/components/code/code/text-and-code";

# Awakeables
Expand All @@ -15,33 +14,17 @@ This pattern is also known as the callback (task token) pattern.

## Creating awakeables

<Scrollycoding>
1. **Create an awakeable**. This contains a String identifier and a Promise.
2. **Trigger a task/process** and attach the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `ctx.run` to avoid re-triggering the task on retries.
3. **Wait** until the other process has executed the task.
The handler **receives the payload and resumes**.

# !!steps
1. The handler **creates an awakeable**. This contains a String identifier and a Promise.
```py
CODE_LOAD::python/src/develop/awakeables.py
```

```python !
CODE_LOAD::python/src/develop/awakeables.py?1
```

# !!steps
2. The handler **triggers a task/process** and attaches the awakeable ID (e.g. over Kafka, via HTTP,...).
For example, send an HTTP request to a service that executes the task, and attach the ID to the payload.
You use `ctx.run` to avoid re-triggering the task on retries.

```python !
CODE_LOAD::python/src/develop/awakeables.py?2
```

# !!steps
3. The handler **waits** until the other process has executed the task.
The handler **receives the payload and resumes**.

```python !
CODE_LOAD::python/src/develop/awakeables.py?3
```

</Scrollycoding>

## Completing awakeables

Expand Down
Loading

0 comments on commit d43b789

Please sign in to comment.