From 0613be1c4f8dfbc43d851e18b61acf6c175b4eb9 Mon Sep 17 00:00:00 2001 From: CahidArda Date: Fri, 31 Oct 2025 16:06:51 +0300 Subject: [PATCH 1/3] feat: add workflow endpoint detection feature and bump version to 0.1.4 --- pyproject.toml | 2 +- upstash_workflow/__init__.py | 2 +- upstash_workflow/asyncio/serve/options.py | 13 +++++++++++-- upstash_workflow/serve/options.py | 13 +++++++++++-- upstash_workflow/workflow_requests.py | 2 +- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7c45f03..9b69116 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "upstash-workflow" -version = "0.1.3" +version = "0.1.4" description = "Python SDK for Upstash Workflow" license = "MIT" authors = ["Upstash "] diff --git a/upstash_workflow/__init__.py b/upstash_workflow/__init__.py index 04aa785..748b76e 100644 --- a/upstash_workflow/__init__.py +++ b/upstash_workflow/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.1.3" +__version__ = "0.1.4" from upstash_workflow.context.context import WorkflowContext from upstash_workflow.serve.serve import serve diff --git a/upstash_workflow/asyncio/serve/options.py b/upstash_workflow/asyncio/serve/options.py index 1a7ad6f..d247e27 100644 --- a/upstash_workflow/asyncio/serve/options.py +++ b/upstash_workflow/asyncio/serve/options.py @@ -4,7 +4,7 @@ from typing import Callable, Dict, Optional, cast, TypeVar, Any, Generic, Awaitable from qstash import AsyncQStash, Receiver from upstash_workflow.workflow_types import _Response -from upstash_workflow.constants import DEFAULT_RETRIES +from upstash_workflow.constants import DEFAULT_RETRIES, WORKFLOW_PROTOCOL_VERSION_HEADER, WORKFLOW_PROTOCOL_VERSION from upstash_workflow.types import ( _FinishCondition, ) @@ -74,11 +74,20 @@ def _on_step_finish( "workflowRunId": workflow_run_id, }, status=400, + headers={ + WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION + } ), ) return cast( - TResponse, _Response(body={"workflowRunId": workflow_run_id}, status=200) + TResponse, _Response( + body={"workflowRunId": workflow_run_id}, + status=200, + headers={ + WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION + } + ) ) def _initial_payload_parser(initial_request: str) -> TInitialPayload: diff --git a/upstash_workflow/serve/options.py b/upstash_workflow/serve/options.py index 8f5599e..6f391fb 100644 --- a/upstash_workflow/serve/options.py +++ b/upstash_workflow/serve/options.py @@ -16,7 +16,7 @@ ) from qstash import QStash, Receiver from upstash_workflow.workflow_types import _Response, _SyncRequest, _AsyncRequest -from upstash_workflow.constants import DEFAULT_RETRIES +from upstash_workflow.constants import DEFAULT_RETRIES, WORKFLOW_PROTOCOL_VERSION_HEADER, WORKFLOW_PROTOCOL_VERSION from upstash_workflow.types import ( _FinishCondition, ) @@ -99,11 +99,20 @@ def _on_step_finish( "workflowRunId": workflow_run_id, }, status=400, + headers={ + WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION + } ), ) return cast( - TResponse, _Response(body={"workflowRunId": workflow_run_id}, status=200) + TResponse, _Response( + body={"workflowRunId": workflow_run_id}, + status=200, + headers={ + WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION + } + ) ) def _initial_payload_parser(initial_request: str) -> TInitialPayload: diff --git a/upstash_workflow/workflow_requests.py b/upstash_workflow/workflow_requests.py index accf056..f47dec5 100644 --- a/upstash_workflow/workflow_requests.py +++ b/upstash_workflow/workflow_requests.py @@ -278,7 +278,7 @@ def _get_headers( WORKFLOW_INIT_HEADER: init_header_value, WORKFLOW_ID_HEADER: workflow_run_id, WORKFLOW_URL_HEADER: workflow_url, - WORKFLOW_FEATURE_HEADER: "LazyFetch,InitialBody", + WORKFLOW_FEATURE_HEADER: "LazyFetch,InitialBody,WF_DetectTrigger", } if not (step and step.call_url): From 61654ffa1835f97983a9952abc822e44fef70064 Mon Sep 17 00:00:00 2001 From: CahidArda Date: Fri, 31 Oct 2025 16:41:35 +0300 Subject: [PATCH 2/3] fix: fmt --- upstash_workflow/asyncio/serve/options.py | 17 ++++++++++------- upstash_workflow/serve/options.py | 17 ++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/upstash_workflow/asyncio/serve/options.py b/upstash_workflow/asyncio/serve/options.py index d247e27..f229d84 100644 --- a/upstash_workflow/asyncio/serve/options.py +++ b/upstash_workflow/asyncio/serve/options.py @@ -4,7 +4,11 @@ from typing import Callable, Dict, Optional, cast, TypeVar, Any, Generic, Awaitable from qstash import AsyncQStash, Receiver from upstash_workflow.workflow_types import _Response -from upstash_workflow.constants import DEFAULT_RETRIES, WORKFLOW_PROTOCOL_VERSION_HEADER, WORKFLOW_PROTOCOL_VERSION +from upstash_workflow.constants import ( + DEFAULT_RETRIES, + WORKFLOW_PROTOCOL_VERSION_HEADER, + WORKFLOW_PROTOCOL_VERSION, +) from upstash_workflow.types import ( _FinishCondition, ) @@ -76,18 +80,17 @@ def _on_step_finish( status=400, headers={ WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION - } + }, ), ) return cast( - TResponse, _Response( + TResponse, + _Response( body={"workflowRunId": workflow_run_id}, status=200, - headers={ - WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION - } - ) + headers={WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION}, + ), ) def _initial_payload_parser(initial_request: str) -> TInitialPayload: diff --git a/upstash_workflow/serve/options.py b/upstash_workflow/serve/options.py index 6f391fb..fb3743b 100644 --- a/upstash_workflow/serve/options.py +++ b/upstash_workflow/serve/options.py @@ -16,7 +16,11 @@ ) from qstash import QStash, Receiver from upstash_workflow.workflow_types import _Response, _SyncRequest, _AsyncRequest -from upstash_workflow.constants import DEFAULT_RETRIES, WORKFLOW_PROTOCOL_VERSION_HEADER, WORKFLOW_PROTOCOL_VERSION +from upstash_workflow.constants import ( + DEFAULT_RETRIES, + WORKFLOW_PROTOCOL_VERSION_HEADER, + WORKFLOW_PROTOCOL_VERSION, +) from upstash_workflow.types import ( _FinishCondition, ) @@ -101,18 +105,17 @@ def _on_step_finish( status=400, headers={ WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION - } + }, ), ) return cast( - TResponse, _Response( + TResponse, + _Response( body={"workflowRunId": workflow_run_id}, status=200, - headers={ - WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION - } - ) + headers={WORKFLOW_PROTOCOL_VERSION_HEADER: WORKFLOW_PROTOCOL_VERSION}, + ), ) def _initial_payload_parser(initial_request: str) -> TInitialPayload: From 3b01b2454e56c7b8922177dbedd11c407d36ccb8 Mon Sep 17 00:00:00 2001 From: CahidArda Date: Tue, 4 Nov 2025 16:03:09 +0300 Subject: [PATCH 3/3] feat: add failure callback feature set headers to workflow requests --- tests/asyncio/test_context.py | 2 ++ tests/test_context.py | 2 ++ upstash_workflow/workflow_requests.py | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/tests/asyncio/test_context.py b/tests/asyncio/test_context.py index f6471e6..922d8a2 100644 --- a/tests/asyncio/test_context.py +++ b/tests/asyncio/test_context.py @@ -66,6 +66,8 @@ async def execute() -> None: "Upstash-Workflow-RunId": "wfr-id", "Upstash-Workflow-Url": "https://www.my-website.com/api", "Upstash-Feature-Set": "WF_NoDelete,InitialBody", + "Upstash-Failure-Callback-Feature-Set": "LazyFetch,InitialBody", + "Upstash-Callback-Failure-Callback-Feature-Set": "LazyFetch,InitialBody", "Upstash-Failure-Callback-Forward-Upstash-Workflow-Is-Failure": "true", "Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback": "true", "Upstash-Failure-Callback-Workflow-Runid": "wfr-id", diff --git a/tests/test_context.py b/tests/test_context.py index ec9845b..b9290f2 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -65,6 +65,8 @@ def execute() -> None: "Upstash-Workflow-RunId": "wfr-id", "Upstash-Workflow-Url": "https://www.my-website.com/api", "Upstash-Feature-Set": "WF_NoDelete,InitialBody", + "Upstash-Failure-Callback-Feature-Set": "LazyFetch,InitialBody", + "Upstash-Callback-Failure-Callback-Feature-Set": "LazyFetch,InitialBody", "Upstash-Failure-Callback-Forward-Upstash-Workflow-Is-Failure": "true", "Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback": "true", "Upstash-Failure-Callback-Workflow-Runid": "wfr-id", diff --git a/upstash_workflow/workflow_requests.py b/upstash_workflow/workflow_requests.py index f47dec5..8863b0a 100644 --- a/upstash_workflow/workflow_requests.py +++ b/upstash_workflow/workflow_requests.py @@ -300,6 +300,7 @@ def _get_headers( base_headers["Upstash-Failure-Callback-Workflow-Init"] = "false" base_headers["Upstash-Failure-Callback-Workflow-Url"] = workflow_url base_headers["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall" + base_headers["Upstash-Failure-Callback-Feature-Set"] = "LazyFetch,InitialBody" if step and step.call_url: base_headers[ f"Upstash-Callback-Failure-Callback-Forward-{WORKFLOW_FAILURE_HEADER}" @@ -317,6 +318,9 @@ def _get_headers( base_headers["Upstash-Callback-Failure-Callback-Workflow-Calltype"] = ( "failureCall" ) + base_headers["Upstash-Callback-Failure-Callback-Feature-Set"] = ( + "LazyFetch,InitialBody" + ) if _should_set_retries(retries): base_headers["Upstash-Failure-Callback-Retries"] = str(retries)