55from upstash_workflow .workflow_types import _Response , _AsyncRequest
66from upstash_workflow .asyncio .workflow_parser import (
77 _get_payload ,
8+ _handle_failure ,
89)
910from upstash_workflow .workflow_parser import _validate_request , _parse_request
1011from upstash_workflow .asyncio .workflow_requests import (
@@ -39,6 +40,10 @@ def _serve_base(
3940 env : Optional [Dict [str , Optional [str ]]] = None ,
4041 retries : Optional [int ] = None ,
4142 url : Optional [str ] = None ,
43+ failure_function : Optional [
44+ Callable [[AsyncWorkflowContext , int , str , Dict [str , str ]], Awaitable [Any ]]
45+ ] = None ,
46+ failure_url : Optional [str ] = None ,
4247) -> Dict [str , Callable [[TRequest ], Awaitable [TResponse ]]]:
4348 processed_options = _process_options (
4449 qstash_client = qstash_client ,
@@ -49,6 +54,8 @@ def _serve_base(
4954 env = env ,
5055 retries = retries ,
5156 url = url ,
57+ failure_function = failure_function ,
58+ failure_url = failure_url ,
5259 )
5360 qstash_client = processed_options .qstash_client
5461 on_step_finish = processed_options .on_step_finish
@@ -58,9 +65,13 @@ def _serve_base(
5865 env = processed_options .env
5966 retries = processed_options .retries
6067 url = processed_options .url
68+ failure_url = processed_options .failure_url
69+ failure_function = processed_options .failure_function
6170
6271 async def _handler (request : TRequest ) -> TResponse :
63- workflow_url = _determine_urls (cast (_AsyncRequest , request ), url , base_url )
72+ workflow_url , workflow_failure_url = _determine_urls (
73+ cast (_AsyncRequest , request ), url , base_url , failure_function , failure_url
74+ )
6475
6576 request_payload = await _get_payload (request ) or ""
6677 _verify_request (
@@ -78,6 +89,20 @@ async def _handler(request: TRequest) -> TResponse:
7889 raw_initial_payload = parse_request_response .raw_initial_payload
7990 steps = parse_request_response .steps
8091
92+ failure_check = await _handle_failure (
93+ request ,
94+ request_payload ,
95+ qstash_client ,
96+ initial_payload_parser ,
97+ route_function ,
98+ failure_function ,
99+ env ,
100+ retries ,
101+ )
102+
103+ if failure_check == "is-failure-callback" :
104+ return on_step_finish (workflow_run_id , "failure-callback" )
105+
81106 workflow_context = AsyncWorkflowContext (
82107 qstash_client = qstash_client ,
83108 workflow_run_id = workflow_run_id ,
@@ -89,6 +114,7 @@ async def _handler(request: TRequest) -> TResponse:
89114 url = workflow_url ,
90115 env = env ,
91116 retries = retries ,
117+ failure_url = workflow_failure_url ,
92118 )
93119
94120 auth_check = await _DisabledWorkflowContext [Any ].try_authentication (
@@ -110,6 +136,7 @@ async def _handler(request: TRequest) -> TResponse:
110136 raw_initial_payload ,
111137 qstash_client ,
112138 workflow_url ,
139+ workflow_failure_url ,
113140 retries ,
114141 )
115142
@@ -153,6 +180,10 @@ def serve(
153180 env : Optional [Dict [str , Optional [str ]]] = None ,
154181 retries : Optional [int ] = None ,
155182 url : Optional [str ] = None ,
183+ failure_function : Optional [
184+ Callable [[AsyncWorkflowContext , int , str , Dict [str , str ]], Awaitable [Any ]]
185+ ] = None ,
186+ failure_url : Optional [str ] = None ,
156187) -> Dict [str , Callable [[TRequest ], Awaitable [TResponse ]]]:
157188 """
158189 Creates a method that handles incoming requests and runs the provided
@@ -178,4 +209,6 @@ def serve(
178209 env = env ,
179210 retries = retries ,
180211 url = url ,
212+ failure_function = failure_function ,
213+ failure_url = failure_url ,
181214 )
0 commit comments