Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ lint = [
"--test",
"manual_tests",
"--test",
"wasm_workflow_tests",
"--test",
"cloud_tests",
"--test",
"integ_runner",
Expand All @@ -53,6 +55,8 @@ lint-fix = [
"--test",
"manual_tests",
"--test",
"wasm_workflow_tests",
"--test",
"cloud_tests",
"--test",
"integ_runner",
Expand Down
34 changes: 25 additions & 9 deletions .github/workflows/per-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,30 @@ jobs:
save-if: ${{ github.ref == 'refs/heads/main' }}
- run: cargo integ-test

wasm-workflow-tests:
name: WASM workflow tests
timeout-minutes: ${{ github.ref == 'refs/heads/main' && 30 || 25 }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- name: Install WASM Rust targets
# Install after checkout so rustup uses this repo's rust-toolchain.toml override.
run: rustup target add wasm32-unknown-unknown wasm32-wasip1
- name: Install protoc
uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3
with:
# TODO: Upgrade proto once https://github.com/arduino/setup-protoc/issues/99 is fixed
version: "23.x"
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
key: wasm-workflow-tests
- name: Install cargo-component
run: cargo install --locked cargo-component
- run: cargo integ-test -t wasm_workflow_tests

cloud-tests:
if: github.event.pull_request.head.repo.full_name == '' || github.event.pull_request.head.repo.full_name == 'temporalio/sdk-rust'
name: Cloud tests
Expand Down Expand Up @@ -275,15 +299,7 @@ jobs:
temporal operator search-attribute create --name CustomKeywordField --type Keyword
temporal operator search-attribute create --name CustomIntField --type Int
- name: Run examples
run: |
for dir in crates/sdk/examples/*/; do
sample="$(basename "$dir" | tr '_' '-')"
cargo run -p temporalio-sdk --features examples --example "${sample}-worker" &
WORKER_PID=$!
timeout 20 cargo run -p temporalio-sdk --features examples --example "${sample}-starter"
kill $WORKER_PID 2>/dev/null || true
wait $WORKER_PID 2>/dev/null || true
done
run: bash ./etc/run-sdk-examples.sh

c-bridge-static-link-test:
name: "C bridge static link test"
Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ document as your quick reference when submitting pull requests.
so helps prevent ambiguous method resolution because of traits. Putting them at the top of a tests module is also acceptable.
- If you want to format, don't bother checking first. Just run formatting, and run it by using
`cargo +nightly fmt`, because some settings require the nightly formatter.
- Do not extract functions for relatively simple helpers that are only used in one location.


## Repo Specific Utilities
Expand Down Expand Up @@ -87,5 +88,5 @@ Reviewers will look for:

- Fetch workflow histories with `cargo run --bin histfetch <workflow_id> [run_id]` (binary lives in
`crates/core/src/histfetch.rs`).
- Protobuf files under `crates/common/protos/api_upstream` are a git subtree; see
- Protobuf files under `crates/protos/protos/api_upstream` are a git subtree; see
`README.md` for update instructions.
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ definitions. The actual implementations of this "service" are not generated by g
the messages themselves are, and make it easier to hit the ground running in new languages.

See the latest API
definition [here](https://github.com/temporalio/sdk-rust/tree/main/crates/common/protos/local/temporal/sdk/core)
definition [here](https://github.com/temporalio/sdk-rust/tree/main/crates/protos/protos/local/temporal/sdk/core)

## Other topics

Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ members = [
"crates/sdk-core",
"crates/client",
"crates/common",
"crates/common-wasm",
"crates/protos",
"crates/macros",
"crates/sdk",
"crates/workflow",
"crates/sdk-core-c-bridge",
]
resolver = "2"
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ equivalent.

## Proto files

This repo uses a subtree for upstream protobuf files. The path `crates/common/protos/api_upstream`
This repo uses a subtree for upstream protobuf files. The path `crates/protos/protos/api_upstream`
is a subtree. To update it, use:

`git pull --squash --rebase=false -s subtree -X subtree=crates/common/protos/api_upstream ssh://git@github.com/temporalio/api.git master --allow-unrelated-histories`
`git pull --squash --rebase=false -s subtree -X subtree=crates/protos/protos/api_upstream ssh://git@github.com/temporalio/api.git master --allow-unrelated-histories`

Do not question why this git command is the way it is. It is not our place to interpret git's ways.
This same approach can be taken for updating `crates/common/protos/api_cloud_upstream` from the
This same approach can be taken for updating `crates/protos/protos/api_cloud_upstream` from the
`api-cloud` repo.

The java testserver protos are also pulled from the sdk-java repo, but since we only need a
Expand All @@ -119,9 +119,9 @@ subdirectory of that repo, we just copy the files with read-tree:
# add sdk-java as a remote if you have not already
git remote add -f -t master --no-tags testsrv-protos git@github.com:temporalio/sdk-java.git
# delete existing protos
git rm -rf crates/common/protos/testsrv_upstream
git rm -rf crates/protos/protos/testsrv_upstream
# pull from upstream & commit
git read-tree --prefix crates/common/protos/testsrv_upstream -u testsrv-protos/master:temporal-test-server/src/main/proto
git read-tree --prefix crates/protos/protos/testsrv_upstream -u testsrv-protos/master:temporal-test-server/src/main/proto
git commit
```

Expand Down
10 changes: 5 additions & 5 deletions crates/client/src/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1932,38 +1932,38 @@ mod tests {
fn verify_all_workflow_service_methods_implemented() {
// This is less work than trying to hook into the codegen process
let proto_def = include_str!(
"../../common/protos/api_upstream/temporal/api/workflowservice/v1/service.proto"
"../../protos/protos/api_upstream/temporal/api/workflowservice/v1/service.proto"
);
verify_methods(proto_def, ALL_IMPLEMENTED_WORKFLOW_SERVICE_RPCS);
}

#[test]
fn verify_all_operator_service_methods_implemented() {
let proto_def = include_str!(
"../../common/protos/api_upstream/temporal/api/operatorservice/v1/service.proto"
"../../protos/protos/api_upstream/temporal/api/operatorservice/v1/service.proto"
);
verify_methods(proto_def, ALL_IMPLEMENTED_OPERATOR_SERVICE_RPCS);
}

#[test]
fn verify_all_cloud_service_methods_implemented() {
let proto_def = include_str!(
"../../common/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto"
"../../protos/protos/api_cloud_upstream/temporal/api/cloud/cloudservice/v1/service.proto"
);
verify_methods(proto_def, ALL_IMPLEMENTED_CLOUD_SERVICE_RPCS);
}

#[test]
fn verify_all_test_service_methods_implemented() {
let proto_def = include_str!(
"../../common/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto"
"../../protos/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto"
);
verify_methods(proto_def, ALL_IMPLEMENTED_TEST_SERVICE_RPCS);
}

#[test]
fn verify_all_health_service_methods_implemented() {
let proto_def = include_str!("../../common/protos/grpc/health/v1/health.proto");
let proto_def = include_str!("../../protos/protos/grpc/health/v1/health.proto");
verify_methods(proto_def, ALL_IMPLEMENTED_HEALTH_SERVICE_RPCS);
}

Expand Down
52 changes: 52 additions & 0 deletions crates/common-wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "temporalio-common-wasm"
version = "0.4.0"
edition = "2024"
authors = ["Temporal Technologies Inc. <sdk@temporal.io>"]
license-file = { workspace = true }
description = "WASM-safe shared functionality for the Temporal Rust workflow surface"
homepage = "https://temporal.io/"
repository = "https://github.com/temporalio/sdk-core"
keywords = ["temporal", "workflow"]
categories = ["development-tools"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
serde_serialize = ["temporalio-protos/serde_serialize"]
grpc-clients = ["temporalio-protos/grpc-clients"]

[dependencies]
anyhow = "1.0"
async-trait = "0.1"
bon = { workspace = true }
crc32fast = "1"
derive_more = { workspace = true }
erased-serde = "0.4"
futures = { version = "0.3", default-features = false, features = ["alloc"] }
parking_lot = { version = "0.12" }
prost = { workspace = true }
serde = { version = "1.0", features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
tracing = "0.1"
tracing-subscriber = { version = "0.3", default-features = false, features = [
"parking_lot",
"env-filter",
"registry",
"ansi",
] }
tracing-core = "0.1"
url = "2.5"
[dependencies.temporalio-protos]
path = "../protos"
version = "0.4"

[lints]
workspace = true

[dev-dependencies]
futures-util = { version = "0.3", default-features = false }
rstest = "0.26"
tempfile = "3.21"
tokio = { version = "1.47", features = ["macros", "rt"] }
73 changes: 73 additions & 0 deletions crates/common-wasm/src/activity_definition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Contains types for activity definitions, used by the code generated by the macros for defining
//! activities, or directly by users targeting activities in other languages.

use crate::{
data_converters::{TemporalDeserializable, TemporalSerializable},
error::{ApplicationFailure, FailurePayloads},
};

/// Implement on a marker struct to define an activity.
///
/// Typically, you will want to use the `#[activity]` attribute within an `#[activities]` macro to
/// define activities. However, this trait may be implemented manually if desired.
pub trait ActivityDefinition {
/// Type of the input argument to the workflow
type Input: TemporalDeserializable + TemporalSerializable + 'static;
/// Type of the output of the workflow
type Output: TemporalDeserializable + TemporalSerializable + 'static;

/// The name that will be used for the activity type.
fn name() -> &'static str
where
Self: Sized;
}

/// Returned as errors from activity functions.
#[derive(Debug)]
pub enum ActivityError {
/// Return this error to attach application-failure metadata to an activity failure.
Application(Box<ApplicationFailure>),
/// Return this error to indicate your activity is cancelling
Cancelled {
/// Optional cancellation details.
details: Option<FailurePayloads>,
},
/// Return this error to indicate that the activity will be completed outside of this activity
/// definition, by an external client.
WillCompleteAsync,
}

impl ActivityError {
/// Construct a cancelled error without details
pub fn cancelled() -> Self {
Self::Cancelled { details: None }
}

/// Construct a cancelled error with details that will be converted using the active data
/// converter.
pub fn cancelled_with_details<T>(details: T) -> Self
where
T: Into<FailurePayloads>,
{
Self::Cancelled {
details: Some(details.into()),
}
}

/// Construct an application activity error.
pub fn application(err: ApplicationFailure) -> Self {
Self::Application(err.into())
}
}

impl<E> From<E> for ActivityError
where
E: Into<anyhow::Error>,
{
fn from(source: E) -> Self {
match source.into().downcast::<ApplicationFailure>() {
Ok(application_failure) => Self::Application(Box::new(application_failure)),
Err(err) => Self::Application(ApplicationFailure::new(err).into()),
}
}
}
File renamed without changes.
39 changes: 39 additions & 0 deletions crates/common-wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#![warn(missing_docs)] // error if there are missing docs

//! This crate contains the shared definitions and serialization/proto surface needed by the
//! workflow authoring APIs, including WASM-targeted builds.

#[allow(unused_imports)] // Not used by all flag combinations, which is fine.
#[macro_use]
extern crate tracing;

mod activity_definition;
pub mod data_converters;
pub mod error;
mod priority;
pub mod protos {
//! Protobuf definitions re-exported from `temporalio-protos`.

pub use temporalio_protos::*;
}
pub mod worker;
mod workflow_definition;

pub use activity_definition::{ActivityDefinition, ActivityError};
pub use priority::Priority;
pub use worker::WorkerDeploymentVersion;
pub use workflow_definition::{
HasWorkflowDefinition, QueryDefinition, SignalDefinition, UntypedWorkflow, UpdateDefinition,
WorkflowDefinition,
};

#[allow(unused_macros)]
macro_rules! dbg_panic {
($($arg:tt)*) => {
use tracing::error;
error!($($arg)*);
debug_assert!(false, $($arg)*);
};
}
#[allow(unused_imports)]
pub(crate) use dbg_panic;
File renamed without changes.
Loading
Loading