diff --git a/.gitignore b/.gitignore index bcf839a4..e914321a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ dist tmp node_modules +.venv .idea .DS_Store diff --git a/.licenserc.yaml b/.licenserc.yaml index 12dc51b8..8226b4e2 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -9,7 +9,7 @@ header: - LICENSE - "**/.*" - "**/go.*" - - "**/*.{json,md,yml,yaml,txt}" + - "**/*.{json,md,yml,yaml,txt,lock,toml}" - "**/.gitkeep" comment: on-failure language: diff --git a/examples/README.md b/examples/README.md index 8710a493..9ccf9e9f 100644 --- a/examples/README.md +++ b/examples/README.md @@ -27,6 +27,7 @@ A collection of examples | [For loops](./for-loop) | An example of how to use the for loop task | | [Money Transfer Demo](./money-transfer) | Temporal's world-famous Money Transfer Demo, in Serverless Workflow form | | [Multiple Workflows](./multiple-workflows) | Configure multiple Temporal workflows | +| [Python](./python) | The basic example, but in Python | | [Listener Workflow (Query)](./query) | Listen for Temporal query events | | [Erroring Workflow](./raise) | Raise a bug | | [Serverless Workflow](./schedule) | Schedule the tasks to be triggered automatically | diff --git a/examples/python/README.md b/examples/python/README.md new file mode 100644 index 00000000..43f785ec --- /dev/null +++ b/examples/python/README.md @@ -0,0 +1,37 @@ +# Python + +The [basic example](../basic/), but in Python + + + +* [Getting started](#getting-started) +* [Running the worker](#running-the-worker) + + + + + +## Getting started + +```sh +uv sync +uv run python main.py +``` + +`uv sync` creates a local virtual environment (by default at `.venv/`) and +installs the dependencies declared in `pyproject.toml`. `uv run python main.py` +runs the script inside that environment, triggering the workflow with some +input data and printing everything to the console. + +## Running the worker + +```sh +uv run python worker.py +``` + +This launches a Temporal worker on the `python-child` task queue (override with +`PYTHON_CHILD_TASK_QUEUE`) with the `SayHelloWorkflow` child workflow and +`greet` activity defined in `workflows.py` and `activities.py`. The DSL +workflow defined in `workflow.yaml` invokes `say-hello-workflow` as a child +workflow on that queue, so leave this worker running while you start the parent +workflow. diff --git a/examples/python/activities.py b/examples/python/activities.py new file mode 100644 index 00000000..ac42644c --- /dev/null +++ b/examples/python/activities.py @@ -0,0 +1,26 @@ +# Copyright 2025 Temporal DSL authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Activities for the Python Temporal example.""" + +from __future__ import annotations + +from temporalio import activity + + +@activity.defn +async def greet(name: str) -> str: + """Return a greeting for the provided name.""" + return f"Hello {name}" diff --git a/examples/python/main.py b/examples/python/main.py new file mode 100644 index 00000000..d7b35aaa --- /dev/null +++ b/examples/python/main.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# Copyright 2025 Temporal DSL authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Trigger the Python basic example workflow defined in workflow.yaml.""" + +from __future__ import annotations + +import asyncio +import os +import sys +import uuid +from typing import Any, Dict + +from temporalio.client import Client + + +async def main() -> None: + address = os.getenv("TEMPORAL_ADDRESS", "localhost:7233") + namespace = os.getenv("TEMPORAL_NAMESPACE", "default") + api_key = os.getenv("TEMPORAL_API_KEY") + tls_enabled = os.getenv("TEMPORAL_TLS", "false").lower() == "true" + + connect_kwargs: Dict[str, Any] = {"namespace": namespace} + if tls_enabled: + # Passing True enables TLS using the platform defaults (e.g. system CAs). + connect_kwargs["tls"] = True + if api_key: + connect_kwargs["api_key"] = api_key + + client = await Client.connect(address, **connect_kwargs) + + handle = await client.start_workflow( + "basic-python", + {"userId": 3, "name": "Temporal DSL"}, + id=f"basic-{uuid.uuid4().hex}", + task_queue="temporal-dsl", + ) + + print(f"Started workflow: {handle.id}") + result = await handle.result() + print(result) + + +def _run() -> None: + try: + asyncio.run(main()) + except KeyboardInterrupt: + print("Cancelled", file=sys.stderr) + sys.exit(130) + except Exception as exc: # pragma: no cover - minimal CLI + print(exc, file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + _run() diff --git a/examples/python/pyproject.toml b/examples/python/pyproject.toml new file mode 100644 index 00000000..b5f6a2dd --- /dev/null +++ b/examples/python/pyproject.toml @@ -0,0 +1,12 @@ +[project] +name = "temporal-dsl-python-example" +version = "0.0.1" +description = "The basic Temporal DSL example, but in Python." +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "temporalio>=1.5.0,<2.0.0", +] + +[tool.uv] +package = false diff --git a/examples/python/uv.lock b/examples/python/uv.lock new file mode 100644 index 00000000..a098df1e --- /dev/null +++ b/examples/python/uv.lock @@ -0,0 +1,102 @@ +version = 1 +revision = 3 +requires-python = ">=3.9" + +[[package]] +name = "nexus-rpc" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/66/540687556bd28cf1ec370cc6881456203dfddb9dab047b8979c6865b5984/nexus_rpc-1.1.0.tar.gz", hash = "sha256:d65ad6a2f54f14e53ebe39ee30555eaeb894102437125733fb13034a04a44553", size = 77383, upload-time = "2025-07-07T19:03:58.368Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, +] + +[[package]] +name = "protobuf" +version = "6.33.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/ff/64a6c8f420818bb873713988ca5492cba3a7946be57e027ac63495157d97/protobuf-6.33.0.tar.gz", hash = "sha256:140303d5c8d2037730c548f8c7b93b20bb1dc301be280c378b82b8894589c954", size = 443463, upload-time = "2025-10-15T20:39:52.159Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/ee/52b3fa8feb6db4a833dfea4943e175ce645144532e8a90f72571ad85df4e/protobuf-6.33.0-cp310-abi3-win32.whl", hash = "sha256:d6101ded078042a8f17959eccd9236fb7a9ca20d3b0098bbcb91533a5680d035", size = 425593, upload-time = "2025-10-15T20:39:40.29Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c6/7a465f1825872c55e0341ff4a80198743f73b69ce5d43ab18043699d1d81/protobuf-6.33.0-cp310-abi3-win_amd64.whl", hash = "sha256:9a031d10f703f03768f2743a1c403af050b6ae1f3480e9c140f39c45f81b13ee", size = 436882, upload-time = "2025-10-15T20:39:42.841Z" }, + { url = "https://files.pythonhosted.org/packages/e1/a9/b6eee662a6951b9c3640e8e452ab3e09f117d99fc10baa32d1581a0d4099/protobuf-6.33.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:905b07a65f1a4b72412314082c7dbfae91a9e8b68a0cc1577515f8df58ecf455", size = 427521, upload-time = "2025-10-15T20:39:43.803Z" }, + { url = "https://files.pythonhosted.org/packages/10/35/16d31e0f92c6d2f0e77c2a3ba93185130ea13053dd16200a57434c882f2b/protobuf-6.33.0-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e0697ece353e6239b90ee43a9231318302ad8353c70e6e45499fa52396debf90", size = 324445, upload-time = "2025-10-15T20:39:44.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/eb/2a981a13e35cda8b75b5585aaffae2eb904f8f351bdd3870769692acbd8a/protobuf-6.33.0-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:e0a1715e4f27355afd9570f3ea369735afc853a6c3951a6afe1f80d8569ad298", size = 339159, upload-time = "2025-10-15T20:39:46.186Z" }, + { url = "https://files.pythonhosted.org/packages/21/51/0b1cbad62074439b867b4e04cc09b93f6699d78fd191bed2bbb44562e077/protobuf-6.33.0-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:35be49fd3f4fefa4e6e2aacc35e8b837d6703c37a2168a55ac21e9b1bc7559ef", size = 323172, upload-time = "2025-10-15T20:39:47.465Z" }, + { url = "https://files.pythonhosted.org/packages/57/33/fbe61bbe91a656619f107b9dfd84b16e1438766bd62157b8d1c1214491fd/protobuf-6.33.0-cp39-cp39-win32.whl", hash = "sha256:cd33a8e38ea3e39df66e1bbc462b076d6e5ba3a4ebbde58219d777223a7873d3", size = 425690, upload-time = "2025-10-15T20:39:48.909Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e4/ccc4814ad9d12fa404f7e5ce1983a2403644b0ed2588678c762b7a26ed92/protobuf-6.33.0-cp39-cp39-win_amd64.whl", hash = "sha256:c963e86c3655af3a917962c9619e1a6b9670540351d7af9439d06064e3317cc9", size = 436876, upload-time = "2025-10-15T20:39:50.009Z" }, + { url = "https://files.pythonhosted.org/packages/07/d1/0a28c21707807c6aacd5dc9c3704b2aa1effbf37adebd8caeaf68b17a636/protobuf-6.33.0-py3-none-any.whl", hash = "sha256:25c9e1963c6734448ea2d308cfa610e692b801304ba0908d7bfa564ac5132995", size = 170477, upload-time = "2025-10-15T20:39:51.311Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "temporal-dsl-python-example" +version = "0.0.1" +source = { virtual = "." } +dependencies = [ + { name = "temporalio" }, +] + +[package.metadata] +requires-dist = [{ name = "temporalio", specifier = ">=1.5.0,<2.0.0" }] + +[[package]] +name = "temporalio" +version = "1.18.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nexus-rpc" }, + { name = "protobuf" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "types-protobuf" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/ab/f866e19e02d46792ebd08e3e975f30ec86f985f1cd0cee4d5bc632d538e6/temporalio-1.18.2.tar.gz", hash = "sha256:b6ecb43562988ac698eef155d9c2527fa6c53a2ae564cb4787421499a0269599", size = 1788530, upload-time = "2025-10-27T19:24:50.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7e/2fc0d8cf18644fba2e4e5d0ba66206bf2e6f22ad04e9da8f038261351ff6/temporalio-1.18.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b97f046b23a492b0a3956dffce3664ed44ca1f3577df6aa4b8023ec988f5d093", size = 12808656, upload-time = "2025-10-27T19:24:26.884Z" }, + { url = "https://files.pythonhosted.org/packages/f9/2f/8ee0836e31f60a03582358ff64210f6f0c91001f34e4fc85da892e5c3087/temporalio-1.18.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:dac1203ebabae3268bc0b43b8c841e6f9102893c616488a278bc5d06043b76e5", size = 12393520, upload-time = "2025-10-27T19:24:32.048Z" }, + { url = "https://files.pythonhosted.org/packages/fc/39/53d9add2e8c1d4066ea0c288476cdc944453ea309e36e7b24d4a1c43db79/temporalio-1.18.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45b124099dbbe32a76a4df0d851db2ad94e6725f778fd74fccc8d33ee4868e9", size = 12733544, upload-time = "2025-10-27T19:24:36.871Z" }, + { url = "https://files.pythonhosted.org/packages/22/b2/5558978e9002fd1e71a1a459ddcc8fdd1fc1f4f595fd578eb7568be266a6/temporalio-1.18.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d427a398f6f402920e9f78d571b7d7a72876244d5affeaeaec8843c34013e84e", size = 12926857, upload-time = "2025-10-27T19:24:43.443Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a2/ea81149ae7faa154aa842e9dd88390df3158a687db694e06d08716c030b6/temporalio-1.18.2-cp39-abi3-win_amd64.whl", hash = "sha256:7e1f3da98cf23af7094467f1c1180374a10c38aa712cd7e868e15412dd2c6cde", size = 13059111, upload-time = "2025-10-27T19:24:48.382Z" }, +] + +[[package]] +name = "types-protobuf" +version = "6.32.1.20250918" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/69/5a/bd06c2dbb77ebd4ea764473c9c4c014c7ba94432192cb965a274f8544b9d/types_protobuf-6.32.1.20250918.tar.gz", hash = "sha256:44ce0ae98475909ca72379946ab61a4435eec2a41090821e713c17e8faf5b88f", size = 63780, upload-time = "2025-09-18T02:50:39.391Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/5a/8d93d4f4af5dc3dd62aa4f020deae746b34b1d94fb5bee1f776c6b7e9d6c/types_protobuf-6.32.1.20250918-py3-none-any.whl", hash = "sha256:22ba6133d142d11cc34d3788ad6dead2732368ebb0406eaa7790ea6ae46c8d0b", size = 77885, upload-time = "2025-09-18T02:50:38.028Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] diff --git a/examples/python/worker.py b/examples/python/worker.py new file mode 100644 index 00000000..b17d7862 --- /dev/null +++ b/examples/python/worker.py @@ -0,0 +1,71 @@ +# Copyright 2025 Temporal DSL authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Run a Temporal worker for the default task queue.""" + +from __future__ import annotations + +import asyncio +import os +import sys +from typing import Any, Dict + +from temporalio.client import Client +from temporalio.worker import Worker + +from activities import greet +from workflows import SayHelloWorkflow + + +async def main() -> None: + address = os.getenv("TEMPORAL_ADDRESS", "localhost:7233") + namespace = os.getenv("TEMPORAL_NAMESPACE", "default") + api_key = os.getenv("TEMPORAL_API_KEY") + tls_enabled = os.getenv("TEMPORAL_TLS", "false").lower() == "true" + + connect_kwargs: Dict[str, Any] = {"namespace": namespace} + if tls_enabled: + connect_kwargs["tls"] = True + if api_key: + connect_kwargs["api_key"] = api_key + + client = await Client.connect(address, **connect_kwargs) + + task_queue = os.getenv("PYTHON_CHILD_TASK_QUEUE", "python-child") + + worker = Worker( + client=client, + task_queue=task_queue, + workflows=[SayHelloWorkflow], + activities=[greet], + ) + + print(f"Worker listening on task queue: {task_queue}") + + await worker.run() + + +def _run() -> None: + try: + asyncio.run(main()) + except KeyboardInterrupt: + print("Worker shut down", file=sys.stderr) + except Exception as exc: # pragma: no cover - CLI surface + print(exc, file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + _run() diff --git a/examples/python/workflow.yaml b/examples/python/workflow.yaml new file mode 100644 index 00000000..35d2e23f --- /dev/null +++ b/examples/python/workflow.yaml @@ -0,0 +1,89 @@ +# This is a simple Serverless Workflow that will be +# translated into a Temporal workflow +document: + dsl: 1.0.0 + namespace: temporal-dsl # Mapped to the task queue + name: basic-python # Workflow name + version: 0.0.1 + title: Python + summary: The basic example, but in Python +# Optionally validate the input received +input: + schema: + format: json + document: + type: object + required: + - userId + properties: + userId: + type: number +timeout: + after: + minutes: 1 +do: + - baseData: + export: + as: data + set: + # Set a variable from an envvar + envvar: ${ .env.EXAMPLE_ENVVAR } + uuid: ${ uuid } + object: + hello: world + uuid: ${ uuid } + inputUserId: ${ .input.userId } + array: + - ${ uuid } + - hello: world + - wait: + wait: + seconds: 5 + - getUser: + call: http + export: + as: getUser + with: + method: get + endpoint: ${ "https://jsonplaceholder.typicode.com/users/" + (.input.userId | tostring) } + - sayHello: + run: + workflow: + name: say-hello-workflow + namespace: default + version: 0.0.1 + input: + taskQueue: python-child + - raiseAlarm: + # A fork is a series of child workflows running in parallel + export: + as: raiseAlarm + fork: + # If not competing, all tasks will run to the finish - this is the default behaviour + compete: false + branches: + # A single step is passed in by the Serverless Workflow task + - callNurse: + call: http + export: + as: callNurse + with: + method: get + endpoint: https://jsonplaceholder.typicode.com/users/2 + # Multiple steps can be passed in by the Serverless Workflow do task + - multiStep: + do: + - wait1: + wait: + seconds: 3 + - wait2: + wait: + seconds: 2 + # Another single step child workflow + - callDoctor: + call: http + export: + as: callDoctor + with: + method: get + endpoint: ${ "https://jsonplaceholder.typicode.com/users/" + (.input.userId | tostring) } diff --git a/examples/python/workflows.py b/examples/python/workflows.py new file mode 100644 index 00000000..c78a45aa --- /dev/null +++ b/examples/python/workflows.py @@ -0,0 +1,51 @@ +# Copyright 2025 Temporal DSL authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Workflows for the Python Temporal example.""" + +from __future__ import annotations + +from datetime import timedelta +from typing import Any, Mapping, Optional + +from temporalio import workflow + +from activities import greet + + +@workflow.defn(name="say-hello-workflow") +class SayHelloWorkflow: + """Workflow that greets the supplied name via an activity.""" + + @workflow.run + async def run( + self, + initial_input: Optional[Mapping[str, Any]] = None, + state_payload: Optional[Mapping[str, Any]] = None, + ) -> str: + _ = state_payload # currently unused but retained for parity with DSL signature + # The DSL parent workflow passes the original input as the first argument. + # Fall back to a reasonable default if the expected key is missing. + name = "Temporal" + if isinstance(initial_input, Mapping): + candidate = initial_input.get("name") + if candidate is not None: + name = str(candidate) + + return await workflow.execute_activity( + greet, + name, + schedule_to_close_timeout=timedelta(seconds=10), + ) diff --git a/pkg/dsl/tasks/task_builder_run.go b/pkg/dsl/tasks/task_builder_run.go index fd413f37..da5e4bd6 100644 --- a/pkg/dsl/tasks/task_builder_run.go +++ b/pkg/dsl/tasks/task_builder_run.go @@ -77,6 +77,15 @@ func (t *RunTaskBuilder) runWorkflow(ctx workflow.Context, input any, state *uti opts.ParentClosePolicy = enums.PARENT_CLOSE_POLICY_ABANDON } + if t.task.Run.Workflow != nil && t.task.Run.Workflow.Input != nil { + if taskQueueRaw, ok := t.task.Run.Workflow.Input["taskQueue"]; ok { + if taskQueue, ok := taskQueueRaw.(string); ok && taskQueue != "" { + logger.Debug("Overriding child workflow task queue", "taskQueue", taskQueue, "task", t.GetTaskName()) + opts.TaskQueue = taskQueue + } + } + } + ctx = workflow.WithChildOptions(ctx, opts) future := workflow.ExecuteChildWorkflow(ctx, t.task.Run.Workflow.Name, input, state)