From 34f5447dd0d5baf92b0a918289ef8ce87de8534f Mon Sep 17 00:00:00 2001 From: James Watkins-Harvey Date: Fri, 18 Sep 2026 15:42:25 -0400 Subject: [PATCH] [WIP] Add experimental Event Groups support --- CHANGELOG.md | 5 + temporalio/Cargo.lock | 259 +++- temporalio/ext/Cargo.toml | 6 +- temporalio/ext/sdk-core | 2 +- temporalio/ext/src/envconfig.rs | 3 + temporalio/ext/src/worker.rs | 8 +- .../lib/temporalio/api/payload_visitor.rb | 8 + .../api/activity_result/activity_result.rb | 3 +- .../workflow_activation.rb | 3 +- .../workflow_commands/workflow_commands.rb | 3 +- .../internal/worker/workflow_instance.rb | 60 +- .../child_workflow_handle.rb | 4 +- .../worker/workflow_instance/context.rb | 60 +- .../external_workflow_handle.rb | 10 +- .../worker/workflow_instance/nexus_client.rb | 5 +- .../outbound_implementation.rb | 79 +- .../lib/temporalio/worker/interceptor.rb | 24 +- temporalio/lib/temporalio/workflow.rb | 141 +- .../workflow/child_workflow_handle.rb | 4 +- .../lib/temporalio/workflow/event_group.rb | 141 ++ .../workflow/external_workflow_handle.rb | 9 +- temporalio/lib/temporalio/workflow/info.rb | 4 + .../lib/temporalio/workflow/nexus_client.rb | 12 +- .../rbi/temporalio/api/payload_visitor.rbi | 3 + .../workflowservice/v1/service_services.rbi | 13 - .../api/activity_result/activity_result.rbi | 43 +- .../workflow_activation.rbi | 102 +- .../workflow_commands/workflow_commands.rbi | 73 +- .../internal/worker/workflow_instance.rbi | 4 +- .../worker/workflow_instance/context.rbi | 55 +- .../worker/workflow_instance/nexus_client.rbi | 6 +- .../outbound_implementation.rbi | 16 +- .../rbi/temporalio/worker/interceptor.rbi | 24 + temporalio/rbi/temporalio/workflow.rbi | 72 +- .../workflow/child_workflow_handle.rbi | 5 +- .../rbi/temporalio/workflow/event_group.rbi | 81 ++ .../workflow/external_workflow_handle.rbi | 9 +- temporalio/rbi/temporalio/workflow/info.rbi | 3 + .../rbi/temporalio/workflow/nexus_client.rbi | 12 +- .../temporalio/api/enums/v1/failed_cause.rbs | 4 +- .../sig/temporalio/api/payload_visitor.rbs | 1 + .../api/activity_result/activity_result.rbs | 46 + .../workflow_activation.rbs | 44 +- .../workflow_commands/workflow_commands.rbs | 32 + .../internal/worker/workflow_instance.rbs | 2 +- .../worker/workflow_instance/context.rbs | 30 +- .../worker/workflow_instance/nexus_client.rbs | 3 +- .../outbound_implementation.rbs | 13 +- .../sig/temporalio/worker/interceptor.rbs | 32 +- temporalio/sig/temporalio/workflow.rbs | 40 +- .../workflow/child_workflow_handle.rbs | 3 +- .../sig/temporalio/workflow/event_group.rbs | 38 + .../workflow/external_workflow_handle.rbs | 5 +- temporalio/sig/temporalio/workflow/info.rbs | 2 + .../sig/temporalio/workflow/nexus_client.rbs | 6 +- temporalio/test/base64_codec.rb | 1 + .../sig/worker_workflow_event_groups_test.rbs | 34 + .../test/worker_workflow_event_groups_test.rb | 1216 +++++++++++++++++ temporalio/test/worker_workflow_test.rb | 1 + 59 files changed, 2607 insertions(+), 320 deletions(-) create mode 100644 temporalio/lib/temporalio/workflow/event_group.rb create mode 100644 temporalio/rbi/temporalio/workflow/event_group.rbi create mode 100644 temporalio/sig/temporalio/workflow/event_group.rbs create mode 100644 temporalio/test/sig/worker_workflow_event_groups_test.rbs create mode 100644 temporalio/test/worker_workflow_event_groups_test.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 89546f02..8aebad07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,11 @@ to docs, or any other relevant information. ### Added +- Experimental Event Groups: `Workflow.create_event_group`, `Workflow.with_event_groups`, and + `event_groups:` on workflow command APIs. Signal and update handlers get implicit inbound groups. +- Added `Workflow::Info#original_execution_run_id`, the run ID recorded on the workflow execution + started event. Unlike `#run_id`, this value is preserved across workflow resets. + ### Changed ### Deprecated diff --git a/temporalio/Cargo.lock b/temporalio/Cargo.lock index c53d6943..4c71c029 100644 --- a/temporalio/Cargo.lock +++ b/temporalio/Cargo.lock @@ -276,6 +276,18 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + [[package]] name = "bimap" version = "0.6.3" @@ -1548,7 +1560,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-util", @@ -1923,6 +1935,72 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "logos" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154" +dependencies = [ + "logos-derive 0.15.1", +] + +[[package]] +name = "logos" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" +dependencies = [ + "logos-derive 0.16.1", +] + +[[package]] +name = "logos-codegen" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "192a3a2b90b0c05b27a0b2c43eecdb7c415e29243acc3f89cc8247a5b693045c" +dependencies = [ + "beef", + "fnv", + "lazy_static", + "proc-macro2", + "quote", + "regex-syntax", + "rustc_version", + "syn", +] + +[[package]] +name = "logos-codegen" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" +dependencies = [ + "fnv", + "proc-macro2", + "quote", + "regex-automata", + "regex-syntax", + "syn", +] + +[[package]] +name = "logos-derive" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470" +dependencies = [ + "logos-codegen 0.15.1", +] + +[[package]] +name = "logos-derive" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" +dependencies = [ + "logos-codegen 0.16.1", +] + [[package]] name = "lru" version = "0.18.0" @@ -2000,6 +2078,28 @@ dependencies = [ "rustix", ] +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "cfg-if", + "miette-derive", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "mime" version = "0.3.17" @@ -2293,7 +2393,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8edd1efdd8ab23ba9cb9ace3d9987a72663d5d7c9f74fa00b51d6213645cf6c" dependencies = [ - "base64", + "base64 0.22.1", "serde", ] @@ -2562,6 +2662,18 @@ dependencies = [ "syn", ] +[[package]] +name = "prost-reflect" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b80ea363c31af2de2b92e3c07ed1156628f7838c4afb4df75ee78a37fedbd1" +dependencies = [ + "logos 0.16.1", + "miette", + "prost", + "prost-types", +] + [[package]] name = "prost-types" version = "0.14.4" @@ -2611,12 +2723,40 @@ dependencies = [ "prost-types", "prost-wkt", "prost-wkt-build", + "protox", "regex", "serde", "serde_derive", "serde_json", ] +[[package]] +name = "protox" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f25a07a73c6717f0b9bbbd685918f5df9815f7efba450b83d9c9dea41f0e3a1" +dependencies = [ + "bytes", + "miette", + "prost", + "prost-reflect", + "prost-types", + "protox-parse", + "thiserror 2.0.18", +] + +[[package]] +name = "protox-parse" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "072eee358134396a4643dff81cfff1c255c9fbd3fb296be14bdb6a26f9156366" +dependencies = [ + "logos 0.15.1", + "miette", + "prost-types", + "thiserror 2.0.18", +] + [[package]] name = "pulldown-cmark" version = "0.13.4" @@ -2959,7 +3099,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", @@ -3526,13 +3666,13 @@ dependencies = [ [[package]] name = "temporalio-client" -version = "0.6.0" +version = "1.0.0" dependencies = [ "anyhow", "assert_matches", "async-trait", "backon", - "base64", + "base64 0.23.1", "bon", "bytes", "derive_more", @@ -3554,19 +3694,23 @@ dependencies = [ "serde_json", "tempfile", "temporalio-common", + "temporalio-macros", + "temporalio-workflow", "thiserror 2.0.18", "tokio", "tokio-rustls", + "tokio-stream", "tonic", "tower", "tracing", + "trybuild", "url", "uuid", ] [[package]] name = "temporalio-common" -version = "0.6.0" +version = "1.0.0" dependencies = [ "anyhow", "async-trait", @@ -3610,7 +3754,7 @@ dependencies = [ [[package]] name = "temporalio-common-wasm" -version = "0.6.0" +version = "1.0.0" dependencies = [ "anyhow", "async-trait", @@ -3639,7 +3783,7 @@ dependencies = [ [[package]] name = "temporalio-macros" -version = "0.6.0" +version = "1.0.0" dependencies = [ "derive_more", "proc-macro2", @@ -3650,17 +3794,17 @@ dependencies = [ [[package]] name = "temporalio-protos" -version = "0.6.0" +version = "0.9.0" dependencies = [ "anyhow", - "base64", + "base64 0.23.1", "derive_more", "http", "pbjson", "pbjson-build", "prost", - "prost-types", "prost-wkt-types", + "protox", "serde", "serde_json", "thiserror 2.0.18", @@ -3671,7 +3815,7 @@ dependencies = [ [[package]] name = "temporalio-sdk" -version = "0.6.0" +version = "1.0.0" dependencies = [ "anyhow", "async-trait", @@ -3696,13 +3840,14 @@ dependencies = [ "tokio-stream", "tokio-util", "tracing", + "url", "uuid", "wasmtime", ] [[package]] name = "temporalio-sdk-core" -version = "0.6.0" +version = "0.9.0" dependencies = [ "antithesis_sdk", "anyhow", @@ -3768,7 +3913,7 @@ dependencies = [ [[package]] name = "temporalio-workflow" -version = "0.6.0" +version = "1.0.0" dependencies = [ "anyhow", "bon", @@ -3779,12 +3924,14 @@ dependencies = [ "prost-wkt-types", "rand 0.10.2", "rand_pcg", + "rstest", "serde", + "siphasher", "temporalio-common-wasm", "temporalio-macros", "thiserror 2.0.18", "uuid", - "wit-bindgen", + "wit-bindgen 0.61.1", ] [[package]] @@ -4061,7 +4208,7 @@ checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", - "base64", + "base64 0.22.1", "bytes", "flate2", "h2", @@ -4328,6 +4475,12 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode-width" version = "0.2.2" @@ -4430,7 +4583,7 @@ version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -4517,34 +4670,34 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.247.0" +version = "0.253.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b6733b8b91d010a6ac5b0fb237dc46a19650bc4c67db66857e2e787d437204" +checksum = "59972d6cd272259de647b7c1f1912e45e289c75ffd4be04e10695507cd7e1b59" dependencies = [ "leb128fmt", - "wasmparser 0.247.0", + "wasmparser 0.253.0", ] [[package]] name = "wasm-encoder" -version = "0.253.0" +version = "0.258.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59972d6cd272259de647b7c1f1912e45e289c75ffd4be04e10695507cd7e1b59" +checksum = "e974fe6821a8cf64575d51ea2194e2c8f77e7b66e9afe7419ce8a97f9ee0d251" dependencies = [ "leb128fmt", - "wasmparser 0.253.0", + "wasmparser 0.258.0", ] [[package]] name = "wasm-metadata" -version = "0.247.0" +version = "0.258.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "665fe59e56cc9b419ca6fcca56673e3421d1a5011e3b65caf6b726fd9e041d10" +checksum = "18a11585adb92fe9b55ad1d760e8d8fb5d87e0d2e303cb8eed57f078d54293a2" dependencies = [ "anyhow", "indexmap", - "wasm-encoder 0.247.0", - "wasmparser 0.247.0", + "wasm-encoder 0.258.0", + "wasmparser 0.258.0", ] [[package]] @@ -4575,23 +4728,23 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.247.0" +version = "0.253.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6fb4c2bee46c5ea4d40f8cdb5c131725cd976718ec56f1c8e82fbde5fa2a80" +checksum = "19db11f87d2486580e1e8b6f494c54df7e0566b87d0b599db843c24019667339" dependencies = [ "bitflags", - "hashbrown 0.17.1", "indexmap", "semver", ] [[package]] name = "wasmparser" -version = "0.253.0" +version = "0.258.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19db11f87d2486580e1e8b6f494c54df7e0566b87d0b599db843c24019667339" +checksum = "d9a61719f93a87b16d325921e251800c4833f8fab50fa21c7de73aed50086313" dependencies = [ "bitflags", + "hashbrown 0.17.1", "indexmap", "semver", ] @@ -4697,7 +4850,7 @@ version = "44.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f14b8b93c2137c88ed84114d9a09cb11cb8bf9394aba4856e48f5304a4f99eec" dependencies = [ - "base64", + "base64 0.22.1", "directories-next", "log", "postcard", @@ -4873,7 +5026,7 @@ dependencies = [ "bumpalo", "leb128fmt", "memchr", - "unicode-width", + "unicode-width 0.2.2", "wasm-encoder 0.253.0", ] @@ -5177,6 +5330,12 @@ name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e473fd0095479f9689ac7d2a52c427cc96bb2b973ace50238dfcc1ab1cd52d93" dependencies = [ "bitflags", "wit-bindgen-rust-macro", @@ -5184,20 +5343,20 @@ dependencies = [ [[package]] name = "wit-bindgen-core" -version = "0.57.1" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dee27a2dc20d1008016c742ec9fc6ea498492994ba3750be7454cbc97ff04c" +checksum = "87445680dfe6d6b5369e884bd63c03a3335268e855365b2fc3f7bcdce96a630e" dependencies = [ "anyhow", "heck", - "wit-parser 0.247.0", + "wit-parser 0.258.0", ] [[package]] name = "wit-bindgen-rust" -version = "0.57.1" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5007dae772945b7a5003d69d90a3a4a78929d41f19d004e980c4259a6af4484" +checksum = "72f2fe494de0d898216caf0fd0ae76af75753fcb3ff4f465b46131537cf24cf8" dependencies = [ "anyhow", "heck", @@ -5211,9 +5370,9 @@ dependencies = [ [[package]] name = "wit-bindgen-rust-macro" -version = "0.57.1" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9237d678e3513ad24e96fe98beacdc0db6405284ba2a2400418cf0d42caa89" +checksum = "59283a01aec94f60f92ada22ffe182a5cea8acfce43be3be688de8d52df55312" dependencies = [ "anyhow", "prettyplease", @@ -5226,9 +5385,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.247.0" +version = "0.258.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d567162a6b9843080e5e0053f696623ff694bae8ae017c9ec536d1873bbe3d8" +checksum = "481b5c47b2ecce0389b5e08a05557d6a190c9cd761773b8880a8017ee04dc7ef" dependencies = [ "anyhow", "bitflags", @@ -5237,10 +5396,10 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.247.0", + "wasm-encoder 0.258.0", "wasm-metadata", - "wasmparser 0.247.0", - "wit-parser 0.247.0", + "wasmparser 0.258.0", + "wit-parser 0.258.0", ] [[package]] @@ -5264,9 +5423,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.247.0" +version = "0.258.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ffe4064318cdf3c08cb99343b44c039fcefe61ccdf58aa9975285f13d74d1fc" +checksum = "ff4daaa3cd97ae49ecd0a99dc009d453f93e0f083dd3be38c0f24a83a93e37ac" dependencies = [ "anyhow", "hashbrown 0.17.1", @@ -5277,8 +5436,8 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "unicode-xid", - "wasmparser 0.247.0", + "unicode-ident", + "wasmparser 0.258.0", ] [[package]] diff --git a/temporalio/ext/Cargo.toml b/temporalio/ext/Cargo.toml index a1f8bdf6..5ccce17b 100644 --- a/temporalio/ext/Cargo.toml +++ b/temporalio/ext/Cargo.toml @@ -17,9 +17,9 @@ magnus = "0.8" parking_lot = "0.12" prost = { workspace = true } rb-sys = "0.9" -temporalio-client = { version = "0.6.0", path = "./sdk-core/crates/client", default-features = false, features = ["envconfig"] } -temporalio-common = { version = "0.6.0", path = "./sdk-core/crates/common", features = ["envconfig", "prometheus"] } -temporalio-sdk-core = { version = "0.6.0", path = "./sdk-core/crates/sdk-core", default-features = false, features = ["ephemeral-server"] } +temporalio-client = { version = "1.0.0", path = "./sdk-core/crates/client", default-features = false, features = ["envconfig", "experimental"] } +temporalio-common = { version = "1.0.0", path = "./sdk-core/crates/common", features = ["envconfig", "prometheus"] } +temporalio-sdk-core = { version = "0.9.0", path = "./sdk-core/crates/sdk-core", default-features = false, features = ["ephemeral-server"] } tokio = "1.47" tokio-stream = "0.1" tokio-util = "0.7" diff --git a/temporalio/ext/sdk-core b/temporalio/ext/sdk-core index 782c738e..24dc2d9b 160000 --- a/temporalio/ext/sdk-core +++ b/temporalio/ext/sdk-core @@ -1 +1 @@ -Subproject commit 782c738ecad0a203a2d7070c1c6d0fd053b8d663 +Subproject commit 24dc2d9b0643ddbaa63a7d7b6c3ac00c16a46a73 diff --git a/temporalio/ext/src/envconfig.rs b/temporalio/ext/src/envconfig.rs index 10c1846f..b6a628f8 100644 --- a/temporalio/ext/src/envconfig.rs +++ b/temporalio/ext/src/envconfig.rs @@ -33,6 +33,9 @@ fn data_source_to_hash(ruby: &Ruby, ds: &DataSource) -> Result { DataSource::Data(d) => { hash.aset(ruby.sym_new("data"), ruby.str_from_slice(d))?; } + _ => { + return Err(error!("Unknown envconfig data source variant")); + } } Ok(hash) } diff --git a/temporalio/ext/src/worker.rs b/temporalio/ext/src/worker.rs index ce3a30fb..b9caac74 100644 --- a/temporalio/ext/src/worker.rs +++ b/temporalio/ext/src/worker.rs @@ -480,10 +480,10 @@ fn build_config(options: Struct, runtime_handle: &RuntimeHandle) -> Result(id!("deployment_name"))?, - build_id: version.member::(id!("build_id"))?, - }; + let deployment_version = WorkerDeploymentVersion::builder() + .deployment_name(version.member::(id!("deployment_name"))?) + .build_id(version.member::(id!("build_id"))?) + .build(); let default_versioning_behavior = { let val = dopts.member::(id!("default_versioning_behavior"))?; if val == 0 { diff --git a/temporalio/lib/temporalio/api/payload_visitor.rb b/temporalio/lib/temporalio/api/payload_visitor.rb index 00ebea27..bfaf12ce 100644 --- a/temporalio/lib/temporalio/api/payload_visitor.rb +++ b/temporalio/lib/temporalio/api/payload_visitor.rb @@ -1828,6 +1828,12 @@ def coresdk_workflow_activation_workflow_activation_job(value) @on_exit&.call(value) end + def coresdk_workflow_commands_cancel_workflow_execution(value) + @on_enter&.call(value) + api_common_v1_payloads(value.details) if value.has_details? + @on_exit&.call(value) + end + def coresdk_workflow_commands_complete_workflow_execution(value) @on_enter&.call(value) api_common_v1_payload(value.result) if value.has_result? @@ -1920,11 +1926,13 @@ def coresdk_workflow_commands_upsert_workflow_search_attributes(value) def coresdk_workflow_commands_workflow_command(value) @on_enter&.call(value) api_sdk_v1_user_metadata(value.user_metadata) if value.has_user_metadata? + value.event_group_markers.each { |v| api_sdk_v1_event_group_marker(v) } coresdk_workflow_commands_schedule_activity(value.schedule_activity) if value.has_schedule_activity? coresdk_workflow_commands_query_result(value.respond_to_query) if value.has_respond_to_query? coresdk_workflow_commands_complete_workflow_execution(value.complete_workflow_execution) if value.has_complete_workflow_execution? coresdk_workflow_commands_fail_workflow_execution(value.fail_workflow_execution) if value.has_fail_workflow_execution? coresdk_workflow_commands_continue_as_new_workflow_execution(value.continue_as_new_workflow_execution) if value.has_continue_as_new_workflow_execution? + coresdk_workflow_commands_cancel_workflow_execution(value.cancel_workflow_execution) if value.has_cancel_workflow_execution? coresdk_workflow_commands_start_child_workflow_execution(value.start_child_workflow_execution) if value.has_start_child_workflow_execution? coresdk_workflow_commands_signal_external_workflow_execution(value.signal_external_workflow_execution) if value.has_signal_external_workflow_execution? coresdk_workflow_commands_schedule_local_activity(value.schedule_local_activity) if value.has_schedule_local_activity? diff --git a/temporalio/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb b/temporalio/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb index 179836e5..2002b4cc 100644 --- a/temporalio/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb +++ b/temporalio/lib/temporalio/internal/bridge/api/activity_result/activity_result.rb @@ -10,7 +10,7 @@ require 'temporalio/api/failure/v1/message' -descriptor_data = "\n7temporal/sdk/core/activity_result/activity_result.proto\x12\x17\x63oresdk.activity_result\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\"\x95\x02\n\x17\x41\x63tivityExecutionResult\x12\x35\n\tcompleted\x18\x01 \x01(\x0b\x32 .coresdk.activity_result.SuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x02 \x01(\x0b\x32 .coresdk.activity_result.FailureH\x00\x12:\n\tcancelled\x18\x03 \x01(\x0b\x32%.coresdk.activity_result.CancellationH\x00\x12I\n\x13will_complete_async\x18\x04 \x01(\x0b\x32*.coresdk.activity_result.WillCompleteAsyncH\x00\x42\x08\n\x06status\"\xfc\x01\n\x12\x41\x63tivityResolution\x12\x35\n\tcompleted\x18\x01 \x01(\x0b\x32 .coresdk.activity_result.SuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x02 \x01(\x0b\x32 .coresdk.activity_result.FailureH\x00\x12:\n\tcancelled\x18\x03 \x01(\x0b\x32%.coresdk.activity_result.CancellationH\x00\x12\x35\n\x07\x62\x61\x63koff\x18\x04 \x01(\x0b\x32\".coresdk.activity_result.DoBackoffH\x00\x42\x08\n\x06status\":\n\x07Success\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\"<\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"A\n\x0c\x43\x61ncellation\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\x13\n\x11WillCompleteAsync\"\x8d\x01\n\tDoBackoff\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\r\x12\x33\n\x10\x62\x61\x63koff_duration\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12:\n\x16original_schedule_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB4\xea\x02\x31Temporalio::Internal::Bridge::Api::ActivityResultb\x06proto3" +descriptor_data = "\n7temporal/sdk/core/activity_result/activity_result.proto\x12\x17\x63oresdk.activity_result\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a$temporal/api/common/v1/message.proto\x1a%temporal/api/failure/v1/message.proto\"\x95\x02\n\x17\x41\x63tivityExecutionResult\x12\x35\n\tcompleted\x18\x01 \x01(\x0b\x32 .coresdk.activity_result.SuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x02 \x01(\x0b\x32 .coresdk.activity_result.FailureH\x00\x12:\n\tcancelled\x18\x03 \x01(\x0b\x32%.coresdk.activity_result.CancellationH\x00\x12I\n\x13will_complete_async\x18\x04 \x01(\x0b\x32*.coresdk.activity_result.WillCompleteAsyncH\x00\x42\x08\n\x06status\"\xfc\x01\n\x12\x41\x63tivityResolution\x12\x35\n\tcompleted\x18\x01 \x01(\x0b\x32 .coresdk.activity_result.SuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x02 \x01(\x0b\x32 .coresdk.activity_result.FailureH\x00\x12:\n\tcancelled\x18\x03 \x01(\x0b\x32%.coresdk.activity_result.CancellationH\x00\x12\x35\n\x07\x62\x61\x63koff\x18\x04 \x01(\x0b\x32\".coresdk.activity_result.DoBackoffH\x00\x42\x08\n\x06status\":\n\x07Success\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\"}\n\x07\x46\x61ilure\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12?\n\x05\x63\x61use\x18\x02 \x01(\x0e\x32\x30.coresdk.activity_result.ActivityTaskFailedCause\"A\n\x0c\x43\x61ncellation\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\x13\n\x11WillCompleteAsync\"\x8d\x01\n\tDoBackoff\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\r\x12\x33\n\x10\x62\x61\x63koff_duration\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12:\n\x16original_schedule_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp*\xf3\x01\n\x17\x41\x63tivityTaskFailedCause\x12*\n&ACTIVITY_TASK_FAILED_CAUSE_UNSPECIFIED\x10\x00\x12\x31\n-ACTIVITY_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE\x10\x01\x12\x37\n3ACTIVITY_TASK_FAILED_CAUSE_EXTERNAL_STORAGE_FAILURE\x10\x02\x12@\n.coresdk.child_workflow.StartChildWorkflowExecutionFailedCause\"`\n+ResolveChildWorkflowExecutionStartCancelled\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"i\n\x1dResolveChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.child_workflow.ChildWorkflowResult\"+\n\x10UpdateRandomSeed\x12\x17\n\x0frandomness_seed\x18\x01 \x01(\x04\"\x84\x02\n\rQueryWorkflow\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12\x12\n\nquery_type\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12H\n\x07headers\x18\x05 \x03(\x0b\x32\x37.coresdk.workflow_activation.QueryWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\" \n\x0e\x43\x61ncelWorkflow\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\x83\x02\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12.\n\x05input\x18\x02 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x10\n\x08identity\x18\x03 \x01(\t\x12I\n\x07headers\x18\x05 \x03(\x0b\x32\x38.coresdk.workflow_activation.SignalWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\"\n\x0eNotifyHasPatch\x12\x10\n\x08patch_id\x18\x01 \x01(\t\"_\n\x1dResolveSignalExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"f\n$ResolveRequestCancelExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\xcb\x02\n\x08\x44oUpdate\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1c\n\x14protocol_instance_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x43\n\x07headers\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.DoUpdate.HeadersEntry\x12*\n\x04meta\x18\x06 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x15\n\rrun_validator\x18\x07 \x01(\x08\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x9a\x01\n\x1aResolveNexusOperationStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x19\n\x0foperation_token\x18\x02 \x01(\tH\x00\x12\x16\n\x0cstarted_sync\x18\x03 \x01(\x08H\x00\x12\x32\n\x06\x66\x61iled\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status\"Y\n\x15ResolveNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x33\n\x06result\x18\x02 \x01(\x0b\x32#.coresdk.nexus.NexusOperationResult\"\xe0\x02\n\x0fRemoveFromCache\x12\x0f\n\x07message\x18\x01 \x01(\t\x12K\n\x06reason\x18\x02 \x01(\x0e\x32;.coresdk.workflow_activation.RemoveFromCache.EvictionReason\"\xee\x01\n\x0e\x45victionReason\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCACHE_FULL\x10\x01\x12\x0e\n\nCACHE_MISS\x10\x02\x12\x12\n\x0eNONDETERMINISM\x10\x03\x12\r\n\tLANG_FAIL\x10\x04\x12\x12\n\x0eLANG_REQUESTED\x10\x05\x12\x12\n\x0eTASK_NOT_FOUND\x10\x06\x12\x15\n\x11UNHANDLED_COMMAND\x10\x07\x12\t\n\x05\x46\x41TAL\x10\x08\x12\x1f\n\x1bPAGINATION_OR_HISTORY_FETCH\x10\t\x12\x1d\n\x19WORKFLOW_EXECUTION_ENDING\x10\nB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowActivationb\x06proto3" +descriptor_data = "\n?temporal/sdk/core/workflow_activation/workflow_activation.proto\x12\x1b\x63oresdk.workflow_activation\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a%temporal/api/failure/v1/message.proto\x1a$temporal/api/update/v1/message.proto\x1a$temporal/api/common/v1/message.proto\x1a(temporal/api/enums/v1/failed_cause.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a\x37temporal/sdk/core/activity_result/activity_result.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a%temporal/sdk/core/common/common.proto\x1a#temporal/sdk/core/nexus/nexus.proto\"\xa2\x04\n\x12WorkflowActivation\x12\x0e\n\x06run_id\x18\x01 \x01(\t\x12-\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0cis_replaying\x18\x03 \x01(\x08\x12\x16\n\x0ehistory_length\x18\x04 \x01(\r\x12@\n\x04jobs\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.WorkflowActivationJob\x12 \n\x18\x61vailable_internal_flags\x18\x06 \x03(\r\x12\x1a\n\x12history_size_bytes\x18\x07 \x01(\x04\x12!\n\x19\x63ontinue_as_new_suggested\x18\x08 \x01(\x08\x12T\n#deployment_version_for_current_task\x18\t \x01(\x0b\x32\'.coresdk.common.WorkerDeploymentVersion\x12\x18\n\x10last_sdk_version\x18\n \x01(\t\x12Z\n\x1fsuggest_continue_as_new_reasons\x18\x0b \x03(\x0e\x32\x31.temporal.api.enums.v1.SuggestContinueAsNewReason\x12\x30\n(target_worker_deployment_version_changed\x18\x0c \x01(\x08\"\xe0\n\n\x15WorkflowActivationJob\x12N\n\x13initialize_workflow\x18\x01 \x01(\x0b\x32/.coresdk.workflow_activation.InitializeWorkflowH\x00\x12<\n\nfire_timer\x18\x02 \x01(\x0b\x32&.coresdk.workflow_activation.FireTimerH\x00\x12K\n\x12update_random_seed\x18\x04 \x01(\x0b\x32-.coresdk.workflow_activation.UpdateRandomSeedH\x00\x12\x44\n\x0equery_workflow\x18\x05 \x01(\x0b\x32*.coresdk.workflow_activation.QueryWorkflowH\x00\x12\x46\n\x0f\x63\x61ncel_workflow\x18\x06 \x01(\x0b\x32+.coresdk.workflow_activation.CancelWorkflowH\x00\x12\x46\n\x0fsignal_workflow\x18\x07 \x01(\x0b\x32+.coresdk.workflow_activation.SignalWorkflowH\x00\x12H\n\x10resolve_activity\x18\x08 \x01(\x0b\x32,.coresdk.workflow_activation.ResolveActivityH\x00\x12G\n\x10notify_has_patch\x18\t \x01(\x0b\x32+.coresdk.workflow_activation.NotifyHasPatchH\x00\x12q\n&resolve_child_workflow_execution_start\x18\n \x01(\x0b\x32?.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartH\x00\x12\x66\n resolve_child_workflow_execution\x18\x0b \x01(\x0b\x32:.coresdk.workflow_activation.ResolveChildWorkflowExecutionH\x00\x12\x66\n resolve_signal_external_workflow\x18\x0c \x01(\x0b\x32:.coresdk.workflow_activation.ResolveSignalExternalWorkflowH\x00\x12u\n(resolve_request_cancel_external_workflow\x18\r \x01(\x0b\x32\x41.coresdk.workflow_activation.ResolveRequestCancelExternalWorkflowH\x00\x12:\n\tdo_update\x18\x0e \x01(\x0b\x32%.coresdk.workflow_activation.DoUpdateH\x00\x12`\n\x1dresolve_nexus_operation_start\x18\x0f \x01(\x0b\x32\x37.coresdk.workflow_activation.ResolveNexusOperationStartH\x00\x12U\n\x17resolve_nexus_operation\x18\x10 \x01(\x0b\x32\x32.coresdk.workflow_activation.ResolveNexusOperationH\x00\x12I\n\x11remove_from_cache\x18\x32 \x01(\x0b\x32,.coresdk.workflow_activation.RemoveFromCacheH\x00\x42\t\n\x07variant\"\xfc\n\n\x12InitializeWorkflow\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x17\n\x0frandomness_seed\x18\x04 \x01(\x04\x12M\n\x07headers\x18\x05 \x03(\x0b\x32<.coresdk.workflow_activation.InitializeWorkflow.HeadersEntry\x12\x10\n\x08identity\x18\x06 \x01(\t\x12I\n\x14parent_workflow_info\x18\x07 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12=\n\x1aworkflow_execution_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\'\n\x1f\x63ontinued_from_execution_run_id\x18\x0b \x01(\t\x12J\n\x13\x63ontinued_initiator\x18\x0c \x01(\x0e\x32-.temporal.api.enums.v1.ContinueAsNewInitiator\x12;\n\x11\x63ontinued_failure\x18\r \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12@\n\x16last_completion_result\x18\x0e \x01(\x0b\x32 .temporal.api.common.v1.Payloads\x12\x1e\n\x16\x66irst_execution_run_id\x18\x0f \x01(\t\x12\x39\n\x0cretry_policy\x18\x10 \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x0f\n\x07\x61ttempt\x18\x11 \x01(\x05\x12\x15\n\rcron_schedule\x18\x12 \x01(\t\x12\x46\n\"workflow_execution_expiration_time\x18\x13 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x45\n\"cron_schedule_to_schedule_interval\x18\x14 \x01(\x0b\x32\x19.google.protobuf.Duration\x12*\n\x04memo\x18\x15 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\x12\x43\n\x11search_attributes\x18\x16 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12.\n\nstart_time\x18\x17 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12@\n\rroot_workflow\x18\x18 \x01(\x0b\x32).temporal.api.common.v1.WorkflowExecution\x12\x32\n\x08priority\x18\x19 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x12!\n\x19original_execution_run_id\x18\x1a \x01(\t\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x18\n\tFireTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\"m\n\x0fResolveActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.activity_result.ActivityResolution\x12\x10\n\x08is_local\x18\x03 \x01(\x08\"\xd1\x02\n\"ResolveChildWorkflowExecutionStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12[\n\tsucceeded\x18\x02 \x01(\x0b\x32\x46.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartSuccessH\x00\x12X\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32\x46.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartFailureH\x00\x12]\n\tcancelled\x18\x04 \x01(\x0b\x32H.coresdk.workflow_activation.ResolveChildWorkflowExecutionStartCancelledH\x00\x42\x08\n\x06status\";\n)ResolveChildWorkflowExecutionStartSuccess\x12\x0e\n\x06run_id\x18\x01 \x01(\t\"\xa6\x01\n)ResolveChildWorkflowExecutionStartFailure\x12\x13\n\x0bworkflow_id\x18\x01 \x01(\t\x12\x15\n\rworkflow_type\x18\x02 \x01(\t\x12M\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32>.coresdk.child_workflow.StartChildWorkflowExecutionFailedCause\"`\n+ResolveChildWorkflowExecutionStartCancelled\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"i\n\x1dResolveChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12;\n\x06result\x18\x02 \x01(\x0b\x32+.coresdk.child_workflow.ChildWorkflowResult\"+\n\x10UpdateRandomSeed\x12\x17\n\x0frandomness_seed\x18\x01 \x01(\x04\"\x84\x02\n\rQueryWorkflow\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12\x12\n\nquery_type\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12H\n\x07headers\x18\x05 \x03(\x0b\x32\x37.coresdk.workflow_activation.QueryWorkflow.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\" \n\x0e\x43\x61ncelWorkflow\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xa1\x02\n\x0eSignalWorkflow\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12.\n\x05input\x18\x02 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x10\n\x08identity\x18\x03 \x01(\t\x12I\n\x07headers\x18\x05 \x03(\x0b\x32\x38.coresdk.workflow_activation.SignalWorkflow.HeadersEntry\x12\x1c\n\x14originating_event_id\x18\x06 \x01(\x03\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\"\n\x0eNotifyHasPatch\x12\x10\n\x08patch_id\x18\x01 \x01(\t\"\xb1\x01\n\x1dResolveSignalExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12P\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32\x41.temporal.api.enums.v1.SignalExternalWorkflowExecutionFailedCause\"\xb8\x01\n$ResolveRequestCancelExternalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x31\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\x12P\n\x05\x63\x61use\x18\x03 \x01(\x0e\x32\x41.temporal.api.enums.v1.CancelExternalWorkflowExecutionFailedCause\"\xcb\x02\n\x08\x44oUpdate\x12\n\n\x02id\x18\x01 \x01(\t\x12\x1c\n\x14protocol_instance_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12.\n\x05input\x18\x04 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x43\n\x07headers\x18\x05 \x03(\x0b\x32\x32.coresdk.workflow_activation.DoUpdate.HeadersEntry\x12*\n\x04meta\x18\x06 \x01(\x0b\x32\x1c.temporal.api.update.v1.Meta\x12\x15\n\rrun_validator\x18\x07 \x01(\x08\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x9a\x01\n\x1aResolveNexusOperationStart\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x19\n\x0foperation_token\x18\x02 \x01(\tH\x00\x12\x16\n\x0cstarted_sync\x18\x03 \x01(\x08H\x00\x12\x32\n\x06\x66\x61iled\x18\x04 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\x08\n\x06status\"Y\n\x15ResolveNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x33\n\x06result\x18\x02 \x01(\x0b\x32#.coresdk.nexus.NexusOperationResult\"\xe0\x02\n\x0fRemoveFromCache\x12\x0f\n\x07message\x18\x01 \x01(\t\x12K\n\x06reason\x18\x02 \x01(\x0e\x32;.coresdk.workflow_activation.RemoveFromCache.EvictionReason\"\xee\x01\n\x0e\x45victionReason\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0e\n\nCACHE_FULL\x10\x01\x12\x0e\n\nCACHE_MISS\x10\x02\x12\x12\n\x0eNONDETERMINISM\x10\x03\x12\r\n\tLANG_FAIL\x10\x04\x12\x12\n\x0eLANG_REQUESTED\x10\x05\x12\x12\n\x0eTASK_NOT_FOUND\x10\x06\x12\x15\n\x11UNHANDLED_COMMAND\x10\x07\x12\t\n\x05\x46\x41TAL\x10\x08\x12\x1f\n\x1bPAGINATION_OR_HISTORY_FETCH\x10\t\x12\x1d\n\x19WORKFLOW_EXECUTION_ENDING\x10\nB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowActivationb\x06proto3" pool = ::Google::Protobuf::DescriptorPool.generated_pool pool.add_serialized_file(descriptor_data) diff --git a/temporalio/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb b/temporalio/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb index 1cc2391b..80487b3e 100644 --- a/temporalio/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb +++ b/temporalio/lib/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rb @@ -11,12 +11,13 @@ require 'temporalio/api/enums/v1/workflow' require 'temporalio/api/failure/v1/message' require 'temporalio/api/sdk/v1/user_metadata' +require 'temporalio/api/sdk/v1/event_group_marker' require 'temporalio/internal/bridge/api/child_workflow/child_workflow' require 'temporalio/internal/bridge/api/nexus/nexus' require 'temporalio/internal/bridge/api/common/common' -descriptor_data = "\n;temporal/sdk/core/workflow_commands/workflow_commands.proto\x12\x19\x63oresdk.workflow_commands\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a#temporal/sdk/core/nexus/nexus.proto\x1a%temporal/sdk/core/common/common.proto\"\xe5\x0f\n\x0fWorkflowCommand\x12\x38\n\ruser_metadata\x18\x64 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12<\n\x0bstart_timer\x18\x01 \x01(\x0b\x32%.coresdk.workflow_commands.StartTimerH\x00\x12H\n\x11schedule_activity\x18\x02 \x01(\x0b\x32+.coresdk.workflow_commands.ScheduleActivityH\x00\x12\x42\n\x10respond_to_query\x18\x03 \x01(\x0b\x32&.coresdk.workflow_commands.QueryResultH\x00\x12S\n\x17request_cancel_activity\x18\x04 \x01(\x0b\x32\x30.coresdk.workflow_commands.RequestCancelActivityH\x00\x12>\n\x0c\x63\x61ncel_timer\x18\x05 \x01(\x0b\x32&.coresdk.workflow_commands.CancelTimerH\x00\x12[\n\x1b\x63omplete_workflow_execution\x18\x06 \x01(\x0b\x32\x34.coresdk.workflow_commands.CompleteWorkflowExecutionH\x00\x12S\n\x17\x66\x61il_workflow_execution\x18\x07 \x01(\x0b\x32\x30.coresdk.workflow_commands.FailWorkflowExecutionH\x00\x12g\n\"continue_as_new_workflow_execution\x18\x08 \x01(\x0b\x32\x39.coresdk.workflow_commands.ContinueAsNewWorkflowExecutionH\x00\x12W\n\x19\x63\x61ncel_workflow_execution\x18\t \x01(\x0b\x32\x32.coresdk.workflow_commands.CancelWorkflowExecutionH\x00\x12\x45\n\x10set_patch_marker\x18\n \x01(\x0b\x32).coresdk.workflow_commands.SetPatchMarkerH\x00\x12`\n\x1estart_child_workflow_execution\x18\x0b \x01(\x0b\x32\x36.coresdk.workflow_commands.StartChildWorkflowExecutionH\x00\x12\x62\n\x1f\x63\x61ncel_child_workflow_execution\x18\x0c \x01(\x0b\x32\x37.coresdk.workflow_commands.CancelChildWorkflowExecutionH\x00\x12w\n*request_cancel_external_workflow_execution\x18\r \x01(\x0b\x32\x41.coresdk.workflow_commands.RequestCancelExternalWorkflowExecutionH\x00\x12h\n\"signal_external_workflow_execution\x18\x0e \x01(\x0b\x32:.coresdk.workflow_commands.SignalExternalWorkflowExecutionH\x00\x12Q\n\x16\x63\x61ncel_signal_workflow\x18\x0f \x01(\x0b\x32/.coresdk.workflow_commands.CancelSignalWorkflowH\x00\x12S\n\x17schedule_local_activity\x18\x10 \x01(\x0b\x32\x30.coresdk.workflow_commands.ScheduleLocalActivityH\x00\x12^\n\x1drequest_cancel_local_activity\x18\x11 \x01(\x0b\x32\x35.coresdk.workflow_commands.RequestCancelLocalActivityH\x00\x12\x66\n!upsert_workflow_search_attributes\x18\x12 \x01(\x0b\x32\x39.coresdk.workflow_commands.UpsertWorkflowSearchAttributesH\x00\x12Y\n\x1amodify_workflow_properties\x18\x13 \x01(\x0b\x32\x33.coresdk.workflow_commands.ModifyWorkflowPropertiesH\x00\x12\x44\n\x0fupdate_response\x18\x14 \x01(\x0b\x32).coresdk.workflow_commands.UpdateResponseH\x00\x12U\n\x18schedule_nexus_operation\x18\x15 \x01(\x0b\x32\x31.coresdk.workflow_commands.ScheduleNexusOperationH\x00\x12`\n\x1erequest_cancel_nexus_operation\x18\x16 \x01(\x0b\x32\x36.coresdk.workflow_commands.RequestCancelNexusOperationH\x00\x42\t\n\x07variant\"S\n\nStartTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\"\x1a\n\x0b\x43\x61ncelTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\"\xb8\x06\n\x10ScheduleActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12I\n\x07headers\x18\x06 \x03(\x0b\x32\x38.coresdk.workflow_commands.ScheduleActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x12\x1e\n\x16\x64o_not_eagerly_execute\x18\x0e \x01(\x08\x12;\n\x11versioning_intent\x18\x0f \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\xee\x05\n\x15ScheduleLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\r\x12:\n\x16original_schedule_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12N\n\x07headers\x18\x06 \x03(\x0b\x32=.coresdk.workflow_commands.ScheduleLocalActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x38\n\x15local_retry_threshold\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"$\n\x15RequestCancelActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\")\n\x1aRequestCancelLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\"\x9c\x01\n\x0bQueryResult\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12<\n\tsucceeded\x18\x02 \x01(\x0b\x32\'.coresdk.workflow_commands.QuerySuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07variant\"A\n\x0cQuerySuccess\x12\x31\n\x08response\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\"L\n\x19\x43ompleteWorkflowExecution\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\"J\n\x15\x46\x61ilWorkflowExecution\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\x92\x07\n\x1e\x43ontinueAsNewWorkflowExecution\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Q\n\x04memo\x18\x06 \x03(\x0b\x32\x43.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.MemoEntry\x12W\n\x07headers\x18\x07 \x03(\x0b\x32\x46.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.HeadersEntry\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11versioning_intent\x18\n \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12[\n\x1binitial_versioning_behavior\x18\x0b \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x19\n\x17\x43\x61ncelWorkflowExecution\"6\n\x0eSetPatchMarker\x12\x10\n\x08patch_id\x18\x01 \x01(\t\x12\x12\n\ndeprecated\x18\x02 \x01(\x08\"\x96\t\n\x1bStartChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x03 \x01(\t\x12\x15\n\rworkflow_type\x18\x04 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12.\n\x05input\x18\x06 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x46\n\x13parent_close_policy\x18\n \x01(\x0e\x32).coresdk.child_workflow.ParentClosePolicy\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12T\n\x07headers\x18\x0f \x03(\x0b\x32\x43.coresdk.workflow_commands.StartChildWorkflowExecution.HeadersEntry\x12N\n\x04memo\x18\x10 \x03(\x0b\x32@.coresdk.workflow_commands.StartChildWorkflowExecution.MemoEntry\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12P\n\x11\x63\x61ncellation_type\x18\x12 \x01(\x0e\x32\x35.coresdk.child_workflow.ChildWorkflowCancellationType\x12;\n\x11versioning_intent\x18\x13 \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"J\n\x1c\x43\x61ncelChildWorkflowExecution\x12\x1a\n\x12\x63hild_workflow_seq\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\t\"\x8e\x01\n&RequestCancelExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12G\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\"\x8f\x03\n\x1fSignalExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12I\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecutionH\x00\x12\x1b\n\x11\x63hild_workflow_id\x18\x03 \x01(\tH\x00\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12-\n\x04\x61rgs\x18\x05 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12X\n\x07headers\x18\x06 \x03(\x0b\x32G.coresdk.workflow_commands.SignalExternalWorkflowExecution.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x42\x08\n\x06target\"#\n\x14\x43\x61ncelSignalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\"e\n\x1eUpsertWorkflowSearchAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\"O\n\x18ModifyWorkflowProperties\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\"\xd2\x01\n\x0eUpdateResponse\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12*\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x08rejected\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x34\n\tcompleted\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x42\n\n\x08response\"\x9a\x04\n\x16ScheduleNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x10\n\x08\x65ndpoint\x18\x02 \x01(\t\x12\x0f\n\x07service\x18\x03 \x01(\t\x12\x11\n\toperation\x18\x04 \x01(\t\x12.\n\x05input\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12X\n\x0cnexus_header\x18\x07 \x03(\x0b\x32\x42.coresdk.workflow_commands.ScheduleNexusOperation.NexusHeaderEntry\x12H\n\x11\x63\x61ncellation_type\x18\x08 \x01(\x0e\x32-.coresdk.nexus.NexusOperationCancellationType\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"*\n\x1bRequestCancelNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r*X\n\x18\x41\x63tivityCancellationType\x12\x0e\n\nTRY_CANCEL\x10\x00\x12\x1f\n\x1bWAIT_CANCELLATION_COMPLETED\x10\x01\x12\x0b\n\x07\x41\x42\x41NDON\x10\x02\x42\x36\xea\x02\x33Temporalio::Internal::Bridge::Api::WorkflowCommandsb\x06proto3" +descriptor_data = "\n;temporal/sdk/core/workflow_commands/workflow_commands.proto\x12\x19\x63oresdk.workflow_commands\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a$temporal/api/common/v1/message.proto\x1a$temporal/api/enums/v1/workflow.proto\x1a%temporal/api/failure/v1/message.proto\x1a\'temporal/api/sdk/v1/user_metadata.proto\x1a,temporal/api/sdk/v1/event_group_marker.proto\x1a\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a#temporal/sdk/core/nexus/nexus.proto\x1a%temporal/sdk/core/common/common.proto\"\xa9\x10\n\x0fWorkflowCommand\x12\x38\n\ruser_metadata\x18\x64 \x01(\x0b\x32!.temporal.api.sdk.v1.UserMetadata\x12\x42\n\x13\x65vent_group_markers\x18\x65 \x03(\x0b\x32%.temporal.api.sdk.v1.EventGroupMarker\x12<\n\x0bstart_timer\x18\x01 \x01(\x0b\x32%.coresdk.workflow_commands.StartTimerH\x00\x12H\n\x11schedule_activity\x18\x02 \x01(\x0b\x32+.coresdk.workflow_commands.ScheduleActivityH\x00\x12\x42\n\x10respond_to_query\x18\x03 \x01(\x0b\x32&.coresdk.workflow_commands.QueryResultH\x00\x12S\n\x17request_cancel_activity\x18\x04 \x01(\x0b\x32\x30.coresdk.workflow_commands.RequestCancelActivityH\x00\x12>\n\x0c\x63\x61ncel_timer\x18\x05 \x01(\x0b\x32&.coresdk.workflow_commands.CancelTimerH\x00\x12[\n\x1b\x63omplete_workflow_execution\x18\x06 \x01(\x0b\x32\x34.coresdk.workflow_commands.CompleteWorkflowExecutionH\x00\x12S\n\x17\x66\x61il_workflow_execution\x18\x07 \x01(\x0b\x32\x30.coresdk.workflow_commands.FailWorkflowExecutionH\x00\x12g\n\"continue_as_new_workflow_execution\x18\x08 \x01(\x0b\x32\x39.coresdk.workflow_commands.ContinueAsNewWorkflowExecutionH\x00\x12W\n\x19\x63\x61ncel_workflow_execution\x18\t \x01(\x0b\x32\x32.coresdk.workflow_commands.CancelWorkflowExecutionH\x00\x12\x45\n\x10set_patch_marker\x18\n \x01(\x0b\x32).coresdk.workflow_commands.SetPatchMarkerH\x00\x12`\n\x1estart_child_workflow_execution\x18\x0b \x01(\x0b\x32\x36.coresdk.workflow_commands.StartChildWorkflowExecutionH\x00\x12\x62\n\x1f\x63\x61ncel_child_workflow_execution\x18\x0c \x01(\x0b\x32\x37.coresdk.workflow_commands.CancelChildWorkflowExecutionH\x00\x12w\n*request_cancel_external_workflow_execution\x18\r \x01(\x0b\x32\x41.coresdk.workflow_commands.RequestCancelExternalWorkflowExecutionH\x00\x12h\n\"signal_external_workflow_execution\x18\x0e \x01(\x0b\x32:.coresdk.workflow_commands.SignalExternalWorkflowExecutionH\x00\x12Q\n\x16\x63\x61ncel_signal_workflow\x18\x0f \x01(\x0b\x32/.coresdk.workflow_commands.CancelSignalWorkflowH\x00\x12S\n\x17schedule_local_activity\x18\x10 \x01(\x0b\x32\x30.coresdk.workflow_commands.ScheduleLocalActivityH\x00\x12^\n\x1drequest_cancel_local_activity\x18\x11 \x01(\x0b\x32\x35.coresdk.workflow_commands.RequestCancelLocalActivityH\x00\x12\x66\n!upsert_workflow_search_attributes\x18\x12 \x01(\x0b\x32\x39.coresdk.workflow_commands.UpsertWorkflowSearchAttributesH\x00\x12Y\n\x1amodify_workflow_properties\x18\x13 \x01(\x0b\x32\x33.coresdk.workflow_commands.ModifyWorkflowPropertiesH\x00\x12\x44\n\x0fupdate_response\x18\x14 \x01(\x0b\x32).coresdk.workflow_commands.UpdateResponseH\x00\x12U\n\x18schedule_nexus_operation\x18\x15 \x01(\x0b\x32\x31.coresdk.workflow_commands.ScheduleNexusOperationH\x00\x12`\n\x1erequest_cancel_nexus_operation\x18\x16 \x01(\x0b\x32\x36.coresdk.workflow_commands.RequestCancelNexusOperationH\x00\x42\t\n\x07variant\"S\n\nStartTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x38\n\x15start_to_fire_timeout\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\"\x1a\n\x0b\x43\x61ncelTimer\x12\x0b\n\x03seq\x18\x01 \x01(\r\"\xb8\x06\n\x10ScheduleActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12I\n\x07headers\x18\x06 \x03(\x0b\x32\x38.coresdk.workflow_commands.ScheduleActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x34\n\x11heartbeat_timeout\x18\x0b \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0c \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x12\x1e\n\x16\x64o_not_eagerly_execute\x18\x0e \x01(\x08\x12;\n\x11versioning_intent\x18\x0f \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x10 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"\x93\x06\n\x15ScheduleLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x13\n\x0b\x61\x63tivity_id\x18\x02 \x01(\t\x12\x15\n\ractivity_type\x18\x03 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x04 \x01(\r\x12:\n\x16original_schedule_time\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12N\n\x07headers\x18\x06 \x03(\x0b\x32=.coresdk.workflow_commands.ScheduleLocalActivity.HeadersEntry\x12\x32\n\targuments\x18\x07 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x0cretry_policy\x18\x0b \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x38\n\x15local_retry_threshold\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x12N\n\x11\x63\x61ncellation_type\x18\r \x01(\x0e\x32\x33.coresdk.workflow_commands.ActivityCancellationType\x12#\n\x1binclude_arguments_in_marker\x18\x0e \x01(\x08\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"$\n\x15RequestCancelActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\")\n\x1aRequestCancelLocalActivity\x12\x0b\n\x03seq\x18\x01 \x01(\r\"\x9c\x01\n\x0bQueryResult\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12<\n\tsucceeded\x18\x02 \x01(\x0b\x32\'.coresdk.workflow_commands.QuerySuccessH\x00\x12\x32\n\x06\x66\x61iled\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x42\t\n\x07variant\"A\n\x0cQuerySuccess\x12\x31\n\x08response\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\"L\n\x19\x43ompleteWorkflowExecution\x12/\n\x06result\x18\x01 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\"J\n\x15\x46\x61ilWorkflowExecution\x12\x31\n\x07\x66\x61ilure\x18\x01 \x01(\x0b\x32 .temporal.api.failure.v1.Failure\"\x92\x07\n\x1e\x43ontinueAsNewWorkflowExecution\x12\x15\n\rworkflow_type\x18\x01 \x01(\t\x12\x12\n\ntask_queue\x18\x02 \x01(\t\x12\x32\n\targuments\x18\x03 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12\x37\n\x14workflow_run_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12Q\n\x04memo\x18\x06 \x03(\x0b\x32\x43.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.MemoEntry\x12W\n\x07headers\x18\x07 \x03(\x0b\x32\x46.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.HeadersEntry\x12\x43\n\x11search_attributes\x18\x08 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12\x39\n\x0cretry_policy\x18\t \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12;\n\x11versioning_intent\x18\n \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12[\n\x1binitial_versioning_behavior\x18\x0b \x01(\x0e\x32\x36.temporal.api.enums.v1.ContinueAsNewVersioningBehavior\x12\x39\n\x16\x62\x61\x63koff_start_interval\x18\x0c \x01(\x0b\x32\x19.google.protobuf.Duration\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"L\n\x17\x43\x61ncelWorkflowExecution\x12\x31\n\x07\x64\x65tails\x18\x01 \x01(\x0b\x32 .temporal.api.common.v1.Payloads\"6\n\x0eSetPatchMarker\x12\x10\n\x08patch_id\x18\x01 \x01(\t\x12\x12\n\ndeprecated\x18\x02 \x01(\x08\"\x96\t\n\x1bStartChildWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x11\n\tnamespace\x18\x02 \x01(\t\x12\x13\n\x0bworkflow_id\x18\x03 \x01(\t\x12\x15\n\rworkflow_type\x18\x04 \x01(\t\x12\x12\n\ntask_queue\x18\x05 \x01(\t\x12.\n\x05input\x18\x06 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12=\n\x1aworkflow_execution_timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x14workflow_run_timeout\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x38\n\x15workflow_task_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x46\n\x13parent_close_policy\x18\n \x01(\x0e\x32).coresdk.child_workflow.ParentClosePolicy\x12N\n\x18workflow_id_reuse_policy\x18\x0c \x01(\x0e\x32,.temporal.api.enums.v1.WorkflowIdReusePolicy\x12\x39\n\x0cretry_policy\x18\r \x01(\x0b\x32#.temporal.api.common.v1.RetryPolicy\x12\x15\n\rcron_schedule\x18\x0e \x01(\t\x12T\n\x07headers\x18\x0f \x03(\x0b\x32\x43.coresdk.workflow_commands.StartChildWorkflowExecution.HeadersEntry\x12N\n\x04memo\x18\x10 \x03(\x0b\x32@.coresdk.workflow_commands.StartChildWorkflowExecution.MemoEntry\x12\x43\n\x11search_attributes\x18\x11 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\x12P\n\x11\x63\x61ncellation_type\x18\x12 \x01(\x0e\x32\x35.coresdk.child_workflow.ChildWorkflowCancellationType\x12;\n\x11versioning_intent\x18\x13 \x01(\x0e\x32 .coresdk.common.VersioningIntent\x12\x32\n\x08priority\x18\x14 \x01(\x0b\x32 .temporal.api.common.v1.Priority\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x1aL\n\tMemoEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\"J\n\x1c\x43\x61ncelChildWorkflowExecution\x12\x1a\n\x12\x63hild_workflow_seq\x18\x01 \x01(\r\x12\x0e\n\x06reason\x18\x02 \x01(\t\"\x8e\x01\n&RequestCancelExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12G\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution\x12\x0e\n\x06reason\x18\x03 \x01(\t\"\x8f\x03\n\x1fSignalExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12I\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecutionH\x00\x12\x1b\n\x11\x63hild_workflow_id\x18\x03 \x01(\tH\x00\x12\x13\n\x0bsignal_name\x18\x04 \x01(\t\x12-\n\x04\x61rgs\x18\x05 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12X\n\x07headers\x18\x06 \x03(\x0b\x32G.coresdk.workflow_commands.SignalExternalWorkflowExecution.HeadersEntry\x1aO\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload:\x02\x38\x01\x42\x08\n\x06target\"#\n\x14\x43\x61ncelSignalWorkflow\x12\x0b\n\x03seq\x18\x01 \x01(\r\"e\n\x1eUpsertWorkflowSearchAttributes\x12\x43\n\x11search_attributes\x18\x01 \x01(\x0b\x32(.temporal.api.common.v1.SearchAttributes\"O\n\x18ModifyWorkflowProperties\x12\x33\n\rupserted_memo\x18\x01 \x01(\x0b\x32\x1c.temporal.api.common.v1.Memo\"\xd2\x01\n\x0eUpdateResponse\x12\x1c\n\x14protocol_instance_id\x18\x01 \x01(\t\x12*\n\x08\x61\x63\x63\x65pted\x18\x02 \x01(\x0b\x32\x16.google.protobuf.EmptyH\x00\x12\x34\n\x08rejected\x18\x03 \x01(\x0b\x32 .temporal.api.failure.v1.FailureH\x00\x12\x34\n\tcompleted\x18\x04 \x01(\x0b\x32\x1f.temporal.api.common.v1.PayloadH\x00\x42\n\n\x08response\"\x9a\x04\n\x16ScheduleNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12\x10\n\x08\x65ndpoint\x18\x02 \x01(\t\x12\x0f\n\x07service\x18\x03 \x01(\t\x12\x11\n\toperation\x18\x04 \x01(\t\x12.\n\x05input\x18\x05 \x01(\x0b\x32\x1f.temporal.api.common.v1.Payload\x12<\n\x19schedule_to_close_timeout\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12X\n\x0cnexus_header\x18\x07 \x03(\x0b\x32\x42.coresdk.workflow_commands.ScheduleNexusOperation.NexusHeaderEntry\x12H\n\x11\x63\x61ncellation_type\x18\x08 \x01(\x0e\x32-.coresdk.nexus.NexusOperationCancellationType\x12<\n\x19schedule_to_start_timeout\x18\t \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x39\n\x16start_to_close_timeout\x18\n \x01(\x0b\x32\x19.google.protobuf.Duration\x1a\x32\n\x10NexusHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"*\n\x1bRequestCancelNexusOperation\x12\x0b\n\x03seq\x18\x01 \x01(\r*X\n\x18\x41\x63tivityCancellationType\x12\x0e\n\nTRY_CANCEL\x10\x00\x12\x1f\n\x1bWAIT_CANCELLATION_COMPLETED\x10\x01\x12\x0b\n\x07\x41\x42\x41NDON\x10\x02\x42\x36\xea\x02\x33Temporalio::Internal::Bridge::Api::WorkflowCommandsb\x06proto3" pool = ::Google::Protobuf::DescriptorPool.generated_pool pool.add_serialized_file(descriptor_data) diff --git a/temporalio/lib/temporalio/internal/worker/workflow_instance.rb b/temporalio/lib/temporalio/internal/worker/workflow_instance.rb index 81e6277b..96a6c2c4 100644 --- a/temporalio/lib/temporalio/internal/worker/workflow_instance.rb +++ b/temporalio/lib/temporalio/internal/worker/workflow_instance.rb @@ -147,6 +147,10 @@ def initialize(details) end, has_last_result?: !@init_job.last_completion_result.nil?, namespace: details.namespace, + original_execution_run_id: ProtoUtils.string_or( + @init_job.original_execution_run_id, + details.initial_activation.run_id + ), parent: if @init_job.parent_workflow_info Workflow::Info::ParentInfo.new( namespace: @init_job.parent_workflow_info.namespace, @@ -289,7 +293,7 @@ def illegal_call_tracing_disabled(&) end end - def patch(patch_id:, deprecated:) + def patch(patch_id:, deprecated:, event_groups: nil) # Use memoized result if present. If this is being deprecated, we can still use memoized result and skip the # command. patch_id = patch_id.to_s @@ -305,7 +309,8 @@ def patch(patch_id:, deprecated:) if patched add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( - set_patch_marker: Bridge::Api::WorkflowCommands::SetPatchMarker.new(patch_id:, deprecated:) + set_patch_marker: Bridge::Api::WorkflowCommands::SetPatchMarker.new(patch_id:, deprecated:), + event_group_markers: Workflow::EventGroup._markers_for_command(event_groups) ) ) end @@ -436,27 +441,29 @@ def apply_signal(job) end # Process as a top level handler so that errors are treated as if in primary workflow method schedule(top_level: true, handler_exec:) do - # Send to interceptor if there is a definition, buffer otherwise - if defn - @inbound.handle_signal( - Temporalio::Worker::Interceptor::Workflow::HandleSignalInput.new( - signal: job.signal_name, - args: begin - convert_handler_args(payload_array: job.input, defn:) - rescue StandardError => e - # Signals argument conversion failure must not fail task - @logger.error("Failed converting signal input arguments for #{job.signal_name}, dropping signal") - @logger.error(e) - next - end, - definition: defn, - headers: ProtoUtils.headers_from_proto_map(job.headers, @payload_converter) || {} + Workflow._with_implicit_event_group(Workflow._inbound_event_group(job.originating_event_id)) do + # Send to interceptor if there is a definition, buffer otherwise + if defn + @inbound.handle_signal( + Temporalio::Worker::Interceptor::Workflow::HandleSignalInput.new( + signal: job.signal_name, + args: begin + convert_handler_args(payload_array: job.input, defn:) + rescue StandardError => e + # Signals argument conversion failure must not fail task + @logger.error("Failed converting signal input arguments for #{job.signal_name}, dropping signal") + @logger.error(e) + next + end, + definition: defn, + headers: ProtoUtils.headers_from_proto_map(job.headers, @payload_converter) || {} + ) ) - ) - else - buffered = @buffered_signals[job.signal_name] - buffered = @buffered_signals[job.signal_name] = [] if buffered.nil? - buffered << job + else + buffered = @buffered_signals[job.signal_name] + buffered = @buffered_signals[job.signal_name] = [] if buffered.nil? + buffered << job + end end end end @@ -586,8 +593,10 @@ def apply_update(job) ) accepted = true - # Issue update - result = @inbound.handle_update(input) + # Issue update. Validators are intentionally not wrapped: only the handler gets the implicit group. + result = Workflow._with_implicit_event_group(Workflow._inbound_update_event_group(job.id)) do + @inbound.handle_update(input) + end add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( @@ -672,7 +681,8 @@ def on_top_level_exception(err) search_attributes: err.search_attributes&._to_proto, retry_policy: err.retry_policy&._to_proto, initial_versioning_behavior: err.initial_versioning_behavior || 0 - ) + ), + event_group_markers: err._event_group_markers || [] ) ) elsif @cancellation.canceled? && Error.canceled?(err) diff --git a/temporalio/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb b/temporalio/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb index 1a0a0e3c..c7d729ed 100644 --- a/temporalio/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb +++ b/temporalio/lib/temporalio/internal/worker/workflow_instance/child_workflow_handle.rb @@ -46,8 +46,8 @@ def _resolve(resolution) @resolution = resolution end - def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil) - @instance.context._signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:) + def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil, event_groups: nil) + @instance.context._signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:, event_groups:) end end end diff --git a/temporalio/lib/temporalio/internal/worker/workflow_instance/context.rb b/temporalio/lib/temporalio/internal/worker/workflow_instance/context.rb index d4068493..e89f20de 100644 --- a/temporalio/lib/temporalio/internal/worker/workflow_instance/context.rb +++ b/temporalio/lib/temporalio/internal/worker/workflow_instance/context.rb @@ -71,8 +71,8 @@ def current_update_info Fiber[:__temporal_update_info] end - def deprecate_patch(patch_id) - @instance.patch(patch_id:, deprecated: true) + def deprecate_patch(patch_id, event_groups: nil) + @instance.patch(patch_id:, deprecated: true, event_groups:) end def durable_scheduler_disabled(&) @@ -102,7 +102,8 @@ def execute_activity( disable_eager_execution:, priority:, arg_hints:, - result_hint: + result_hint:, + event_groups: ) activity, defn_arg_hints, defn_result_hint = case activity @@ -135,7 +136,8 @@ def execute_activity( priority:, arg_hints: arg_hints || defn_arg_hints, result_hint: result_hint || defn_result_hint, - headers: {} + headers: {}, + event_groups: ) ) end @@ -153,7 +155,8 @@ def execute_local_activity( cancellation_type:, activity_id:, arg_hints:, - result_hint: + result_hint:, + event_groups: ) activity, defn_arg_hints, defn_result_hint = case activity @@ -182,7 +185,8 @@ def execute_local_activity( activity_id:, arg_hints: arg_hints || defn_arg_hints, result_hint: result_hint || defn_result_hint, - headers: {} + headers: {}, + event_groups: ) ) end @@ -204,6 +208,7 @@ def instance end def initialize_continue_as_new_error(error) + error._event_group_markers = Workflow::EventGroup._markers_for_command(error.event_groups) @outbound.initialize_continue_as_new_error( Temporalio::Worker::Interceptor::Workflow::InitializeContinueAsNewErrorInput.new(error:) ) @@ -235,8 +240,8 @@ def now @instance.now end - def patched(patch_id) - @instance.patch(patch_id:, deprecated: false) + def patched(patch_id, event_groups: nil) + @instance.patch(patch_id:, deprecated: false, event_groups:) end def payload_converter @@ -269,12 +274,13 @@ def signal_handlers @instance.signal_handlers end - def sleep(duration, summary:, cancellation:) + def sleep(duration, summary:, cancellation:, event_groups: nil) @outbound.sleep( Temporalio::Worker::Interceptor::Workflow::SleepInput.new( duration:, summary:, - cancellation: + cancellation:, + event_groups: ) ) end @@ -299,7 +305,8 @@ def start_child_workflow( search_attributes:, priority:, arg_hints:, - result_hint: + result_hint:, + event_groups: ) workflow, defn_arg_hints, defn_result_hint = Workflow::Definition._workflow_type_and_hints_from_workflow_parameter(workflow) @@ -325,7 +332,8 @@ def start_child_workflow( priority:, arg_hints: arg_hints || defn_arg_hints, result_hint: result_hint || defn_result_hint, - headers: {} + headers: {}, + event_groups: ) ) end @@ -334,7 +342,7 @@ def storage @storage ||= {} end - def timeout(duration, exception_class, *exception_args, summary:, &) + def timeout(duration, exception_class, *exception_args, summary:, event_groups: nil, &) raise 'Block required for timeout' unless block_given? # Run timer in background and block in foreground. This gives better stack traces than a future any-of race. @@ -342,7 +350,7 @@ def timeout(duration, exception_class, *exception_args, summary:, &) sleep_cancel, sleep_cancel_proc = Cancellation.new fiber = Fiber.current Workflow::Future.new do - Workflow.sleep(duration, summary:, cancellation: sleep_cancel) + Workflow.sleep(duration, summary:, cancellation: sleep_cancel, event_groups:) fiber.raise(exception_class, *exception_args) if fiber.alive? # steep:ignore rescue Exception => e # rubocop:disable Lint/RescueException # Re-raise in fiber @@ -360,7 +368,7 @@ def update_handlers @instance.update_handlers end - def upsert_memo(hash) + def upsert_memo(hash, event_groups: nil) # Convert to memo, apply updates, then add the command (so command adding is post validation) upserted_memo = ProtoUtils.memo_to_proto(hash, payload_converter) memo._update do |new_hash| @@ -377,12 +385,13 @@ def upsert_memo(hash) Bridge::Api::WorkflowCommands::WorkflowCommand.new( modify_workflow_properties: Bridge::Api::WorkflowCommands::ModifyWorkflowProperties.new( upserted_memo: - ) + ), + event_group_markers: Workflow::EventGroup._markers_for_command(event_groups) ) ) end - def upsert_search_attributes(*updates) + def upsert_search_attributes(*updates, event_groups: nil) # Apply updates then add the command (so command adding is post validation) search_attributes._disable_mutations = false search_attributes.update!(*updates) @@ -392,7 +401,8 @@ def upsert_search_attributes(*updates) search_attributes: Api::Common::V1::SearchAttributes.new( indexed_fields: updates.to_h(&:_to_proto_pair) ) - ) + ), + event_group_markers: Workflow::EventGroup._markers_for_command(event_groups) ) ) ensure @@ -403,9 +413,9 @@ def wait_condition(cancellation:, &) @instance.scheduler.wait_condition(cancellation:, &) end - def _cancel_external_workflow(id:, run_id:) + def _cancel_external_workflow(id:, run_id:, event_groups: nil) @outbound.cancel_external_workflow( - Temporalio::Worker::Interceptor::Workflow::CancelExternalWorkflowInput.new(id:, run_id:) + Temporalio::Worker::Interceptor::Workflow::CancelExternalWorkflowInput.new(id:, run_id:, event_groups:) ) end @@ -413,7 +423,7 @@ def _outbound=(outbound) @outbound = outbound end - def _signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:) + def _signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:, event_groups: nil) signal, defn_arg_hints = Workflow::Definition::Signal._name_and_hints_from_parameter(signal) @outbound.signal_child_workflow( Temporalio::Worker::Interceptor::Workflow::SignalChildWorkflowInput.new( @@ -422,12 +432,13 @@ def _signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:) args:, cancellation:, arg_hints: arg_hints || defn_arg_hints, - headers: {} + headers: {}, + event_groups: ) ) end - def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:) + def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:, event_groups: nil) signal, defn_arg_hints = Workflow::Definition::Signal._name_and_hints_from_parameter(signal) @outbound.signal_external_workflow( Temporalio::Worker::Interceptor::Workflow::SignalExternalWorkflowInput.new( @@ -437,7 +448,8 @@ def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_h args:, cancellation:, arg_hints: arg_hints || defn_arg_hints, - headers: {} + headers: {}, + event_groups: ) ) end diff --git a/temporalio/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb b/temporalio/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb index fb6cf494..9c81e584 100644 --- a/temporalio/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb +++ b/temporalio/lib/temporalio/internal/worker/workflow_instance/external_workflow_handle.rb @@ -18,12 +18,14 @@ def initialize(id:, run_id:, instance:) # rubocop:disable Lint/MissingSuper @instance = instance end - def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil) - @instance.context._signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:) + def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil, event_groups: nil) + @instance.context._signal_external_workflow( + id:, run_id:, signal:, args:, cancellation:, arg_hints:, event_groups: + ) end - def cancel - @instance.context._cancel_external_workflow(id:, run_id:) + def cancel(event_groups: nil) + @instance.context._cancel_external_workflow(id:, run_id:, event_groups:) end end end diff --git a/temporalio/lib/temporalio/internal/worker/workflow_instance/nexus_client.rb b/temporalio/lib/temporalio/internal/worker/workflow_instance/nexus_client.rb index 04c77c7f..3a1922d8 100644 --- a/temporalio/lib/temporalio/internal/worker/workflow_instance/nexus_client.rb +++ b/temporalio/lib/temporalio/internal/worker/workflow_instance/nexus_client.rb @@ -19,7 +19,7 @@ def initialize(endpoint:, service:, outbound:) # rubocop:disable Lint/MissingSup def start_operation(operation, arg, schedule_to_close_timeout: nil, schedule_to_start_timeout: nil, start_to_close_timeout: nil, cancellation_type: nil, summary: nil, - cancellation: Workflow.cancellation, arg_hint: nil, result_hint: nil) + cancellation: Workflow.cancellation, arg_hint: nil, result_hint: nil, event_groups: nil) @outbound.start_nexus_operation( Temporalio::Worker::Interceptor::Workflow::StartNexusOperationInput.new( endpoint: @endpoint, @@ -34,7 +34,8 @@ def start_operation(operation, arg, schedule_to_close_timeout: nil, schedule_to_ cancellation:, arg_hint:, result_hint:, - headers: {} + headers: {}, + event_groups: ) ) end diff --git a/temporalio/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb b/temporalio/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb index 3be8d123..21e7141e 100644 --- a/temporalio/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb +++ b/temporalio/lib/temporalio/internal/worker/workflow_instance/outbound_implementation.rb @@ -31,6 +31,7 @@ def initialize(instance) def cancel_external_workflow(input) # Add command seq = (@external_cancel_counter += 1) + markers = Workflow::EventGroup._markers_for_command(input.event_groups) cmd = Bridge::Api::WorkflowCommands::RequestCancelExternalWorkflowExecution.new( seq:, workflow_execution: Bridge::Api::Common::NamespacedWorkflowExecution.new( @@ -40,7 +41,10 @@ def cancel_external_workflow(input) ) ) @instance.add_command( - Bridge::Api::WorkflowCommands::WorkflowCommand.new(request_cancel_external_workflow_execution: cmd) + Bridge::Api::WorkflowCommands::WorkflowCommand.new( + request_cancel_external_workflow_execution: cmd, + event_group_markers: markers + ) ) @instance.pending_external_cancels[seq] = Fiber.current @@ -64,7 +68,8 @@ def execute_activity(input) end execute_activity_with_local_backoffs(local: false, cancellation: input.cancellation, - result_hint: input.result_hint) do + result_hint: input.result_hint, + event_groups: input.event_groups) do |_do_backoff, markers| seq = (@activity_counter += 1) @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( @@ -86,7 +91,8 @@ def execute_activity(input) do_not_eagerly_execute: input.disable_eager_execution, priority: input.priority._to_proto ), - user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter) + user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter), + event_group_markers: markers ) ) seq @@ -101,7 +107,8 @@ def execute_local_activity(input) @instance.assert_valid_local_activity.call(input.activity) execute_activity_with_local_backoffs(local: true, cancellation: input.cancellation, - result_hint: input.result_hint) do |do_backoff| + result_hint: input.result_hint, + event_groups: input.event_groups) do |do_backoff, markers| seq = (@activity_counter += 1) @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( @@ -122,37 +129,42 @@ def execute_local_activity(input) attempt: do_backoff&.attempt || 0, original_schedule_time: do_backoff&.original_schedule_time ), - user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter) + user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter), + event_group_markers: markers ) ) seq end end - def execute_activity_with_local_backoffs(local:, cancellation:, result_hint:, &block) + def execute_activity_with_local_backoffs(local:, cancellation:, result_hint:, event_groups:, &block) # We do not even want to schedule if the cancellation is already cancelled. We choose to use canceled # failure instead of wrapping in activity failure which is similar to what other SDKs do, with the accepted # tradeoff that it makes rescue more difficult (hence the presence of Error.canceled? helper). raise Error::CanceledError, 'Activity canceled before scheduled' if cancellation.canceled? + # Capture at request time. Cancel callbacks run on the canceler's fiber, and backoff sleep happens later. + markers = Workflow::EventGroup._markers_for_command(event_groups) + # This has to be done in a loop for local activity backoff last_local_backoff = nil loop do - result = execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &block) + result = execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, markers:, + &block) return result unless result.is_a?(Bridge::Api::ActivityResult::DoBackoff) # @type var result: untyped last_local_backoff = result # Have to sleep the amount of the backoff, which can be canceled with the same cancellation # TODO(cretz): What should this cancellation raise? - Workflow.sleep(ProtoUtils.duration_to_seconds(result.backoff_duration), cancellation:) + Workflow.sleep(ProtoUtils.duration_to_seconds(result.backoff_duration), cancellation:, event_groups:) end end # If this doesn't raise, it returns success | DoBackoff - def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &block) + def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, markers:, &block) # Add to pending activities (removed by the resolver) - seq = block.call(last_local_backoff) + seq = block.call(last_local_backoff, markers) @instance.pending_activities[seq] = Fiber.current # Add cancellation hook @@ -162,13 +174,17 @@ def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hin if local @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( - request_cancel_local_activity: Bridge::Api::WorkflowCommands::RequestCancelLocalActivity.new(seq:) + request_cancel_local_activity: Bridge::Api::WorkflowCommands::RequestCancelLocalActivity.new( + seq: + ), + event_group_markers: markers ) ) else @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( - request_cancel_activity: Bridge::Api::WorkflowCommands::RequestCancelActivity.new(seq:) + request_cancel_activity: Bridge::Api::WorkflowCommands::RequestCancelActivity.new(seq:), + event_group_markers: markers ) ) end @@ -211,7 +227,8 @@ def signal_child_workflow(input) args: input.args, cancellation: input.cancellation, arg_hints: input.arg_hints, - headers: input.headers + headers: input.headers, + event_groups: input.event_groups ) end @@ -224,15 +241,18 @@ def signal_external_workflow(input) args: input.args, cancellation: input.cancellation, arg_hints: input.arg_hints, - headers: input.headers + headers: input.headers, + event_groups: input.event_groups ) end - def _signal_external_workflow(id:, run_id:, child:, signal:, args:, cancellation:, arg_hints:, headers:) + def _signal_external_workflow(id:, run_id:, child:, signal:, args:, cancellation:, arg_hints:, headers:, + event_groups:) raise Error::CanceledError, 'Signal canceled before scheduled' if cancellation.canceled? # Add command seq = (@external_signal_counter += 1) + markers = Workflow::EventGroup._markers_for_command(event_groups) cmd = Bridge::Api::WorkflowCommands::SignalExternalWorkflowExecution.new( seq:, signal_name: signal, @@ -249,7 +269,10 @@ def _signal_external_workflow(id:, run_id:, child:, signal:, args:, cancellation ) end @instance.add_command( - Bridge::Api::WorkflowCommands::WorkflowCommand.new(signal_external_workflow_execution: cmd) + Bridge::Api::WorkflowCommands::WorkflowCommand.new( + signal_external_workflow_execution: cmd, + event_group_markers: markers + ) ) @instance.pending_external_signals[seq] = Fiber.current @@ -258,7 +281,8 @@ def _signal_external_workflow(id:, run_id:, child:, signal:, args:, cancellation # Add the command but do not raise, we will let resolution do that @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( - cancel_signal_workflow: Bridge::Api::WorkflowCommands::CancelSignalWorkflow.new(seq:) + cancel_signal_workflow: Bridge::Api::WorkflowCommands::CancelSignalWorkflow.new(seq:), + event_group_markers: markers ) ) end @@ -301,13 +325,15 @@ def sleep(input) # Add command seq = (@timer_counter += 1) + markers = Workflow::EventGroup._markers_for_command(input.event_groups) @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( start_timer: Bridge::Api::WorkflowCommands::StartTimer.new( seq:, start_to_fire_timeout: ProtoUtils.seconds_to_duration(duration) ), - user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter) + user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter), + event_group_markers: markers ) ) @instance.pending_timers[seq] = Fiber.current @@ -320,7 +346,8 @@ def sleep(input) # Add the command for cancel then raise @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( - cancel_timer: Bridge::Api::WorkflowCommands::CancelTimer.new(seq:) + cancel_timer: Bridge::Api::WorkflowCommands::CancelTimer.new(seq:), + event_group_markers: markers ) ) if fiber.alive? @@ -346,6 +373,7 @@ def start_child_workflow(input) # Add the command seq = (@child_counter += 1) + markers = Workflow::EventGroup._markers_for_command(input.event_groups) @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( start_child_workflow_execution: Bridge::Api::WorkflowCommands::StartChildWorkflowExecution.new( @@ -371,7 +399,8 @@ def start_child_workflow(input) ), user_metadata: ProtoUtils.to_user_metadata( input.static_summary, input.static_details, @instance.payload_converter - ) + ), + event_group_markers: markers ) ) @@ -385,7 +414,8 @@ def start_child_workflow(input) Bridge::Api::WorkflowCommands::WorkflowCommand.new( cancel_child_workflow_execution: Bridge::Api::WorkflowCommands::CancelChildWorkflowExecution.new( child_workflow_seq: seq - ) + ), + event_group_markers: markers ) ) end @@ -437,6 +467,7 @@ def start_nexus_operation(input) # Add the command seq = (@nexus_operation_counter += 1) + markers = Workflow::EventGroup._markers_for_command(input.event_groups) @instance.add_command( Bridge::Api::WorkflowCommands::WorkflowCommand.new( schedule_nexus_operation: Bridge::Api::WorkflowCommands::ScheduleNexusOperation.new( @@ -451,7 +482,8 @@ def start_nexus_operation(input) nexus_header: input.headers, cancellation_type: input.cancellation_type ), - user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter) + user_metadata: ProtoUtils.to_user_metadata(input.summary, nil, @instance.payload_converter), + event_group_markers: markers ) ) @@ -467,7 +499,8 @@ def start_nexus_operation(input) Bridge::Api::WorkflowCommands::WorkflowCommand.new( request_cancel_nexus_operation: Bridge::Api::WorkflowCommands::RequestCancelNexusOperation.new( seq: - ) + ), + event_group_markers: markers ) ) end diff --git a/temporalio/lib/temporalio/worker/interceptor.rb b/temporalio/lib/temporalio/worker/interceptor.rb index 763a0764..2160e2f2 100644 --- a/temporalio/lib/temporalio/worker/interceptor.rb +++ b/temporalio/lib/temporalio/worker/interceptor.rb @@ -200,7 +200,8 @@ def handle_update(input) # Input for {Outbound.cancel_external_workflow}. CancelExternalWorkflowInput = Data.define( :id, - :run_id + :run_id, + :event_groups ) # Input for {Outbound.execute_activity}. @@ -221,7 +222,8 @@ def handle_update(input) :priority, :arg_hints, :result_hint, - :headers + :headers, + :event_groups ) # Input for {Outbound.execute_local_activity}. @@ -239,7 +241,8 @@ def handle_update(input) :activity_id, :arg_hints, :result_hint, - :headers + :headers, + :event_groups ) # Input for {Outbound.initialize_continue_as_new_error}. @@ -254,7 +257,8 @@ def handle_update(input) :args, :cancellation, :arg_hints, - :headers + :headers, + :event_groups ) # Input for {Outbound.signal_external_workflow}. @@ -265,14 +269,16 @@ def handle_update(input) :args, :cancellation, :arg_hints, - :headers + :headers, + :event_groups ) # Input for {Outbound.sleep}. SleepInput = Data.define( :duration, :summary, - :cancellation + :cancellation, + :event_groups ) # Input for {Outbound.start_child_workflow}. @@ -297,7 +303,8 @@ def handle_update(input) :priority, :arg_hints, :result_hint, - :headers + :headers, + :event_groups ) # Input for {Outbound.start_nexus_operation}. @@ -316,7 +323,8 @@ def handle_update(input) :cancellation, :arg_hint, :result_hint, - :headers + :headers, + :event_groups ) # Outbound interceptor for intercepting outbound workflow calls. This should be extended by users needing to diff --git a/temporalio/lib/temporalio/workflow.rb b/temporalio/lib/temporalio/workflow.rb index 712e0929..1947197b 100644 --- a/temporalio/lib/temporalio/workflow.rb +++ b/temporalio/lib/temporalio/workflow.rb @@ -8,6 +8,7 @@ require 'temporalio/workflow/child_workflow_cancellation_type' require 'temporalio/workflow/child_workflow_handle' require 'temporalio/workflow/definition' +require 'temporalio/workflow/event_group' require 'temporalio/workflow/external_workflow_handle' require 'temporalio/workflow/future' require 'temporalio/workflow/handler_unfinished_policy' @@ -54,6 +55,82 @@ def self.create_nexus_client(endpoint:, service:) _current.create_nexus_client(endpoint:, service:) end + # Create an Event Group that can be attached to commands scheduled by this workflow. + # + # Attach the returned group via command `event_groups:` options, or via {with_event_groups}. + # + # @param id [String] Non-empty group identity. Commands with the same `id` belong to the same group. The + # user-provided ID is stored as plain text in the workflow history and should therefore not contain sensitive + # information. + # @param label [String, nil] Optional non-empty display text for the UI / CLI. If provided, it is persisted to + # history as a codec-encoded Payload. + # @return [EventGroup] Created Event Group. + # + # WARNING: Event Groups is an experimental API and may change without notice. + def self.create_event_group(id, label: nil) + _current + raise ArgumentError, 'Event group id cannot be empty' if !id.is_a?(String) || id.empty? + raise ArgumentError, 'Event group label cannot be empty' if !label.nil? && (!label.is_a?(String) || label.empty?) + + EventGroup::Label.new(id, label) + end + + # Run the given block with one or more Event Groups attached to every command produced inside it. + # + # Nested scopes compose: a command produced inside an inner scope carries the Event Groups of all enclosing scopes. + # Fibers started within a scope inherit it, since they capture Fiber storage at creation. + # + # @param groups [Array] Event Groups created via {create_event_group}. + # @yield Block to run with the given Event Groups in scope. + # @return [Object] Result of the block. + # + # WARNING: Event Groups is an experimental API and may change without notice. + def self.with_event_groups(*groups, &) + raise ArgumentError, 'Block required' unless block_given? + + _current + active = EventGroup._active + explicit = active.explicit.dup + groups.each do |group| + unless group.is_a?(EventGroup::Label) + raise TypeError, 'Event groups must be created with Temporalio::Workflow.create_event_group' + end + + explicit[group.id] = group + end + EventGroup._with_active(EventGroup::Active.new(implicit: active.implicit, explicit:), &) + end + + # @!visibility private + def self._with_implicit_event_group(group, &) + EventGroup._with_active(group._applied_over(EventGroup._active), &) + end + + # @!visibility private + def self._inbound_event_group(event_id) + if event_id.nil? || event_id <= 0 + _current_or_nil&.logger&.warn( + "Cannot create implicit Event Group for signal with invalid originating event ID: #{event_id}" + ) + EventGroup::StubImplicit.new + else + EventGroup::Implicit.new( + Api::Sdk::V1::EventGroupMarker.new( + inbound_event: Api::Sdk::V1::EventGroupMarker::InboundEvent.new(inbound_event_id: event_id) + ) + ) + end + end + + # @!visibility private + def self._inbound_update_event_group(update_id) + EventGroup::Implicit.new( + Api::Sdk::V1::EventGroupMarker.new( + inbound_update: Api::Sdk::V1::EventGroupMarker::InboundUpdate.new(inbound_update_id: update_id) + ) + ) + end + # @return [Array] Reasons the server suggests continue-as-new. Empty if no # suggestion. This is currently experimental. def self.suggest_continue_as_new_reasons @@ -121,8 +198,9 @@ def self.current_update_info # removed as well. # # @param patch_id [Symbol, String] Patch ID. - def self.deprecate_patch(patch_id) - _current.deprecate_patch(patch_id) + # @param event_groups [Array, nil] Event Groups to attach to the patch marker command. + def self.deprecate_patch(patch_id, event_groups: nil) + _current.deprecate_patch(patch_id, event_groups:) end # Execute an activity and return its result. Either `start_to_close_timeout` or `schedule_to_close_timeout` _must_ @@ -163,6 +241,8 @@ def self.deprecate_patch(patch_id) # activity definition has arg hints, those are used by default. # @param result_hint [Object, nil] Overrides converter hint for result if any. If unset/nil and the activity # definition has result hint, it is used by default. + # @param event_groups [Array, nil] Event Groups to attach to the activity command, in addition to any + # groups from enclosing {with_event_groups} scopes. # # @return [Object] Result of the activity. # @raise [Error::ActivityError] Activity failed (and retry was disabled or exhausted). @@ -184,13 +264,14 @@ def self.execute_activity( disable_eager_execution: false, priority: Priority.default, arg_hints: nil, - result_hint: nil + result_hint: nil, + event_groups: nil ) _current.execute_activity( activity, *args, task_queue:, summary:, schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:, heartbeat_timeout:, retry_policy:, cancellation:, cancellation_type:, activity_id:, disable_eager_execution:, - priority:, arg_hints:, result_hint: + priority:, arg_hints:, result_hint:, event_groups: ) end @@ -215,13 +296,15 @@ def self.execute_child_workflow( search_attributes: nil, priority: Priority.default, arg_hints: nil, - result_hint: nil + result_hint: nil, + event_groups: nil ) start_child_workflow( workflow, *args, id:, task_queue:, static_summary:, static_details:, cancellation:, cancellation_type:, parent_close_policy:, execution_timeout:, run_timeout:, task_timeout:, id_reuse_policy:, - retry_policy:, cron_schedule:, memo:, search_attributes:, priority:, arg_hints:, result_hint: + retry_policy:, cron_schedule:, memo:, search_attributes:, priority:, arg_hints:, result_hint:, + event_groups: ).result end @@ -258,6 +341,8 @@ def self.execute_child_workflow( # activity definition has arg hints, those are used by default. # @param result_hint [Object, nil] Overrides converter hint for result if any. If unset/nil and the activity # definition has result hint, it is used by default. + # @param event_groups [Array, nil] Event Groups to attach to the activity command, in addition to any + # groups from enclosing {with_event_groups} scopes. # # @return [Object] Result of the activity. # @raise [Error::ActivityError] Activity failed (and retry was disabled or exhausted). @@ -276,13 +361,14 @@ def self.execute_local_activity( cancellation_type: ActivityCancellationType::TRY_CANCEL, activity_id: nil, arg_hints: nil, - result_hint: nil + result_hint: nil, + event_groups: nil ) _current.execute_local_activity( activity, *args, summary:, schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:, retry_policy:, local_retry_threshold:, cancellation:, cancellation_type:, - activity_id:, arg_hints:, result_hint: + activity_id:, arg_hints:, result_hint:, event_groups: ) end @@ -348,9 +434,10 @@ def self.now # deployments. That callback is only used when the patch marker would otherwise be created for the first time. # # @param patch_id [Symbol, String] Patch ID. + # @param event_groups [Array, nil] Event Groups to attach to the patch marker command. # @return [Boolean] True if this should take the newer patch, false if it should take the old path. - def self.patched(patch_id) - _current.patched(patch_id) + def self.patched(patch_id, event_groups: nil) + _current.patched(patch_id, event_groups:) end # @return [Converters::PayloadConverter] Payload converter for the workflow. @@ -395,9 +482,11 @@ def self.signal_handlers # @param summary [String, nil] A simple string identifying this timer that may be visible in UI/CLI. While it can be # normal text, it is best to treat as a timer ID. # @param cancellation [Cancellation] Cancellation for this timer. + # @param event_groups [Array, nil] Event Groups to attach to the timer command, in addition to any + # groups from enclosing {with_event_groups} scopes. # @raise [Error::CanceledError] Sleep canceled. - def self.sleep(duration, summary: nil, cancellation: Workflow.cancellation) - _current.sleep(duration, summary:, cancellation:) + def self.sleep(duration, summary: nil, cancellation: Workflow.cancellation, event_groups: nil) + _current.sleep(duration, summary:, cancellation:, event_groups:) end # Start a child workflow and return the handle. @@ -453,13 +542,15 @@ def self.start_child_workflow( search_attributes: nil, priority: Priority.default, arg_hints: nil, - result_hint: nil + result_hint: nil, + event_groups: nil ) _current.start_child_workflow( workflow, *args, id:, task_queue:, static_summary:, static_details:, cancellation:, cancellation_type:, parent_close_policy:, execution_timeout:, run_timeout:, task_timeout:, id_reuse_policy:, - retry_policy:, cron_schedule:, memo:, search_attributes:, priority:, arg_hints:, result_hint: + retry_policy:, cron_schedule:, memo:, search_attributes:, priority:, arg_hints:, result_hint:, + event_groups: ) end @@ -480,6 +571,8 @@ def self.storage # {::Timeout.timeout}. # @param summary [String] Timer summary for the timer created by this timeout. This is backed by {sleep} so see that # method for details. + # @param event_groups [Array, nil] Event Groups to attach to the timeout timer, in addition to any + # groups from enclosing {with_event_groups} scopes. Prefer this over {wait_condition} for wait-with-timeout. # # @yield Block to run with a timeout. # @return [Object] The result of the block. @@ -489,9 +582,10 @@ def self.timeout( exception_class = Timeout::Error, message = 'execution expired', summary: 'Timeout timer', + event_groups: nil, & ) - _current.timeout(duration, exception_class, message, summary:, &) + _current.timeout(duration, exception_class, message, summary:, event_groups:, &) end # @return [Hash] Update handlers for this workflow. This hash is mostly immutable except @@ -505,16 +599,18 @@ def self.update_handlers # # @param hash [Hash{String, Symbol => Object, nil}] Updates to apply. Value can be `nil` to effectively remove the # memo value. - def self.upsert_memo(hash) - _current.upsert_memo(hash) + # @param event_groups [Array, nil] Event Groups to attach to the modify-properties command. + def self.upsert_memo(hash, event_groups: nil) + _current.upsert_memo(hash, event_groups:) end # Issue updates to the workflow search attributes. # # @param updates [Array] Updates to apply. Note these are {SearchAttributes::Update} # objects which are created via {SearchAttributes::Key.value_set} and {SearchAttributes::Key.value_unset} methods. - def self.upsert_search_attributes(*updates) - _current.upsert_search_attributes(*updates) + # @param event_groups [Array, nil] Event Groups to attach to the upsert-search-attributes command. + def self.upsert_search_attributes(*updates, event_groups: nil) + _current.upsert_search_attributes(*updates, event_groups:) end # Wait for the given block to return a "truthy" value (i.e. any value other than `false` or `nil`). The block must @@ -650,7 +746,7 @@ class ContinueAsNewError < Error attr_accessor :args, :workflow, :task_queue, :run_timeout, :task_timeout, :backoff_start_interval, :retry_policy, :memo, :search_attributes, :arg_hints, :headers, - :initial_versioning_behavior + :initial_versioning_behavior, :event_groups, :_event_group_markers # Create a continue as new error. # @@ -679,6 +775,7 @@ class ContinueAsNewError < Error # first task of the new run. Set to {ContinueAsNewVersioningBehavior::AUTO_UPGRADE} to upgrade a pinned workflow # to the latest version on continue-as-new or {ContinueAsNewVersioningBehavior::USE_RAMPING_VERSION} to start on # the task queue's Ramping Version. This is currently experimental. + # @param event_groups [Array, nil] Event Groups to attach to the continue-as-new command. def initialize( *args, workflow: nil, @@ -691,7 +788,8 @@ def initialize( search_attributes: nil, arg_hints: nil, headers: {}, - initial_versioning_behavior: nil + initial_versioning_behavior: nil, + event_groups: nil ) super('Continue as new') @args = args @@ -706,6 +804,7 @@ def initialize( @arg_hints = arg_hints @headers = headers @initial_versioning_behavior = initial_versioning_behavior + @event_groups = event_groups Workflow._current.initialize_continue_as_new_error(self) end end diff --git a/temporalio/lib/temporalio/workflow/child_workflow_handle.rb b/temporalio/lib/temporalio/workflow/child_workflow_handle.rb index 43086504..8a9e5ce6 100644 --- a/temporalio/lib/temporalio/workflow/child_workflow_handle.rb +++ b/temporalio/lib/temporalio/workflow/child_workflow_handle.rb @@ -43,7 +43,9 @@ def result(result_hint: nil) # @param cancellation [Cancellation] Cancellation for canceling the signalling. # @param arg_hints [Array, nil] Overrides converter hints for arguments if any. If unset/nil and the # signal definition has arg hints, those are used by default. - def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil) + # @param event_groups [Array, nil] Event Groups to attach to the signal command, in addition to any + # groups from enclosing {Workflow.with_event_groups} scopes. + def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil, event_groups: nil) raise NotImplementedError end end diff --git a/temporalio/lib/temporalio/workflow/event_group.rb b/temporalio/lib/temporalio/workflow/event_group.rb new file mode 100644 index 00000000..cfde719b --- /dev/null +++ b/temporalio/lib/temporalio/workflow/event_group.rb @@ -0,0 +1,141 @@ +# frozen_string_literal: true + +require 'temporalio/api/sdk/v1/event_group_marker' +require 'temporalio/converters/payload_converter' + +module Temporalio + module Workflow + # A discrete token associating workflow commands, and the history events they produce, with a logical group for UI + # and observability purposes. + # + # Multiple Event Groups may be attached to a single command, and a single Event Group may be attached to multiple + # commands. Instances are created with {Workflow.create_event_group}. Attach them to specific commands via the + # `event_groups:` option, or to every command produced within a block via {Workflow.with_event_groups}. + # + # WARNING: Event Groups is an experimental API and may change without notice. + class EventGroup + # @!visibility private + Active = Struct.new(:implicit, :explicit, keyword_init: true) + + # @!visibility private + EMPTY_ACTIVE = Active.new(implicit: nil, explicit: {}.freeze).freeze + + # @!visibility private + STORAGE_KEY = :__temporal_event_groups + + class << self + # @!visibility private + def _active + Fiber[STORAGE_KEY] || EMPTY_ACTIVE + end + + # @!visibility private + def _with_active(active) + prev = Fiber[STORAGE_KEY] + Fiber[STORAGE_KEY] = active + yield + ensure + Fiber[STORAGE_KEY] = prev + end + + # @!visibility private + def _markers_for_command(directs) + active = _active + explicit = active.explicit + if directs + explicit = explicit.dup + directs.each do |group| + unless group.is_a?(Label) + raise TypeError, 'Event groups must be created with Temporalio::Workflow.create_event_group' + end + + explicit[group.id] = group + end + end + groups = explicit.values + groups.unshift(active.implicit) if active.implicit + groups.filter_map(&:_to_proto) + end + end + + # @!visibility private + def initialize + raise NotImplementedError, 'Cannot instantiate EventGroup directly, use Temporalio::Workflow.create_event_group' + end + + # @!visibility private + def _applied_over(_active) + raise NotImplementedError + end + + # @!visibility private + def _to_proto + raise NotImplementedError + end + + # An Event Group explicitly created by workflow code. + # + # @!visibility private + class Label < EventGroup + attr_reader :id, :label + + def initialize(id, label) # rubocop:disable Lint/MissingSuper + @id = id + @label = label + end + + # @!visibility private + def _applied_over(active) + Active.new(implicit: active.implicit, explicit: active.explicit.merge(id => self)) + end + + # @!visibility private + def _to_proto + marker_label = Api::Sdk::V1::EventGroupMarker::Label.new(id:) + # Deliberately the SDK's default converter, not the user-provided one. + marker_label.label = Converters::PayloadConverter.default.to_payload(label) if label + Api::Sdk::V1::EventGroupMarker.new(label: marker_label) + end + end + + # An Event Group created by the SDK around an inbound signal or update. + # + # @!visibility private + class Implicit < EventGroup + def initialize(marker) # rubocop:disable Lint/MissingSuper + @marker = marker + end + + # @!visibility private + def _applied_over(_active) + # Implicit groups do not inherit enclosing explicit scopes: a handler registered inside an explicit scope must + # not attribute its commands to that scope. + Active.new(implicit: self, explicit: {}) + end + + # @!visibility private + def _to_proto + @marker + end + end + + # No-op implicit group used when an inbound event ID is missing or invalid. + # + # @!visibility private + class StubImplicit < EventGroup + def initialize # rubocop:disable Lint/MissingSuper + end + + # @!visibility private + def _applied_over(_active) + EMPTY_ACTIVE + end + + # @!visibility private + def _to_proto + nil + end + end + end + end +end diff --git a/temporalio/lib/temporalio/workflow/external_workflow_handle.rb b/temporalio/lib/temporalio/workflow/external_workflow_handle.rb index 0e2a0ef7..78bad19e 100644 --- a/temporalio/lib/temporalio/workflow/external_workflow_handle.rb +++ b/temporalio/lib/temporalio/workflow/external_workflow_handle.rb @@ -30,12 +30,17 @@ def run_id # @param cancellation [Cancellation] Cancellation for canceling the signalling. # @param arg_hints [Array, nil] Overrides converter hints for arguments if any. If unset/nil and the # signal definition has arg hints, those are used by default. - def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil) + # @param event_groups [Array, nil] Event Groups to attach to the signal command, in addition to any + # groups from enclosing {Workflow.with_event_groups} scopes. + def signal(signal, *args, cancellation: Workflow.cancellation, arg_hints: nil, event_groups: nil) raise NotImplementedError end # Cancel the external workflow. - def cancel + # + # @param event_groups [Array, nil] Event Groups to attach to the cancel command, in addition to any + # groups from enclosing {Workflow.with_event_groups} scopes. + def cancel(event_groups: nil) raise NotImplementedError end end diff --git a/temporalio/lib/temporalio/workflow/info.rb b/temporalio/lib/temporalio/workflow/info.rb index abf73296..dca9c0c6 100644 --- a/temporalio/lib/temporalio/workflow/info.rb +++ b/temporalio/lib/temporalio/workflow/info.rb @@ -13,6 +13,7 @@ module Workflow :last_result, :has_last_result?, :namespace, + :original_execution_run_id, :parent, :priority, :retry_policy, @@ -49,6 +50,9 @@ module Workflow # @!attribute namespace # @return [String] Namespace for the workflow. + # @!attribute original_execution_run_id + # @return [String] Run ID recorded on the workflow execution started event. Unlike {#run_id}, + # this value is preserved across workflow resets. # @!attribute parent # @return [ParentInfo, nil] Parent information for the workflow if this is a child. # @!attribute priority diff --git a/temporalio/lib/temporalio/workflow/nexus_client.rb b/temporalio/lib/temporalio/workflow/nexus_client.rb index 64da87a8..0da089d1 100644 --- a/temporalio/lib/temporalio/workflow/nexus_client.rb +++ b/temporalio/lib/temporalio/workflow/nexus_client.rb @@ -37,6 +37,8 @@ def service # @param cancellation [Cancellation] Cancellation for the operation. # @param arg_hint [Object, nil] Converter hint for the argument. # @param result_hint [Object, nil] Converter hint for the result. + # @param event_groups [Array, nil] Event Groups to attach to the schedule command, in addition to any + # groups from enclosing {Workflow.with_event_groups} scopes. # @return [NexusOperationHandle] Handle to the started operation. def start_operation( operation, @@ -48,7 +50,8 @@ def start_operation( summary: nil, cancellation: Workflow.cancellation, arg_hint: nil, - result_hint: nil + result_hint: nil, + event_groups: nil ) raise NotImplementedError end @@ -69,6 +72,8 @@ def start_operation( # @param cancellation [Cancellation] Cancellation for the operation. # @param arg_hint [Object, nil] Converter hint for the argument. # @param result_hint [Object, nil] Converter hint for the result. + # @param event_groups [Array, nil] Event Groups to attach to the schedule command, in addition to any + # groups from enclosing {Workflow.with_event_groups} scopes. # @return [Object] Result of the operation. # @raise [Error::NexusOperationError] Operation failed. def execute_operation( @@ -81,11 +86,12 @@ def execute_operation( summary: nil, cancellation: Workflow.cancellation, arg_hint: nil, - result_hint: nil + result_hint: nil, + event_groups: nil ) start_operation( operation, arg, schedule_to_close_timeout:, schedule_to_start_timeout:, start_to_close_timeout:, - cancellation_type:, summary:, cancellation:, arg_hint:, result_hint: + cancellation_type:, summary:, cancellation:, arg_hint:, result_hint:, event_groups: ).result end end diff --git a/temporalio/rbi/temporalio/api/payload_visitor.rbi b/temporalio/rbi/temporalio/api/payload_visitor.rbi index cc0f0bb4..a44035f4 100644 --- a/temporalio/rbi/temporalio/api/payload_visitor.rbi +++ b/temporalio/rbi/temporalio/api/payload_visitor.rbi @@ -822,6 +822,9 @@ sig { params(value: Object).void } sig { params(value: Object).void } def coresdk_workflow_activation_workflow_activation_job(value); end + sig { params(value: Object).void } + def coresdk_workflow_commands_cancel_workflow_execution(value); end + sig { params(value: Object).void } def coresdk_workflow_commands_complete_workflow_execution(value); end diff --git a/temporalio/rbi/temporalio/api/workflowservice/v1/service_services.rbi b/temporalio/rbi/temporalio/api/workflowservice/v1/service_services.rbi index 4a2c96f5..23e9e514 100644 --- a/temporalio/rbi/temporalio/api/workflowservice/v1/service_services.rbi +++ b/temporalio/rbi/temporalio/api/workflowservice/v1/service_services.rbi @@ -772,7 +772,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService end # Describes a worker deployment. -# Experimental. This API might significantly change or be removed in a future release. # Deprecated. Replaced with `DescribeWorkerDeploymentVersion`. sig do params( @@ -783,7 +782,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService end # Describes a worker deployment version. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::DescribeWorkerDeploymentVersionRequest @@ -794,7 +792,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # Lists worker deployments in the namespace. Optionally can filter based on deployment series # name. -# Experimental. This API might significantly change or be removed in a future release. # Deprecated. Replaced with `ListWorkerDeployments`. sig do params( @@ -810,7 +807,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # Calculating reachability is relatively expensive. Therefore, server might return a recently # cached value. In such a case, the `last_update_time` will inform you about the actual # reachability calculation time. -# Experimental. This API might significantly change or be removed in a future release. # Deprecated. Replaced with `DrainageInfo` returned by `DescribeWorkerDeploymentVersion`. sig do params( @@ -821,7 +817,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService end # Returns the current deployment (and its info) for a given deployment series. -# Experimental. This API might significantly change or be removed in a future release. # Deprecated. Replaced by `current_version` returned by `DescribeWorkerDeployment`. sig do params( @@ -833,7 +828,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # Sets a deployment as the current deployment for its deployment series. Can optionally update # the metadata of the deployment as well. -# Experimental. This API might significantly change or be removed in a future release. # Deprecated. Replaced by `SetWorkerDeploymentCurrentVersion`. sig do params( @@ -845,7 +839,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # Set/unset the Current Version of a Worker Deployment. Automatically unsets the Ramping # Version if it is the Version being set as Current. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::SetWorkerDeploymentCurrentVersionRequest @@ -855,7 +848,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService end # Describes a Worker Deployment. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::DescribeWorkerDeploymentRequest @@ -866,7 +858,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # Deletes records of (an old) Deployment. A deployment can only be deleted if # it has no Version in it. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::DeleteWorkerDeploymentRequest @@ -881,7 +872,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # - It has no active pollers (none of the task queues in the Version have pollers) # - It is not draining (see WorkerDeploymentVersionInfo.drainage_info). This condition # can be skipped by passing `skip-drainage=true`. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::DeleteWorkerDeploymentVersionRequest @@ -892,7 +882,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService # Set/unset the Ramping Version of a Worker Deployment and its ramp percentage. Can be used for # gradual ramp to unversioned workers too. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::SetWorkerDeploymentRampingVersionRequest @@ -902,7 +891,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService end # Lists all Worker Deployments that are tracked in the Namespace. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::ListWorkerDeploymentsRequest @@ -956,7 +944,6 @@ module Temporalio::Api::WorkflowService::V1::WorkflowService end # Updates the user-given metadata attached to a Worker Deployment Version. -# Experimental. This API might significantly change or be removed in a future release. sig do params( request: Temporalio::Api::WorkflowService::V1::UpdateWorkerDeploymentVersionMetadataRequest diff --git a/temporalio/rbi/temporalio/internal/bridge/api/activity_result/activity_result.rbi b/temporalio/rbi/temporalio/internal/bridge/api/activity_result/activity_result.rbi index e1a1549a..b9b7cd91 100644 --- a/temporalio/rbi/temporalio/internal/bridge/api/activity_result/activity_result.rbi +++ b/temporalio/rbi/temporalio/internal/bridge/api/activity_result/activity_result.rbi @@ -282,11 +282,13 @@ class Temporalio::Internal::Bridge::Api::ActivityResult::Failure sig do params( - failure: T.nilable(Temporalio::Api::Failure::V1::Failure) + failure: T.nilable(Temporalio::Api::Failure::V1::Failure), + cause: T.nilable(T.any(Symbol, String, Integer)) ).void end def initialize( - failure: nil + failure: nil, + cause: :ACTIVITY_TASK_FAILED_CAUSE_UNSPECIFIED ) end @@ -302,6 +304,24 @@ class Temporalio::Internal::Bridge::Api::ActivityResult::Failure def clear_failure end + # Only meaningful on ActivityExecutionResult (lang -> core); ignored on ActivityResolution, +# which reuses this message. + sig { returns(T.any(Symbol, Integer)) } + def cause + end + + # Only meaningful on ActivityExecutionResult (lang -> core); ignored on ActivityResolution, +# which reuses this message. + sig { params(value: T.any(Symbol, String, Integer)).void } + def cause=(value) + end + + # Only meaningful on ActivityExecutionResult (lang -> core); ignored on ActivityResolution, +# which reuses this message. + sig { void } + def clear_cause + end + sig { params(field: String).returns(T.untyped) } def [](field) end @@ -545,3 +565,22 @@ class Temporalio::Internal::Bridge::Api::ActivityResult::DoBackoff def self.descriptor end end + +module Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause + self::ACTIVITY_TASK_FAILED_CAUSE_UNSPECIFIED = T.let(0, Integer) + self::ACTIVITY_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE = T.let(1, Integer) + self::ACTIVITY_TASK_FAILED_CAUSE_EXTERNAL_STORAGE_FAILURE = T.let(2, Integer) + self::ACTIVITY_TASK_FAILED_CAUSE_ACTIVITY_WORKER_UNHANDLED_FAILURE = T.let(3, Integer) + + sig { params(value: Integer).returns(T.nilable(Symbol)) } + def self.lookup(value) + end + + sig { params(value: Symbol).returns(T.nilable(Integer)) } + def self.resolve(value) + end + + sig { returns(::Google::Protobuf::EnumDescriptor) } + def self.descriptor + end +end diff --git a/temporalio/rbi/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbi b/temporalio/rbi/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbi index 58244169..cbb78481 100644 --- a/temporalio/rbi/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbi +++ b/temporalio/rbi/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbi @@ -704,7 +704,8 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::InitializeWorkflow search_attributes: T.nilable(Temporalio::Api::Common::V1::SearchAttributes), start_time: T.nilable(Google::Protobuf::Timestamp), root_workflow: T.nilable(Temporalio::Api::Common::V1::WorkflowExecution), - priority: T.nilable(Temporalio::Api::Common::V1::Priority) + priority: T.nilable(Temporalio::Api::Common::V1::Priority), + original_execution_run_id: T.nilable(String) ).void end def initialize( @@ -732,7 +733,8 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::InitializeWorkflow search_attributes: nil, start_time: nil, root_workflow: nil, - priority: nil + priority: nil, + original_execution_run_id: "" ) end @@ -1150,6 +1152,27 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::InitializeWorkflow def clear_priority end + # The run id recorded on the `WORKFLOW_EXECUTION_STARTED` event. Unlike the execution's current +# run id, this value is preserved across workflow resets. Mirrors the `original_execution_run_id` +# field from `WorkflowExecutionStartedEventAttributes`. + sig { returns(String) } + def original_execution_run_id + end + + # The run id recorded on the `WORKFLOW_EXECUTION_STARTED` event. Unlike the execution's current +# run id, this value is preserved across workflow resets. Mirrors the `original_execution_run_id` +# field from `WorkflowExecutionStartedEventAttributes`. + sig { params(value: String).void } + def original_execution_run_id=(value) + end + + # The run id recorded on the `WORKFLOW_EXECUTION_STARTED` event. Unlike the execution's current +# run id, this value is preserved across workflow resets. Mirrors the `original_execution_run_id` +# field from `WorkflowExecutionStartedEventAttributes`. + sig { void } + def clear_original_execution_run_id + end + sig { params(field: String).returns(T.untyped) } def [](field) end @@ -1995,14 +2018,16 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::SignalWorkflow signal_name: T.nilable(String), input: T.nilable(T::Array[T.nilable(Temporalio::Api::Common::V1::Payload)]), identity: T.nilable(String), - headers: T.nilable(T::Hash[String, T.nilable(Temporalio::Api::Common::V1::Payload)]) + headers: T.nilable(T::Hash[String, T.nilable(Temporalio::Api::Common::V1::Payload)]), + originating_event_id: T.nilable(Integer) ).void end def initialize( signal_name: "", input: [], identity: "", - headers: ::Google::Protobuf::Map.new(:string, :message, Temporalio::Api::Common::V1::Payload) + headers: ::Google::Protobuf::Map.new(:string, :message, Temporalio::Api::Common::V1::Payload), + originating_event_id: 0 ) end @@ -2060,6 +2085,21 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::SignalWorkflow def clear_headers end + # Event ID of the `WORKFLOW_EXECUTION_SIGNALED` history event that produced this job. + sig { returns(Integer) } + def originating_event_id + end + + # Event ID of the `WORKFLOW_EXECUTION_SIGNALED` history event that produced this job. + sig { params(value: Integer).void } + def originating_event_id=(value) + end + + # Event ID of the `WORKFLOW_EXECUTION_SIGNALED` history event that produced this job. + sig { void } + def clear_originating_event_id + end + sig { params(field: String).returns(T.untyped) } def [](field) end @@ -2161,12 +2201,14 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::ResolveSignalExtern sig do params( seq: T.nilable(Integer), - failure: T.nilable(Temporalio::Api::Failure::V1::Failure) + failure: T.nilable(Temporalio::Api::Failure::V1::Failure), + cause: T.nilable(T.any(Symbol, String, Integer)) ).void end def initialize( seq: 0, - failure: nil + failure: nil, + cause: :SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED ) end @@ -2206,6 +2248,24 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::ResolveSignalExtern def clear_failure end + # The server-reported cause when the signal failed. Unspecified when the signal succeeded or +# was cancelled before being sent. + sig { returns(T.any(Symbol, Integer)) } + def cause + end + + # The server-reported cause when the signal failed. Unspecified when the signal succeeded or +# was cancelled before being sent. + sig { params(value: T.any(Symbol, String, Integer)).void } + def cause=(value) + end + + # The server-reported cause when the signal failed. Unspecified when the signal succeeded or +# was cancelled before being sent. + sig { void } + def clear_cause + end + sig { params(field: String).returns(T.untyped) } def [](field) end @@ -2246,12 +2306,14 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::ResolveRequestCance sig do params( seq: T.nilable(Integer), - failure: T.nilable(Temporalio::Api::Failure::V1::Failure) + failure: T.nilable(Temporalio::Api::Failure::V1::Failure), + cause: T.nilable(T.any(Symbol, String, Integer)) ).void end def initialize( seq: 0, - failure: nil + failure: nil, + cause: :CANCEL_EXTERNAL_WORKFLOW_EXECUTION_FAILED_CAUSE_UNSPECIFIED ) end @@ -2273,24 +2335,36 @@ class Temporalio::Internal::Bridge::Api::WorkflowActivation::ResolveRequestCance def clear_seq end - # If populated, this signal either failed to be sent or was cancelled depending on failure -# type / info. + # If populated, the cancellation request failed. sig { returns(T.nilable(Temporalio::Api::Failure::V1::Failure)) } def failure end - # If populated, this signal either failed to be sent or was cancelled depending on failure -# type / info. + # If populated, the cancellation request failed. sig { params(value: T.nilable(Temporalio::Api::Failure::V1::Failure)).void } def failure=(value) end - # If populated, this signal either failed to be sent or was cancelled depending on failure -# type / info. + # If populated, the cancellation request failed. sig { void } def clear_failure end + # The server-reported cause when the cancellation request failed. + sig { returns(T.any(Symbol, Integer)) } + def cause + end + + # The server-reported cause when the cancellation request failed. + sig { params(value: T.any(Symbol, String, Integer)).void } + def cause=(value) + end + + # The server-reported cause when the cancellation request failed. + sig { void } + def clear_cause + end + sig { params(field: String).returns(T.untyped) } def [](field) end diff --git a/temporalio/rbi/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbi b/temporalio/rbi/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbi index f39f9a60..c295e16e 100644 --- a/temporalio/rbi/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbi +++ b/temporalio/rbi/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbi @@ -9,6 +9,7 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::WorkflowCommand sig do params( user_metadata: T.nilable(Temporalio::Api::Sdk::V1::UserMetadata), + event_group_markers: T.nilable(T::Array[T.nilable(Temporalio::Api::Sdk::V1::EventGroupMarker)]), start_timer: T.nilable(Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer), schedule_activity: T.nilable(Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleActivity), respond_to_query: T.nilable(Temporalio::Internal::Bridge::Api::WorkflowCommands::QueryResult), @@ -35,6 +36,7 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::WorkflowCommand end def initialize( user_metadata: nil, + event_group_markers: [], start_timer: nil, schedule_activity: nil, respond_to_query: nil, @@ -81,6 +83,27 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::WorkflowCommand def clear_user_metadata end + # Event group markers attached to the command. These are forwarded onto +# the corresponding server-side Command, and consequently surfaced on the +# resulting HistoryEvent. See `temporal/api/sdk/v1/event_group_marker.proto`. + sig { returns(T::Array[T.nilable(Temporalio::Api::Sdk::V1::EventGroupMarker)]) } + def event_group_markers + end + + # Event group markers attached to the command. These are forwarded onto +# the corresponding server-side Command, and consequently surfaced on the +# resulting HistoryEvent. See `temporal/api/sdk/v1/event_group_marker.proto`. + sig { params(value: ::Google::Protobuf::RepeatedField).void } + def event_group_markers=(value) + end + + # Event group markers attached to the command. These are forwarded onto +# the corresponding server-side Command, and consequently surfaced on the +# resulting HistoryEvent. See `temporal/api/sdk/v1/event_group_marker.proto`. + sig { void } + def clear_event_group_markers + end + sig { returns(T.nilable(Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer)) } def start_timer end @@ -856,7 +879,8 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleLocalActivity start_to_close_timeout: T.nilable(Google::Protobuf::Duration), retry_policy: T.nilable(Temporalio::Api::Common::V1::RetryPolicy), local_retry_threshold: T.nilable(Google::Protobuf::Duration), - cancellation_type: T.nilable(T.any(Symbol, String, Integer)) + cancellation_type: T.nilable(T.any(Symbol, String, Integer)), + include_arguments_in_marker: T.nilable(T::Boolean) ).void end def initialize( @@ -872,7 +896,8 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleLocalActivity start_to_close_timeout: nil, retry_policy: nil, local_retry_threshold: nil, - cancellation_type: :TRY_CANCEL + cancellation_type: :TRY_CANCEL, + include_arguments_in_marker: false ) end @@ -1113,6 +1138,27 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleLocalActivity def clear_cancellation_type end + # If set, the local activity arguments will be included in the resulting marker under the +# `input` key. This is disabled by default to avoid increasing history size unless the lang +# SDK explicitly chooses to expose it. + sig { returns(T::Boolean) } + def include_arguments_in_marker + end + + # If set, the local activity arguments will be included in the resulting marker under the +# `input` key. This is disabled by default to avoid increasing history size unless the lang +# SDK explicitly chooses to expose it. + sig { params(value: T::Boolean).void } + def include_arguments_in_marker=(value) + end + + # If set, the local activity arguments will be included in the resulting marker under the +# `input` key. This is disabled by default to avoid increasing history size unless the lang +# SDK explicitly chooses to expose it. + sig { void } + def clear_include_arguments_in_marker + end + sig { params(field: String).returns(T.untyped) } def [](field) end @@ -1817,8 +1863,27 @@ class Temporalio::Internal::Bridge::Api::WorkflowCommands::CancelWorkflowExecuti include ::Google::Protobuf::MessageExts extend ::Google::Protobuf::MessageExts::ClassMethods - sig {void} - def initialize; end + sig do + params( + details: T.nilable(Temporalio::Api::Common::V1::Payloads) + ).void + end + def initialize( + details: nil + ) + end + + sig { returns(T.nilable(Temporalio::Api::Common::V1::Payloads)) } + def details + end + + sig { params(value: T.nilable(Temporalio::Api::Common::V1::Payloads)).void } + def details=(value) + end + + sig { void } + def clear_details + end sig { params(field: String).returns(T.untyped) } def [](field) diff --git a/temporalio/rbi/temporalio/internal/worker/workflow_instance.rbi b/temporalio/rbi/temporalio/internal/worker/workflow_instance.rbi index e06ad4f2..0215b700 100644 --- a/temporalio/rbi/temporalio/internal/worker/workflow_instance.rbi +++ b/temporalio/rbi/temporalio/internal/worker/workflow_instance.rbi @@ -142,8 +142,8 @@ class Temporalio::Internal::Worker::WorkflowInstance sig { type_parameters(:T).params(block: T.proc.returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) } def illegal_call_tracing_disabled(&block); end - sig { params(patch_id: T.any(Symbol, String), deprecated: T::Boolean).returns(T::Boolean) } - def patch(patch_id:, deprecated:); end + sig { params(patch_id: T.any(Symbol, String), deprecated: T::Boolean, event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).returns(T::Boolean) } + def patch(patch_id:, deprecated:, event_groups: T.unsafe(nil)); end sig { params(patch_id: String).returns(T::Boolean) } def patch_activated?(patch_id); end diff --git a/temporalio/rbi/temporalio/internal/worker/workflow_instance/context.rbi b/temporalio/rbi/temporalio/internal/worker/workflow_instance/context.rbi index acf0f559..3b795104 100644 --- a/temporalio/rbi/temporalio/internal/worker/workflow_instance/context.rbi +++ b/temporalio/rbi/temporalio/internal/worker/workflow_instance/context.rbi @@ -42,8 +42,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context sig { returns(T.nilable(Temporalio::Workflow::UpdateInfo)) } def current_update_info; end - sig { params(patch_id: T.any(Symbol, String)).void } - def deprecate_patch(patch_id); end + sig { params(patch_id: T.any(Symbol, String), event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def deprecate_patch(patch_id, event_groups: T.unsafe(nil)); end sig { type_parameters(:T).params(block: T.proc.returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) } def durable_scheduler_disabled(&block); end @@ -65,7 +65,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context disable_eager_execution: T::Boolean, priority: Temporalio::Priority, arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(T.nilable(Object)) end def execute_activity( @@ -84,7 +85,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context disable_eager_execution:, priority:, arg_hints:, - result_hint: + result_hint:, + event_groups: T.unsafe(nil) ); end sig do @@ -101,7 +103,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context cancellation_type: Integer, activity_id: T.nilable(String), arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(T.nilable(Object)) end def execute_local_activity( @@ -117,7 +120,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context cancellation_type:, activity_id:, arg_hints:, - result_hint: + result_hint:, + event_groups: T.unsafe(nil) ); end sig do @@ -153,8 +157,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context sig { returns(Time) } def now; end - sig { params(patch_id: T.any(Symbol, String)).returns(T::Boolean) } - def patched(patch_id); end + sig { params(patch_id: T.any(Symbol, String), event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).returns(T::Boolean) } + def patched(patch_id, event_groups: T.unsafe(nil)); end sig { returns(Temporalio::Converters::PayloadConverter) } def payload_converter; end @@ -177,8 +181,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context sig { returns(Temporalio::Internal::Worker::WorkflowInstance::HandlerHash) } def signal_handlers; end - sig { params(duration: T.nilable(T.any(Integer, Float)), summary: T.nilable(String), cancellation: Temporalio::Cancellation).void } - def sleep(duration, summary:, cancellation:); end + sig { params(duration: T.nilable(T.any(Integer, Float)), summary: T.nilable(String), cancellation: Temporalio::Cancellation, event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def sleep(duration, summary:, cancellation:, event_groups: T.unsafe(nil)); end sig do params( @@ -201,7 +205,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context search_attributes: T.nilable(Temporalio::SearchAttributes), priority: Temporalio::Priority, arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(Temporalio::Internal::Worker::WorkflowInstance::ChildWorkflowHandle) end def start_child_workflow( @@ -224,7 +229,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context search_attributes:, priority:, arg_hints:, - result_hint: + result_hint:, + event_groups: T.unsafe(nil) ); end sig { returns(T::Hash[Object, Object]) } @@ -237,20 +243,21 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context exception_class: T.class_of(Exception), exception_args: T.nilable(Object), summary: T.nilable(String), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]), block: T.proc.returns(T.type_parameter(:T)) ) .returns(T.type_parameter(:T)) end - def timeout(duration, exception_class, *exception_args, summary:, &block); end + def timeout(duration, exception_class, *exception_args, summary:, event_groups: T.unsafe(nil), &block); end sig { returns(Temporalio::Internal::Worker::WorkflowInstance::HandlerHash) } def update_handlers; end - sig { params(hash: T::Hash[T.any(Symbol, String), T.nilable(Object)]).void } - def upsert_memo(hash); end + sig { params(hash: T::Hash[T.any(Symbol, String), T.nilable(Object)], event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def upsert_memo(hash, event_groups: T.unsafe(nil)); end - sig { params(updates: Temporalio::SearchAttributes::Update).void } - def upsert_search_attributes(*updates); end + sig { params(updates: Temporalio::SearchAttributes::Update, event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def upsert_search_attributes(*updates, event_groups: T.unsafe(nil)); end sig do type_parameters(:T) @@ -259,8 +266,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context end def wait_condition(cancellation:, &block); end - sig { params(id: String, run_id: T.nilable(String)).void } - def _cancel_external_workflow(id:, run_id:); end + sig { params(id: String, run_id: T.nilable(String), event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def _cancel_external_workflow(id:, run_id:, event_groups: T.unsafe(nil)); end sig { params(outbound: Temporalio::Worker::Interceptor::Workflow::Outbound).void } def _outbound=(outbound); end @@ -271,10 +278,11 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context signal: T.any(Temporalio::Workflow::Definition::Signal, Symbol, String), args: T::Array[T.nilable(Object)], cancellation: Temporalio::Cancellation, - arg_hints: T.nilable(T::Array[Object]) + arg_hints: T.nilable(T::Array[Object]), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).void end - def _signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:); end + def _signal_child_workflow(id:, signal:, args:, cancellation:, arg_hints:, event_groups: T.unsafe(nil)); end sig do params( @@ -283,8 +291,9 @@ class Temporalio::Internal::Worker::WorkflowInstance::Context signal: T.any(Temporalio::Workflow::Definition::Signal, Symbol, String), args: T::Array[T.nilable(Object)], cancellation: Temporalio::Cancellation, - arg_hints: T.nilable(T::Array[Object]) + arg_hints: T.nilable(T::Array[Object]), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).void end - def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:); end + def _signal_external_workflow(id:, run_id:, signal:, args:, cancellation:, arg_hints:, event_groups: T.unsafe(nil)); end end diff --git a/temporalio/rbi/temporalio/internal/worker/workflow_instance/nexus_client.rbi b/temporalio/rbi/temporalio/internal/worker/workflow_instance/nexus_client.rbi index a5436a3b..7e5b5599 100644 --- a/temporalio/rbi/temporalio/internal/worker/workflow_instance/nexus_client.rbi +++ b/temporalio/rbi/temporalio/internal/worker/workflow_instance/nexus_client.rbi @@ -29,7 +29,8 @@ class Temporalio::Internal::Worker::WorkflowInstance::NexusClient < Temporalio:: summary: T.nilable(String), cancellation: Temporalio::Cancellation, arg_hint: T.nilable(Object), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(Temporalio::Workflow::NexusOperationHandle) end def start_operation( @@ -42,6 +43,7 @@ class Temporalio::Internal::Worker::WorkflowInstance::NexusClient < Temporalio:: summary: T.unsafe(nil), cancellation: T.unsafe(nil), arg_hint: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end end diff --git a/temporalio/rbi/temporalio/internal/worker/workflow_instance/outbound_implementation.rbi b/temporalio/rbi/temporalio/internal/worker/workflow_instance/outbound_implementation.rbi index e0c684bf..2bbfad2c 100644 --- a/temporalio/rbi/temporalio/internal/worker/workflow_instance/outbound_implementation.rbi +++ b/temporalio/rbi/temporalio/internal/worker/workflow_instance/outbound_implementation.rbi @@ -11,10 +11,11 @@ class Temporalio::Internal::Worker::WorkflowInstance::OutboundImplementation < T local: T::Boolean, cancellation: Temporalio::Cancellation, result_hint: T.nilable(Object), - block: T.proc.params(arg0: T.nilable(Object)).returns(Integer) + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]), + block: T.proc.params(arg0: T.nilable(Object), arg1: T.untyped).returns(Integer) ).returns(T.nilable(Object)) end - def execute_activity_with_local_backoffs(local:, cancellation:, result_hint:, &block); end + def execute_activity_with_local_backoffs(local:, cancellation:, result_hint:, event_groups:, &block); end sig do params( @@ -22,10 +23,11 @@ class Temporalio::Internal::Worker::WorkflowInstance::OutboundImplementation < T cancellation: Temporalio::Cancellation, last_local_backoff: T.nilable(Object), result_hint: T.nilable(Object), - block: T.proc.params(arg0: T.nilable(Object)).returns(Integer) + markers: T.untyped, + block: T.proc.params(arg0: T.nilable(Object), arg1: T.untyped).returns(Integer) ).returns(T.nilable(Object)) end - def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, &block); end + def execute_activity_once(local:, cancellation:, last_local_backoff:, result_hint:, markers:, &block); end sig do params( @@ -36,8 +38,10 @@ class Temporalio::Internal::Worker::WorkflowInstance::OutboundImplementation < T args: T::Array[T.nilable(Object)], cancellation: Temporalio::Cancellation, arg_hints: T.nilable(T::Array[Object]), - headers: T::Hash[String, T.nilable(Object)] + headers: T::Hash[String, T.nilable(Object)], + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).void end - def _signal_external_workflow(id:, run_id:, child:, signal:, args:, cancellation:, arg_hints:, headers:); end + def _signal_external_workflow(id:, run_id:, child:, signal:, args:, cancellation:, arg_hints:, headers:, + event_groups:); end end diff --git a/temporalio/rbi/temporalio/worker/interceptor.rbi b/temporalio/rbi/temporalio/worker/interceptor.rbi index e22d885b..53732c69 100644 --- a/temporalio/rbi/temporalio/worker/interceptor.rbi +++ b/temporalio/rbi/temporalio/worker/interceptor.rbi @@ -171,6 +171,9 @@ class Temporalio::Worker::Interceptor::Workflow::CancelExternalWorkflowInput < : sig { returns(T.nilable(String)) } def run_id; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::ExecuteActivityInput < ::Data @@ -226,6 +229,9 @@ class Temporalio::Worker::Interceptor::Workflow::ExecuteActivityInput < ::Data sig { returns(T::Hash[String, T.nilable(Object)]) } def headers; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::ExecuteLocalActivityInput < ::Data @@ -272,6 +278,9 @@ class Temporalio::Worker::Interceptor::Workflow::ExecuteLocalActivityInput < ::D sig { returns(T::Hash[String, T.nilable(Object)]) } def headers; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::InitializeContinueAsNewErrorInput < ::Data @@ -301,6 +310,9 @@ class Temporalio::Worker::Interceptor::Workflow::SignalChildWorkflowInput < ::Da sig { returns(T::Hash[String, T.nilable(Object)]) } def headers; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::SignalExternalWorkflowInput < ::Data @@ -326,6 +338,9 @@ class Temporalio::Worker::Interceptor::Workflow::SignalExternalWorkflowInput < : sig { returns(T::Hash[String, T.nilable(Object)]) } def headers; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::SleepInput < ::Data @@ -339,6 +354,9 @@ class Temporalio::Worker::Interceptor::Workflow::SleepInput < ::Data sig { returns(Temporalio::Cancellation) } def cancellation; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::StartChildWorkflowInput < ::Data @@ -406,6 +424,9 @@ class Temporalio::Worker::Interceptor::Workflow::StartChildWorkflowInput < ::Dat sig { returns(T::Hash[String, T.nilable(Object)]) } def headers; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::StartNexusOperationInput < ::Data @@ -449,6 +470,9 @@ class Temporalio::Worker::Interceptor::Workflow::StartNexusOperationInput < ::Da sig { returns(T::Hash[String, String]) } def headers; end + + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + def event_groups; end end class Temporalio::Worker::Interceptor::Workflow::Outbound diff --git a/temporalio/rbi/temporalio/workflow.rbi b/temporalio/rbi/temporalio/workflow.rbi index 28d2c529..8003cf82 100644 --- a/temporalio/rbi/temporalio/workflow.rbi +++ b/temporalio/rbi/temporalio/workflow.rbi @@ -16,6 +16,19 @@ module Temporalio::Workflow sig { params(endpoint: T.any(Symbol, String), service: T.any(Symbol, String)).returns(Temporalio::Workflow::NexusClient) } def create_nexus_client(endpoint:, service:); end + sig { params(id: String, label: T.nilable(String)).returns(Temporalio::Workflow::EventGroup) } + def create_event_group(id, label: nil); end + + sig do + type_parameters(:T) + .params( + groups: Temporalio::Workflow::EventGroup, + block: T.proc.returns(T.type_parameter(:T)) + ) + .returns(T.type_parameter(:T)) + end + def with_event_groups(*groups, &block); end + sig { returns(T::Array[Integer]) } def suggest_continue_as_new_reasons; end @@ -40,8 +53,8 @@ module Temporalio::Workflow sig { returns(T.nilable(Temporalio::Workflow::UpdateInfo)) } def current_update_info; end - sig { params(patch_id: T.any(Symbol, String)).void } - def deprecate_patch(patch_id); end + sig { params(patch_id: T.any(Symbol, String), event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def deprecate_patch(patch_id, event_groups: nil); end sig do params( @@ -60,7 +73,8 @@ module Temporalio::Workflow disable_eager_execution: T::Boolean, priority: Temporalio::Priority, arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(T.nilable(Object)) end def execute_activity( @@ -79,7 +93,8 @@ module Temporalio::Workflow disable_eager_execution: T.unsafe(nil), priority: T.unsafe(nil), arg_hints: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end sig do @@ -103,7 +118,8 @@ module Temporalio::Workflow search_attributes: T.nilable(Temporalio::SearchAttributes), priority: Temporalio::Priority, arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(T.nilable(Object)) end def execute_child_workflow( @@ -126,7 +142,8 @@ module Temporalio::Workflow search_attributes: T.unsafe(nil), priority: T.unsafe(nil), arg_hints: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end sig do @@ -143,7 +160,8 @@ module Temporalio::Workflow cancellation_type: Integer, activity_id: T.nilable(String), arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(T.nilable(Object)) end def execute_local_activity( @@ -159,7 +177,8 @@ module Temporalio::Workflow cancellation_type: T.unsafe(nil), activity_id: T.unsafe(nil), arg_hints: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end sig { params(workflow_id: String, run_id: T.nilable(String)).returns(Temporalio::Workflow::ExternalWorkflowHandle) } @@ -186,8 +205,8 @@ module Temporalio::Workflow sig { returns(Time) } def now; end - sig { params(patch_id: T.any(Symbol, String)).returns(T::Boolean) } - def patched(patch_id); end + sig { params(patch_id: T.any(Symbol, String), event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).returns(T::Boolean) } + def patched(patch_id, event_groups: nil); end sig { returns(Temporalio::Converters::PayloadConverter) } def payload_converter; end @@ -204,8 +223,8 @@ module Temporalio::Workflow sig { returns(T::Hash[T.nilable(String), Temporalio::Workflow::Definition::Signal]) } def signal_handlers; end - sig { params(duration: T.nilable(T.any(Integer, Float)), summary: T.nilable(String), cancellation: Temporalio::Cancellation).void } - def sleep(duration, summary: T.unsafe(nil), cancellation: T.unsafe(nil)); end + sig { params(duration: T.nilable(T.any(Integer, Float)), summary: T.nilable(String), cancellation: Temporalio::Cancellation, event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def sleep(duration, summary: T.unsafe(nil), cancellation: T.unsafe(nil), event_groups: T.unsafe(nil)); end sig do params( @@ -228,7 +247,8 @@ module Temporalio::Workflow search_attributes: T.nilable(Temporalio::SearchAttributes), priority: Temporalio::Priority, arg_hints: T.nilable(T::Array[Object]), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(Temporalio::Workflow::ChildWorkflowHandle) end def start_child_workflow( @@ -251,7 +271,8 @@ module Temporalio::Workflow search_attributes: T.unsafe(nil), priority: T.unsafe(nil), arg_hints: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end sig { returns(T::Hash[Object, Object]) } @@ -264,19 +285,20 @@ module Temporalio::Workflow exception_class: T.class_of(Exception), message: String, summary: T.nilable(String), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]), block: T.proc.returns(T.type_parameter(:T)) ).returns(T.type_parameter(:T)) end - def timeout(duration, exception_class = T.unsafe(nil), message = T.unsafe(nil), summary: T.unsafe(nil), &block); end + def timeout(duration, exception_class = T.unsafe(nil), message = T.unsafe(nil), summary: T.unsafe(nil), event_groups: T.unsafe(nil), &block); end sig { returns(T::Hash[T.nilable(String), Temporalio::Workflow::Definition::Update]) } def update_handlers; end - sig { params(hash: T::Hash[T.any(Symbol, String), T.nilable(Object)]).void } - def upsert_memo(hash); end + sig { params(hash: T::Hash[T.any(Symbol, String), T.nilable(Object)], event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def upsert_memo(hash, event_groups: nil); end - sig { params(updates: Temporalio::SearchAttributes::Update).void } - def upsert_search_attributes(*updates); end + sig { params(updates: Temporalio::SearchAttributes::Update, event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def upsert_search_attributes(*updates, event_groups: nil); end sig do type_parameters(:T) @@ -326,7 +348,8 @@ class Temporalio::Workflow::ContinueAsNewError < ::Temporalio::Error search_attributes: T.nilable(Temporalio::SearchAttributes), arg_hints: T.nilable(T::Array[Object]), headers: T::Hash[String, T.nilable(Object)], - initial_versioning_behavior: T.nilable(Integer) + initial_versioning_behavior: T.nilable(Integer), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).void end def initialize( @@ -341,7 +364,8 @@ class Temporalio::Workflow::ContinueAsNewError < ::Temporalio::Error search_attributes: T.unsafe(nil), arg_hints: T.unsafe(nil), headers: T.unsafe(nil), - initial_versioning_behavior: T.unsafe(nil) + initial_versioning_behavior: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end sig { returns(T::Array[T.nilable(Object)]) } @@ -380,6 +404,12 @@ class Temporalio::Workflow::ContinueAsNewError < ::Temporalio::Error sig { returns(T.nilable(Integer)) } attr_accessor :initial_versioning_behavior + sig { returns(T.nilable(T::Array[Temporalio::Workflow::EventGroup])) } + attr_accessor :event_groups + + sig { returns(T.nilable(T::Array[Temporalio::Api::Sdk::V1::EventGroupMarker])) } + attr_accessor :_event_group_markers + end class Temporalio::Workflow::InvalidWorkflowStateError < ::Temporalio::Error; end diff --git a/temporalio/rbi/temporalio/workflow/child_workflow_handle.rbi b/temporalio/rbi/temporalio/workflow/child_workflow_handle.rbi index afe68e8f..40781351 100644 --- a/temporalio/rbi/temporalio/workflow/child_workflow_handle.rbi +++ b/temporalio/rbi/temporalio/workflow/child_workflow_handle.rbi @@ -20,8 +20,9 @@ class Temporalio::Workflow::ChildWorkflowHandle signal: T.any(Temporalio::Workflow::Definition::Signal, Symbol, String), args: T.nilable(Object), cancellation: Temporalio::Cancellation, - arg_hints: T.nilable(T::Array[Object]) + arg_hints: T.nilable(T::Array[Object]), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).void end - def signal(signal, *args, cancellation: T.unsafe(nil), arg_hints: T.unsafe(nil)); end + def signal(signal, *args, cancellation: T.unsafe(nil), arg_hints: T.unsafe(nil), event_groups: T.unsafe(nil)); end end diff --git a/temporalio/rbi/temporalio/workflow/event_group.rbi b/temporalio/rbi/temporalio/workflow/event_group.rbi new file mode 100644 index 00000000..d5e72c14 --- /dev/null +++ b/temporalio/rbi/temporalio/workflow/event_group.rbi @@ -0,0 +1,81 @@ +# typed: true + +class Temporalio::Workflow::EventGroup + extend T::Sig + + sig { returns(Temporalio::Workflow::EventGroup::Active) } + def self._active; end + + sig do + type_parameters(:T) + .params( + active: Temporalio::Workflow::EventGroup::Active, + block: T.proc.returns(T.type_parameter(:T)) + ) + .returns(T.type_parameter(:T)) + end + def self._with_active(active, &block); end + + sig do + params(directs: T.nilable(T::Array[Temporalio::Workflow::EventGroup])) + .returns(T::Array[Temporalio::Api::Sdk::V1::EventGroupMarker]) + end + def self._markers_for_command(directs); end + + sig { void } + def initialize; end + + sig do + params(_active: Temporalio::Workflow::EventGroup::Active) + .returns(Temporalio::Workflow::EventGroup::Active) + end + def _applied_over(_active); end + + sig { returns(T.nilable(Temporalio::Api::Sdk::V1::EventGroupMarker)) } + def _to_proto; end +end + +class Temporalio::Workflow::EventGroup::Active + extend T::Sig + + sig { returns(T.nilable(Temporalio::Workflow::EventGroup)) } + attr_accessor :implicit + + sig { returns(T::Hash[String, Temporalio::Workflow::EventGroup]) } + attr_accessor :explicit + + sig do + params( + implicit: T.nilable(Temporalio::Workflow::EventGroup), + explicit: T::Hash[String, Temporalio::Workflow::EventGroup] + ).void + end + def initialize(implicit: nil, explicit: {}); end +end + +class Temporalio::Workflow::EventGroup::Label < Temporalio::Workflow::EventGroup + extend T::Sig + + sig { returns(String) } + attr_reader :id + + sig { returns(T.nilable(String)) } + attr_reader :label + + sig { params(id: String, label: T.nilable(String)).void } + def initialize(id, label); end +end + +class Temporalio::Workflow::EventGroup::Implicit < Temporalio::Workflow::EventGroup + extend T::Sig + + sig { params(marker: Temporalio::Api::Sdk::V1::EventGroupMarker).void } + def initialize(marker); end +end + +class Temporalio::Workflow::EventGroup::StubImplicit < Temporalio::Workflow::EventGroup + extend T::Sig + + sig { void } + def initialize; end +end diff --git a/temporalio/rbi/temporalio/workflow/external_workflow_handle.rbi b/temporalio/rbi/temporalio/workflow/external_workflow_handle.rbi index 0ea37ddd..a6dbc045 100644 --- a/temporalio/rbi/temporalio/workflow/external_workflow_handle.rbi +++ b/temporalio/rbi/temporalio/workflow/external_workflow_handle.rbi @@ -14,11 +14,12 @@ class Temporalio::Workflow::ExternalWorkflowHandle signal: T.any(Temporalio::Workflow::Definition::Signal, Symbol, String), args: T.nilable(Object), cancellation: Temporalio::Cancellation, - arg_hints: T.nilable(T::Array[Object]) + arg_hints: T.nilable(T::Array[Object]), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).void end - def signal(signal, *args, cancellation: T.unsafe(nil), arg_hints: T.unsafe(nil)); end + def signal(signal, *args, cancellation: T.unsafe(nil), arg_hints: T.unsafe(nil), event_groups: T.unsafe(nil)); end - sig { void } - def cancel; end + sig { params(event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup])).void } + def cancel(event_groups: nil); end end diff --git a/temporalio/rbi/temporalio/workflow/info.rbi b/temporalio/rbi/temporalio/workflow/info.rbi index 681eb053..b99ad5dc 100644 --- a/temporalio/rbi/temporalio/workflow/info.rbi +++ b/temporalio/rbi/temporalio/workflow/info.rbi @@ -33,6 +33,9 @@ class Temporalio::Workflow::Info < ::Struct sig { returns(String) } def namespace; end + sig { returns(String) } + def original_execution_run_id; end + sig { returns(T.nilable(Temporalio::Workflow::Info::ParentInfo)) } def parent; end diff --git a/temporalio/rbi/temporalio/workflow/nexus_client.rbi b/temporalio/rbi/temporalio/workflow/nexus_client.rbi index b0a2ddc5..d0c77ee5 100644 --- a/temporalio/rbi/temporalio/workflow/nexus_client.rbi +++ b/temporalio/rbi/temporalio/workflow/nexus_client.rbi @@ -20,7 +20,8 @@ class Temporalio::Workflow::NexusClient summary: T.nilable(String), cancellation: Temporalio::Cancellation, arg_hint: T.nilable(Object), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(Temporalio::Workflow::NexusOperationHandle) end def start_operation( @@ -33,7 +34,8 @@ class Temporalio::Workflow::NexusClient summary: T.unsafe(nil), cancellation: T.unsafe(nil), arg_hint: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end sig do @@ -47,7 +49,8 @@ class Temporalio::Workflow::NexusClient summary: T.nilable(String), cancellation: Temporalio::Cancellation, arg_hint: T.nilable(Object), - result_hint: T.nilable(Object) + result_hint: T.nilable(Object), + event_groups: T.nilable(T::Array[Temporalio::Workflow::EventGroup]) ).returns(T.nilable(Object)) end def execute_operation( @@ -60,6 +63,7 @@ class Temporalio::Workflow::NexusClient summary: T.unsafe(nil), cancellation: T.unsafe(nil), arg_hint: T.unsafe(nil), - result_hint: T.unsafe(nil) + result_hint: T.unsafe(nil), + event_groups: T.unsafe(nil) ); end end diff --git a/temporalio/sig/temporalio/api/enums/v1/failed_cause.rbs b/temporalio/sig/temporalio/api/enums/v1/failed_cause.rbs index cff1dbe5..4be64dcc 100644 --- a/temporalio/sig/temporalio/api/enums/v1/failed_cause.rbs +++ b/temporalio/sig/temporalio/api/enums/v1/failed_cause.rbs @@ -261,10 +261,10 @@ module Temporalio RESOURCE_EXHAUSTED_SCOPE_UNSPECIFIED: 0 - # Exhausted resource is a system-level resource. + # Exhausted resource is a namespace-level resource. RESOURCE_EXHAUSTED_SCOPE_NAMESPACE: 1 - # Exhausted resource is a namespace-level resource. + # Exhausted resource is a system-level resource. RESOURCE_EXHAUSTED_SCOPE_SYSTEM: 2 def self.lookup: (::Integer number) -> ::Symbol diff --git a/temporalio/sig/temporalio/api/payload_visitor.rbs b/temporalio/sig/temporalio/api/payload_visitor.rbs index 82467c54..bf924ca7 100644 --- a/temporalio/sig/temporalio/api/payload_visitor.rbs +++ b/temporalio/sig/temporalio/api/payload_visitor.rbs @@ -276,6 +276,7 @@ def api_activity_v1_activity_execution_info: (untyped value) -> void def coresdk_workflow_activation_signal_workflow: (untyped value) -> void def coresdk_workflow_activation_workflow_activation: (untyped value) -> void def coresdk_workflow_activation_workflow_activation_job: (untyped value) -> void + def coresdk_workflow_commands_cancel_workflow_execution: (untyped value) -> void def coresdk_workflow_commands_complete_workflow_execution: (untyped value) -> void def coresdk_workflow_commands_continue_as_new_workflow_execution: (untyped value) -> void def coresdk_workflow_commands_fail_workflow_execution: (untyped value) -> void diff --git a/temporalio/sig/temporalio/internal/bridge/api/activity_result/activity_result.rbs b/temporalio/sig/temporalio/internal/bridge/api/activity_result/activity_result.rbs index e0582cbd..54849869 100644 --- a/temporalio/sig/temporalio/internal/bridge/api/activity_result/activity_result.rbs +++ b/temporalio/sig/temporalio/internal/bridge/api/activity_result/activity_result.rbs @@ -137,18 +137,29 @@ module Temporalio def has_failure?: () -> bool def clear_failure: () -> void + # Only meaningful on ActivityExecutionResult (lang -> core); ignored on ActivityResolution, + # which reuses this message. + attr_reader cause(): ::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::names | ::Integer + attr_writer cause(): ::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::names | ::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::strings | ::Integer | ::Float + attr_reader cause_const(): ::Integer + def clear_cause: () -> void + type init_map = { failure: (::Temporalio::Api::Failure::V1::Failure | ::Temporalio::Api::Failure::V1::Failure::init_map)?, "failure" => (::Temporalio::Api::Failure::V1::Failure | ::Temporalio::Api::Failure::V1::Failure::init_map)?, + cause: (::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::names | ::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::strings | ::Integer | ::Float)?, + "cause" => (::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::names | ::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::strings | ::Integer | ::Float)?, } def initialize: (?init_map initial_value) -> void def []: ("failure" name) -> ::Temporalio::Api::Failure::V1::Failure? + | ("cause" name) -> (::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::names | ::Integer) def []=: ("failure" name, ::Temporalio::Api::Failure::V1::Failure? value) -> void + | ("cause" name, (::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::names | ::Temporalio::Internal::Bridge::Api::ActivityResult::ActivityTaskFailedCause::strings | ::Integer | ::Float) value) -> void end # Used to report cancellation from both Core and Lang. @@ -232,6 +243,41 @@ module Temporalio | ("backoff_duration" name, ((::Google::Protobuf::Duration | ::int)?) value) -> void | ("original_schedule_time" name, ((::Google::Protobuf::Timestamp | ::Time)?) value) -> void end + + # A well-known condition that caused an activity task to fail. Lang reports one alongside the + # failure so core can categorize activity failures instead of treating them all alike; it becomes + # the `failure_reason` metric label, so the set of values is deliberately small and bounded. + module ActivityTaskFailedCause + + ACTIVITY_TASK_FAILED_CAUSE_UNSPECIFIED: 0 + + # A payload-bearing field on a request the worker sent for this activity task exceeded the + # per-field size limit configured on the server for the namespace. + # Check the activity task failure message for more information. + ACTIVITY_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE: 1 + + # The worker failed to offload a payload to, or retrieve one from, external storage while + # processing this activity task. + # Check the activity task failure message for more information. + ACTIVITY_TASK_FAILED_CAUSE_EXTERNAL_STORAGE_FAILURE: 2 + + # The default cause for an activity task failure reported by a worker; a more specific cause + # takes precedence whenever the condition is recognized. + # Check the activity task failure message for more information. + ACTIVITY_TASK_FAILED_CAUSE_ACTIVITY_WORKER_UNHANDLED_FAILURE: 3 + + def self.lookup: (::Integer number) -> ::Symbol + + + def self.resolve: (::Symbol name) -> ::Integer + + + type names = :ACTIVITY_TASK_FAILED_CAUSE_UNSPECIFIED | :ACTIVITY_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE | :ACTIVITY_TASK_FAILED_CAUSE_EXTERNAL_STORAGE_FAILURE | :ACTIVITY_TASK_FAILED_CAUSE_ACTIVITY_WORKER_UNHANDLED_FAILURE + + type strings = "ACTIVITY_TASK_FAILED_CAUSE_UNSPECIFIED" | "ACTIVITY_TASK_FAILED_CAUSE_PAYLOADS_TOO_LARGE" | "ACTIVITY_TASK_FAILED_CAUSE_EXTERNAL_STORAGE_FAILURE" | "ACTIVITY_TASK_FAILED_CAUSE_ACTIVITY_WORKER_UNHANDLED_FAILURE" + + type numbers = 0 | 1 | 2 | 3 + end end end end diff --git a/temporalio/sig/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbs b/temporalio/sig/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbs index 240e6569..42b37479 100644 --- a/temporalio/sig/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbs +++ b/temporalio/sig/temporalio/internal/bridge/api/workflow_activation/workflow_activation.rbs @@ -487,6 +487,13 @@ module Temporalio def has_priority?: () -> bool def clear_priority: () -> void + # The run id recorded on the `WORKFLOW_EXECUTION_STARTED` event. Unlike the execution's current + # run id, this value is preserved across workflow resets. Mirrors the `original_execution_run_id` + # field from `WorkflowExecutionStartedEventAttributes`. + attr_reader original_execution_run_id(): ::String + attr_writer original_execution_run_id(): ::String | ::Symbol + def clear_original_execution_run_id: () -> void + type init_map = { workflow_type: (::String | ::Symbol)?, "workflow_type" => (::String | ::Symbol)?, @@ -538,6 +545,8 @@ module Temporalio "root_workflow" => (::Temporalio::Api::Common::V1::WorkflowExecution | ::Temporalio::Api::Common::V1::WorkflowExecution::init_map)?, priority: (::Temporalio::Api::Common::V1::Priority | ::Temporalio::Api::Common::V1::Priority::init_map)?, "priority" => (::Temporalio::Api::Common::V1::Priority | ::Temporalio::Api::Common::V1::Priority::init_map)?, + original_execution_run_id: (::String | ::Symbol)?, + "original_execution_run_id" => (::String | ::Symbol)?, } def initialize: (?init_map initial_value) -> void @@ -568,6 +577,7 @@ module Temporalio | ("start_time" name) -> ::Google::Protobuf::Timestamp? | ("root_workflow" name) -> ::Temporalio::Api::Common::V1::WorkflowExecution? | ("priority" name) -> ::Temporalio::Api::Common::V1::Priority? + | ("original_execution_run_id" name) -> ::String def []=: ("workflow_type" name, (::String | ::Symbol) value) -> void @@ -595,6 +605,7 @@ module Temporalio | ("start_time" name, ((::Google::Protobuf::Timestamp | ::Time)?) value) -> void | ("root_workflow" name, ::Temporalio::Api::Common::V1::WorkflowExecution? value) -> void | ("priority" name, ::Temporalio::Api::Common::V1::Priority? value) -> void + | ("original_execution_run_id" name, (::String | ::Symbol) value) -> void end # Notify a workflow that a timer has fired @@ -932,6 +943,11 @@ module Temporalio attr_accessor headers(): ::Google::Protobuf::Map[::String, ::Temporalio::Api::Common::V1::Payload] def clear_headers: () -> void + # Event ID of the `WORKFLOW_EXECUTION_SIGNALED` history event that produced this job. + attr_reader originating_event_id(): ::Integer + attr_writer originating_event_id(): ::Integer | ::Float + def clear_originating_event_id: () -> void + type init_map = { signal_name: (::String | ::Symbol)?, "signal_name" => (::String | ::Symbol)?, @@ -941,6 +957,8 @@ module Temporalio "identity" => (::String | ::Symbol)?, headers: ::Hash[::String | ::Symbol, ::Temporalio::Api::Common::V1::Payload]?, "headers" => ::Hash[::String | ::Symbol, ::Temporalio::Api::Common::V1::Payload]?, + originating_event_id: (::Integer | ::Float)?, + "originating_event_id" => (::Integer | ::Float)?, } def initialize: (?init_map initial_value) -> void @@ -950,12 +968,14 @@ module Temporalio | ("input" name) -> ::Google::Protobuf::RepeatedField | ("identity" name) -> ::String | ("headers" name) -> (::Google::Protobuf::Map[::String, ::Temporalio::Api::Common::V1::Payload]) + | ("originating_event_id" name) -> ::Integer def []=: ("signal_name" name, (::String | ::Symbol) value) -> void | ("input" name, ::Google::Protobuf::RepeatedField value) -> void | ("identity" name, (::String | ::Symbol) value) -> void | ("headers" name, (::Google::Protobuf::Map[::String, ::Temporalio::Api::Common::V1::Payload]) value) -> void + | ("originating_event_id" name, (::Integer | ::Float) value) -> void end # Inform lang what the result of a call to `patched` or similar API should be -- this is always @@ -994,11 +1014,20 @@ module Temporalio def has_failure?: () -> bool def clear_failure: () -> void + # The server-reported cause when the signal failed. Unspecified when the signal succeeded or + # was cancelled before being sent. + attr_reader cause(): ::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::names | ::Integer + attr_writer cause(): ::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float + attr_reader cause_const(): ::Integer + def clear_cause: () -> void + type init_map = { seq: (::Integer | ::Float)?, "seq" => (::Integer | ::Float)?, failure: (::Temporalio::Api::Failure::V1::Failure | ::Temporalio::Api::Failure::V1::Failure::init_map)?, "failure" => (::Temporalio::Api::Failure::V1::Failure | ::Temporalio::Api::Failure::V1::Failure::init_map)?, + cause: (::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float)?, + "cause" => (::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float)?, } def initialize: (?init_map initial_value) -> void @@ -1006,10 +1035,12 @@ module Temporalio def []: ("seq" name) -> ::Integer | ("failure" name) -> ::Temporalio::Api::Failure::V1::Failure? + | ("cause" name) -> (::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::names | ::Integer) def []=: ("seq" name, (::Integer | ::Float) value) -> void | ("failure" name, ::Temporalio::Api::Failure::V1::Failure? value) -> void + | ("cause" name, (::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::SignalExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float) value) -> void end class ResolveRequestCancelExternalWorkflow < ::Google::Protobuf::AbstractMessage @@ -1020,17 +1051,24 @@ module Temporalio attr_writer seq(): ::Integer | ::Float def clear_seq: () -> void - # If populated, this signal either failed to be sent or was cancelled depending on failure - # type / info. + # If populated, the cancellation request failed. attr_accessor failure(): ::Temporalio::Api::Failure::V1::Failure? def has_failure?: () -> bool def clear_failure: () -> void + # The server-reported cause when the cancellation request failed. + attr_reader cause(): ::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::names | ::Integer + attr_writer cause(): ::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float + attr_reader cause_const(): ::Integer + def clear_cause: () -> void + type init_map = { seq: (::Integer | ::Float)?, "seq" => (::Integer | ::Float)?, failure: (::Temporalio::Api::Failure::V1::Failure | ::Temporalio::Api::Failure::V1::Failure::init_map)?, "failure" => (::Temporalio::Api::Failure::V1::Failure | ::Temporalio::Api::Failure::V1::Failure::init_map)?, + cause: (::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float)?, + "cause" => (::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float)?, } def initialize: (?init_map initial_value) -> void @@ -1038,10 +1076,12 @@ module Temporalio def []: ("seq" name) -> ::Integer | ("failure" name) -> ::Temporalio::Api::Failure::V1::Failure? + | ("cause" name) -> (::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::names | ::Integer) def []=: ("seq" name, (::Integer | ::Float) value) -> void | ("failure" name, ::Temporalio::Api::Failure::V1::Failure? value) -> void + | ("cause" name, (::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::names | ::Temporalio::Api::Enums::V1::CancelExternalWorkflowExecutionFailedCause::strings | ::Integer | ::Float) value) -> void end # Lang is requested to invoke an update handler on the workflow. Lang should invoke the update diff --git a/temporalio/sig/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbs b/temporalio/sig/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbs index a16900a3..a6c27161 100644 --- a/temporalio/sig/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbs +++ b/temporalio/sig/temporalio/internal/bridge/api/workflow_commands/workflow_commands.rbs @@ -19,6 +19,12 @@ module Temporalio def has_user_metadata?: () -> bool def clear_user_metadata: () -> void + # Event group markers attached to the command. These are forwarded onto + # the corresponding server-side Command, and consequently surfaced on the + # resulting HistoryEvent. See `temporal/api/sdk/v1/event_group_marker.proto`. + attr_accessor event_group_markers(): ::Google::Protobuf::RepeatedField + def clear_event_group_markers: () -> void + attr_accessor start_timer(): ::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer? def has_start_timer?: () -> bool def clear_start_timer: () -> void @@ -114,6 +120,8 @@ module Temporalio type init_map = { user_metadata: (::Temporalio::Api::Sdk::V1::UserMetadata | ::Temporalio::Api::Sdk::V1::UserMetadata::init_map)?, "user_metadata" => (::Temporalio::Api::Sdk::V1::UserMetadata | ::Temporalio::Api::Sdk::V1::UserMetadata::init_map)?, + event_group_markers: ::Array[::Temporalio::Api::Sdk::V1::EventGroupMarker]?, + "event_group_markers" => ::Array[::Temporalio::Api::Sdk::V1::EventGroupMarker]?, start_timer: (::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer | ::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer::init_map)?, "start_timer" => (::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer | ::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer::init_map)?, schedule_activity: (::Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleActivity | ::Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleActivity::init_map)?, @@ -164,6 +172,7 @@ module Temporalio def []: ("user_metadata" name) -> ::Temporalio::Api::Sdk::V1::UserMetadata? + | ("event_group_markers" name) -> ::Google::Protobuf::RepeatedField | ("start_timer" name) -> ::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer? | ("schedule_activity" name) -> ::Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleActivity? | ("respond_to_query" name) -> ::Temporalio::Internal::Bridge::Api::WorkflowCommands::QueryResult? @@ -189,6 +198,7 @@ module Temporalio def []=: ("user_metadata" name, ::Temporalio::Api::Sdk::V1::UserMetadata? value) -> void + | ("event_group_markers" name, ::Google::Protobuf::RepeatedField value) -> void | ("start_timer" name, ::Temporalio::Internal::Bridge::Api::WorkflowCommands::StartTimer? value) -> void | ("schedule_activity" name, ::Temporalio::Internal::Bridge::Api::WorkflowCommands::ScheduleActivity? value) -> void | ("respond_to_query" name, ::Temporalio::Internal::Bridge::Api::WorkflowCommands::QueryResult? value) -> void @@ -505,6 +515,12 @@ module Temporalio attr_reader cancellation_type_const(): ::Integer def clear_cancellation_type: () -> void + # If set, the local activity arguments will be included in the resulting marker under the + # `input` key. This is disabled by default to avoid increasing history size unless the lang + # SDK explicitly chooses to expose it. + attr_accessor include_arguments_in_marker(): bool + def clear_include_arguments_in_marker: () -> void + type init_map = { seq: (::Integer | ::Float)?, "seq" => (::Integer | ::Float)?, @@ -532,6 +548,8 @@ module Temporalio "local_retry_threshold" => (::Google::Protobuf::Duration | ::Google::Protobuf::Duration)?, cancellation_type: (::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::names | ::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::strings | ::Integer | ::Float)?, "cancellation_type" => (::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::names | ::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::strings | ::Integer | ::Float)?, + include_arguments_in_marker: bool?, + "include_arguments_in_marker" => bool?, } def initialize: (?init_map initial_value) -> void @@ -550,6 +568,7 @@ module Temporalio | ("retry_policy" name) -> ::Temporalio::Api::Common::V1::RetryPolicy? | ("local_retry_threshold" name) -> ::Google::Protobuf::Duration? | ("cancellation_type" name) -> (::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::names | ::Integer) + | ("include_arguments_in_marker" name) -> bool def []=: ("seq" name, (::Integer | ::Float) value) -> void @@ -565,6 +584,7 @@ module Temporalio | ("retry_policy" name, ::Temporalio::Api::Common::V1::RetryPolicy? value) -> void | ("local_retry_threshold" name, ((::Google::Protobuf::Duration | ::int)?) value) -> void | ("cancellation_type" name, (::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::names | ::Temporalio::Internal::Bridge::Api::WorkflowCommands::ActivityCancellationType::strings | ::Integer | ::Float) value) -> void + | ("include_arguments_in_marker" name, bool value) -> void end class RequestCancelActivity < ::Google::Protobuf::AbstractMessage @@ -845,10 +865,22 @@ module Temporalio # containing a cancellation job. class CancelWorkflowExecution < ::Google::Protobuf::AbstractMessage + attr_accessor details(): ::Temporalio::Api::Common::V1::Payloads? + def has_details?: () -> bool + def clear_details: () -> void + type init_map = { + details: (::Temporalio::Api::Common::V1::Payloads | ::Temporalio::Api::Common::V1::Payloads::init_map)?, + "details" => (::Temporalio::Api::Common::V1::Payloads | ::Temporalio::Api::Common::V1::Payloads::init_map)?, } def initialize: (?init_map initial_value) -> void + + def []: + ("details" name) -> ::Temporalio::Api::Common::V1::Payloads? + + def []=: + ("details" name, ::Temporalio::Api::Common::V1::Payloads? value) -> void end # A request to set/check if a certain patch is present or not diff --git a/temporalio/sig/temporalio/internal/worker/workflow_instance.rbs b/temporalio/sig/temporalio/internal/worker/workflow_instance.rbs index 4732a717..a5204071 100644 --- a/temporalio/sig/temporalio/internal/worker/workflow_instance.rbs +++ b/temporalio/sig/temporalio/internal/worker/workflow_instance.rbs @@ -61,7 +61,7 @@ module Temporalio def illegal_call_tracing_disabled: [T] { -> T } -> T - def patch: (patch_id: Symbol | String, deprecated: bool) -> bool + def patch: (patch_id: Symbol | String, deprecated: bool, ?event_groups: Array[Workflow::EventGroup]?) -> bool def patch_activated?: (String patch_id) -> bool diff --git a/temporalio/sig/temporalio/internal/worker/workflow_instance/context.rbs b/temporalio/sig/temporalio/internal/worker/workflow_instance/context.rbs index 8e2a98e1..64dce4fe 100644 --- a/temporalio/sig/temporalio/internal/worker/workflow_instance/context.rbs +++ b/temporalio/sig/temporalio/internal/worker/workflow_instance/context.rbs @@ -28,7 +28,7 @@ module Temporalio def current_update_info: -> Workflow::UpdateInfo? - def deprecate_patch: (Symbol | String patch_id) -> void + def deprecate_patch: (Symbol | String patch_id, ?event_groups: Array[Workflow::EventGroup]?) -> void def durable_scheduler_disabled: [T] { -> T } -> T @@ -48,7 +48,8 @@ module Temporalio disable_eager_execution: bool, priority: Priority, arg_hints: Array[Object]?, - result_hint: Object? + result_hint: Object?, + event_groups: Array[Workflow::EventGroup]? ) -> Object? def execute_local_activity: ( @@ -64,7 +65,8 @@ module Temporalio cancellation_type: Workflow::ActivityCancellationType::enum, activity_id: String?, arg_hints: Array[Object]?, - result_hint: Object? + result_hint: Object?, + event_groups: Array[Workflow::EventGroup]? ) -> Object? def external_workflow_handle: (String workflow_id, ?run_id: String?) -> ExternalWorkflowHandle @@ -87,7 +89,7 @@ module Temporalio def now: -> Time - def patched: (Symbol | String patch_id) -> bool + def patched: (Symbol | String patch_id, ?event_groups: Array[Workflow::EventGroup]?) -> bool def payload_converter: -> Converters::PayloadConverter @@ -103,7 +105,7 @@ module Temporalio def signal_handlers: -> HandlerHash[Workflow::Definition::Signal] - def sleep: (duration? duration, summary: String?, cancellation: Cancellation) -> void + def sleep: (duration? duration, summary: String?, cancellation: Cancellation, ?event_groups: Array[Workflow::EventGroup]?) -> void def start_child_workflow: ( singleton(Workflow::Definition) | Workflow::Definition::Info | Symbol | String workflow, @@ -125,7 +127,8 @@ module Temporalio search_attributes: SearchAttributes?, priority: Priority, arg_hints: Array[Object]?, - result_hint: Object? + result_hint: Object?, + event_groups: Array[Workflow::EventGroup]? ) -> ChildWorkflowHandle def storage: -> Hash[Object, Object] @@ -134,18 +137,19 @@ module Temporalio duration? duration, singleton(Exception) exception_class, *Object? exception_args, - summary: String? + summary: String?, + ?event_groups: Array[Workflow::EventGroup]? ) { -> T } -> T def update_handlers: -> HandlerHash[Workflow::Definition::Update] - def upsert_memo: (Hash[Symbol | String, Object?] hash) -> void + def upsert_memo: (Hash[Symbol | String, Object?] hash, ?event_groups: Array[Workflow::EventGroup]?) -> void - def upsert_search_attributes: (*SearchAttributes::Update updates) -> void + def upsert_search_attributes: (*SearchAttributes::Update updates, ?event_groups: Array[Workflow::EventGroup]?) -> void def wait_condition: [T] (cancellation: Cancellation?) { -> T } -> T - def _cancel_external_workflow: (id: String, run_id: String?) -> void + def _cancel_external_workflow: (id: String, run_id: String?, ?event_groups: Array[Workflow::EventGroup]?) -> void def _outbound=: (Temporalio::Worker::Interceptor::Workflow::Outbound outbound) -> void @@ -154,7 +158,8 @@ module Temporalio signal: Workflow::Definition::Signal | Symbol | String, args: Array[Object?], cancellation: Cancellation, - arg_hints: Array[Object]? + arg_hints: Array[Object]?, + ?event_groups: Array[Workflow::EventGroup]? ) -> void def _signal_external_workflow: ( @@ -163,7 +168,8 @@ module Temporalio signal: Workflow::Definition::Signal | Symbol | String, args: Array[Object?], cancellation: Cancellation, - arg_hints: Array[Object]? + arg_hints: Array[Object]?, + ?event_groups: Array[Workflow::EventGroup]? ) -> void end end diff --git a/temporalio/sig/temporalio/internal/worker/workflow_instance/nexus_client.rbs b/temporalio/sig/temporalio/internal/worker/workflow_instance/nexus_client.rbs index 315176fe..9b74668b 100644 --- a/temporalio/sig/temporalio/internal/worker/workflow_instance/nexus_client.rbs +++ b/temporalio/sig/temporalio/internal/worker/workflow_instance/nexus_client.rbs @@ -16,7 +16,8 @@ module Temporalio ?summary: String?, ?cancellation: Cancellation, ?arg_hint: Object?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[Workflow::EventGroup]? ) -> Workflow::NexusOperationHandle end end diff --git a/temporalio/sig/temporalio/internal/worker/workflow_instance/outbound_implementation.rbs b/temporalio/sig/temporalio/internal/worker/workflow_instance/outbound_implementation.rbs index 47b01144..413328a1 100644 --- a/temporalio/sig/temporalio/internal/worker/workflow_instance/outbound_implementation.rbs +++ b/temporalio/sig/temporalio/internal/worker/workflow_instance/outbound_implementation.rbs @@ -8,15 +8,17 @@ module Temporalio def execute_activity_with_local_backoffs: ( local: bool, cancellation: Cancellation, - result_hint: Object? - ) { (untyped?) -> Integer } -> Object? + result_hint: Object?, + event_groups: Array[Workflow::EventGroup]? + ) { (untyped?, untyped) -> Integer } -> Object? def execute_activity_once: ( local: bool, cancellation: Cancellation, last_local_backoff: untyped?, - result_hint: Object? - ) { (untyped?) -> Integer } -> Object? + result_hint: Object?, + markers: untyped + ) { (untyped?, untyped) -> Integer } -> Object? def _signal_external_workflow: ( id: String, @@ -26,7 +28,8 @@ module Temporalio args: Array[Object?], cancellation: Cancellation, arg_hints: Array[Object]?, - headers: Hash[String, Object?] + headers: Hash[String, Object?], + event_groups: Array[Workflow::EventGroup]? ) -> void end end diff --git a/temporalio/sig/temporalio/worker/interceptor.rbs b/temporalio/sig/temporalio/worker/interceptor.rbs index 0219c510..656f8ba9 100644 --- a/temporalio/sig/temporalio/worker/interceptor.rbs +++ b/temporalio/sig/temporalio/worker/interceptor.rbs @@ -125,10 +125,12 @@ module Temporalio class CancelExternalWorkflowInput attr_reader id: String attr_reader run_id: String? + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( id: String, - run_id: String? + run_id: String?, + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -150,6 +152,7 @@ module Temporalio attr_reader arg_hints: Array[Object]? attr_reader result_hint: Object? attr_reader headers: Hash[String, Object?] + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( activity: String, @@ -168,7 +171,8 @@ module Temporalio priority: Temporalio::Priority, arg_hints: Array[Object]?, result_hint: Object?, - headers: Hash[String, Object?] + headers: Hash[String, Object?], + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -187,6 +191,7 @@ module Temporalio attr_reader arg_hints: Array[Object]? attr_reader result_hint: Object? attr_reader headers: Hash[String, Object?] + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( activity: String, @@ -202,7 +207,8 @@ module Temporalio activity_id: String?, arg_hints: Array[Object]?, result_hint: Object?, - headers: Hash[String, Object?] + headers: Hash[String, Object?], + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -221,6 +227,7 @@ module Temporalio attr_reader cancellation: Cancellation attr_reader arg_hints: Array[Object]? attr_reader headers: Hash[String, Object?] + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( id: String, @@ -228,7 +235,8 @@ module Temporalio args: Array[Object?], cancellation: Cancellation, arg_hints: Array[Object]?, - headers: Hash[String, Object?] + headers: Hash[String, Object?], + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -240,6 +248,7 @@ module Temporalio attr_reader cancellation: Cancellation attr_reader arg_hints: Array[Object]? attr_reader headers: Hash[String, Object?] + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( id: String, @@ -248,7 +257,8 @@ module Temporalio args: Array[Object?], cancellation: Cancellation, arg_hints: Array[Object]?, - headers: Hash[String, Object?] + headers: Hash[String, Object?], + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -256,11 +266,13 @@ module Temporalio attr_reader duration: duration? attr_reader summary: String? attr_reader cancellation: Cancellation + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( duration: duration?, summary: String?, - cancellation: Cancellation + cancellation: Cancellation, + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -286,6 +298,7 @@ module Temporalio attr_reader arg_hints: Array[Object]? attr_reader result_hint: Object? attr_reader headers: Hash[String, Object?] + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( workflow: String, @@ -308,7 +321,8 @@ module Temporalio priority: Temporalio::Priority, arg_hints: Array[Object]?, result_hint: Object?, - headers: Hash[String, Object?] + headers: Hash[String, Object?], + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end @@ -326,6 +340,7 @@ module Temporalio attr_reader arg_hint: Object? attr_reader result_hint: Object? attr_reader headers: Hash[String, String] + attr_reader event_groups: Array[Temporalio::Workflow::EventGroup]? def initialize: ( endpoint: String, @@ -340,7 +355,8 @@ module Temporalio cancellation: Cancellation, arg_hint: Object?, result_hint: Object?, - headers: Hash[String, String] + headers: Hash[String, String], + event_groups: Array[Temporalio::Workflow::EventGroup]? ) -> void end diff --git a/temporalio/sig/temporalio/workflow.rbs b/temporalio/sig/temporalio/workflow.rbs index ed5e03cc..971cadac 100644 --- a/temporalio/sig/temporalio/workflow.rbs +++ b/temporalio/sig/temporalio/workflow.rbs @@ -8,6 +8,16 @@ module Temporalio def self.create_nexus_client: (endpoint: Symbol | String, service: Symbol | String) -> NexusClient + def self.create_event_group: (String id, ?label: String?) -> EventGroup + + def self.with_event_groups: [T] (*EventGroup groups) { -> T } -> T + + def self._with_implicit_event_group: [T] (EventGroup group) { -> T } -> T + + def self._inbound_event_group: (Integer? event_id) -> EventGroup + + def self._inbound_update_event_group: (String update_id) -> EventGroup + def self.suggest_continue_as_new_reasons: -> Array[SuggestContinueAsNewReason::enum] def self.target_worker_deployment_version_changed?: -> bool @@ -23,7 +33,7 @@ module Temporalio def self.current_update_info: -> UpdateInfo? - def self.deprecate_patch: (Symbol | String patch_id) -> void + def self.deprecate_patch: (Symbol | String patch_id, ?event_groups: Array[EventGroup]?) -> void def self.execute_activity: ( singleton(Activity::Definition) | Symbol | String activity, @@ -41,7 +51,8 @@ module Temporalio ?disable_eager_execution: bool, ?priority: Priority, ?arg_hints: Array[Object]?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[EventGroup]? ) -> Object? def self.execute_child_workflow: ( @@ -64,7 +75,8 @@ module Temporalio ?search_attributes: SearchAttributes?, ?priority: Priority, ?arg_hints: Array[Object]?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[EventGroup]? ) -> Object? def self.execute_local_activity: ( @@ -80,7 +92,8 @@ module Temporalio ?cancellation_type: ActivityCancellationType::enum, ?activity_id: String?, ?arg_hints: Array[Object]?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[EventGroup]? ) -> Object? def self.external_workflow_handle: (String workflow_id, ?run_id: String?) -> ExternalWorkflowHandle @@ -99,7 +112,7 @@ module Temporalio def self.now: -> Time - def self.patched: (Symbol | String patch_id) -> bool + def self.patched: (Symbol | String patch_id, ?event_groups: Array[EventGroup]?) -> bool def self.payload_converter: -> Converters::PayloadConverter @@ -111,7 +124,7 @@ module Temporalio def self.signal_handlers: -> Hash[String?, Workflow::Definition::Signal] - def self.sleep: (duration? duration, ?summary: String?, ?cancellation: Cancellation) -> void + def self.sleep: (duration? duration, ?summary: String?, ?cancellation: Cancellation, ?event_groups: Array[EventGroup]?) -> void def self.start_child_workflow: ( singleton(Workflow::Definition) | Workflow::Definition::Info | Symbol | String workflow, @@ -133,7 +146,8 @@ module Temporalio ?search_attributes: SearchAttributes?, ?priority: Priority, ?arg_hints: Array[Object]?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[EventGroup]? ) -> ChildWorkflowHandle def self.storage: -> Hash[Object, Object] @@ -142,14 +156,15 @@ module Temporalio duration? duration, ?singleton(Exception) exception_class, ?String message, - ?summary: String? + ?summary: String?, + ?event_groups: Array[EventGroup]? ) { -> T } -> T def self.update_handlers: -> Hash[String?, Workflow::Definition::Update] - def self.upsert_memo: (Hash[Symbol | String, Object?] hash) -> void + def self.upsert_memo: (Hash[Symbol | String, Object?] hash, ?event_groups: Array[EventGroup]?) -> void - def self.upsert_search_attributes: (*SearchAttributes::Update updates) -> void + def self.upsert_search_attributes: (*SearchAttributes::Update updates, ?event_groups: Array[EventGroup]?) -> void def self.wait_condition: [T] (?cancellation: Cancellation?) { -> T } -> T @@ -183,6 +198,8 @@ module Temporalio attr_accessor arg_hints: Array[Object]? attr_accessor headers: Hash[String, Object?] attr_accessor initial_versioning_behavior: ContinueAsNewVersioningBehavior::enum? + attr_accessor event_groups: Array[EventGroup]? + attr_accessor _event_group_markers: Array[Api::Sdk::V1::EventGroupMarker]? def initialize: ( *Object? args, @@ -196,7 +213,8 @@ module Temporalio ?search_attributes: SearchAttributes?, ?arg_hints: Array[Object]?, ?headers: Hash[String, Object?], - ?initial_versioning_behavior: ContinueAsNewVersioningBehavior::enum? + ?initial_versioning_behavior: ContinueAsNewVersioningBehavior::enum?, + ?event_groups: Array[EventGroup]? ) -> void end diff --git a/temporalio/sig/temporalio/workflow/child_workflow_handle.rbs b/temporalio/sig/temporalio/workflow/child_workflow_handle.rbs index ddce2945..50ac1e22 100644 --- a/temporalio/sig/temporalio/workflow/child_workflow_handle.rbs +++ b/temporalio/sig/temporalio/workflow/child_workflow_handle.rbs @@ -11,7 +11,8 @@ module Temporalio Workflow::Definition::Signal | Symbol | String signal, *Object? args, ?cancellation: Cancellation, - ?arg_hints: Array[Object]? + ?arg_hints: Array[Object]?, + ?event_groups: Array[EventGroup]? ) -> void end end diff --git a/temporalio/sig/temporalio/workflow/event_group.rbs b/temporalio/sig/temporalio/workflow/event_group.rbs new file mode 100644 index 00000000..dbc2d980 --- /dev/null +++ b/temporalio/sig/temporalio/workflow/event_group.rbs @@ -0,0 +1,38 @@ +module Temporalio + module Workflow + class EventGroup + class Active + attr_accessor implicit: EventGroup? + attr_accessor explicit: Hash[String, EventGroup] + + def initialize: (?implicit: EventGroup?, ?explicit: Hash[String, EventGroup]) -> void + end + + EMPTY_ACTIVE: Active + STORAGE_KEY: Symbol + + def self._active: -> Active + def self._with_active: [T] (Active active) { -> T } -> T + def self._markers_for_command: (Array[EventGroup]? directs) -> Array[Api::Sdk::V1::EventGroupMarker] + + def initialize: -> void + def _applied_over: (Active _active) -> Active + def _to_proto: -> Api::Sdk::V1::EventGroupMarker? + + class Label < EventGroup + attr_reader id: String + attr_reader label: String? + + def initialize: (String id, String? label) -> void + end + + class Implicit < EventGroup + def initialize: (Api::Sdk::V1::EventGroupMarker marker) -> void + end + + class StubImplicit < EventGroup + def initialize: -> void + end + end + end +end diff --git a/temporalio/sig/temporalio/workflow/external_workflow_handle.rbs b/temporalio/sig/temporalio/workflow/external_workflow_handle.rbs index 762ca16e..af73af3f 100644 --- a/temporalio/sig/temporalio/workflow/external_workflow_handle.rbs +++ b/temporalio/sig/temporalio/workflow/external_workflow_handle.rbs @@ -8,10 +8,11 @@ module Temporalio Workflow::Definition::Signal | Symbol | String signal, *Object? args, ?cancellation: Cancellation, - ?arg_hints: Array[Object]? + ?arg_hints: Array[Object]?, + ?event_groups: Array[EventGroup]? ) -> void - def cancel: -> void + def cancel: (?event_groups: Array[EventGroup]?) -> void end end end \ No newline at end of file diff --git a/temporalio/sig/temporalio/workflow/info.rbs b/temporalio/sig/temporalio/workflow/info.rbs index 5fa9bd80..cfc8c724 100644 --- a/temporalio/sig/temporalio/workflow/info.rbs +++ b/temporalio/sig/temporalio/workflow/info.rbs @@ -11,6 +11,7 @@ module Temporalio attr_reader last_result: Object? attr_reader has_last_result?: bool attr_reader namespace: String + attr_reader original_execution_run_id: String attr_reader parent: ParentInfo? attr_reader priority: Temporalio::Priority attr_reader retry_policy: RetryPolicy? @@ -34,6 +35,7 @@ module Temporalio last_result: Object?, has_last_result?: bool, namespace: String, + original_execution_run_id: String, parent: ParentInfo?, priority: Temporalio::Priority?, retry_policy: RetryPolicy?, diff --git a/temporalio/sig/temporalio/workflow/nexus_client.rbs b/temporalio/sig/temporalio/workflow/nexus_client.rbs index fbef0123..7bb821b6 100644 --- a/temporalio/sig/temporalio/workflow/nexus_client.rbs +++ b/temporalio/sig/temporalio/workflow/nexus_client.rbs @@ -14,7 +14,8 @@ module Temporalio ?summary: String?, ?cancellation: Cancellation, ?arg_hint: Object?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[EventGroup]? ) -> NexusOperationHandle def execute_operation: ( @@ -27,7 +28,8 @@ module Temporalio ?summary: String?, ?cancellation: Cancellation, ?arg_hint: Object?, - ?result_hint: Object? + ?result_hint: Object?, + ?event_groups: Array[EventGroup]? ) -> Object? end end diff --git a/temporalio/test/base64_codec.rb b/temporalio/test/base64_codec.rb index 17306bd6..ed38b8a3 100644 --- a/temporalio/test/base64_codec.rb +++ b/temporalio/test/base64_codec.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'base64' require 'temporalio/api' require 'temporalio/converters/payload_codec' diff --git a/temporalio/test/sig/worker_workflow_event_groups_test.rbs b/temporalio/test/sig/worker_workflow_event_groups_test.rbs new file mode 100644 index 00000000..d81f4720 --- /dev/null +++ b/temporalio/test/sig/worker_workflow_event_groups_test.rbs @@ -0,0 +1,34 @@ +class WorkerWorkflowEventGroupsTest < Test + ACT_TIMEOUT: Integer + + def self.activity: ( + String activity_id, + ?event_groups: Array[Temporalio::Workflow::EventGroup]? + ) -> untyped + + def events_of_type: (Array[untyped] events, untyped event_type) -> Array[untyped] + def single_event: (Array[untyped] events, untyped event_type) -> untyped + def activity_event: (Array[untyped] events, String activity_id) -> untyped + def markers_named: (Array[untyped] events, String marker_name) -> Array[untyped] + def signaled_event_ids: (Array[untyped] events) -> Array[Integer] + def render_marker: (untyped marker) -> String + def render_marker_id: (untyped marker) -> String + def marker_ids: (untyped event) -> Array[String] + def assert_markers: (untyped event, *String expected) -> void + def assert_marker_ids: (untyped event, *String expected) -> void + def label_marker: (String group_id, String label) -> String + def label_marker_id: (String group_id) -> String + def event_marker: (Integer event_id) -> String + def update_marker: (String update_id) -> String + def label_payload_of: (untyped event, String marker_id) -> [untyped, untyped] + def label_payload_set?: (untyped event, String marker_id) -> bool + def raw_label_payload: (untyped event, String marker_id) -> untyped + def fetch_events: (Temporalio::Client::WorkflowHandle handle) -> Array[untyped] + def run_and_events: [T] ( + singleton(Temporalio::Workflow::Definition) workflow, + *untyped args, + ?activities: Array[untyped], + ?more_workflows: Array[singleton(Temporalio::Workflow::Definition)], + **untyped kwargs + ) { (Temporalio::Client::WorkflowHandle, Array[untyped]) -> T } -> T +end diff --git a/temporalio/test/worker_workflow_event_groups_test.rb b/temporalio/test/worker_workflow_event_groups_test.rb new file mode 100644 index 00000000..19584429 --- /dev/null +++ b/temporalio/test/worker_workflow_event_groups_test.rb @@ -0,0 +1,1216 @@ +# frozen_string_literal: true + +require 'base64' +require 'base64_codec' +require 'temporalio/client' +require 'temporalio/converters/data_converter' +require 'temporalio/converters/payload_converter' +require 'temporalio/error' +require 'temporalio/testing' +require 'temporalio/worker' +require 'temporalio/workflow' +require 'test' +require 'timeout' + +class WorkerWorkflowEventGroupsTest < Test + exclude_class_from_cloud :requires_cloud_provisioning, + 'Event Groups history transcription is not yet available in Temporal Cloud.' + + ACT_TIMEOUT = 10 + + class NoopActivity < Temporalio::Activity::Definition + def execute + nil + end + end + + class ControlActivity < Temporalio::Activity::Definition + def execute(value) + value + end + end + + class SleepActivity < Temporalio::Activity::Definition + def execute + sleep 5 + end + end + + class FailFirstActivity < Temporalio::Activity::Definition + def execute + return unless Temporalio::Activity::Context.current.info.attempt == 1 + + raise Temporalio::Error::ApplicationError, 'retry me' + end + end + + class NoopChildWorkflow < Temporalio::Workflow::Definition + def execute + nil + end + end + + class SleepChildWorkflow < Temporalio::Workflow::Definition + def execute + Temporalio::Workflow.sleep(5) + end + end + + class WaitForSignalChildWorkflow < Temporalio::Workflow::Definition + def execute + Temporalio::Workflow.wait_condition { @done } + end + + workflow_signal + def noop + @done = true + end + end + + class CustomStringConverter < Temporalio::Converters::PayloadConverter::Encoding + def encoding + 'custom' + end + + def to_payload(value, hint: nil) # rubocop:disable Lint/UnusedMethodArgument + return unless value.is_a?(String) + + Temporalio::Api::Common::V1::Payload.new( + metadata: { 'encoding' => encoding }, + data: "custom-converter-#{value}".b + ) + end + + def from_payload(payload, hint: nil) # rubocop:disable Lint/UnusedMethodArgument + text = payload.data + prefix = 'custom-converter-' + text.start_with?(prefix) ? text.delete_prefix(prefix) : text + end + end + + def self.activity(activity_id, event_groups: nil) + Temporalio::Workflow.execute_activity( + NoopActivity, + start_to_close_timeout: ACT_TIMEOUT, + activity_id:, + event_groups: + ) + end + + def events_of_type(events, event_type) + events.select { |event| event.event_type == event_type } + end + + def single_event(events, event_type) + matches = events_of_type(events, event_type) + assert_equal 1, matches.size, "expected 1 #{event_type}, got #{matches.size}" + matches.first + end + + def activity_event(events, activity_id) + match = events.find do |event| + event.event_type == :EVENT_TYPE_ACTIVITY_TASK_SCHEDULED && + event.activity_task_scheduled_event_attributes.activity_id == activity_id + end + refute_nil match, "no activity #{activity_id.inspect}" + match + end + + def markers_named(events, marker_name) + events.select do |event| + event.event_type == :EVENT_TYPE_MARKER_RECORDED && + event.marker_recorded_event_attributes.marker_name == marker_name + end + end + + def signaled_event_ids(events) + events.filter_map do |event| + event.event_id if event.event_type == :EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED + end + end + + def render_marker(marker) + case marker.variant + when :inbound_event + "event:#{marker.inbound_event.inbound_event_id}" + when :inbound_update + "update:#{marker.inbound_update.inbound_update_id}" + else + if marker.label.has_label? + begin + label = Temporalio::Converters::PayloadConverter.default.from_payload(marker.label.label) + "label:#{marker.label.id}:#{label}" + rescue StandardError + "label:#{marker.label.id}" + end + else + "label:#{marker.label.id}" + end + end + end + + def render_marker_id(marker) + case marker.variant + when :inbound_event + "event:#{marker.inbound_event.inbound_event_id}" + when :inbound_update + "update:#{marker.inbound_update.inbound_update_id}" + else + "label:#{marker.label.id}" + end + end + + def marker_ids(event) + event.event_group_markers.map { |marker| render_marker_id(marker) }.sort + end + + def assert_markers(event, *expected) + actual = event.event_group_markers.map { |marker| render_marker(marker) } + assert_equal expected.size, actual.size, "marker count #{actual} != #{expected}" + assert_equal expected.sort, actual.sort + end + + def assert_marker_ids(event, *expected) + actual = marker_ids(event) + assert_equal expected.size, actual.size, "marker id count #{actual} != #{expected}" + assert_equal expected.sort, actual.sort + end + + def label_marker(group_id, label) + "label:#{group_id}:#{label}" + end + + def label_marker_id(group_id) + "label:#{group_id}" + end + + def event_marker(event_id) + "event:#{event_id}" + end + + def update_marker(update_id) + "update:#{update_id}" + end + + def label_payload_of(event, marker_id) + event.event_group_markers.each do |marker| + next unless marker.variant == :label && marker.label.id == marker_id + + flunk "label marker #{marker_id.inspect} has no payload" unless marker.label.has_label? + + encoding = marker.label.label.metadata['encoding'] + return [encoding, marker.label.label.data] + end + flunk "no label marker #{marker_id.inspect} on event" + end + + def label_payload_set?(event, marker_id) + event.event_group_markers.each do |marker| + next unless marker.variant == :label && marker.label.id == marker_id + + return marker.label.has_label? + end + flunk "no label marker #{marker_id.inspect} on event" + end + + def raw_label_payload(event, marker_id) + event.event_group_markers.each do |marker| + next unless marker.variant == :label && marker.label.id == marker_id + + return marker.label.label + end + flunk "no label marker #{marker_id.inspect} on event" + end + + def fetch_events(handle) + handle.fetch_history_events.to_a + end + + def run_and_events(workflow, *args, activities: [NoopActivity], more_workflows: [], **kwargs) + execute_workflow(workflow, *args, activities:, more_workflows:, **kwargs) do |handle| + handle.result + yield handle, fetch_events(handle) + end + end + + #################################################################################################### + # EG-LABEL-ID + #################################################################################################### + + class UserProvidedIdsWorkflow < Temporalio::Workflow::Definition + def execute + c = Temporalio::Workflow.create_event_group('c-id', label: 'ccc') + d1 = Temporalio::Workflow.create_event_group('d-id', label: 'ddd1') + d2 = Temporalio::Workflow.create_event_group('d-id', label: 'ddd2') + not_c = Temporalio::Workflow.create_event_group('not-c-id', label: 'ccc') + WorkerWorkflowEventGroupsTest.activity('activity-c', event_groups: [c]) + WorkerWorkflowEventGroupsTest.activity('activity-d1', event_groups: [d1]) + WorkerWorkflowEventGroupsTest.activity('activity-d2', event_groups: [d2]) + WorkerWorkflowEventGroupsTest.activity('activity-not-c', event_groups: [not_c]) + end + end + + def test_user_provided_label_ids + run_and_events(UserProvidedIdsWorkflow) do |_handle, events| + assert_equal 4, events_of_type(events, :EVENT_TYPE_ACTIVITY_TASK_SCHEDULED).size + assert_marker_ids(activity_event(events, 'activity-c'), label_marker_id('c-id')) + assert_equal marker_ids(activity_event(events, 'activity-d1')), + marker_ids(activity_event(events, 'activity-d2')) + refute_equal marker_ids(activity_event(events, 'activity-c')), + marker_ids(activity_event(events, 'activity-not-c')) + end + end + + #################################################################################################### + # EG-LABEL-PAYLOAD + #################################################################################################### + + class LabelPayloadWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + b = Temporalio::Workflow.create_event_group('bbb', label: 'Label B') + Temporalio::Workflow.execute_activity( + ControlActivity, 'control', start_to_close_timeout: ACT_TIMEOUT, activity_id: 'control' + ) + WorkerWorkflowEventGroupsTest.activity('activity-a', event_groups: [a]) + WorkerWorkflowEventGroupsTest.activity('activity-b', event_groups: [b]) + end + end + + def test_label_payload_is_json_plain + run_and_events(LabelPayloadWorkflow, activities: [NoopActivity, ControlActivity]) do |_handle, events| + activity_a = activity_event(events, 'activity-a') + activity_b = activity_event(events, 'activity-b') + assert_markers(activity_a, label_marker_id('aaa')) + assert_markers(activity_b, label_marker('bbb', 'Label B')) + assert_equal ['json/plain', '"Label B"'], label_payload_of(activity_b, 'bbb') + refute label_payload_set?(activity_a, 'aaa') + end + end + + def test_label_payload_uses_default_converter_not_worker_converter + payload_converter = Temporalio::Converters::PayloadConverter::Composite.new( + CustomStringConverter.new, + *Temporalio::Converters::PayloadConverter.new_with_defaults.converters.values + ) + client = Temporalio::Client.new( + **env.client.options.with(data_converter: Temporalio::Converters::DataConverter.new(payload_converter:)).to_h + ) + run_and_events(LabelPayloadWorkflow, activities: [NoopActivity, ControlActivity], client:) do |_handle, events| + control = activity_event(events, 'control') + control_payload = control.activity_task_scheduled_event_attributes.input.payloads.first + assert_equal 'custom', control_payload.metadata['encoding'] + assert_equal 'custom-converter-control', control_payload.data + + activity_a = activity_event(events, 'activity-a') + activity_b = activity_event(events, 'activity-b') + assert_equal ['json/plain', '"Label B"'], label_payload_of(activity_b, 'bbb') + refute label_payload_set?(activity_a, 'aaa') + end + end + + def test_label_payload_is_codec_encoded_but_ids_are_not + codec = Base64Codec.new + client = Temporalio::Client.new( + **env.client.options.with(data_converter: Temporalio::Converters::DataConverter.new(payload_codec: codec)).to_h + ) + run_and_events( + LabelPayloadWorkflow, + activities: [NoopActivity, ControlActivity], + client:, + workflow_payload_codec_thread_pool: Temporalio::Worker::ThreadPool.default + ) do |_handle, events| + activity_a = activity_event(events, 'activity-a') + activity_b = activity_event(events, 'activity-b') + assert_marker_ids(activity_a, label_marker_id('aaa')) + assert_marker_ids(activity_b, label_marker_id('bbb')) + assert_equal 'test/base64', label_payload_of(activity_b, 'bbb').first + decoded = codec.decode([raw_label_payload(activity_b, 'bbb')]).first + assert_equal 'Label B', Temporalio::Converters::PayloadConverter.default.from_payload(decoded) + refute label_payload_set?(activity_a, 'aaa') + end + end + + #################################################################################################### + # EG-SCOPE + #################################################################################################### + + class ScopeBaselineWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + Temporalio::Workflow.with_event_groups(a) do + WorkerWorkflowEventGroupsTest.activity('activity') + Temporalio::Workflow.sleep(0.001) + Temporalio::Workflow.start_child_workflow( + NoopChildWorkflow, id: "#{Temporalio::Workflow.info.workflow_id}_child" + ) + end + end + end + + def test_commands_in_a_scope_carry_its_marker + run_and_events(ScopeBaselineWorkflow, more_workflows: [NoopChildWorkflow]) do |_handle, events| + a = label_marker_id('aaa') + assert_markers(activity_event(events, 'activity'), a) + assert_markers(single_event(events, :EVENT_TYPE_TIMER_STARTED), a) + assert_markers(single_event(events, :EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED), a) + end + end + + class NestedScopesWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + b = Temporalio::Workflow.create_event_group('bbb') + Temporalio::Workflow.with_event_groups(a) do + WorkerWorkflowEventGroupsTest.activity('a-before') + Temporalio::Workflow.with_event_groups(b) { WorkerWorkflowEventGroupsTest.activity('a-b') } + WorkerWorkflowEventGroupsTest.activity('a-after') + end + WorkerWorkflowEventGroupsTest.activity('outside') + end + end + + def test_nesting_scopes_composes + run_and_events(NestedScopesWorkflow) do |_handle, events| + a = label_marker_id('aaa') + b = label_marker_id('bbb') + assert_equal 4, events_of_type(events, :EVENT_TYPE_ACTIVITY_TASK_SCHEDULED).size + assert_markers(activity_event(events, 'a-before'), a) + assert_markers(activity_event(events, 'a-b'), a, b) + assert_markers(activity_event(events, 'a-after'), a) + assert_markers(activity_event(events, 'outside')) + end + end + + class ReenteredScopeWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + Temporalio::Workflow.with_event_groups(a) do + WorkerWorkflowEventGroupsTest.activity('a-before') + Temporalio::Workflow.with_event_groups(a) { WorkerWorkflowEventGroupsTest.activity('a-a') } + WorkerWorkflowEventGroupsTest.activity('a-after') + end + end + end + + def test_reentering_a_group_nests_correctly + run_and_events(ReenteredScopeWorkflow) do |_handle, events| + a = label_marker_id('aaa') + assert_markers(activity_event(events, 'a-before'), a) + assert_markers(activity_event(events, 'a-a'), a) + assert_markers(activity_event(events, 'a-after'), a) + end + end + + class ConcurrentScopesWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + b = Temporalio::Workflow.create_event_group('bbb') + c = Temporalio::Workflow.create_event_group('ccc') + d = Temporalio::Workflow.create_event_group('ddd') + e = Temporalio::Workflow.create_event_group('eee') + + left = Temporalio::Workflow::Future.new do + Temporalio::Workflow.with_event_groups(b) do + Temporalio::Workflow.with_event_groups(a) do + Temporalio::Workflow.with_event_groups(c) { WorkerWorkflowEventGroupsTest.activity('b-a-c') } + WorkerWorkflowEventGroupsTest.activity('b-a') + end + WorkerWorkflowEventGroupsTest.activity('b-after-a') + end + end + right = Temporalio::Workflow::Future.new do + Temporalio::Workflow.with_event_groups(d) do + Temporalio::Workflow.with_event_groups(a) do + Temporalio::Workflow.with_event_groups(e) { WorkerWorkflowEventGroupsTest.activity('d-a-e') } + WorkerWorkflowEventGroupsTest.activity('d-a') + end + WorkerWorkflowEventGroupsTest.activity('d-after-a') + end + end + left.wait + right.wait + WorkerWorkflowEventGroupsTest.activity('outside') + end + end + + def test_a_group_can_be_scoped_from_two_concurrent_branches + run_and_events(ConcurrentScopesWorkflow) do |_handle, events| + a = label_marker_id('aaa') + b = label_marker_id('bbb') + c = label_marker_id('ccc') + d = label_marker_id('ddd') + e = label_marker_id('eee') + assert_equal 7, events_of_type(events, :EVENT_TYPE_ACTIVITY_TASK_SCHEDULED).size + assert_markers(activity_event(events, 'b-a-c'), b, a, c) + assert_markers(activity_event(events, 'b-a'), b, a) + assert_markers(activity_event(events, 'b-after-a'), b) + assert_markers(activity_event(events, 'd-a-e'), d, a, e) + assert_markers(activity_event(events, 'd-a'), d, a) + assert_markers(activity_event(events, 'd-after-a'), d) + assert_markers(activity_event(events, 'outside')) + end + end + + class DetachedTaskScopeWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + # @type var fut: Temporalio::Workflow::Future[untyped] + fut = Temporalio::Workflow.with_event_groups(a) do + started = Temporalio::Workflow::Future.new do + WorkerWorkflowEventGroupsTest.activity('inside-before') + @started = true + Temporalio::Workflow.wait_condition { @released } + WorkerWorkflowEventGroupsTest.activity('inside-after') + end + Temporalio::Workflow.wait_condition { @started } + started + end + WorkerWorkflowEventGroupsTest.activity('outside-after-scope') + @released = true + fut.wait + end + end + + def test_a_task_started_inside_a_scope_keeps_it_after_exit + run_and_events(DetachedTaskScopeWorkflow) do |_handle, events| + a = label_marker_id('aaa') + assert_markers(activity_event(events, 'inside-before'), a) + assert_markers(activity_event(events, 'inside-after'), a) + assert_markers(activity_event(events, 'outside-after-scope')) + end + end + + class OutsiderTaskScopeWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + fut = Temporalio::Workflow::Future.new do + Temporalio::Workflow.wait_condition { @started } + WorkerWorkflowEventGroupsTest.activity('outside-task') + end + Temporalio::Workflow.with_event_groups(a) do + @started = true + WorkerWorkflowEventGroupsTest.activity('in-a') + fut.wait + end + end + end + + def test_a_task_created_outside_a_scope_does_not_inherit_it + run_and_events(OutsiderTaskScopeWorkflow) do |_handle, events| + assert_markers(activity_event(events, 'in-a'), label_marker_id('aaa')) + assert_markers(activity_event(events, 'outside-task')) + end + end + + class ThrowingScopeWorkflow < Temporalio::Workflow::Definition + def execute + a = Temporalio::Workflow.create_event_group('aaa') + b = Temporalio::Workflow.create_event_group('bbb') + Temporalio::Workflow.with_event_groups(a) do + begin + Temporalio::Workflow.with_event_groups(b) do + WorkerWorkflowEventGroupsTest.activity('a-b') + raise 'boom' + end + rescue RuntimeError + nil + end + WorkerWorkflowEventGroupsTest.activity('a-after') + end + end + end + + def test_a_scope_unwinds_cleanly_when_its_body_throws + run_and_events(ThrowingScopeWorkflow) do |_handle, events| + a = label_marker_id('aaa') + b = label_marker_id('bbb') + assert_equal 2, events_of_type(events, :EVENT_TYPE_ACTIVITY_TASK_SCHEDULED).size + assert_markers(activity_event(events, 'a-b'), a, b) + assert_markers(activity_event(events, 'a-after'), a) + end + end + + #################################################################################################### + # EG-IMPLICIT + #################################################################################################### + + def test_invalid_inbound_event_id_is_noop_stub + stub = Temporalio::Workflow._inbound_event_group(0) + assert_instance_of Temporalio::Workflow::EventGroup::StubImplicit, stub + assert_instance_of Temporalio::Workflow::EventGroup::StubImplicit, Temporalio::Workflow._inbound_event_group(-1) + + enclosing = Temporalio::Workflow::EventGroup::Active.new( + implicit: nil, + explicit: { 'id' => Temporalio::Workflow::EventGroup::Label.new('id', 'label') } + ) + applied = stub._applied_over(enclosing) + assert_nil applied.implicit + assert_empty applied.explicit + + prev = Fiber[Temporalio::Workflow::EventGroup::STORAGE_KEY] + Fiber[Temporalio::Workflow::EventGroup::STORAGE_KEY] = applied + begin + assert_empty Temporalio::Workflow::EventGroup._markers_for_command(nil) + ensure + Fiber[Temporalio::Workflow::EventGroup::STORAGE_KEY] = prev + end + end + + class StaticSignalHandlerWorkflow < Temporalio::Workflow::Definition + def execute + WorkerWorkflowEventGroupsTest.activity('from-main-before-signal') + Temporalio::Workflow.wait_condition { @done } + WorkerWorkflowEventGroupsTest.activity('from-main-after-signal') + end + + workflow_signal + def my_signal + WorkerWorkflowEventGroupsTest.activity('from-static-signal') + a = Temporalio::Workflow.create_event_group('aaa') + Temporalio::Workflow.with_event_groups(a) { WorkerWorkflowEventGroupsTest.activity('from-static-signal-scoped') } + @done = true + end + end + + def test_static_signal_handler_implicit_group + execute_workflow(StaticSignalHandlerWorkflow, activities: [NoopActivity]) do |handle| + handle.signal(StaticSignalHandlerWorkflow.my_signal) + handle.result + events = fetch_events(handle) + signal = event_marker(signaled_event_ids(events).first) + a = label_marker_id('aaa') + assert_markers(activity_event(events, 'from-static-signal'), signal) + assert_markers(activity_event(events, 'from-static-signal-scoped'), signal, a) + assert_markers(activity_event(events, 'from-main-before-signal')) + assert_markers(activity_event(events, 'from-main-after-signal')) + end + end + + class RuntimeSignalHandlerWorkflow < Temporalio::Workflow::Definition + def execute + outside = Temporalio::Workflow.create_event_group('outside') + inside = Temporalio::Workflow.create_event_group('inside') + Temporalio::Workflow.with_event_groups(outside) do + Temporalio::Workflow.signal_handlers['mySignal'] = Temporalio::Workflow::Definition::Signal.new( + name: 'mySignal', + to_invoke: proc do + WorkerWorkflowEventGroupsTest.activity('from-runtime-signal') + Temporalio::Workflow.with_event_groups(inside) do + WorkerWorkflowEventGroupsTest.activity('from-runtime-signal-scoped') + end + @done = true + end + ) + WorkerWorkflowEventGroupsTest.activity('in-outside') + end + WorkerWorkflowEventGroupsTest.activity('from-main-before-signal') + Temporalio::Workflow.wait_condition { @done } + WorkerWorkflowEventGroupsTest.activity('from-main-after-signal') + end + end + + def test_runtime_signal_handler_implicit_group + execute_workflow(RuntimeSignalHandlerWorkflow, activities: [NoopActivity]) do |handle| + handle.signal(:mySignal) + handle.result + events = fetch_events(handle) + signal_ids = signaled_event_ids(events) + assert_equal 1, signal_ids.size + signal = event_marker(signal_ids.first) + outside = label_marker_id('outside') + inside = label_marker_id('inside') + assert_markers(activity_event(events, 'from-runtime-signal'), signal) + assert_markers(activity_event(events, 'in-outside'), outside) + assert_markers(activity_event(events, 'from-runtime-signal-scoped'), signal, inside) + assert_markers(activity_event(events, 'from-main-before-signal')) + assert_markers(activity_event(events, 'from-main-after-signal')) + end + end + + class BufferedSignalWorkflow < Temporalio::Workflow::Definition + def execute + Temporalio::Workflow.signal_handlers['unblock'] = Temporalio::Workflow::Definition::Signal.new( + name: 'unblock', + to_invoke: proc { @unblocked = true } + ) + Temporalio::Workflow.wait_condition { @unblocked } + Temporalio::Workflow.signal_handlers['mySignal'] = Temporalio::Workflow::Definition::Signal.new( + name: 'mySignal', + to_invoke: proc do + WorkerWorkflowEventGroupsTest.activity('from-runtime-signal') + @handled = true + end + ) + Temporalio::Workflow.wait_condition { @handled } + end + end + + def test_buffered_signal_keeps_its_original_implicit_marker + execute_workflow(BufferedSignalWorkflow, activities: [NoopActivity]) do |handle| + handle.signal(:mySignal) + handle.signal(:unblock) + handle.result + events = fetch_events(handle) + my_signal = events.find do |event| + event.event_type == :EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED && + event.workflow_execution_signaled_event_attributes.signal_name == 'mySignal' + end + assert_markers(activity_event(events, 'from-runtime-signal'), event_marker(my_signal.event_id)) + end + end + + class CatchAllSignalWorkflow < Temporalio::Workflow::Definition + def execute + Temporalio::Workflow.wait_condition { @done } + end + + workflow_signal dynamic: true + def catch_all(_name) + WorkerWorkflowEventGroupsTest.activity('from-catch-all-signal') + @done = true + end + end + + def test_catch_all_signal_handler_implicit_group + execute_workflow(CatchAllSignalWorkflow, activities: [NoopActivity]) do |handle| + handle.signal(:unknownSignal) + handle.result + events = fetch_events(handle) + assert_markers(activity_event(events, 'from-catch-all-signal'), event_marker(signaled_event_ids(events).first)) + end + end + + class StaticUpdateHandlerWorkflow < Temporalio::Workflow::Definition + def execute + WorkerWorkflowEventGroupsTest.activity('from-main-before-update') + Temporalio::Workflow.wait_condition { @done } + WorkerWorkflowEventGroupsTest.activity('from-main-after-update') + end + + workflow_update + def my_update + WorkerWorkflowEventGroupsTest.activity('from-static-update') + inside = Temporalio::Workflow.create_event_group('inside') + Temporalio::Workflow.with_event_groups(inside) do + WorkerWorkflowEventGroupsTest.activity('from-static-update-scoped') + end + @done = true + end + end + + def test_static_update_handler_implicit_group + update_id = 'static-update-1' + execute_workflow(StaticUpdateHandlerWorkflow, activities: [NoopActivity]) do |handle| + handle.execute_update(StaticUpdateHandlerWorkflow.my_update, id: update_id) + handle.result + events = fetch_events(handle) + update = update_marker(update_id) + inside = label_marker_id('inside') + assert_markers(activity_event(events, 'from-static-update'), update) + assert_markers(activity_event(events, 'from-static-update-scoped'), update, inside) + assert_markers(activity_event(events, 'from-main-before-update')) + assert_markers(activity_event(events, 'from-main-after-update')) + end + end + + class RuntimeUpdateHandlerWorkflow < Temporalio::Workflow::Definition + def execute + outside = Temporalio::Workflow.create_event_group('outside') + inside = Temporalio::Workflow.create_event_group('inside') + Temporalio::Workflow.with_event_groups(outside) do + Temporalio::Workflow.update_handlers['myUpdate'] = Temporalio::Workflow::Definition::Update.new( + name: 'myUpdate', + to_invoke: proc do + WorkerWorkflowEventGroupsTest.activity('from-runtime-update') + Temporalio::Workflow.with_event_groups(inside) do + WorkerWorkflowEventGroupsTest.activity('from-runtime-update-scoped') + end + @done = true + end + ) + WorkerWorkflowEventGroupsTest.activity('in-outside') + end + WorkerWorkflowEventGroupsTest.activity('from-main-before-update') + Temporalio::Workflow.wait_condition { @done } + WorkerWorkflowEventGroupsTest.activity('from-main-after-update') + end + end + + def test_runtime_update_handler_implicit_group + update_id = 'runtime-update-1' + execute_workflow(RuntimeUpdateHandlerWorkflow, activities: [NoopActivity]) do |handle| + # Updates that arrive before registration are rejected, not buffered. + assert_eventually { activity_event(fetch_events(handle), 'in-outside') } + handle.execute_update(:myUpdate, id: update_id) + handle.result + events = fetch_events(handle) + update = update_marker(update_id) + outside = label_marker_id('outside') + inside = label_marker_id('inside') + assert_markers(activity_event(events, 'from-runtime-update'), update) + assert_markers(activity_event(events, 'in-outside'), outside) + assert_markers(activity_event(events, 'from-runtime-update-scoped'), update, inside) + assert_markers(activity_event(events, 'from-main-before-update')) + assert_markers(activity_event(events, 'from-main-after-update')) + end + end + + class CatchAllUpdateWorkflow < Temporalio::Workflow::Definition + def execute + Temporalio::Workflow.wait_condition { @done } + end + + workflow_update dynamic: true + def catch_all(_name) + WorkerWorkflowEventGroupsTest.activity('from-catch-all-update') + @done = true + end + end + + def test_catch_all_update_handler_implicit_group + update_id = 'catch-all-update-1' + execute_workflow(CatchAllUpdateWorkflow, activities: [NoopActivity]) do |handle| + handle.execute_update(:unknownUpdate, id: update_id) + handle.result + events = fetch_events(handle) + assert_markers(activity_event(events, 'from-catch-all-update'), update_marker(update_id)) + end + end + + #################################################################################################### + # EG-AGGREGATION + #################################################################################################### + + class AggregationWorkflow < Temporalio::Workflow::Definition + def execute + a1 = Temporalio::Workflow.create_event_group('aaa') + a2 = Temporalio::Workflow.create_event_group('aaa') + b1 = Temporalio::Workflow.create_event_group('b-id', label: 'bbb1') + b2 = Temporalio::Workflow.create_event_group('b-id', label: 'bbb2') + WorkerWorkflowEventGroupsTest.activity('direct-duplicates', event_groups: [a2, b1, a1, b1, a2, a1]) + Temporalio::Workflow.with_event_groups(a1) do + Temporalio::Workflow.with_event_groups(a2) do + Temporalio::Workflow.with_event_groups(b1) { WorkerWorkflowEventGroupsTest.activity('nested-scopes') } + end + end + Temporalio::Workflow.with_event_groups(a1) do + Temporalio::Workflow.with_event_groups(b1) do + WorkerWorkflowEventGroupsTest.activity('scope-and-direct-b', event_groups: [b1]) + WorkerWorkflowEventGroupsTest.activity('scope-and-direct-a-b', event_groups: [b1, a1]) + end + end + WorkerWorkflowEventGroupsTest.activity('same-instance-twice', event_groups: [a1, a1]) + WorkerWorkflowEventGroupsTest.activity('same-id-direct', event_groups: [b1, b2]) + Temporalio::Workflow.with_event_groups(b1) do + WorkerWorkflowEventGroupsTest.activity('same-id-scope-and-direct', event_groups: [b2]) + end + end + end + + def test_markers_dedupe_by_id + run_and_events(AggregationWorkflow) do |_handle, events| + a = label_marker_id('aaa') + b = label_marker('b-id', 'bbb1') + both = [a, b] + assert_markers(activity_event(events, 'direct-duplicates'), *both) + assert_markers(activity_event(events, 'nested-scopes'), *both) + assert_markers(activity_event(events, 'scope-and-direct-b'), *both) + assert_markers(activity_event(events, 'scope-and-direct-a-b'), *both) + assert_markers(activity_event(events, 'same-instance-twice'), a) + assert_marker_ids(activity_event(events, 'same-id-direct'), label_marker_id('b-id')) + assert_marker_ids(activity_event(events, 'same-id-scope-and-direct'), label_marker_id('b-id')) + end + end + + #################################################################################################### + # EG-COMMANDS + #################################################################################################### + + class TimerCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + Temporalio::Workflow.with_event_groups(scope) do + Temporalio::Workflow.sleep(0.001, event_groups: [direct]) + begin + Temporalio::Workflow.timeout(0.001, event_groups: [direct]) { Temporalio::Workflow.wait_condition { false } } + rescue Timeout::Error + nil + end + cancel, cancel_proc = Temporalio::Cancellation.new + long = Temporalio::Workflow::Future.new do + Temporalio::Workflow.sleep(60, cancellation: cancel, event_groups: [direct]) + end + Temporalio::Workflow.sleep(0.001) + cancel_proc.call + begin + long.wait + rescue Temporalio::Error::CanceledError + nil + end + end + end + end + + def test_timer_commands_carry_markers + run_and_events(TimerCommandsWorkflow, activities: []) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + ambient = [label_marker_id('scope')] + timers = events_of_type(events, :EVENT_TYPE_TIMER_STARTED) + assert_equal 4, timers.size + cancels = events_of_type(events, :EVENT_TYPE_TIMER_CANCELED) + assert_equal 1, cancels.size + assert_markers(timers[0], *both) + assert_markers(timers[1], *both) + rest = timers.drop(2) + ambient_timers = rest.select { |timer| timer.event_group_markers.map { render_marker(_1) }.sort == ambient.sort } + both_timers = rest.select { |timer| timer.event_group_markers.map { render_marker(_1) }.sort == both.sort } + assert_equal 1, ambient_timers.size + assert_equal 1, both_timers.size + assert_markers(cancels[0], *both) + end + end + + class ActivityCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + Temporalio::Workflow.with_event_groups(scope) do + Temporalio::Workflow.execute_activity( + NoopActivity, + start_to_close_timeout: ACT_TIMEOUT, + schedule_to_start_timeout: 10, + event_groups: [direct], + activity_id: 'activity' + ) + cancel, cancel_proc = Temporalio::Cancellation.new + fut = Temporalio::Workflow::Future.new do + Temporalio::Workflow.execute_activity( + SleepActivity, + start_to_close_timeout: ACT_TIMEOUT, + schedule_to_start_timeout: 10, + cancellation: cancel, + cancellation_type: Temporalio::Workflow::ActivityCancellationType::TRY_CANCEL, + event_groups: [direct], + activity_id: 'activity-cancelled-sleep-5s' + ) + end + Temporalio::Workflow.sleep(0.001) + cancel_proc.call + begin + fut.wait + rescue Temporalio::Error::ActivityError, Temporalio::Error::CanceledError + nil + end + end + end + end + + def test_activity_commands_carry_markers + run_and_events(ActivityCommandsWorkflow, activities: [NoopActivity, SleepActivity]) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + assert_markers(activity_event(events, 'activity'), *both) + assert_markers(activity_event(events, 'activity-cancelled-sleep-5s'), *both) + assert_markers(single_event(events, :EVENT_TYPE_ACTIVITY_TASK_CANCEL_REQUESTED), *both) + end + end + + class LocalActivityCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + Temporalio::Workflow.with_event_groups(scope) do + Temporalio::Workflow.execute_local_activity( + NoopActivity, + start_to_close_timeout: ACT_TIMEOUT, + event_groups: [direct], + activity_id: 'local-activity' + ) + + cancel_trigger = Temporalio::Workflow.create_event_group('cancel-trigger') + cancelled_la = Temporalio::Workflow.create_event_group('cancelled-la') + cancel, cancel_proc = Temporalio::Cancellation.new + sleeping = Temporalio::Workflow::Future.new do + Temporalio::Workflow.execute_local_activity( + SleepActivity, + start_to_close_timeout: ACT_TIMEOUT, + cancellation: cancel, + cancellation_type: Temporalio::Workflow::ActivityCancellationType::TRY_CANCEL, + event_groups: [direct, cancelled_la], + activity_id: 'cancelled-local-activity-sleep-5s' + ) + end + trigger = Temporalio::Workflow::Future.new do + Temporalio::Workflow.execute_local_activity( + NoopActivity, + start_to_close_timeout: ACT_TIMEOUT, + event_groups: [direct, cancel_trigger], + activity_id: 'cancel-trigger' + ) + cancel_proc.call + end + begin + sleeping.wait + rescue Temporalio::Error::ActivityError, Temporalio::Error::CanceledError + nil + end + trigger.wait + + Temporalio::Workflow.execute_local_activity( + FailFirstActivity, + start_to_close_timeout: ACT_TIMEOUT, + local_retry_threshold: 0.001, + retry_policy: Temporalio::RetryPolicy.new(initial_interval: 1, backoff_coefficient: 1, max_attempts: 2), + event_groups: [direct], + activity_id: 'backoff-local-activity-fail-first-attempt' + ) + end + end + end + + def test_local_activity_commands_carry_markers + execute_workflow( + LocalActivityCommandsWorkflow, + activities: [NoopActivity, SleepActivity, FailFirstActivity], + task_timeout: 5 + ) do |handle| + handle.result + events = fetch_events(handle) + both = [label_marker_id('direct'), label_marker_id('scope')] + cancel_trigger = [*both, label_marker_id('cancel-trigger')] + cancelled_la = [*both, label_marker_id('cancelled-la')] + local_acts = markers_named(events, 'core_local_activity') + assert_equal 5, local_acts.size + assert_markers(local_acts[0], *both) + assert_markers(local_acts[1], *cancel_trigger) + assert_markers(local_acts[2], *cancelled_la) + backoff_timer = events_of_type(events, :EVENT_TYPE_TIMER_STARTED) + assert_equal 1, backoff_timer.size + assert_markers(backoff_timer[0], *both) + assert_markers(local_acts[3], *both) + assert_markers(local_acts[4], *both) + end + end + + class ChildWorkflowCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + Temporalio::Workflow.with_event_groups(scope) do + Temporalio::Workflow.start_child_workflow( + NoopChildWorkflow, + id: "#{Temporalio::Workflow.info.workflow_id}_child", + event_groups: [direct] + ) + cancel, cancel_proc = Temporalio::Cancellation.new + fut = Temporalio::Workflow::Future.new do + Temporalio::Workflow.execute_child_workflow( + SleepChildWorkflow, + id: "#{Temporalio::Workflow.info.workflow_id}_child_cancel", + cancellation: cancel, + cancellation_type: Temporalio::Workflow::ChildWorkflowCancellationType::WAIT_CANCELLATION_REQUESTED, + event_groups: [direct] + ) + end + Temporalio::Workflow.sleep(0.001) + cancel_proc.call + begin + fut.wait + rescue Temporalio::Error::ChildWorkflowError, Temporalio::Error::CanceledError + nil + end + end + end + end + + def test_child_workflow_commands_carry_markers + run_and_events( + ChildWorkflowCommandsWorkflow, + activities: [], + more_workflows: [NoopChildWorkflow, SleepChildWorkflow] + ) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + initiated = events_of_type(events, :EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED) + assert_equal 2, initiated.size + assert_markers(initiated[0], *both) + assert_markers(initiated[1], *both) + assert_markers(single_event(events, :EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED), *both) + end + end + + class NexusCommandsWorkflow < Temporalio::Workflow::Definition + def execute(endpoint) + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + client = Temporalio::Workflow.create_nexus_client(endpoint:, service: 'test-service') + Temporalio::Workflow.with_event_groups(scope) do + client.execute_operation('echo', 'success', event_groups: [direct]) + cancel, cancel_proc = Temporalio::Cancellation.new + running = Temporalio::Workflow::Future.new do + client.execute_operation( + 'workflow-operation', + { 'action' => 'wait-for-cancel' }, + cancellation: cancel, + cancellation_type: Temporalio::Workflow::NexusOperationCancellationType::TRY_CANCEL, + event_groups: [direct] + ) + end + Temporalio::Workflow.sleep(0.001) + cancel_proc.call + begin + running.wait + rescue Temporalio::Error::NexusOperationError, Temporalio::Error::CanceledError + nil + end + end + end + end + + def test_nexus_operation_commands_carry_markers + env.with_kitchen_sink_worker(nexus: true) do |task_queue| + endpoint = "nexus-endpoint-#{task_queue}" + run_and_events(NexusCommandsWorkflow, endpoint, activities: []) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + scheduled = events_of_type(events, :EVENT_TYPE_NEXUS_OPERATION_SCHEDULED) + assert_equal 2, scheduled.size + assert_markers(scheduled[0], *both) + assert_markers(scheduled[1], *both) + assert_markers(single_event(events, :EVENT_TYPE_NEXUS_OPERATION_CANCEL_REQUESTED), *both) + end + end + end + + class ExternalWorkflowCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + missing = Temporalio::Workflow.external_workflow_handle('event-groups-no-such-workflow') + Temporalio::Workflow.with_event_groups(scope) do + begin + missing.signal('signal', event_groups: [direct]) + rescue Temporalio::Error + nil + end + begin + missing.cancel(event_groups: [direct]) + rescue Temporalio::Error + nil + end + end + end + end + + def test_external_workflow_commands_carry_markers + run_and_events(ExternalWorkflowCommandsWorkflow, activities: []) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + assert_markers(single_event(events, :EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED), *both) + assert_markers(single_event(events, :EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED), *both) + end + end + + class ChildWorkflowSignalCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + child = Temporalio::Workflow.start_child_workflow( + WaitForSignalChildWorkflow, + id: "#{Temporalio::Workflow.info.workflow_id}_child" + ) + Temporalio::Workflow.with_event_groups(scope) { child.signal(:noop, event_groups: [direct]) } + child.result + end + end + + def test_child_workflow_signal_commands_carry_markers + run_and_events( + ChildWorkflowSignalCommandsWorkflow, + activities: [], + more_workflows: [WaitForSignalChildWorkflow] + ) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + assert_markers(single_event(events, :EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED), *both) + end + end + + class MetadataCommandsWorkflow < Temporalio::Workflow::Definition + def execute + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + Temporalio::Workflow.with_event_groups(scope) do + Temporalio::Workflow.upsert_memo({ 'some-key' => 'some-value' }, event_groups: [direct]) + Temporalio::Workflow.upsert_search_attributes( + WorkerWorkflowEventGroupsTest::ATTR_KEY_BOOLEAN.value_set(false), + event_groups: [direct] + ) + Temporalio::Workflow.patched('my-patch-1', event_groups: [direct]) + Temporalio::Workflow.deprecate_patch('my-patch-2', event_groups: [direct]) + end + end + end + + def test_metadata_commands_carry_markers + env.ensure_common_search_attribute_keys + run_and_events(MetadataCommandsWorkflow, activities: []) do |_handle, events| + both = [label_marker_id('direct'), label_marker_id('scope')] + assert_markers(single_event(events, :EVENT_TYPE_WORKFLOW_PROPERTIES_MODIFIED), *both) + patches = markers_named(events, 'core_patch') + assert_equal 2, patches.size + patches.each { |patch| assert_markers(patch, *both) } + upserts = events_of_type(events, :EVENT_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES) + assert_equal 3, upserts.size + upserts.each { |upsert| assert_markers(upsert, *both) } + end + end + + class ContinueAsNewCommandsWorkflow < Temporalio::Workflow::Definition + def execute(second_run = nil) + return if second_run + + direct = Temporalio::Workflow.create_event_group('direct') + scope = Temporalio::Workflow.create_event_group('scope') + Temporalio::Workflow.with_event_groups(scope) do + raise Temporalio::Workflow::ContinueAsNewError.new(true, event_groups: [direct]) + end + end + end + + def test_continue_as_new_carries_markers + execute_workflow(ContinueAsNewCommandsWorkflow, false, activities: []) do |handle| + handle.result + first = env.client.workflow_handle(handle.id, run_id: handle.first_execution_run_id) + events = fetch_events(first) + both = [label_marker_id('direct'), label_marker_id('scope')] + assert_markers(single_event(events, :EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW), *both) + end + end + + class EmptyIdAndLabelWorkflow < Temporalio::Workflow::Definition + def execute + errors = [] + begin + Temporalio::Workflow.create_event_group('') + rescue ArgumentError => e + errors << e.message + end + begin + Temporalio::Workflow.create_event_group('id', label: '') + rescue ArgumentError => e + errors << e.message + end + errors + end + end + + def test_event_group_rejects_empty_id_and_label + assert_equal( + ['Event group id cannot be empty', 'Event group label cannot be empty'], + execute_workflow(EmptyIdAndLabelWorkflow, activities: []) + ) + end + + def test_create_event_group_requires_workflow_context + err = assert_raises(Temporalio::Error) { Temporalio::Workflow.create_event_group('outside-workflow') } + assert_equal 'Not in workflow environment', err.message + end +end diff --git a/temporalio/test/worker_workflow_test.rb b/temporalio/test/worker_workflow_test.rb index 38d11324..04842417 100644 --- a/temporalio/test/worker_workflow_test.rb +++ b/temporalio/test/worker_workflow_test.rb @@ -212,6 +212,7 @@ def test_info assert_nil info.fetch('retry_policy') assert_nil info.fetch('root') assert_equal handle.result_run_id, info['run_id'] + assert_equal handle.result_run_id, info['original_execution_run_id'] assert_nil info.fetch('run_timeout') assert_equal desc.start_time.to_s, info['start_time'] assert_equal worker.task_queue, info['task_queue']