-
Notifications
You must be signed in to change notification settings - Fork 330
Documentation for Rust Standalone Activities #5339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
f6e6c35
rust SAA docs
GregoryTravis 4a225ae
rust SAA docs
GregoryTravis 62d7059
Make docs code match samples code.
GregoryTravis c3e01b4
Merge branch 'main' into gmt/rust-standalone-activities-docs
GregoryTravis 17fb389
Add missing references
GregoryTravis 38adad9
Merge branch 'main' into gmt/rust-standalone-activities-docs
GregoryTravis ccf2251
Merge branch 'main' into gmt/rust-standalone-activities-docs
GregoryTravis 139772a
Merge branch 'main' into gmt/rust-standalone-activities-docs
jsundai 71a255b
edits
jsundai 411ca15
Align describe defaults with ActivityDescribeOptions
jsundai 541518b
Merge branch 'main' into gmt/rust-standalone-activities-docs
GregoryTravis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
290 changes: 290 additions & 0 deletions
290
docs/develop/rust/activities/standalone-activities-quickstart.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,290 @@ | ||
| --- | ||
| id: standalone-activities-quickstart | ||
| title: Standalone Activities Rust Quickstart | ||
| sidebar_label: Quickstart | ||
| description: Execute a Standalone Activity with the Temporal Rust SDK without writing a Workflow. | ||
| tags: | ||
| - Activities | ||
| - Temporal Client | ||
| - Rust SDK | ||
| - setup | ||
| - getting started | ||
| hide_table_of_contents: true | ||
| --- | ||
|
|
||
| import { SetupSteps, SetupStep, CodeSnippet } from '@site/src/components'; | ||
|
|
||
| # Quickstart | ||
|
|
||
| Standalone Activities are Activities that run independently, without being orchestrated by a | ||
| Workflow. Instead of executing an Activity from within a Workflow Definition using | ||
| `ctx.execute_activity()`, you execute a Standalone Activity directly from a | ||
| [`Client`](https://docs.rs/temporalio-client/latest/temporalio_client/struct.Client.html). | ||
|
GregoryTravis marked this conversation as resolved.
|
||
|
|
||
| The way you write the Activity and register it with a Worker is identical to [Workflow | ||
| Activities](/develop/rust/activities/basics). The only difference is that you execute a Standalone | ||
| Activity directly from your Temporal Client. | ||
|
|
||
| :::note | ||
|
|
||
| This documentation uses source code from the | ||
| [standalone_activities](https://github.com/temporalio/sdk-rust/tree/main/crates/sdk/examples/standalone_activities) | ||
| sample. | ||
|
|
||
| ::: | ||
|
|
||
| <SetupSteps> | ||
|
|
||
| <SetupStep code={ | ||
| <> | ||
| <CodeSnippet language="bash"> | ||
| {`brew install temporal`} | ||
| </CodeSnippet> | ||
| <CodeSnippet language="bash"> | ||
| {`temporal --version`} | ||
| </CodeSnippet> | ||
| <CodeSnippet language="bash"> | ||
| {`temporal server start-dev`} | ||
| </CodeSnippet> | ||
| </> | ||
| }> | ||
|
|
||
| ## Get started with Standalone Activities {/* #get-started */} | ||
|
|
||
| Prerequisites: | ||
|
|
||
| - **Rust** 1.92.0+ | ||
|
|
||
| - **Temporal Rust SDK** (v1.0.0 or higher). See the [Rust Quickstart](/develop/rust/quickstart) for install instructions. | ||
|
|
||
| - **Temporal CLI** v1.9.1 or higher. Install with Homebrew, or see the [Temporal CLI install guide](/cli/setup-cli) for other platforms. Verify the installation with `temporal --version`. | ||
|
|
||
| Start the Temporal development server with `temporal server start-dev`. | ||
|
|
||
| This command automatically starts the Temporal development server with the Web UI, and creates the `default` Namespace. | ||
| It uses an in-memory database, so do not use it for real use cases. | ||
|
|
||
| The Temporal Server will now be available for client connections on `localhost:7233`, and the | ||
| Temporal Web UI will now be accessible at [http://localhost:8233](http://localhost:8233). | ||
|
|
||
| </SetupStep> | ||
|
|
||
| <SetupStep code={ | ||
| <> | ||
| <CodeSnippet language="toml" title="Cargo.toml"> | ||
| {`[dependencies] | ||
| futures = "0.3" | ||
| temporalio-client = "1.0.0" | ||
| temporalio-macros = "1.0.0" | ||
| temporalio-sdk = "1.0.0" | ||
| tokio = { version = "1", features = ["full"] } | ||
| `} | ||
| </CodeSnippet> | ||
| </> | ||
| }> | ||
|
|
||
| ## Clone the sample | ||
|
|
||
| Clone the [sdk-rust](https://github.com/temporalio/sdk-rust) repository to follow along: | ||
|
|
||
| ```bash | ||
| git clone https://github.com/temporalio/sdk-rust.git | ||
| cd sdk-rust/crates/sdk | ||
| ``` | ||
|
|
||
| The sample consists of separate programs in the `crates/sdk/examples/standalone_activities` directory: | ||
|
|
||
| ``` | ||
| standalone_activities/ | ||
| ├── activities.rs # Activity definition, shared by the programs below | ||
| ├── worker.rs # Worker that processes Activity Tasks | ||
| ├── execute_activity.rs # Executes an Activity and waits for the result | ||
| ├── start_activity.rs # Starts an Activity without blocking | ||
| ├── get_activity_handle.rs # Gets a handle to an existing Activity | ||
| ├── list_activities.rs # Lists Activity Executions | ||
| └── count_activities.rs # Counts Activity Executions | ||
| ``` | ||
|
|
||
| To write the same code in your own project, add the dependencies shown here to your `Cargo.toml`. | ||
| Standalone Activities need `temporalio-client` for the Client, `temporalio-sdk` and | ||
| `temporalio-macros` for the Activity and Worker, and `tokio` as the async runtime. `futures` is | ||
| needed to consume the stream returned by `list_activities`. | ||
|
|
||
| </SetupStep> | ||
|
|
||
| <SetupStep code={ | ||
| <> | ||
| <CodeSnippet language="rust" title="activities.rs"> | ||
| {`use temporalio_macros::activities; | ||
| use temporalio_sdk::activities::{ActivityContext, ActivityError}; | ||
|
|
||
| pub struct GreetingActivities; | ||
|
|
||
| #[activities] | ||
| impl GreetingActivities { | ||
| #[activity] | ||
| pub async fn compose_greeting( | ||
| _ctx: ActivityContext, | ||
| input: (String, String), | ||
| ) -> Result<String, ActivityError> { | ||
| let (greeting, name) = input; | ||
| Ok(format!("{greeting}, {name}!")) | ||
| } | ||
| }`} | ||
| </CodeSnippet> | ||
| </> | ||
| }> | ||
|
|
||
| ## Define your Activity {/* #define-activity */} | ||
|
|
||
| An Activity in the Temporal Rust SDK is an `async` method on an `impl` block marked with the | ||
| `#[activities]` macro, annotated with `#[activity]`. The way you define a Standalone Activity is | ||
| identical to how you define an Activity orchestrated by a Workflow. In fact, the same Activity can | ||
| be executed both as a Standalone Activity and as a Workflow Activity. | ||
|
GregoryTravis marked this conversation as resolved.
|
||
|
|
||
| Each Activity method takes an | ||
| [`ActivityContext`](https://docs.rs/temporalio-sdk/latest/temporalio_sdk/activities/struct.ActivityContext.html) | ||
| as its first parameter and returns `Result<T, ActivityError>`. Use `_ctx` if you don't need the | ||
| context. To pass more than one value to an Activity, take them as a tuple, as | ||
| `compose_greeting` does here. | ||
|
|
||
| By default, the macro names each Activity `<ImplType>::<method_name>`, so this one registers as | ||
| `GreetingActivities::compose_greeting`. That's the name to use from the Temporal CLI and in [List | ||
| Filter](/list-filter) queries. | ||
|
|
||
| [activities.rs](https://github.com/temporalio/sdk-rust/blob/main/crates/sdk/examples/standalone_activities/activities.rs) | ||
|
|
||
| </SetupStep> | ||
|
|
||
| <SetupStep code={ | ||
| <> | ||
| <CodeSnippet language="rust" title="worker.rs"> | ||
| {`#[tokio::main] | ||
| async fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
| let runtime = Runtime::from_current_tokio(Default::default())?; | ||
| let (conn_opts, client_opts) = | ||
| ClientOptions::load_from_config(LoadClientConfigProfileOptions::default())?; | ||
| let connection = Connection::connect(conn_opts).await?; | ||
| let client = Client::new(connection, client_opts)?; | ||
|
|
||
| // A Worker that only runs Standalone Activities needs no registered workflows. | ||
| let worker_options = WorkerOptions::new("standalone-activities") | ||
| .register_activities(GreetingActivities) | ||
| .build(); | ||
|
|
||
| let mut worker = Worker::new(&runtime, client, worker_options)?; | ||
| println!("Worker started on task queue: standalone-activities"); | ||
| worker.run().await?; | ||
|
|
||
| Ok(()) | ||
| }`} | ||
| </CodeSnippet> | ||
| <CodeSnippet language="bash"> | ||
| {`cargo run --features examples --example standalone-activities-worker`} | ||
| </CodeSnippet> | ||
| </> | ||
| }> | ||
|
|
||
| ## Run a Worker with the Activity registered {/* #run-worker */} | ||
|
|
||
| Running a Worker for Standalone Activities is the same as running a Worker for Workflow Activities — | ||
| you build [`WorkerOptions`](https://docs.rs/temporalio-sdk/latest/temporalio_sdk/struct.WorkerOptions.html) | ||
| for a Task Queue, register the Activities with `register_activities`, and call `worker.run()`. The | ||
| Worker doesn't need to know whether the Activity will be invoked from a Workflow or as a Standalone | ||
| Activity, and a Worker that runs Standalone Activities needs no registered Workflows at all. See | ||
| [How to run a Worker](/develop/rust/workers/worker-process) for more details on Worker setup and | ||
| configuration options. | ||
|
|
||
| [worker.rs](https://github.com/temporalio/sdk-rust/blob/main/crates/sdk/examples/standalone_activities/worker.rs) | ||
|
|
||
| Open a new terminal, navigate to the `crates/sdk` directory, and run the Worker. | ||
| Leave this terminal running — the Worker needs to stay up to process activities. | ||
|
|
||
| </SetupStep> | ||
|
|
||
| <SetupStep code={ | ||
| <> | ||
| <CodeSnippet language="rust" title="execute_activity.rs"> | ||
| {`let options = ActivityStartOptions::with_start_to_close_timeout( | ||
| "standalone-activities", | ||
| "standalone-activity-id", | ||
| Duration::from_secs(10), | ||
| ) | ||
| .build(); | ||
|
|
||
| // There is no single "execute" call: start the activity, then await its result. | ||
| let handle = client | ||
| .start_activity( | ||
| GreetingActivities::compose_greeting, | ||
| ("Hello".to_string(), "Temporal".to_string()), | ||
| options, | ||
| ) | ||
| .await?; | ||
|
|
||
| let result = handle.result().await?; | ||
| println!("Activity result: {result}");`} | ||
| </CodeSnippet> | ||
| <CodeSnippet language="bash"> | ||
| {`cargo run --features examples --example standalone-activities-execute`} | ||
| </CodeSnippet> | ||
| <CodeSnippet language="bash"> | ||
| {`temporal activity execute \\ | ||
| --type 'GreetingActivities::compose_greeting' \\ | ||
| --activity-id standalone-activity-id \\ | ||
| --task-queue standalone-activities \\ | ||
| --start-to-close-timeout 10s \\ | ||
| --input '["Hello","Temporal"]'`} | ||
| </CodeSnippet> | ||
| </> | ||
| }> | ||
|
|
||
| ## Execute a Standalone Activity {/* #execute-activity */} | ||
|
|
||
| Use [`Client::start_activity`](https://docs.rs/temporalio-client/latest/temporalio_client/struct.Client.html#method.start_activity) | ||
| to start a Standalone Activity, then | ||
| [`ActivityHandle::result`](https://docs.rs/temporalio-client/latest/temporalio_client/struct.ActivityHandle.html#method.result) | ||
| to block until it completes. Call these from your application code, not from inside a Workflow | ||
| Definition. `start_activity` durably enqueues your Standalone Activity in the Temporal Server, and | ||
| `result` waits for it to be executed on your Worker and returns the result. | ||
|
|
||
| [execute_activity.rs](https://github.com/temporalio/sdk-rust/blob/main/crates/sdk/examples/standalone_activities/execute_activity.rs) | ||
|
|
||
| The first argument to `start_activity` is the Activity to run. Passing the Activity method itself, | ||
| `GreetingActivities::compose_greeting`, gives you a typed | ||
| [`ActivityHandle`](https://docs.rs/temporalio-client/latest/temporalio_client/struct.ActivityHandle.html), | ||
| so the input and output types are checked at compile time and `result` returns the Activity's own | ||
| return type. The second argument is the Activity's input. | ||
|
|
||
| [`ActivityStartOptions`](https://docs.rs/temporalio-client/latest/temporalio_client/struct.ActivityStartOptions.html) | ||
| requires a Task Queue, an Activity ID, and a close timeout. The `with_start_to_close_timeout` and | ||
| `with_schedule_to_close_timeout` constructors return a builder with that timeout already set; call | ||
| `.build()` to finish. | ||
|
|
||
| To run it: | ||
|
|
||
| 1. Make sure the Temporal Server is running (from the [Get Started](#get-started) step above). | ||
| 2. Make sure the Worker is running (from the [Run a Worker](#run-worker) step above). | ||
| 3. Open a new terminal, navigate to the `crates/sdk` directory, and run the execute command. | ||
|
|
||
| Or use the Temporal CLI. Because `compose_greeting` takes its two values as a tuple, the CLI input | ||
| is a single two-element JSON array. | ||
|
|
||
| </SetupStep> | ||
|
|
||
| </SetupSteps> | ||
|
|
||
| ## Run with Temporal Cloud | ||
|
|
||
| All code samples on this page use | ||
| [`ClientOptions::load_from_config`](https://docs.rs/temporalio-client/latest/temporalio_client/struct.ClientOptions.html#method.load_from_config) | ||
| to configure the Temporal Client connection. It responds to [environment | ||
| variables](/references/client-environment-configuration) and [TOML configuration | ||
| files](/references/client-environment-configuration), so the same code works against a local dev | ||
| server and Temporal Cloud without changes. See [Run Standalone Activities with Temporal | ||
| Cloud](/develop/rust/activities/standalone-activities#run-standalone-activities-temporal-cloud) in the Feature Guide | ||
| for mTLS and API key setup. | ||
|
|
||
| ## Next steps | ||
|
|
||
| - **[Standalone Activities Feature Guide](/develop/rust/activities/standalone-activities)**: Start without waiting, get handles, list and count Activities, and connect to Temporal Cloud. | ||
| - **[Activity basics](/develop/rust/activities/basics)**: How to write and register Activities with the Rust SDK. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have to test this out before approving but so far looks good!