diff --git a/.gitignore b/.gitignore index 021ac7338..f94200d1b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ temporalio/bridge/temporal_sdk_bridge* /tests/helpers/golangworker/golangworker /.idea /sdk-python.iml +/.zed diff --git a/README.md b/README.md index 2206e108a..533bae74f 100644 --- a/README.md +++ b/README.md @@ -680,7 +680,7 @@ Some things to note about the above code: #### Timers -* A timer is represented by normal `asyncio.sleep()` +* A timer is represented by normal `asyncio.sleep()` or a `workflow.sleep()` call * Timers are also implicitly started on any `asyncio` calls with timeouts (e.g. `asyncio.wait_for`) * Timers are Temporal server timers, not local ones, so sub-second resolution rarely has value * Calls that use a specific point in time, e.g. `call_at` or `timeout_at`, should be based on the current loop time diff --git a/temporalio/bridge/Cargo.lock b/temporalio/bridge/Cargo.lock index ba644121d..b4dcb97e2 100644 --- a/temporalio/bridge/Cargo.lock +++ b/temporalio/bridge/Cargo.lock @@ -244,9 +244,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -267,9 +267,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "num-traits", "serde", @@ -595,9 +595,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "filetime" @@ -1223,9 +1223,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ "once_cell", "wasm-bindgen", @@ -1239,9 +1239,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libredox" @@ -1464,9 +1464,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "opentelemetry" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" +checksum = "570074cc999d1a58184080966e5bd3bf3a9a4af650c3b05047c2621e7405cd17" dependencies = [ "futures-core", "futures-sink", @@ -1478,9 +1478,9 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.17.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" +checksum = "29e1f9c8b032d4f635c730c0efcf731d5e2530ea13fa8bef7939ddc8420696bd" dependencies = [ "async-trait", "futures-core", @@ -1497,8 +1497,7 @@ dependencies = [ [[package]] name = "opentelemetry-prometheus" version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4191ce34aa274621861a7a9d68dbcf618d5b6c66b10081631b61fd81fbc015" +source = "git+https://github.com/open-telemetry/opentelemetry-rust.git?rev=e911383#e91138351a689cd21923c15eb48f5fbc95ded807" dependencies = [ "once_cell", "opentelemetry", @@ -1509,9 +1508,9 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.7.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" +checksum = "c9d3968ce3aefdcca5c27e3c4ea4391b37547726a70893aab52d3de95d5f8b34" dependencies = [ "opentelemetry", "opentelemetry_sdk", @@ -1521,9 +1520,9 @@ dependencies = [ [[package]] name = "opentelemetry_sdk" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" +checksum = "d2c627d9f4c9cdc1f21a29ee4bfbd6028fcb8bcf2a857b43f3abdf72c9c862f3" dependencies = [ "async-trait", "futures-channel", @@ -1725,9 +1724,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" dependencies = [ "bytes", "prost-derive", @@ -1735,11 +1734,10 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +checksum = "d0f3e5beed80eb580c68e2c600937ac2c4eedabdfd5ef1e5b7ea4f3fba84497b" dependencies = [ - "bytes", "heck 0.5.0", "itertools", "log", @@ -1756,9 +1754,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" dependencies = [ "anyhow", "itertools", @@ -1769,9 +1767,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" dependencies = [ "prost", ] @@ -1943,7 +1941,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.4", + "thiserror 2.0.6", "tokio", "tracing", ] @@ -1962,7 +1960,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.4", + "thiserror 2.0.6", "tinyvec", "tracing", "web-time", @@ -1970,9 +1968,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" dependencies = [ "cfg_aliases", "libc", @@ -2189,15 +2187,15 @@ version = "0.1.0" [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2565,7 +2563,7 @@ dependencies = [ "slotmap", "temporal-sdk-core-api", "temporal-sdk-core-protos", - "thiserror 1.0.69", + "thiserror 2.0.6", "tokio", "tonic", "tower 0.5.1", @@ -2644,7 +2642,7 @@ dependencies = [ "temporal-client", "temporal-sdk-core-api", "temporal-sdk-core-protos", - "thiserror 1.0.69", + "thiserror 2.0.6", "tokio", "tokio-stream", "tokio-util", @@ -2669,7 +2667,7 @@ dependencies = [ "prost-types", "serde_json", "temporal-sdk-core-protos", - "thiserror 1.0.69", + "thiserror 2.0.6", "tonic", "tracing-core", "url", @@ -2684,13 +2682,14 @@ dependencies = [ "derive_more", "prost", "prost-build", + "prost-types", "prost-wkt", "prost-wkt-build", "prost-wkt-types", "rand", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.6", "tonic", "tonic-build", "uuid", @@ -2713,11 +2712,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.4" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ - "thiserror-impl 2.0.4", + "thiserror-impl 2.0.6", ] [[package]] @@ -2733,9 +2732,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.4" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", @@ -2837,9 +2836,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3141,9 +3140,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -3152,13 +3151,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -3167,9 +3165,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.47" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", @@ -3180,9 +3178,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3190,9 +3188,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -3203,9 +3201,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-streams" @@ -3222,9 +3220,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -3580,7 +3578,7 @@ dependencies = [ "pbkdf2", "rand", "sha1", - "thiserror 2.0.4", + "thiserror 2.0.6", "time", "zeroize", "zopfli", diff --git a/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.py b/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.py index 03a6d8698..0ac544a2f 100644 --- a/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.py +++ b/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.py @@ -40,7 +40,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\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%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/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"\xc7\x02\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\x12!\n\x19\x62uild_id_for_current_task\x18\t \x01(\t"\xa7\t\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\x12I\n\x11remove_from_cache\x18\x32 \x01(\x0b\x32,.coresdk.workflow_activation.RemoveFromCacheH\x00\x42\t\n\x07variant"\xe3\t\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\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"B\n\x0e\x43\x61ncelWorkflow\x12\x30\n\x07\x64\x65tails\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\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"\xc1\x02\n\x0fRemoveFromCache\x12\x0f\n\x07message\x18\x01 \x01(\t\x12K\n\x06reason\x18\x02 \x01(\x0e\x32;.coresdk.workflow_activation.RemoveFromCache.EvictionReason"\xcf\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\tB8\xea\x02\x35Temporalio::Internal::Bridge::Api::WorkflowActivationb\x06proto3' + b'\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%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/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"\xc7\x02\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\x12!\n\x19\x62uild_id_for_current_task\x18\t \x01(\t"\xa7\t\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\x12I\n\x11remove_from_cache\x18\x32 \x01(\x0b\x32,.coresdk.workflow_activation.RemoveFromCacheH\x00\x42\t\n\x07variant"\xe3\t\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\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"B\n\x0e\x43\x61ncelWorkflow\x12\x30\n\x07\x64\x65tails\x18\x01 \x03(\x0b\x32\x1f.temporal.api.common.v1.Payload"\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"\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' ) @@ -391,7 +391,7 @@ _DOUPDATE_HEADERSENTRY._serialized_start = 3162 _DOUPDATE_HEADERSENTRY._serialized_end = 3241 _REMOVEFROMCACHE._serialized_start = 5365 - _REMOVEFROMCACHE._serialized_end = 5686 + _REMOVEFROMCACHE._serialized_end = 5717 _REMOVEFROMCACHE_EVICTIONREASON._serialized_start = 5479 - _REMOVEFROMCACHE_EVICTIONREASON._serialized_end = 5686 + _REMOVEFROMCACHE_EVICTIONREASON._serialized_end = 5717 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.pyi b/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.pyi index a543959d4..db52a5024 100644 --- a/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.pyi +++ b/temporalio/bridge/proto/workflow_activation/workflow_activation_pb2.pyi @@ -1281,6 +1281,10 @@ class RemoveFromCache(google.protobuf.message.Message): """ PAGINATION_OR_HISTORY_FETCH: RemoveFromCache._EvictionReason.ValueType # 9 """Something went wrong attempting to fetch more history events.""" + WORKFLOW_EXECUTION_ENDING: RemoveFromCache._EvictionReason.ValueType # 10 + """The workflow is being completed with a terminal command and we sent the WFT completion + to server successfully. + """ class EvictionReason(_EvictionReason, metaclass=_EvictionReasonEnumTypeWrapper): ... UNSPECIFIED: RemoveFromCache.EvictionReason.ValueType # 0 @@ -1310,6 +1314,10 @@ class RemoveFromCache(google.protobuf.message.Message): """ PAGINATION_OR_HISTORY_FETCH: RemoveFromCache.EvictionReason.ValueType # 9 """Something went wrong attempting to fetch more history events.""" + WORKFLOW_EXECUTION_ENDING: RemoveFromCache.EvictionReason.ValueType # 10 + """The workflow is being completed with a terminal command and we sent the WFT completion + to server successfully. + """ MESSAGE_FIELD_NUMBER: builtins.int REASON_FIELD_NUMBER: builtins.int diff --git a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py index 078dfa8a7..5c2cf25b8 100644 --- a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py +++ b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.py @@ -28,6 +28,9 @@ from temporalio.api.failure.v1 import ( message_pb2 as temporal_dot_api_dot_failure_dot_v1_dot_message__pb2, ) +from temporalio.api.sdk.v1 import ( + user_metadata_pb2 as temporal_dot_api_dot_sdk_dot_v1_dot_user__metadata__pb2, +) from temporalio.bridge.proto.child_workflow import ( child_workflow_pb2 as temporal_dot_sdk_dot_core_dot_child__workflow_dot_child__workflow__pb2, ) @@ -36,7 +39,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\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\x35temporal/sdk/core/child_workflow/child_workflow.proto\x1a%temporal/sdk/core/common/common.proto"\xf2\r\n\x0fWorkflowCommand\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\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"\x84\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\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"\xfb\x06\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\x12j\n\x11search_attributes\x18\x08 \x03(\x0b\x32O.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.SearchAttributesEntry\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\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\x1aX\n\x15SearchAttributesEntry\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"\xe0\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\x12g\n\x11search_attributes\x18\x11 \x03(\x0b\x32L.coresdk.workflow_commands.StartChildWorkflowExecution.SearchAttributesEntry\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\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\x1aX\n\x15SearchAttributesEntry\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\x1c\x43\x61ncelChildWorkflowExecution\x12\x1a\n\x12\x63hild_workflow_seq\x18\x01 \x01(\r"\xa7\x01\n&RequestCancelExternalWorkflowExecution\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\x42\x08\n\x06target"\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"\xe6\x01\n\x1eUpsertWorkflowSearchAttributes\x12j\n\x11search_attributes\x18\x01 \x03(\x0b\x32O.coresdk.workflow_commands.UpsertWorkflowSearchAttributes.SearchAttributesEntry\x1aX\n\x15SearchAttributesEntry\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"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*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' + b'\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/common/common.proto"\xac\x0e\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\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"\x84\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\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"\xfb\x06\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\x12j\n\x11search_attributes\x18\x08 \x03(\x0b\x32O.coresdk.workflow_commands.ContinueAsNewWorkflowExecution.SearchAttributesEntry\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\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\x1aX\n\x15SearchAttributesEntry\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"\xe0\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\x12g\n\x11search_attributes\x18\x11 \x03(\x0b\x32L.coresdk.workflow_commands.StartChildWorkflowExecution.SearchAttributesEntry\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\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\x1aX\n\x15SearchAttributesEntry\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\x1c\x43\x61ncelChildWorkflowExecution\x12\x1a\n\x12\x63hild_workflow_seq\x18\x01 \x01(\r"~\n&RequestCancelExternalWorkflowExecution\x12\x0b\n\x03seq\x18\x01 \x01(\r\x12G\n\x12workflow_execution\x18\x02 \x01(\x0b\x32+.coresdk.common.NamespacedWorkflowExecution"\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"\xe6\x01\n\x1eUpsertWorkflowSearchAttributes\x12j\n\x11search_attributes\x18\x01 \x03(\x0b\x32O.coresdk.workflow_commands.UpsertWorkflowSearchAttributes.SearchAttributesEntry\x1aX\n\x15SearchAttributesEntry\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"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*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' ) _ACTIVITYCANCELLATIONTYPE = DESCRIPTOR.enum_types_by_name["ActivityCancellationType"] @@ -479,70 +482,70 @@ _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_options = b"8\001" _UPSERTWORKFLOWSEARCHATTRIBUTES_SEARCHATTRIBUTESENTRY._options = None _UPSERTWORKFLOWSEARCHATTRIBUTES_SEARCHATTRIBUTESENTRY._serialized_options = b"8\001" - _ACTIVITYCANCELLATIONTYPE._serialized_start = 7700 - _ACTIVITYCANCELLATIONTYPE._serialized_end = 7788 - _WORKFLOWCOMMAND._serialized_start = 394 - _WORKFLOWCOMMAND._serialized_end = 2172 - _STARTTIMER._serialized_start = 2174 - _STARTTIMER._serialized_end = 2257 - _CANCELTIMER._serialized_start = 2259 - _CANCELTIMER._serialized_end = 2285 - _SCHEDULEACTIVITY._serialized_start = 2288 - _SCHEDULEACTIVITY._serialized_end = 3060 - _SCHEDULEACTIVITY_HEADERSENTRY._serialized_start = 2981 - _SCHEDULEACTIVITY_HEADERSENTRY._serialized_end = 3060 - _SCHEDULELOCALACTIVITY._serialized_start = 3063 - _SCHEDULELOCALACTIVITY._serialized_end = 3813 - _SCHEDULELOCALACTIVITY_HEADERSENTRY._serialized_start = 2981 - _SCHEDULELOCALACTIVITY_HEADERSENTRY._serialized_end = 3060 - _REQUESTCANCELACTIVITY._serialized_start = 3815 - _REQUESTCANCELACTIVITY._serialized_end = 3851 - _REQUESTCANCELLOCALACTIVITY._serialized_start = 3853 - _REQUESTCANCELLOCALACTIVITY._serialized_end = 3894 - _QUERYRESULT._serialized_start = 3897 - _QUERYRESULT._serialized_end = 4053 - _QUERYSUCCESS._serialized_start = 4055 - _QUERYSUCCESS._serialized_end = 4120 - _COMPLETEWORKFLOWEXECUTION._serialized_start = 4122 - _COMPLETEWORKFLOWEXECUTION._serialized_end = 4198 - _FAILWORKFLOWEXECUTION._serialized_start = 4200 - _FAILWORKFLOWEXECUTION._serialized_end = 4274 - _CONTINUEASNEWWORKFLOWEXECUTION._serialized_start = 4277 - _CONTINUEASNEWWORKFLOWEXECUTION._serialized_end = 5168 - _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 4921 - _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 4997 - _CONTINUEASNEWWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 2981 - _CONTINUEASNEWWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3060 - _CONTINUEASNEWWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_start = 5080 - _CONTINUEASNEWWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_end = 5168 - _CANCELWORKFLOWEXECUTION._serialized_start = 5170 - _CANCELWORKFLOWEXECUTION._serialized_end = 5195 - _SETPATCHMARKER._serialized_start = 5197 - _SETPATCHMARKER._serialized_end = 5251 - _STARTCHILDWORKFLOWEXECUTION._serialized_start = 5254 - _STARTCHILDWORKFLOWEXECUTION._serialized_end = 6502 - _STARTCHILDWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 2981 - _STARTCHILDWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3060 - _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 4921 - _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 4997 - _STARTCHILDWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_start = 5080 - _STARTCHILDWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_end = 5168 - _CANCELCHILDWORKFLOWEXECUTION._serialized_start = 6504 - _CANCELCHILDWORKFLOWEXECUTION._serialized_end = 6562 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_start = 6565 - _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_end = 6732 - _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_start = 6735 - _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_end = 7134 - _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 2981 - _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3060 - _CANCELSIGNALWORKFLOW._serialized_start = 7136 - _CANCELSIGNALWORKFLOW._serialized_end = 7171 - _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_start = 7174 - _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_end = 7404 - _UPSERTWORKFLOWSEARCHATTRIBUTES_SEARCHATTRIBUTESENTRY._serialized_start = 5080 - _UPSERTWORKFLOWSEARCHATTRIBUTES_SEARCHATTRIBUTESENTRY._serialized_end = 5168 - _MODIFYWORKFLOWPROPERTIES._serialized_start = 7406 - _MODIFYWORKFLOWPROPERTIES._serialized_end = 7485 - _UPDATERESPONSE._serialized_start = 7488 - _UPDATERESPONSE._serialized_end = 7698 + _ACTIVITYCANCELLATIONTYPE._serialized_start = 7757 + _ACTIVITYCANCELLATIONTYPE._serialized_end = 7845 + _WORKFLOWCOMMAND._serialized_start = 435 + _WORKFLOWCOMMAND._serialized_end = 2271 + _STARTTIMER._serialized_start = 2273 + _STARTTIMER._serialized_end = 2356 + _CANCELTIMER._serialized_start = 2358 + _CANCELTIMER._serialized_end = 2384 + _SCHEDULEACTIVITY._serialized_start = 2387 + _SCHEDULEACTIVITY._serialized_end = 3159 + _SCHEDULEACTIVITY_HEADERSENTRY._serialized_start = 3080 + _SCHEDULEACTIVITY_HEADERSENTRY._serialized_end = 3159 + _SCHEDULELOCALACTIVITY._serialized_start = 3162 + _SCHEDULELOCALACTIVITY._serialized_end = 3912 + _SCHEDULELOCALACTIVITY_HEADERSENTRY._serialized_start = 3080 + _SCHEDULELOCALACTIVITY_HEADERSENTRY._serialized_end = 3159 + _REQUESTCANCELACTIVITY._serialized_start = 3914 + _REQUESTCANCELACTIVITY._serialized_end = 3950 + _REQUESTCANCELLOCALACTIVITY._serialized_start = 3952 + _REQUESTCANCELLOCALACTIVITY._serialized_end = 3993 + _QUERYRESULT._serialized_start = 3996 + _QUERYRESULT._serialized_end = 4152 + _QUERYSUCCESS._serialized_start = 4154 + _QUERYSUCCESS._serialized_end = 4219 + _COMPLETEWORKFLOWEXECUTION._serialized_start = 4221 + _COMPLETEWORKFLOWEXECUTION._serialized_end = 4297 + _FAILWORKFLOWEXECUTION._serialized_start = 4299 + _FAILWORKFLOWEXECUTION._serialized_end = 4373 + _CONTINUEASNEWWORKFLOWEXECUTION._serialized_start = 4376 + _CONTINUEASNEWWORKFLOWEXECUTION._serialized_end = 5267 + _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 5020 + _CONTINUEASNEWWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 5096 + _CONTINUEASNEWWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 3080 + _CONTINUEASNEWWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3159 + _CONTINUEASNEWWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_start = 5179 + _CONTINUEASNEWWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_end = 5267 + _CANCELWORKFLOWEXECUTION._serialized_start = 5269 + _CANCELWORKFLOWEXECUTION._serialized_end = 5294 + _SETPATCHMARKER._serialized_start = 5296 + _SETPATCHMARKER._serialized_end = 5350 + _STARTCHILDWORKFLOWEXECUTION._serialized_start = 5353 + _STARTCHILDWORKFLOWEXECUTION._serialized_end = 6601 + _STARTCHILDWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 3080 + _STARTCHILDWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3159 + _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_start = 5020 + _STARTCHILDWORKFLOWEXECUTION_MEMOENTRY._serialized_end = 5096 + _STARTCHILDWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_start = 5179 + _STARTCHILDWORKFLOWEXECUTION_SEARCHATTRIBUTESENTRY._serialized_end = 5267 + _CANCELCHILDWORKFLOWEXECUTION._serialized_start = 6603 + _CANCELCHILDWORKFLOWEXECUTION._serialized_end = 6661 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_start = 6663 + _REQUESTCANCELEXTERNALWORKFLOWEXECUTION._serialized_end = 6789 + _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_start = 6792 + _SIGNALEXTERNALWORKFLOWEXECUTION._serialized_end = 7191 + _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_start = 3080 + _SIGNALEXTERNALWORKFLOWEXECUTION_HEADERSENTRY._serialized_end = 3159 + _CANCELSIGNALWORKFLOW._serialized_start = 7193 + _CANCELSIGNALWORKFLOW._serialized_end = 7228 + _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_start = 7231 + _UPSERTWORKFLOWSEARCHATTRIBUTES._serialized_end = 7461 + _UPSERTWORKFLOWSEARCHATTRIBUTES_SEARCHATTRIBUTESENTRY._serialized_start = 5179 + _UPSERTWORKFLOWSEARCHATTRIBUTES_SEARCHATTRIBUTESENTRY._serialized_end = 5267 + _MODIFYWORKFLOWPROPERTIES._serialized_start = 7463 + _MODIFYWORKFLOWPROPERTIES._serialized_end = 7542 + _UPDATERESPONSE._serialized_start = 7545 + _UPDATERESPONSE._serialized_end = 7755 # @@protoc_insertion_point(module_scope) diff --git a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi index 53e8a8305..ca2959159 100644 --- a/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi +++ b/temporalio/bridge/proto/workflow_commands/workflow_commands_pb2.pyi @@ -23,6 +23,7 @@ import google.protobuf.timestamp_pb2 import temporalio.api.common.v1.message_pb2 import temporalio.api.enums.v1.workflow_pb2 import temporalio.api.failure.v1.message_pb2 +import temporalio.api.sdk.v1.user_metadata_pb2 import temporalio.bridge.proto.child_workflow.child_workflow_pb2 import temporalio.bridge.proto.common.common_pb2 @@ -76,6 +77,7 @@ global___ActivityCancellationType = ActivityCancellationType class WorkflowCommand(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor + USER_METADATA_FIELD_NUMBER: builtins.int START_TIMER_FIELD_NUMBER: builtins.int SCHEDULE_ACTIVITY_FIELD_NUMBER: builtins.int RESPOND_TO_QUERY_FIELD_NUMBER: builtins.int @@ -97,6 +99,12 @@ class WorkflowCommand(google.protobuf.message.Message): MODIFY_WORKFLOW_PROPERTIES_FIELD_NUMBER: builtins.int UPDATE_RESPONSE_FIELD_NUMBER: builtins.int @property + def user_metadata(self) -> temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata: + """User metadata that may or may not be persisted into history depending on the command type. + Lang layers are expected to expose the setting of the internals of this metadata on a + per-command basis where applicable. + """ + @property def start_timer(self) -> global___StartTimer: ... @property def schedule_activity(self) -> global___ScheduleActivity: ... @@ -151,6 +159,8 @@ class WorkflowCommand(google.protobuf.message.Message): def __init__( self, *, + user_metadata: temporalio.api.sdk.v1.user_metadata_pb2.UserMetadata + | None = ..., start_timer: global___StartTimer | None = ..., schedule_activity: global___ScheduleActivity | None = ..., respond_to_query: global___QueryResult | None = ..., @@ -221,6 +231,8 @@ class WorkflowCommand(google.protobuf.message.Message): b"update_response", "upsert_workflow_search_attributes", b"upsert_workflow_search_attributes", + "user_metadata", + b"user_metadata", "variant", b"variant", ], @@ -268,6 +280,8 @@ class WorkflowCommand(google.protobuf.message.Message): b"update_response", "upsert_workflow_search_attributes", b"upsert_workflow_search_attributes", + "user_metadata", + b"user_metadata", "variant", b"variant", ], @@ -1340,59 +1354,40 @@ class CancelChildWorkflowExecution(google.protobuf.message.Message): global___CancelChildWorkflowExecution = CancelChildWorkflowExecution class RequestCancelExternalWorkflowExecution(google.protobuf.message.Message): - """Request cancellation of an external workflow execution (which may be a started child)""" + """Request cancellation of an external workflow execution. For cancellation of a child workflow, + prefer `CancelChildWorkflowExecution` instead, as it guards against cancel-before-start issues. + """ DESCRIPTOR: google.protobuf.descriptor.Descriptor SEQ_FIELD_NUMBER: builtins.int WORKFLOW_EXECUTION_FIELD_NUMBER: builtins.int - CHILD_WORKFLOW_ID_FIELD_NUMBER: builtins.int seq: builtins.int """Lang's incremental sequence number, used as the operation identifier""" @property def workflow_execution( self, ) -> temporalio.bridge.proto.common.common_pb2.NamespacedWorkflowExecution: - """A specific workflow instance""" - child_workflow_id: builtins.str - """The desired target must be a child of the issuing workflow, and this is its workflow id""" + """The workflow instance being targeted""" def __init__( self, *, seq: builtins.int = ..., workflow_execution: temporalio.bridge.proto.common.common_pb2.NamespacedWorkflowExecution | None = ..., - child_workflow_id: builtins.str = ..., ) -> None: ... def HasField( self, field_name: typing_extensions.Literal[ - "child_workflow_id", - b"child_workflow_id", - "target", - b"target", - "workflow_execution", - b"workflow_execution", + "workflow_execution", b"workflow_execution" ], ) -> builtins.bool: ... def ClearField( self, field_name: typing_extensions.Literal[ - "child_workflow_id", - b"child_workflow_id", - "seq", - b"seq", - "target", - b"target", - "workflow_execution", - b"workflow_execution", + "seq", b"seq", "workflow_execution", b"workflow_execution" ], ) -> None: ... - def WhichOneof( - self, oneof_group: typing_extensions.Literal["target", b"target"] - ) -> ( - typing_extensions.Literal["workflow_execution", "child_workflow_id"] | None - ): ... global___RequestCancelExternalWorkflowExecution = RequestCancelExternalWorkflowExecution diff --git a/temporalio/bridge/sdk-core b/temporalio/bridge/sdk-core index 9879b552e..75800f1c3 160000 --- a/temporalio/bridge/sdk-core +++ b/temporalio/bridge/sdk-core @@ -1 +1 @@ -Subproject commit 9879b552e4acda73236a3593d91b7ccc052c5c36 +Subproject commit 75800f1c399b1d2b1e86b4cfd6fa81f913a085b6 diff --git a/temporalio/client.py b/temporalio/client.py index e9ecefe62..765c00714 100644 --- a/temporalio/client.py +++ b/temporalio/client.py @@ -26,6 +26,7 @@ Mapping, Optional, Sequence, + Tuple, Type, Union, cast, @@ -43,6 +44,7 @@ import temporalio.api.failure.v1 import temporalio.api.history.v1 import temporalio.api.schedule.v1 +import temporalio.api.sdk.v1 import temporalio.api.taskqueue.v1 import temporalio.api.update.v1 import temporalio.api.workflow.v1 @@ -308,6 +310,8 @@ async def start_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -339,6 +343,8 @@ async def start_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -372,6 +378,8 @@ async def start_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -405,6 +413,8 @@ async def start_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -436,6 +446,8 @@ async def start_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -470,6 +482,12 @@ async def start_workflow( search_attributes: Search attributes for the workflow. The dictionary form of this is deprecated, use :py:class:`temporalio.common.TypedSearchAttributes`. + static_summary: A single-line fixed summary for this workflow execution that may appear + in the UI/CLI. This can be in single-line Temporal markdown format. + static_details: General fixed details for this workflow execution that may appear in + UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is + a fixed value on the workflow that cannot be updated. For details that can be + updated, use `Workflow.CurrentDetails` within the workflow. start_delay: Amount of time to wait before starting the workflow. This does not work with ``cron_schedule``. start_signal: If present, this signal is sent as signal-with-start @@ -526,6 +544,8 @@ async def start_workflow( search_attributes=search_attributes, start_delay=start_delay, headers={}, + static_summary=static_summary, + static_details=static_details, start_signal=start_signal, start_signal_args=start_signal_args, ret_type=result_type, @@ -557,6 +577,8 @@ async def execute_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -588,6 +610,8 @@ async def execute_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -621,6 +645,8 @@ async def execute_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -654,6 +680,8 @@ async def execute_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -685,6 +713,8 @@ async def execute_workflow( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, start_delay: Optional[timedelta] = None, start_signal: Optional[str] = None, start_signal_args: Sequence[Any] = [], @@ -716,6 +746,8 @@ async def execute_workflow( cron_schedule=cron_schedule, memo=memo, search_attributes=search_attributes, + static_summary=static_summary, + static_details=static_details, start_delay=start_delay, start_signal=start_signal, start_signal_args=start_signal_args, @@ -923,6 +955,8 @@ async def create_schedule( temporalio.common.SearchAttributes, ] ] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, rpc_metadata: Mapping[str, str] = {}, rpc_timeout: Optional[timedelta] = None, ) -> ScheduleHandle: @@ -941,6 +975,12 @@ async def create_schedule( attributes for a scheduled workflow are part of the scheduled action. The dictionary form of this is DEPRECATED, use :py:class:`temporalio.common.TypedSearchAttributes`. + static_summary: A single-line fixed summary for this workflow execution that may appear + in the UI/CLI. This can be in single-line Temporal markdown format. + static_details: General fixed details for this workflow execution that may appear in + UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is + a fixed value on the workflow that cannot be updated. For details that can be + updated, use `Workflow.CurrentDetails` within the workflow. rpc_metadata: Headers used on the RPC call. Keys here override client-level RPC metadata keys. rpc_timeout: Optional RPC deadline to set for the RPC call. @@ -2373,16 +2413,27 @@ class WorkflowExecutionDescription(WorkflowExecution): raw_description: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse """Underlying protobuf description.""" + static_summary: Optional[str] + """Gets the single-line fixed summary for this workflow execution that may appear in + UI/CLI. This can be in single-line Temporal markdown format.""" + static_details: Optional[str] + """Gets the general fixed details for this workflow execution that may appear in UI/CLI. + This can be in Temporal markdown format and can span multiple lines.""" @staticmethod - def _from_raw_description( + async def _from_raw_description( description: temporalio.api.workflowservice.v1.DescribeWorkflowExecutionResponse, converter: temporalio.converter.DataConverter, ) -> WorkflowExecutionDescription: + (summ, deets) = await _decode_user_metadata( + converter, description.execution_config.user_metadata + ) return WorkflowExecutionDescription._from_raw_info( # type: ignore description.workflow_execution_info, converter, raw_description=description, + static_summary=summ, + static_details=deets, ) @@ -2421,7 +2472,7 @@ class WorkflowExecutionCount: count: int """Approximate number of workflows matching the original query. - + If the query had a group-by clause, this is simply the sum of all the counts in py:attr:`groups`. """ @@ -2985,7 +3036,7 @@ class ScheduleSpec: cron_expressions: Sequence[str] = dataclasses.field(default_factory=list) """Cron-based specification of times. - + This is provided for easy migration from legacy string-based cron scheduling. New uses should use :py:attr:`calendars` instead. These expressions will be translated to calendar-based specifications on the @@ -3067,7 +3118,7 @@ class ScheduleRange: end: int = 0 """Inclusive end of the range. - + If unset or less than start, defaults to start. """ @@ -3244,6 +3295,8 @@ class ScheduleActionStartWorkflow(ScheduleAction): """This is deprecated and is only present in case existing untyped attributes already exist for update. This should never be used when creating.""" + static_summary: Optional[Union[str, temporalio.api.common.v1.Payload]] + static_details: Optional[Union[str, temporalio.api.common.v1.Payload]] headers: Optional[Mapping[str, temporalio.api.common.v1.Payload]] @@ -3267,6 +3320,8 @@ def __init__( retry_policy: Optional[temporalio.common.RetryPolicy] = None, memo: Optional[Mapping[str, Any]] = None, typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> None: ... # Overload for single-param workflow @@ -3284,6 +3339,8 @@ def __init__( retry_policy: Optional[temporalio.common.RetryPolicy] = None, memo: Optional[Mapping[str, Any]] = None, typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> None: ... # Overload for multi-param workflow @@ -3303,6 +3360,8 @@ def __init__( retry_policy: Optional[temporalio.common.RetryPolicy] = None, memo: Optional[Mapping[str, Any]] = None, typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> None: ... # Overload for string-name workflow @@ -3321,6 +3380,8 @@ def __init__( retry_policy: Optional[temporalio.common.RetryPolicy] = None, memo: Optional[Mapping[str, Any]] = None, typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> None: ... # Overload for raw info @@ -3347,6 +3408,8 @@ def __init__( memo: Optional[Mapping[str, Any]] = None, typed_search_attributes: temporalio.common.TypedSearchAttributes = temporalio.common.TypedSearchAttributes.empty, untyped_search_attributes: temporalio.common.SearchAttributes = {}, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, headers: Optional[Mapping[str, temporalio.api.common.v1.Payload]] = None, raw_info: Optional[temporalio.api.workflow.v1.NewWorkflowExecutionInfo] = None, ) -> None: @@ -3400,6 +3463,16 @@ def __init__( if pair.key.name in self.untyped_search_attributes: # We know this is mutable here del self.untyped_search_attributes[pair.key.name] # type: ignore + self.static_summary = ( + raw_info.user_metadata.summary + if raw_info.HasField("user_metadata") and raw_info.user_metadata.summary + else None + ) + self.static_details = ( + raw_info.user_metadata.details + if raw_info.HasField("user_metadata") and raw_info.user_metadata.details + else None + ) else: if not id: raise ValueError("ID required") @@ -3425,6 +3498,8 @@ def __init__( self.typed_search_attributes = typed_search_attributes self.untyped_search_attributes = untyped_search_attributes self.headers = headers + self.static_summary = static_summary + self.static_details = static_details async def _to_proto( self, client: Client @@ -3474,6 +3549,9 @@ async def _to_proto( for k, v in self.memo.items() }, ), + user_metadata=await _encode_user_metadata( + client.data_converter, self.static_summary, self.static_details + ), ), ) # Add any untyped attributes that are not also in the typed set @@ -3506,7 +3584,7 @@ class ScheduleOverlapPolicy(IntEnum): temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_SKIP ) """Don't start anything. - + When the workflow completes, the next scheduled event after that time will be considered. """ @@ -3516,7 +3594,7 @@ class ScheduleOverlapPolicy(IntEnum): ) """Start the workflow again soon as the current one completes, but only buffer one start in this way. - + If another start is supposed to happen when the workflow is running, and one is already buffered, then only the first one will be started after the running workflow finishes. @@ -3544,7 +3622,7 @@ class ScheduleOverlapPolicy(IntEnum): temporalio.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL ) """Start any number of concurrent workflows. - + Note that with this policy, last completion result and last failure will not be available since workflows are not sequential.""" @@ -3557,7 +3635,7 @@ class ScheduleBackfill: start_at: datetime """Start of the range to evaluate the schedule in. - + This is exclusive """ end_at: datetime @@ -3596,7 +3674,7 @@ class SchedulePolicy: pause_on_failure: bool = False """Whether to pause the schedule if an action fails or times out. - + Note: For workflows, this only applies after all retries have been exhausted. """ @@ -3627,7 +3705,7 @@ class ScheduleState: note: Optional[str] = None """Human readable message for the schedule. - + The system may overwrite this value on certain conditions like pause-on-failure. """ @@ -3646,7 +3724,7 @@ class ScheduleState: remaining_actions: int = 0 """Actions remaining on this schedule. - + Once this number hits 0, no further actions are scheduled automatically. """ @@ -3722,7 +3800,7 @@ class ScheduleDescription: search_attributes: temporalio.common.SearchAttributes """Search attributes on the schedule. - + .. deprecated:: Use :py:attr:`typed_search_attributes` instead. """ @@ -3948,14 +4026,14 @@ class ScheduleListDescription: schedule: Optional[ScheduleListSchedule] """Schedule details that can be mutated. - + This may not be present in older Temporal servers without advanced visibility. """ info: Optional[ScheduleListInfo] """Information about the schedule. - + This may not be present in older Temporal servers without advanced visibility. """ @@ -3965,7 +4043,7 @@ class ScheduleListDescription: search_attributes: temporalio.common.SearchAttributes """Search attributes on the schedule. - + .. deprecated:: Use :py:attr:`typed_search_attributes` instead. """ @@ -4111,14 +4189,14 @@ class ScheduleListInfo: recent_actions: Sequence[ScheduleActionResult] """Most recent actions, oldest first. - + This may be a smaller amount than present on :py:attr:`ScheduleDescription.info`. """ next_action_times: Sequence[datetime] """Next scheduled action times. - + This may be a smaller amount than present on :py:attr:`ScheduleDescription.info`. """ @@ -4144,7 +4222,7 @@ class ScheduleListState: note: Optional[str] """Human readable message for the schedule. - + The system may overwrite this value on certain conditions like pause-on-failure. """ @@ -4536,6 +4614,8 @@ class StartWorkflowInput: headers: Mapping[str, temporalio.api.common.v1.Payload] start_signal: Optional[str] start_signal_args: Sequence[Any] + static_summary: Optional[str] + static_details: Optional[str] # Type may be absent ret_type: Optional[Type] rpc_metadata: Mapping[str, str] @@ -5063,6 +5143,11 @@ async def start_workflow( temporalio.converter.encode_search_attributes( input.search_attributes, req.search_attributes ) + metadata = await _encode_user_metadata( + self._client.data_converter, input.static_summary, input.static_details + ) + if metadata is not None: + req.user_metadata.CopyFrom(metadata) if input.start_delay is not None: req.workflow_start_delay.FromTimedelta(input.start_delay) if input.headers is not None: @@ -5135,7 +5220,7 @@ async def cancel_workflow(self, input: CancelWorkflowInput) -> None: async def describe_workflow( self, input: DescribeWorkflowInput ) -> WorkflowExecutionDescription: - return WorkflowExecutionDescription._from_raw_description( + return await WorkflowExecutionDescription._from_raw_description( await self._client.workflow_service.describe_workflow_execution( temporalio.api.workflowservice.v1.DescribeWorkflowExecutionRequest( namespace=self._client.namespace, @@ -5955,7 +6040,7 @@ class BuildIdOpAddNewCompatible(BuildIdOp): """The Build Id to add to the compatible set.""" existing_compatible_build_id: str - """A Build Id which must already be defined on the task queue, and is used to find the + """A Build Id which must already be defined on the task queue, and is used to find the compatible set to add the new id to. """ @@ -5982,7 +6067,7 @@ class BuildIdOpPromoteSetByBuildId(BuildIdOp): """ build_id: str - """A Build Id which must already be defined on the task queue, and is used to find the + """A Build Id which must already be defined on the task queue, and is used to find the compatible set to promote.""" def _as_partial_proto( @@ -6077,7 +6162,7 @@ class BuildIdReachability: """ unretrieved_task_queues: FrozenSet[str] - """If any Task Queues could not be retrieved because the server limits the number that can be + """If any Task Queues could not be retrieved because the server limits the number that can be queried at once, they will be listed here. """ @@ -6290,3 +6375,42 @@ def api_key(self, value: Optional[str]) -> None: # Update config and perform update self.service_client.config.api_key = value self.service_client.update_api_key(value) + + +async def _encode_user_metadata( + converter: temporalio.converter.DataConverter, + summary: Optional[Union[str, temporalio.api.common.v1.Payload]], + details: Optional[Union[str, temporalio.api.common.v1.Payload]], +) -> Optional[temporalio.api.sdk.v1.UserMetadata]: + if summary is None and details is None: + return None + enc_summary = None + enc_details = None + if summary is not None: + if isinstance(summary, str): + enc_summary = (await converter.encode([summary]))[0] + else: + enc_summary = summary + if details is not None: + if isinstance(details, str): + enc_details = (await converter.encode([details]))[0] + else: + enc_details = details + return temporalio.api.sdk.v1.UserMetadata(summary=enc_summary, details=enc_details) + + +async def _decode_user_metadata( + converter: temporalio.converter.DataConverter, + metadata: Optional[temporalio.api.sdk.v1.UserMetadata], +) -> Tuple[Optional[str], Optional[str]]: + """Returns (summary, details)""" + if metadata is None: + return None, None + return ( + None + if not metadata.HasField("summary") + else (await converter.decode([metadata.summary]))[0], + None + if not metadata.HasField("details") + else (await converter.decode([metadata.details]))[0], + ) diff --git a/temporalio/converter.py b/temporalio/converter.py index 24f9b6b47..61037dc3b 100644 --- a/temporalio/converter.py +++ b/temporalio/converter.py @@ -43,6 +43,7 @@ import temporalio.api.common.v1 import temporalio.api.enums.v1 import temporalio.api.failure.v1 +import temporalio.api.sdk.v1 import temporalio.common import temporalio.exceptions import temporalio.types @@ -1192,7 +1193,7 @@ def encode_typed_search_attribute_value( if isinstance(value, Sequence): for v in value: if not isinstance(v, str): - raise TypeError(f"All values of a keyword list must be strings") + raise TypeError("All values of a keyword list must be strings") # Convert value payload = default().payload_converter.to_payload(value) # Set metadata type @@ -1230,7 +1231,7 @@ def encode_search_attribute_values( ) elif val_type and type(v) is not val_type: raise TypeError( - f"Search attribute values must have the same type for the same key" + "Search attribute values must have the same type for the same key" ) elif not val_type: val_type = type(v) diff --git a/temporalio/worker/_interceptor.py b/temporalio/worker/_interceptor.py index ef0970de2..6606e5ec2 100644 --- a/temporalio/worker/_interceptor.py +++ b/temporalio/worker/_interceptor.py @@ -246,6 +246,7 @@ class StartActivityInput: headers: Mapping[str, temporalio.api.common.v1.Payload] disable_eager_execution: bool versioning_intent: Optional[VersioningIntent] + summary: Optional[str] # The types may be absent arg_types: Optional[List[Type]] ret_type: Optional[Type] @@ -275,6 +276,8 @@ class StartChildWorkflowInput: ] headers: Mapping[str, temporalio.api.common.v1.Payload] versioning_intent: Optional[VersioningIntent] + static_summary: Optional[str] + static_details: Optional[str] # The types may be absent arg_types: Optional[List[Type]] ret_type: Optional[Type] diff --git a/temporalio/worker/_workflow_instance.py b/temporalio/worker/_workflow_instance.py index c1748848c..8c59992bd 100644 --- a/temporalio/worker/_workflow_instance.py +++ b/temporalio/worker/_workflow_instance.py @@ -282,6 +282,16 @@ def __init__(self, det: WorkflowInstanceDetails) -> None: ret_type=temporalio.api.sdk.v1.EnhancedStackTrace, ) + self._queries["__temporal_workflow_metadata"] = ( + temporalio.workflow._QueryDefinition( + name="__temporal_workflow_metadata", + fn=self._temporal_workflow_metadata, + is_method=False, + arg_types=[], + ret_type=temporalio.api.sdk.v1.WorkflowMetadata, + ) + ) + # Maintain buffered signals for later-added dynamic handlers self._buffered_signals: Dict[ str, List[temporalio.bridge.proto.workflow_activation.SignalWorkflow] @@ -315,6 +325,10 @@ def __init__(self, det: WorkflowInstanceDetails) -> None: # For tracking the thread this workflow is running on (primarily for deadlock situations) self._current_thread_id: Optional[int] = None + # The current details (as opposed to static details on workflow start), returned in the + # metadata query + self._current_details = "" + def get_thread_id(self) -> Optional[int]: return self._current_thread_id @@ -1159,6 +1173,7 @@ def workflow_start_activity( cancellation_type: temporalio.workflow.ActivityCancellationType, activity_id: Optional[str], versioning_intent: Optional[temporalio.workflow.VersioningIntent], + summary: Optional[str] = None, ) -> temporalio.workflow.ActivityHandle[Any]: self._assert_not_read_only("start activity") # Get activity definition if it's callable @@ -1194,6 +1209,7 @@ def workflow_start_activity( arg_types=arg_types, ret_type=ret_type, versioning_intent=versioning_intent, + summary=summary, ) ) @@ -1220,6 +1236,8 @@ async def workflow_start_child_workflow( ] ], versioning_intent: Optional[temporalio.workflow.VersioningIntent], + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> temporalio.workflow.ChildWorkflowHandle[Any, Any]: # Use definition if callable name: str @@ -1257,6 +1275,8 @@ async def workflow_start_child_workflow( arg_types=arg_types, ret_type=ret_type, versioning_intent=versioning_intent, + static_summary=static_summary, + static_details=static_details, ) ) @@ -1415,13 +1435,55 @@ def workflow_upsert_search_attributes( else [update.value] ) + async def workflow_sleep( + self, duration: float, *, summary: Optional[str] = None + ) -> None: + user_metadata = ( + temporalio.api.sdk.v1.UserMetadata( + summary=self._payload_converter.to_payload(summary) + ) + if summary + else None + ) + fut = self.create_future() + self._timer_impl( + duration, + _TimerOptions(user_metadata=user_metadata), + lambda: fut.set_result(None), + ) + await fut + async def workflow_wait_condition( - self, fn: Callable[[], bool], *, timeout: Optional[float] = None + self, + fn: Callable[[], bool], + *, + timeout: Optional[float] = None, + timeout_summary: Optional[str] = None, ) -> None: self._assert_not_read_only("wait condition") fut = self.create_future() self._conditions.append((fn, fut)) - await asyncio.wait_for(fut, timeout) + user_metadata = ( + temporalio.api.sdk.v1.UserMetadata( + summary=self._payload_converter.to_payload(timeout_summary) + ) + if timeout_summary + else None + ) + ctxvars = contextvars.copy_context() + + async def in_context(): + _TimerOptionsCtxVar.set(_TimerOptions(user_metadata=user_metadata)) + await asyncio.wait_for(fut, timeout) + + await ctxvars.run(in_context) + + def workflow_get_current_details(self) -> str: + return self._current_details + + def workflow_set_current_details(self, details: str): + self._assert_not_read_only("set current details") + self._current_details = details #### Calls from outbound impl #### # These are in alphabetical order and all start with "_outbound_". @@ -1773,8 +1835,9 @@ def _run_once(self, *, check_conditions: bool) -> None: asyncio._set_running_loop(self) # We instantiate the workflow class _inside_ here because __init__ - # needs to run with this event loop set - if not self._object: + # needs to run with this event loop set. If we're deleting and + # we've never initialized, we don't need to bother. + if not self._object and not self._deleting: self._object = self._instantiate_workflow_object() # Run while there is anything ready @@ -1954,6 +2017,64 @@ def _enhanced_stack_trace(self) -> temporalio.api.sdk.v1.EnhancedStackTrace: ) return est + def _temporal_workflow_metadata(self) -> temporalio.api.sdk.v1.WorkflowMetadata: + query_definitions = [ + temporalio.api.sdk.v1.WorkflowInteractionDefinition( + name=qd.name or "", + description=qd.description or "", + ) + for qd in self._queries.values() + ] + query_definitions.sort(key=lambda qd: qd.name) + signal_definitions = [ + temporalio.api.sdk.v1.WorkflowInteractionDefinition( + name=sd.name or "", + description=sd.description or "", + ) + for sd in self._signals.values() + ] + signal_definitions.sort(key=lambda sd: sd.name) + update_definitions = [ + temporalio.api.sdk.v1.WorkflowInteractionDefinition( + name=ud.name or "", + description=ud.description or "", + ) + for ud in self._updates.values() + ] + update_definitions.sort(key=lambda ud: ud.name) + wf_def = temporalio.api.sdk.v1.WorkflowDefinition( + type=self._info.workflow_type, + query_definitions=query_definitions, + signal_definitions=signal_definitions, + update_definitions=update_definitions, + ) + cur_details = self.workflow_get_current_details() + return temporalio.api.sdk.v1.WorkflowMetadata( + definition=wf_def, current_details=cur_details + ) + + def _timer_impl( + self, + delay: float, + options: _TimerOptions, + callback: Callable[..., Any], + *args: Any, + context: Optional[contextvars.Context] = None, + ): + self._assert_not_read_only("schedule timer") + # Delay must be positive + if delay < 0: + raise RuntimeError("Attempting to schedule timer with negative delay") + + # Create, schedule, and return + seq = self._next_seq("timer") + handle = _TimerHandle( + seq, self.time() + delay, options, callback, args, self, context + ) + handle._apply_start_command(self._add_command(), delay) + self._pending_timers[seq] = handle + return handle + #### asyncio.AbstractEventLoop function impls #### # These are in the order defined in CPython's impl of the base class. Many # functions are intentionally not implemented/supported. @@ -1985,17 +2106,8 @@ def call_later( *args: Any, context: Optional[contextvars.Context] = None, ) -> asyncio.TimerHandle: - self._assert_not_read_only("schedule timer") - # Delay must be positive - if delay < 0: - raise RuntimeError("Attempting to schedule timer with negative delay") - - # Create, schedule, and return - seq = self._next_seq("timer") - handle = _TimerHandle(seq, self.time() + delay, callback, args, self, context) - handle._apply_start_command(self._add_command(), delay) - self._pending_timers[seq] = handle - return handle + options = _TimerOptionsCtxVar.get() + return self._timer_impl(delay, options, callback, *args, context=context) def call_at( self, @@ -2217,11 +2329,22 @@ def start_local_activity( return self._instance._outbound_schedule_activity(input) +@dataclass(frozen=True) +class _TimerOptions: + user_metadata: Optional[temporalio.api.sdk.v1.UserMetadata] = None + + +_TimerOptionsCtxVar: contextvars.ContextVar[_TimerOptions] = contextvars.ContextVar( + "__temporal_timer_options", default=_TimerOptions() +) + + class _TimerHandle(asyncio.TimerHandle): def __init__( self, seq: int, when: float, + options: Optional[_TimerOptions], callback: Callable[..., Any], args: Sequence[Any], loop: asyncio.AbstractEventLoop, @@ -2229,6 +2352,7 @@ def __init__( ) -> None: super().__init__(when, callback, args, loop, context) self._seq = seq + self._options = options def _apply_start_command( self, @@ -2236,6 +2360,8 @@ def _apply_start_command( delay: float, ) -> None: command.start_timer.seq = self._seq + if self._options and self._options.user_metadata: + command.user_metadata.CopyFrom(self._options.user_metadata) command.start_timer.start_to_fire_timeout.FromNanoseconds(int(delay * 1e9)) def _apply_cancel_command( @@ -2369,6 +2495,10 @@ def _apply_schedule_command( command.schedule_activity.versioning_intent = ( self._input.versioning_intent._to_proto() ) + if self._input.summary: + command.user_metadata.summary.CopyFrom( + self._instance._payload_converter.to_payload(self._input.summary) + ) if isinstance(self._input, StartLocalActivityInput): if self._input.local_retry_threshold: command.schedule_local_activity.local_retry_threshold.FromTimedelta( @@ -2379,8 +2509,6 @@ def _apply_schedule_command( command.schedule_local_activity.original_schedule_time.CopyFrom( local_backoff.original_schedule_time ) - # TODO(cretz): Remove when https://github.com/temporalio/sdk-core/issues/316 fixed - command.schedule_local_activity.retry_policy.SetInParent() def _apply_cancel_command( self, @@ -2506,6 +2634,14 @@ def _apply_start_command(self) -> None: ) if self._input.versioning_intent: v.versioning_intent = self._input.versioning_intent._to_proto() + if self._input.static_summary: + command.user_metadata.summary.CopyFrom( + self._instance._payload_converter.to_payload(self._input.static_summary) + ) + if self._input.static_details: + command.user_metadata.details.CopyFrom( + self._instance._payload_converter.to_payload(self._input.static_details) + ) # If request cancel external, result does _not_ have seq def _apply_cancel_command( diff --git a/temporalio/workflow.py b/temporalio/workflow.py index 521d3c10e..dd52d49f9 100644 --- a/temporalio/workflow.py +++ b/temporalio/workflow.py @@ -224,6 +224,7 @@ def signal( def signal( *, unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ) -> Callable[ [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType ]: ... @@ -234,6 +235,7 @@ def signal( *, name: str, unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ) -> Callable[ [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType ]: ... @@ -244,6 +246,7 @@ def signal( *, dynamic: Literal[True], unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ) -> Callable[ [CallableSyncOrAsyncReturnNoneType], CallableSyncOrAsyncReturnNoneType ]: ... @@ -255,6 +258,7 @@ def signal( name: Optional[str] = None, dynamic: Optional[bool] = False, unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ): """Decorator for a workflow signal method. @@ -277,6 +281,7 @@ def signal( present. unfinished_policy: Actions taken if a workflow terminates with a running instance of this handler. + description: A short description of the signal that may appear in the UI/CLI. """ def decorator( @@ -291,6 +296,7 @@ def decorator( fn=fn, is_method=True, unfinished_policy=unfinished_policy, + description=description, ) setattr(fn, "__temporal_signal_definition", defn) if defn.dynamic_vararg: @@ -314,11 +320,19 @@ def query(fn: CallableType) -> CallableType: ... @overload -def query(*, name: str) -> Callable[[CallableType], CallableType]: ... +def query( + *, name: str, description: Optional[str] = None +) -> Callable[[CallableType], CallableType]: ... + + +@overload +def query( + *, dynamic: Literal[True], description: Optional[str] = None +) -> Callable[[CallableType], CallableType]: ... @overload -def query(*, dynamic: Literal[True]) -> Callable[[CallableType], CallableType]: ... +def query(*, description: str) -> Callable[[CallableType], CallableType]: ... def query( @@ -326,6 +340,7 @@ def query( *, name: Optional[str] = None, dynamic: Optional[bool] = False, + description: Optional[str] = None, ): """Decorator for a workflow query method. @@ -346,18 +361,27 @@ def query( ``Sequence[RawValue]``. An older form of this accepted vararg parameters which will now warn. Cannot be present when ``name`` is present. + description: A short description of the query that may appear in the UI/CLI. """ - def with_name( - name: Optional[str], fn: CallableType, *, bypass_async_check: bool = False + def decorator( + name: Optional[str], + description: Optional[str], + fn: CallableType, + *, + bypass_async_check: bool = False, ) -> CallableType: + if not name and not dynamic: + name = fn.__name__ if not bypass_async_check and inspect.iscoroutinefunction(fn): warnings.warn( "Queries as async def functions are deprecated", DeprecationWarning, stacklevel=2, ) - defn = _QueryDefinition(name=name, fn=fn, is_method=True) + defn = _QueryDefinition( + name=name, fn=fn, is_method=True, description=description + ) setattr(fn, "__temporal_query_definition", defn) if defn.dynamic_vararg: warnings.warn( @@ -367,10 +391,10 @@ def with_name( ) return fn - if name is not None or dynamic: + if name is not None or dynamic or description: if name is not None and dynamic: raise RuntimeError("Cannot provide name and dynamic boolean") - return partial(with_name, name) + return partial(decorator, name, description) if fn is None: raise RuntimeError("Cannot create query without function or name or dynamic") if inspect.iscoroutinefunction(fn): @@ -379,7 +403,7 @@ def with_name( DeprecationWarning, stacklevel=2, ) - return with_name(fn.__name__, fn, bypass_async_check=True) + return decorator(fn.__name__, description, fn, bypass_async_check=True) @dataclass(frozen=True) @@ -659,6 +683,7 @@ def workflow_start_activity( cancellation_type: ActivityCancellationType, activity_id: Optional[str], versioning_intent: Optional[VersioningIntent], + summary: Optional[str] = None, ) -> ActivityHandle[Any]: ... @abstractmethod @@ -685,6 +710,8 @@ async def workflow_start_child_workflow( ] ], versioning_intent: Optional[VersioningIntent], + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> ChildWorkflowHandle[Any, Any]: ... @abstractmethod @@ -714,11 +741,26 @@ def workflow_upsert_search_attributes( ], ) -> None: ... + @abstractmethod + async def workflow_sleep( + self, duration: float, *, summary: Optional[str] = None + ) -> None: ... + @abstractmethod async def workflow_wait_condition( - self, fn: Callable[[], bool], *, timeout: Optional[float] = None + self, + fn: Callable[[], bool], + *, + timeout: Optional[float] = None, + timeout_summary: Optional[str] = None, ) -> None: ... + @abstractmethod + def workflow_get_current_details(self) -> str: ... + + @abstractmethod + def workflow_set_current_details(self, details: str): ... + _current_update_info: contextvars.ContextVar[UpdateInfo] = contextvars.ContextVar( "__temporal_current_update_info" @@ -830,6 +872,24 @@ def memo_value( return _Runtime.current().workflow_memo_value(key, default, type_hint=type_hint) +def get_current_details() -> str: + """Get the current details of the workflow which may appear in the UI/CLI. + Unlike static details set at start, this value can be updated throughout + the life of the workflow and is independent of the static details. + This can be in Temporal markdown format and can span multiple lines. + """ + return _Runtime.current().workflow_get_current_details() + + +def set_current_details(description: str) -> None: + """Set the current details of the workflow which may appear in the UI/CLI. + Unlike static details set at start, this value can be updated throughout + the life of the workflow and is independent of the static details. + This can be in Temporal markdown format and can span multiple lines. + """ + _Runtime.current().workflow_set_current_details(description) + + def metric_meter() -> temporalio.common.MetricMeter: """Get the metric meter for the current workflow. @@ -976,6 +1036,7 @@ def update( def update( *, unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ) -> Callable[ [Callable[MultiParamSpec, ReturnType]], UpdateMethodMultiParam[MultiParamSpec, ReturnType], @@ -987,6 +1048,7 @@ def update( *, name: str, unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ) -> Callable[ [Callable[MultiParamSpec, ReturnType]], UpdateMethodMultiParam[MultiParamSpec, ReturnType], @@ -998,6 +1060,7 @@ def update( *, dynamic: Literal[True], unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ) -> Callable[ [Callable[MultiParamSpec, ReturnType]], UpdateMethodMultiParam[MultiParamSpec, ReturnType], @@ -1010,6 +1073,7 @@ def update( name: Optional[str] = None, dynamic: Optional[bool] = False, unfinished_policy: HandlerUnfinishedPolicy = HandlerUnfinishedPolicy.WARN_AND_ABANDON, + description: Optional[str] = None, ): """Decorator for a workflow update handler method. @@ -1039,6 +1103,7 @@ def update( present. unfinished_policy: Actions taken if a workflow terminates with a running instance of this handler. + description: A short description of the update that may appear in the UI/CLI. """ def decorator( @@ -1053,6 +1118,7 @@ def decorator( fn=fn, is_method=True, unfinished_policy=unfinished_policy, + description=description, ) if defn.dynamic_vararg: raise RuntimeError( @@ -1091,8 +1157,29 @@ def uuid4() -> uuid.UUID: return uuid.UUID(bytes=random().getrandbits(16 * 8).to_bytes(16, "big"), version=4) +async def sleep( + duration: Union[float, timedelta], *, summary: Optional[str] = None +) -> None: + """Sleep for the given duration. + + Args: + duration: Duration to sleep in seconds or as a timedelta. + summary: A single-line fixed summary for this timer that may appear in UI/CLI. + This can be in single-line Temporal markdown format. + """ + await _Runtime.current().workflow_sleep( + duration=duration.total_seconds() + if isinstance(duration, timedelta) + else duration, + summary=summary, + ) + + async def wait_condition( - fn: Callable[[], bool], *, timeout: Optional[Union[timedelta, float]] = None + fn: Callable[[], bool], + *, + timeout: Optional[Union[timedelta, float]] = None, + timeout_summary: Optional[str] = None, ) -> None: """Wait on a callback to become true. @@ -1103,10 +1190,14 @@ async def wait_condition( fn: Non-async callback that accepts no parameters and returns a boolean. timeout: Optional number of seconds to wait until throwing :py:class:`asyncio.TimeoutError`. + timeout_summary: Optional simple string identifying the timer (created if `timeout` is + present) that may be visible in UI/CLI. While it can be normal text, it is best to treat + as a timer ID. """ await _Runtime.current().workflow_wait_condition( fn, timeout=timeout.total_seconds() if isinstance(timeout, timedelta) else timeout, + timeout_summary=timeout_summary, ) @@ -1559,6 +1650,7 @@ class _SignalDefinition: unfinished_policy: HandlerUnfinishedPolicy = ( HandlerUnfinishedPolicy.WARN_AND_ABANDON ) + description: Optional[str] = None # Types loaded on post init if None arg_types: Optional[List[Type]] = None dynamic_vararg: bool = False @@ -1606,6 +1698,7 @@ class _QueryDefinition: name: Optional[str] fn: Callable[..., Any] is_method: bool + description: Optional[str] = None # Types loaded on post init if both are None arg_types: Optional[List[Type]] = None ret_type: Optional[Type] = None @@ -1643,6 +1736,7 @@ class _UpdateDefinition: unfinished_policy: HandlerUnfinishedPolicy = ( HandlerUnfinishedPolicy.WARN_AND_ABANDON ) + description: Optional[str] = None # Types loaded on post init if None arg_types: Optional[List[Type]] = None ret_type: Optional[Type] = None @@ -1869,6 +1963,7 @@ def start_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[Any]: """Start an activity and return its handle. @@ -1902,6 +1997,8 @@ def start_activity( need to. Contact Temporal before setting this value. versioning_intent: When using the Worker Versioning feature, specifies whether this Activity should run on a worker with a compatible Build Id or not. + summary: A single-line fixed summary for this activity that may appear in UI/CLI. + This can be in single-line Temporal markdown format. Returns: An activity handle to the activity which is an async task. @@ -1919,6 +2016,7 @@ def start_activity( cancellation_type=cancellation_type, activity_id=activity_id, versioning_intent=versioning_intent, + summary=summary, ) @@ -1936,6 +2034,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -1953,6 +2052,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -1971,6 +2071,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -1989,6 +2090,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2007,6 +2109,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2025,6 +2128,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2045,6 +2149,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> Any: ... @@ -2063,6 +2168,7 @@ async def execute_activity( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> Any: """Start an activity and wait for completion. @@ -2083,6 +2189,7 @@ async def execute_activity( cancellation_type=cancellation_type, activity_id=activity_id, versioning_intent=versioning_intent, + summary=summary, ) @@ -2100,6 +2207,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2117,6 +2225,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2135,6 +2244,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2153,6 +2263,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2171,6 +2282,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2189,6 +2301,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2206,6 +2319,7 @@ def start_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[Any]: """Start an activity from a callable class. @@ -2224,6 +2338,7 @@ def start_activity_class( cancellation_type=cancellation_type, activity_id=activity_id, versioning_intent=versioning_intent, + summary=summary, ) @@ -2241,6 +2356,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2258,6 +2374,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2276,6 +2393,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2294,6 +2412,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2312,6 +2431,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2330,6 +2450,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2347,6 +2468,7 @@ async def execute_activity_class( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> Any: """Start an activity from a callable class and wait for completion. @@ -2365,6 +2487,7 @@ async def execute_activity_class( cancellation_type=cancellation_type, activity_id=activity_id, versioning_intent=versioning_intent, + summary=summary, ) @@ -2382,6 +2505,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2399,6 +2523,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2417,6 +2542,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2435,6 +2561,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2453,6 +2580,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2471,6 +2599,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[ReturnType]: ... @@ -2488,6 +2617,7 @@ def start_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ActivityHandle[Any]: """Start an activity from a method. @@ -2506,6 +2636,7 @@ def start_activity_method( cancellation_type=cancellation_type, activity_id=activity_id, versioning_intent=versioning_intent, + summary=summary, ) @@ -2523,6 +2654,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2540,6 +2672,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2558,6 +2691,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2576,6 +2710,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2594,6 +2729,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2612,6 +2748,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -2629,6 +2766,7 @@ async def execute_activity_method( cancellation_type: ActivityCancellationType = ActivityCancellationType.TRY_CANCEL, activity_id: Optional[str] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> Any: """Start an activity from a method and wait for completion. @@ -2649,6 +2787,7 @@ async def execute_activity_method( cancellation_type=cancellation_type, activity_id=activity_id, versioning_intent=versioning_intent, + summary=summary, ) @@ -3651,6 +3790,8 @@ async def start_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> ChildWorkflowHandle[SelfType, ReturnType]: ... @@ -3677,6 +3818,8 @@ async def start_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> ChildWorkflowHandle[SelfType, ReturnType]: ... @@ -3703,6 +3846,8 @@ async def start_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> ChildWorkflowHandle[SelfType, ReturnType]: ... @@ -3731,6 +3876,8 @@ async def start_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> ChildWorkflowHandle[Any, Any]: ... @@ -3757,6 +3904,8 @@ async def start_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + static_summary: Optional[str] = None, + static_details: Optional[str] = None, ) -> ChildWorkflowHandle[Any, Any]: """Start a child workflow and return its handle. @@ -3786,6 +3935,12 @@ async def start_child_workflow( form of this is DEPRECATED. versioning_intent: When using the Worker Versioning feature, specifies whether this Child Workflow should run on a worker with a compatible Build Id or not. + static_summary: A single-line fixed summary for this child workflow execution that may appear + in the UI/CLI. This can be in single-line Temporal markdown format. + static_details: General fixed details for this child workflow execution that may appear in + UI/CLI. This can be in Temporal markdown format and can span multiple lines. This is + a fixed value on the workflow that cannot be updated. For details that can be + updated, use `Workflow.CurrentDetails` within the workflow. Returns: A workflow handle to the started/existing workflow. @@ -3808,6 +3963,8 @@ async def start_child_workflow( memo=memo, search_attributes=search_attributes, versioning_intent=versioning_intent, + static_summary=static_summary, + static_details=static_details, ) @@ -3833,6 +3990,7 @@ async def execute_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -3859,6 +4017,7 @@ async def execute_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -3885,6 +4044,7 @@ async def execute_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> ReturnType: ... @@ -3913,6 +4073,7 @@ async def execute_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> Any: ... @@ -3939,6 +4100,7 @@ async def execute_child_workflow( ] ] = None, versioning_intent: Optional[VersioningIntent] = None, + summary: Optional[str] = None, ) -> Any: """Start a child workflow and wait for completion. @@ -3964,6 +4126,7 @@ async def execute_child_workflow( memo=memo, search_attributes=search_attributes, versioning_intent=versioning_intent, + static_summary=summary, ) return await handle diff --git a/tests/test_client.py b/tests/test_client.py index e1bc2448a..dc0128f38 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -792,6 +792,8 @@ async def test_schedule_basics( task_timeout=timedelta(hours=3), retry_policy=RetryPolicy(maximum_attempts=20), memo={"memokey1": "memoval1"}, + static_summary="summary", + static_details="details", ), spec=ScheduleSpec( calendars=[ @@ -862,6 +864,15 @@ async def test_schedule_basics( day_of_week=(ScheduleRange(1),), ) ) + # Summary & description are encoded + assert schedule.action.static_summary + assert schedule.action.static_details + schedule.action.static_summary = ( + await DataConverter.default.encode([schedule.action.static_summary]) + )[0] + schedule.action.static_details = ( + await DataConverter.default.encode([schedule.action.static_details]) + )[0] # Describe it and confirm desc = await handle.describe() diff --git a/tests/test_workflow.py b/tests/test_workflow.py index d4a5b45e1..1c3478a91 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -36,11 +36,11 @@ async def run(self, name: str) -> str: def signal1(self): pass - @workflow.signal(name="signal-custom") + @workflow.signal(name="signal-custom", description="fun") def signal2(self): pass - @workflow.signal(dynamic=True) + @workflow.signal(dynamic=True, description="boo") def signal3(self, name: str, args: Sequence[RawValue]): pass @@ -48,11 +48,11 @@ def signal3(self, name: str, args: Sequence[RawValue]): def query1(self): pass - @workflow.query(name="query-custom") + @workflow.query(name="query-custom", description="qd") def query2(self): pass - @workflow.query(dynamic=True) + @workflow.query(dynamic=True, description="dqd") def query3(self, name: str, args: Sequence[RawValue]): pass @@ -60,11 +60,11 @@ def query3(self, name: str, args: Sequence[RawValue]): def update1(self): pass - @workflow.update(name="update-custom") + @workflow.update(name="update-custom", description="ud") def update2(self): pass - @workflow.update(dynamic=True) + @workflow.update(dynamic=True, description="dud") def update3(self, name: str, args: Sequence[RawValue]): pass @@ -82,10 +82,13 @@ def test_workflow_defn_good(): name="signal1", fn=GoodDefn.signal1, is_method=True ), "signal-custom": workflow._SignalDefinition( - name="signal-custom", fn=GoodDefn.signal2, is_method=True + name="signal-custom", + fn=GoodDefn.signal2, + is_method=True, + description="fun", ), None: workflow._SignalDefinition( - name=None, fn=GoodDefn.signal3, is_method=True + name=None, fn=GoodDefn.signal3, is_method=True, description="boo" ), "base_signal": workflow._SignalDefinition( name="base_signal", fn=GoodDefnBase.base_signal, is_method=True @@ -96,10 +99,13 @@ def test_workflow_defn_good(): name="query1", fn=GoodDefn.query1, is_method=True ), "query-custom": workflow._QueryDefinition( - name="query-custom", fn=GoodDefn.query2, is_method=True + name="query-custom", + fn=GoodDefn.query2, + is_method=True, + description="qd", ), None: workflow._QueryDefinition( - name=None, fn=GoodDefn.query3, is_method=True + name=None, fn=GoodDefn.query3, is_method=True, description="dqd" ), "base_query": workflow._QueryDefinition( name="base_query", fn=GoodDefnBase.base_query, is_method=True @@ -110,10 +116,13 @@ def test_workflow_defn_good(): name="update1", fn=GoodDefn.update1, is_method=True ), "update-custom": workflow._UpdateDefinition( - name="update-custom", fn=GoodDefn.update2, is_method=True + name="update-custom", + fn=GoodDefn.update2, + is_method=True, + description="ud", ), None: workflow._UpdateDefinition( - name=None, fn=GoodDefn.update3, is_method=True + name=None, fn=GoodDefn.update3, is_method=True, description="dud" ), "base_update": workflow._UpdateDefinition( name="base_update", fn=GoodDefnBase.base_update, is_method=True diff --git a/tests/worker/test_workflow.py b/tests/worker/test_workflow.py index 91eb8c49e..2611ecd54 100644 --- a/tests/worker/test_workflow.py +++ b/tests/worker/test_workflow.py @@ -504,7 +504,7 @@ async def test_workflow_signal_and_query_errors(client: Client): await handle.query("non-existent query") assert str(rpc_err.value) == ( "Query handler for 'non-existent query' expected but not found," - " known queries: [__enhanced_stack_trace __stack_trace bad_query other_query]" + " known queries: [__enhanced_stack_trace __stack_trace __temporal_workflow_metadata bad_query other_query]" ) @@ -1552,12 +1552,12 @@ async def test_workflow_with_custom_runner(client: Client): task_queue=worker.task_queue, ) assert result == "Hello, Temporal!" - # Confirm first activation and last completion + # Confirm first activation and last non-eviction-reply completion assert ( runner._pairs[0][0].jobs[0].initialize_workflow.workflow_type == "HelloWorkflow" ) assert ( - runner._pairs[-1][-1] + runner._pairs[-2][-1] .successful.commands[0] .complete_workflow_execution.result.data == b'"Hello, Temporal!"' @@ -3018,7 +3018,9 @@ def __init__(self) -> None: async def run(self) -> None: # Force timeout, ignore, wait again try: - await workflow.wait_condition(lambda: self._done, timeout=0.01) + await workflow.wait_condition( + lambda: self._done, timeout=0.01, timeout_summary="hi!" + ) raise RuntimeError("Expected timeout") except asyncio.TimeoutError: pass @@ -6169,3 +6171,218 @@ async def test_workflow_run_sees_workflow_init(client: Client): task_queue=worker.task_queue, ) assert workflow_result == "hello, world" + + +@workflow.defn +class UserMetadataWorkflow: + def __init__(self) -> None: + self._done = False + self._waiting = False + + @workflow.run + async def run(self) -> None: + await workflow.execute_activity( + say_hello, + "Enchi", + start_to_close_timeout=timedelta(seconds=5), + summary="meow", + ) + # Force timeout, ignore, wait again + try: + await workflow.wait_condition( + lambda: self._done, timeout=0.01, timeout_summary="hi!" + ) + raise RuntimeError("Expected timeout") + except asyncio.TimeoutError: + pass + await workflow.sleep(0.01, summary="timer2") + self._waiting = True + workflow.set_current_details("such detail") + await workflow.wait_condition(lambda: self._done) + + @workflow.signal(description="sdesc") + def done(self) -> None: + self._done = True + + @workflow.query(description="qdesc") + def waiting(self) -> bool: + return self._waiting + + @workflow.update(description="udesc") + def some_update(self): + pass + + +async def test_user_metadata_is_set(client: Client, env: WorkflowEnvironment): + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2219" + ) + async with new_worker( + client, UserMetadataWorkflow, activities=[say_hello] + ) as worker: + handle = await client.start_workflow( + UserMetadataWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + static_summary="cool workflow bro", + static_details="xtremely detailed", + ) + + # Wait until it's waiting, then send the signal + async def waiting() -> bool: + return await handle.query(UserMetadataWorkflow.waiting) + + await assert_eq_eventually(True, waiting) + + md_query: temporalio.api.sdk.v1.WorkflowMetadata = await handle.query( + "__temporal_workflow_metadata", + result_type=temporalio.api.sdk.v1.WorkflowMetadata, + ) + matched_q = [ + q for q in md_query.definition.query_definitions if q.name == "waiting" + ] + assert len(matched_q) == 1 + assert matched_q[0].description == "qdesc" + + matched_u = [ + u for u in md_query.definition.update_definitions if u.name == "some_update" + ] + assert len(matched_u) == 1 + assert matched_u[0].description == "udesc" + + matched_s = [ + s for s in md_query.definition.signal_definitions if s.name == "done" + ] + assert len(matched_s) == 1 + assert matched_s[0].description == "sdesc" + + assert md_query.current_details == "such detail" + + await handle.signal(UserMetadataWorkflow.done) + await handle.result() + + # Ensure metadatas are present in history + resp = await client.workflow_service.get_workflow_execution_history( + GetWorkflowExecutionHistoryRequest( + namespace=client.namespace, + execution=WorkflowExecution(workflow_id=handle.id), + ) + ) + timer_summs = set() + for event in resp.history.events: + if event.event_type == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED: + assert "cool workflow bro" in PayloadConverter.default.from_payload( + event.user_metadata.summary + ) + assert "xtremely detailed" in PayloadConverter.default.from_payload( + event.user_metadata.details + ) + elif event.event_type == EventType.EVENT_TYPE_ACTIVITY_TASK_SCHEDULED: + assert "meow" in PayloadConverter.default.from_payload( + event.user_metadata.summary + ) + elif event.event_type == EventType.EVENT_TYPE_TIMER_STARTED: + timer_summs.add( + PayloadConverter.default.from_payload(event.user_metadata.summary) + ) + assert timer_summs == {"hi!", "timer2"} + + describe_r = await handle.describe() + assert describe_r.static_summary == "cool workflow bro" + assert describe_r.static_details == "xtremely detailed" + + +@workflow.defn +class WorkflowSleepWorkflow: + @workflow.run + async def run(self) -> None: + await workflow.sleep(1) + + +async def test_workflow_sleep(client: Client): + async with new_worker(client, WorkflowSleepWorkflow) as worker: + start_time = datetime.now() + await client.execute_workflow( + WorkflowSleepWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + assert (datetime.now() - start_time) >= timedelta(seconds=1) + + +@workflow.defn +class ConcurrentSleepsWorkflow: + @workflow.run + async def run(self) -> None: + sleeps_a = [workflow.sleep(0.1, summary=f"t{i}") for i in range(5)] + zero_a = workflow.sleep(0, summary="zero_timer") + wait_some = workflow.wait_condition( + lambda: False, timeout=0.1, timeout_summary="wait_some" + ) + zero_b = workflow.wait_condition( + lambda: False, timeout=0, timeout_summary="zero_wait" + ) + no_summ = workflow.sleep(0.1) + sleeps_b = [workflow.sleep(0.1, summary=f"t{i}") for i in range(5, 10)] + try: + await asyncio.gather( + *sleeps_a, + zero_a, + wait_some, + zero_b, + no_summ, + *sleeps_b, + return_exceptions=True, + ) + except asyncio.TimeoutError: + pass + + task_1 = asyncio.create_task(self.make_timers(100, 105)) + task_2 = asyncio.create_task(self.make_timers(105, 110)) + await asyncio.gather(task_1, task_2) + + async def make_timers(self, start: int, end: int): + await asyncio.gather( + *[workflow.sleep(0.1, summary=f"m_t{i}") for i in range(start, end)] + ) + + +async def test_concurrent_sleeps_use_proper_options( + client: Client, env: WorkflowEnvironment +): + if env.supports_time_skipping: + pytest.skip( + "Java test server: https://github.com/temporalio/sdk-java/issues/2219" + ) + async with new_worker(client, ConcurrentSleepsWorkflow) as worker: + handle = await client.start_workflow( + ConcurrentSleepsWorkflow.run, + id=f"workflow-{uuid.uuid4()}", + task_queue=worker.task_queue, + ) + await handle.result() + resp = await client.workflow_service.get_workflow_execution_history( + GetWorkflowExecutionHistoryRequest( + namespace=client.namespace, + execution=WorkflowExecution(workflow_id=handle.id), + ) + ) + timer_summaries = [ + PayloadConverter.default.from_payload(e.user_metadata.summary) + if e.user_metadata.HasField("summary") + else "" + for e in resp.history.events + if e.event_type == EventType.EVENT_TYPE_TIMER_STARTED + ] + assert timer_summaries == [ + *[f"t{i}" for i in range(5)], + "zero_timer", + "wait_some", + "", + *[f"t{i}" for i in range(5, 10)], + *[f"m_t{i}" for i in range(100, 110)], + ] + + # Force replay with a query to ensure determinism + await handle.query("__temporal_workflow_metadata")