hatchet-sdk 1.7.0__py3-none-any.whl → 1.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hatchet-sdk might be problematic. Click here for more details.

@@ -245,6 +245,8 @@ from hatchet_sdk.clients.rest.models.v1_task_run_status import V1TaskRunStatus
245
245
  from hatchet_sdk.clients.rest.models.v1_task_status import V1TaskStatus
246
246
  from hatchet_sdk.clients.rest.models.v1_task_summary import V1TaskSummary
247
247
  from hatchet_sdk.clients.rest.models.v1_task_summary_list import V1TaskSummaryList
248
+ from hatchet_sdk.clients.rest.models.v1_task_timing import V1TaskTiming
249
+ from hatchet_sdk.clients.rest.models.v1_task_timing_list import V1TaskTimingList
248
250
  from hatchet_sdk.clients.rest.models.v1_trigger_workflow_run_request import (
249
251
  V1TriggerWorkflowRunRequest,
250
252
  )
@@ -1555,6 +1555,9 @@ class TaskApi:
1555
1555
  since: Annotated[
1556
1556
  datetime, Field(description="The start time to get metrics for")
1557
1557
  ],
1558
+ until: Annotated[
1559
+ Optional[datetime], Field(description="The end time to get metrics for")
1560
+ ] = None,
1558
1561
  workflow_ids: Annotated[
1559
1562
  Optional[
1560
1563
  List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
@@ -1585,6 +1588,8 @@ class TaskApi:
1585
1588
  :type tenant: str
1586
1589
  :param since: The start time to get metrics for (required)
1587
1590
  :type since: datetime
1591
+ :param until: The end time to get metrics for
1592
+ :type until: datetime
1588
1593
  :param workflow_ids: The workflow id to find runs for
1589
1594
  :type workflow_ids: List[str]
1590
1595
  :param parent_task_external_id: The parent task's external id
@@ -1614,6 +1619,7 @@ class TaskApi:
1614
1619
  _param = self._v1_task_list_status_metrics_serialize(
1615
1620
  tenant=tenant,
1616
1621
  since=since,
1622
+ until=until,
1617
1623
  workflow_ids=workflow_ids,
1618
1624
  parent_task_external_id=parent_task_external_id,
1619
1625
  _request_auth=_request_auth,
@@ -1649,6 +1655,9 @@ class TaskApi:
1649
1655
  since: Annotated[
1650
1656
  datetime, Field(description="The start time to get metrics for")
1651
1657
  ],
1658
+ until: Annotated[
1659
+ Optional[datetime], Field(description="The end time to get metrics for")
1660
+ ] = None,
1652
1661
  workflow_ids: Annotated[
1653
1662
  Optional[
1654
1663
  List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
@@ -1679,6 +1688,8 @@ class TaskApi:
1679
1688
  :type tenant: str
1680
1689
  :param since: The start time to get metrics for (required)
1681
1690
  :type since: datetime
1691
+ :param until: The end time to get metrics for
1692
+ :type until: datetime
1682
1693
  :param workflow_ids: The workflow id to find runs for
1683
1694
  :type workflow_ids: List[str]
1684
1695
  :param parent_task_external_id: The parent task's external id
@@ -1708,6 +1719,7 @@ class TaskApi:
1708
1719
  _param = self._v1_task_list_status_metrics_serialize(
1709
1720
  tenant=tenant,
1710
1721
  since=since,
1722
+ until=until,
1711
1723
  workflow_ids=workflow_ids,
1712
1724
  parent_task_external_id=parent_task_external_id,
1713
1725
  _request_auth=_request_auth,
@@ -1743,6 +1755,9 @@ class TaskApi:
1743
1755
  since: Annotated[
1744
1756
  datetime, Field(description="The start time to get metrics for")
1745
1757
  ],
1758
+ until: Annotated[
1759
+ Optional[datetime], Field(description="The end time to get metrics for")
1760
+ ] = None,
1746
1761
  workflow_ids: Annotated[
1747
1762
  Optional[
1748
1763
  List[Annotated[str, Field(min_length=36, strict=True, max_length=36)]]
@@ -1773,6 +1788,8 @@ class TaskApi:
1773
1788
  :type tenant: str
1774
1789
  :param since: The start time to get metrics for (required)
1775
1790
  :type since: datetime
1791
+ :param until: The end time to get metrics for
1792
+ :type until: datetime
1776
1793
  :param workflow_ids: The workflow id to find runs for
1777
1794
  :type workflow_ids: List[str]
1778
1795
  :param parent_task_external_id: The parent task's external id
@@ -1802,6 +1819,7 @@ class TaskApi:
1802
1819
  _param = self._v1_task_list_status_metrics_serialize(
1803
1820
  tenant=tenant,
1804
1821
  since=since,
1822
+ until=until,
1805
1823
  workflow_ids=workflow_ids,
1806
1824
  parent_task_external_id=parent_task_external_id,
1807
1825
  _request_auth=_request_auth,
@@ -1825,6 +1843,7 @@ class TaskApi:
1825
1843
  self,
1826
1844
  tenant,
1827
1845
  since,
1846
+ until,
1828
1847
  workflow_ids,
1829
1848
  parent_task_external_id,
1830
1849
  _request_auth,
@@ -1863,6 +1882,17 @@ class TaskApi:
1863
1882
  else:
1864
1883
  _query_params.append(("since", since))
1865
1884
 
1885
+ if until is not None:
1886
+ if isinstance(until, datetime):
1887
+ _query_params.append(
1888
+ (
1889
+ "until",
1890
+ until.strftime(self.api_client.configuration.datetime_format),
1891
+ )
1892
+ )
1893
+ else:
1894
+ _query_params.append(("until", until))
1895
+
1866
1896
  if workflow_ids is not None:
1867
1897
 
1868
1898
  _query_params.append(("workflow_ids", workflow_ids))
@@ -23,6 +23,7 @@ from hatchet_sdk.clients.rest.api_response import ApiResponse
23
23
  from hatchet_sdk.clients.rest.models.v1_task_event_list import V1TaskEventList
24
24
  from hatchet_sdk.clients.rest.models.v1_task_status import V1TaskStatus
25
25
  from hatchet_sdk.clients.rest.models.v1_task_summary_list import V1TaskSummaryList
26
+ from hatchet_sdk.clients.rest.models.v1_task_timing_list import V1TaskTimingList
26
27
  from hatchet_sdk.clients.rest.models.v1_trigger_workflow_run_request import (
27
28
  V1TriggerWorkflowRunRequest,
28
29
  )
@@ -914,6 +915,304 @@ class WorkflowRunsApi:
914
915
  _request_auth=_request_auth,
915
916
  )
916
917
 
918
+ @validate_call
919
+ def v1_workflow_run_get_timings(
920
+ self,
921
+ v1_workflow_run: Annotated[
922
+ str,
923
+ Field(
924
+ min_length=36,
925
+ strict=True,
926
+ max_length=36,
927
+ description="The workflow run id to get",
928
+ ),
929
+ ],
930
+ depth: Annotated[
931
+ Optional[StrictInt], Field(description="The depth to retrieve children")
932
+ ] = None,
933
+ _request_timeout: Union[
934
+ None,
935
+ Annotated[StrictFloat, Field(gt=0)],
936
+ Tuple[
937
+ Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
938
+ ],
939
+ ] = None,
940
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
941
+ _content_type: Optional[StrictStr] = None,
942
+ _headers: Optional[Dict[StrictStr, Any]] = None,
943
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
944
+ ) -> V1TaskTimingList:
945
+ """List timings for a workflow run
946
+
947
+ Get the timings for a workflow run
948
+
949
+ :param v1_workflow_run: The workflow run id to get (required)
950
+ :type v1_workflow_run: str
951
+ :param depth: The depth to retrieve children
952
+ :type depth: int
953
+ :param _request_timeout: timeout setting for this request. If one
954
+ number provided, it will be total request
955
+ timeout. It can also be a pair (tuple) of
956
+ (connection, read) timeouts.
957
+ :type _request_timeout: int, tuple(int, int), optional
958
+ :param _request_auth: set to override the auth_settings for an a single
959
+ request; this effectively ignores the
960
+ authentication in the spec for a single request.
961
+ :type _request_auth: dict, optional
962
+ :param _content_type: force content-type for the request.
963
+ :type _content_type: str, Optional
964
+ :param _headers: set to override the headers for a single
965
+ request; this effectively ignores the headers
966
+ in the spec for a single request.
967
+ :type _headers: dict, optional
968
+ :param _host_index: set to override the host_index for a single
969
+ request; this effectively ignores the host_index
970
+ in the spec for a single request.
971
+ :type _host_index: int, optional
972
+ :return: Returns the result object.
973
+ """ # noqa: E501
974
+
975
+ _param = self._v1_workflow_run_get_timings_serialize(
976
+ v1_workflow_run=v1_workflow_run,
977
+ depth=depth,
978
+ _request_auth=_request_auth,
979
+ _content_type=_content_type,
980
+ _headers=_headers,
981
+ _host_index=_host_index,
982
+ )
983
+
984
+ _response_types_map: Dict[str, Optional[str]] = {
985
+ "200": "V1TaskTimingList",
986
+ "400": "APIErrors",
987
+ "403": "APIErrors",
988
+ "501": "APIErrors",
989
+ }
990
+ response_data = self.api_client.call_api(
991
+ *_param, _request_timeout=_request_timeout
992
+ )
993
+ response_data.read()
994
+ return self.api_client.response_deserialize(
995
+ response_data=response_data,
996
+ response_types_map=_response_types_map,
997
+ ).data
998
+
999
+ @validate_call
1000
+ def v1_workflow_run_get_timings_with_http_info(
1001
+ self,
1002
+ v1_workflow_run: Annotated[
1003
+ str,
1004
+ Field(
1005
+ min_length=36,
1006
+ strict=True,
1007
+ max_length=36,
1008
+ description="The workflow run id to get",
1009
+ ),
1010
+ ],
1011
+ depth: Annotated[
1012
+ Optional[StrictInt], Field(description="The depth to retrieve children")
1013
+ ] = None,
1014
+ _request_timeout: Union[
1015
+ None,
1016
+ Annotated[StrictFloat, Field(gt=0)],
1017
+ Tuple[
1018
+ Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
1019
+ ],
1020
+ ] = None,
1021
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
1022
+ _content_type: Optional[StrictStr] = None,
1023
+ _headers: Optional[Dict[StrictStr, Any]] = None,
1024
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
1025
+ ) -> ApiResponse[V1TaskTimingList]:
1026
+ """List timings for a workflow run
1027
+
1028
+ Get the timings for a workflow run
1029
+
1030
+ :param v1_workflow_run: The workflow run id to get (required)
1031
+ :type v1_workflow_run: str
1032
+ :param depth: The depth to retrieve children
1033
+ :type depth: int
1034
+ :param _request_timeout: timeout setting for this request. If one
1035
+ number provided, it will be total request
1036
+ timeout. It can also be a pair (tuple) of
1037
+ (connection, read) timeouts.
1038
+ :type _request_timeout: int, tuple(int, int), optional
1039
+ :param _request_auth: set to override the auth_settings for an a single
1040
+ request; this effectively ignores the
1041
+ authentication in the spec for a single request.
1042
+ :type _request_auth: dict, optional
1043
+ :param _content_type: force content-type for the request.
1044
+ :type _content_type: str, Optional
1045
+ :param _headers: set to override the headers for a single
1046
+ request; this effectively ignores the headers
1047
+ in the spec for a single request.
1048
+ :type _headers: dict, optional
1049
+ :param _host_index: set to override the host_index for a single
1050
+ request; this effectively ignores the host_index
1051
+ in the spec for a single request.
1052
+ :type _host_index: int, optional
1053
+ :return: Returns the result object.
1054
+ """ # noqa: E501
1055
+
1056
+ _param = self._v1_workflow_run_get_timings_serialize(
1057
+ v1_workflow_run=v1_workflow_run,
1058
+ depth=depth,
1059
+ _request_auth=_request_auth,
1060
+ _content_type=_content_type,
1061
+ _headers=_headers,
1062
+ _host_index=_host_index,
1063
+ )
1064
+
1065
+ _response_types_map: Dict[str, Optional[str]] = {
1066
+ "200": "V1TaskTimingList",
1067
+ "400": "APIErrors",
1068
+ "403": "APIErrors",
1069
+ "501": "APIErrors",
1070
+ }
1071
+ response_data = self.api_client.call_api(
1072
+ *_param, _request_timeout=_request_timeout
1073
+ )
1074
+ response_data.read()
1075
+ return self.api_client.response_deserialize(
1076
+ response_data=response_data,
1077
+ response_types_map=_response_types_map,
1078
+ )
1079
+
1080
+ @validate_call
1081
+ def v1_workflow_run_get_timings_without_preload_content(
1082
+ self,
1083
+ v1_workflow_run: Annotated[
1084
+ str,
1085
+ Field(
1086
+ min_length=36,
1087
+ strict=True,
1088
+ max_length=36,
1089
+ description="The workflow run id to get",
1090
+ ),
1091
+ ],
1092
+ depth: Annotated[
1093
+ Optional[StrictInt], Field(description="The depth to retrieve children")
1094
+ ] = None,
1095
+ _request_timeout: Union[
1096
+ None,
1097
+ Annotated[StrictFloat, Field(gt=0)],
1098
+ Tuple[
1099
+ Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
1100
+ ],
1101
+ ] = None,
1102
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
1103
+ _content_type: Optional[StrictStr] = None,
1104
+ _headers: Optional[Dict[StrictStr, Any]] = None,
1105
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
1106
+ ) -> RESTResponseType:
1107
+ """List timings for a workflow run
1108
+
1109
+ Get the timings for a workflow run
1110
+
1111
+ :param v1_workflow_run: The workflow run id to get (required)
1112
+ :type v1_workflow_run: str
1113
+ :param depth: The depth to retrieve children
1114
+ :type depth: int
1115
+ :param _request_timeout: timeout setting for this request. If one
1116
+ number provided, it will be total request
1117
+ timeout. It can also be a pair (tuple) of
1118
+ (connection, read) timeouts.
1119
+ :type _request_timeout: int, tuple(int, int), optional
1120
+ :param _request_auth: set to override the auth_settings for an a single
1121
+ request; this effectively ignores the
1122
+ authentication in the spec for a single request.
1123
+ :type _request_auth: dict, optional
1124
+ :param _content_type: force content-type for the request.
1125
+ :type _content_type: str, Optional
1126
+ :param _headers: set to override the headers for a single
1127
+ request; this effectively ignores the headers
1128
+ in the spec for a single request.
1129
+ :type _headers: dict, optional
1130
+ :param _host_index: set to override the host_index for a single
1131
+ request; this effectively ignores the host_index
1132
+ in the spec for a single request.
1133
+ :type _host_index: int, optional
1134
+ :return: Returns the result object.
1135
+ """ # noqa: E501
1136
+
1137
+ _param = self._v1_workflow_run_get_timings_serialize(
1138
+ v1_workflow_run=v1_workflow_run,
1139
+ depth=depth,
1140
+ _request_auth=_request_auth,
1141
+ _content_type=_content_type,
1142
+ _headers=_headers,
1143
+ _host_index=_host_index,
1144
+ )
1145
+
1146
+ _response_types_map: Dict[str, Optional[str]] = {
1147
+ "200": "V1TaskTimingList",
1148
+ "400": "APIErrors",
1149
+ "403": "APIErrors",
1150
+ "501": "APIErrors",
1151
+ }
1152
+ response_data = self.api_client.call_api(
1153
+ *_param, _request_timeout=_request_timeout
1154
+ )
1155
+ return response_data.response
1156
+
1157
+ def _v1_workflow_run_get_timings_serialize(
1158
+ self,
1159
+ v1_workflow_run,
1160
+ depth,
1161
+ _request_auth,
1162
+ _content_type,
1163
+ _headers,
1164
+ _host_index,
1165
+ ) -> RequestSerialized:
1166
+
1167
+ _host = None
1168
+
1169
+ _collection_formats: Dict[str, str] = {}
1170
+
1171
+ _path_params: Dict[str, str] = {}
1172
+ _query_params: List[Tuple[str, str]] = []
1173
+ _header_params: Dict[str, Optional[str]] = _headers or {}
1174
+ _form_params: List[Tuple[str, str]] = []
1175
+ _files: Dict[
1176
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
1177
+ ] = {}
1178
+ _body_params: Optional[bytes] = None
1179
+
1180
+ # process the path parameters
1181
+ if v1_workflow_run is not None:
1182
+ _path_params["v1-workflow-run"] = v1_workflow_run
1183
+ # process the query parameters
1184
+ if depth is not None:
1185
+
1186
+ _query_params.append(("depth", depth))
1187
+
1188
+ # process the header parameters
1189
+ # process the form parameters
1190
+ # process the body parameter
1191
+
1192
+ # set the HTTP header `Accept`
1193
+ if "Accept" not in _header_params:
1194
+ _header_params["Accept"] = self.api_client.select_header_accept(
1195
+ ["application/json"]
1196
+ )
1197
+
1198
+ # authentication setting
1199
+ _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
1200
+
1201
+ return self.api_client.param_serialize(
1202
+ method="GET",
1203
+ resource_path="/api/v1/stable/workflow-runs/{v1-workflow-run}/task-timings",
1204
+ path_params=_path_params,
1205
+ query_params=_query_params,
1206
+ header_params=_header_params,
1207
+ body=_body_params,
1208
+ post_params=_form_params,
1209
+ files=_files,
1210
+ auth_settings=_auth_settings,
1211
+ collection_formats=_collection_formats,
1212
+ _host=_host,
1213
+ _request_auth=_request_auth,
1214
+ )
1215
+
917
1216
  @validate_call
918
1217
  def v1_workflow_run_list(
919
1218
  self,
@@ -40,6 +40,7 @@ from hatchet_sdk.clients.rest.exceptions import (
40
40
  ServiceException,
41
41
  UnauthorizedException,
42
42
  )
43
+ from hatchet_sdk.logger import logger
43
44
 
44
45
  RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]]
45
46
 
@@ -356,7 +357,20 @@ class ApiClient:
356
357
  return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
357
358
  elif isinstance(obj, tuple):
358
359
  return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj)
359
- elif isinstance(obj, (datetime.datetime, datetime.date)):
360
+ ## IMPORTANT: Checking `datetime` must come before `date` since `datetime` is a subclass of `date`
361
+ elif isinstance(obj, datetime.datetime):
362
+ if not obj.tzinfo:
363
+ current_tz = (
364
+ datetime.datetime.now(datetime.timezone(datetime.timedelta(0)))
365
+ .astimezone()
366
+ .tzinfo
367
+ or datetime.timezone.utc
368
+ )
369
+ logger.warning(f"timezone-naive datetime found. assuming {current_tz}.")
370
+ obj = obj.replace(tzinfo=current_tz)
371
+
372
+ return obj.isoformat()
373
+ elif isinstance(obj, datetime.date):
360
374
  return obj.isoformat()
361
375
  elif isinstance(obj, decimal.Decimal):
362
376
  return str(obj)
@@ -210,6 +210,8 @@ from hatchet_sdk.clients.rest.models.v1_task_run_status import V1TaskRunStatus
210
210
  from hatchet_sdk.clients.rest.models.v1_task_status import V1TaskStatus
211
211
  from hatchet_sdk.clients.rest.models.v1_task_summary import V1TaskSummary
212
212
  from hatchet_sdk.clients.rest.models.v1_task_summary_list import V1TaskSummaryList
213
+ from hatchet_sdk.clients.rest.models.v1_task_timing import V1TaskTiming
214
+ from hatchet_sdk.clients.rest.models.v1_task_timing_list import V1TaskTimingList
213
215
  from hatchet_sdk.clients.rest.models.v1_trigger_workflow_run_request import (
214
216
  V1TriggerWorkflowRunRequest,
215
217
  )
@@ -95,10 +95,8 @@ class V1TaskSummary(BaseModel):
95
95
  )
96
96
  workflow_id: StrictStr = Field(alias="workflowId")
97
97
  workflow_name: Optional[StrictStr] = Field(default=None, alias="workflowName")
98
- workflow_run_external_id: Optional[StrictStr] = Field(
99
- default=None,
100
- description="The external ID of the workflow run",
101
- alias="workflowRunExternalId",
98
+ workflow_run_external_id: StrictStr = Field(
99
+ description="The external ID of the workflow run", alias="workflowRunExternalId"
102
100
  )
103
101
  workflow_version_id: Optional[StrictStr] = Field(
104
102
  default=None,
@@ -0,0 +1,159 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Hatchet API
5
+
6
+ The Hatchet API
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ import pprint
19
+ import re # noqa: F401
20
+ from datetime import datetime
21
+ from typing import Any, ClassVar, Dict, List, Optional, Set
22
+
23
+ from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
24
+ from typing_extensions import Annotated, Self
25
+
26
+ from hatchet_sdk.clients.rest.models.api_resource_meta import APIResourceMeta
27
+ from hatchet_sdk.clients.rest.models.v1_task_status import V1TaskStatus
28
+
29
+
30
+ class V1TaskTiming(BaseModel):
31
+ """
32
+ V1TaskTiming
33
+ """ # noqa: E501
34
+
35
+ metadata: APIResourceMeta
36
+ depth: StrictInt = Field(description="The depth of the task in the waterfall.")
37
+ status: V1TaskStatus
38
+ task_display_name: StrictStr = Field(
39
+ description="The display name of the task run.", alias="taskDisplayName"
40
+ )
41
+ task_external_id: Annotated[
42
+ str, Field(min_length=36, strict=True, max_length=36)
43
+ ] = Field(description="The external ID of the task.", alias="taskExternalId")
44
+ task_id: StrictInt = Field(description="The ID of the task.", alias="taskId")
45
+ task_inserted_at: datetime = Field(
46
+ description="The timestamp the task was inserted.", alias="taskInsertedAt"
47
+ )
48
+ tenant_id: Annotated[str, Field(min_length=36, strict=True, max_length=36)] = Field(
49
+ description="The ID of the tenant.", alias="tenantId"
50
+ )
51
+ parent_task_external_id: Optional[
52
+ Annotated[str, Field(min_length=36, strict=True, max_length=36)]
53
+ ] = Field(
54
+ default=None,
55
+ description="The external ID of the parent task.",
56
+ alias="parentTaskExternalId",
57
+ )
58
+ queued_at: Optional[datetime] = Field(
59
+ default=None,
60
+ description="The timestamp the task run was queued.",
61
+ alias="queuedAt",
62
+ )
63
+ started_at: Optional[datetime] = Field(
64
+ default=None,
65
+ description="The timestamp the task run started.",
66
+ alias="startedAt",
67
+ )
68
+ finished_at: Optional[datetime] = Field(
69
+ default=None,
70
+ description="The timestamp the task run finished.",
71
+ alias="finishedAt",
72
+ )
73
+ __properties: ClassVar[List[str]] = [
74
+ "metadata",
75
+ "depth",
76
+ "status",
77
+ "taskDisplayName",
78
+ "taskExternalId",
79
+ "taskId",
80
+ "taskInsertedAt",
81
+ "tenantId",
82
+ "parentTaskExternalId",
83
+ "queuedAt",
84
+ "startedAt",
85
+ "finishedAt",
86
+ ]
87
+
88
+ model_config = ConfigDict(
89
+ populate_by_name=True,
90
+ validate_assignment=True,
91
+ protected_namespaces=(),
92
+ )
93
+
94
+ def to_str(self) -> str:
95
+ """Returns the string representation of the model using alias"""
96
+ return pprint.pformat(self.model_dump(by_alias=True))
97
+
98
+ def to_json(self) -> str:
99
+ """Returns the JSON representation of the model using alias"""
100
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
101
+ return json.dumps(self.to_dict())
102
+
103
+ @classmethod
104
+ def from_json(cls, json_str: str) -> Optional[Self]:
105
+ """Create an instance of V1TaskTiming from a JSON string"""
106
+ return cls.from_dict(json.loads(json_str))
107
+
108
+ def to_dict(self) -> Dict[str, Any]:
109
+ """Return the dictionary representation of the model using alias.
110
+
111
+ This has the following differences from calling pydantic's
112
+ `self.model_dump(by_alias=True)`:
113
+
114
+ * `None` is only added to the output dict for nullable fields that
115
+ were set at model initialization. Other fields with value `None`
116
+ are ignored.
117
+ """
118
+ excluded_fields: Set[str] = set([])
119
+
120
+ _dict = self.model_dump(
121
+ by_alias=True,
122
+ exclude=excluded_fields,
123
+ exclude_none=True,
124
+ )
125
+ # override the default output from pydantic by calling `to_dict()` of metadata
126
+ if self.metadata:
127
+ _dict["metadata"] = self.metadata.to_dict()
128
+ return _dict
129
+
130
+ @classmethod
131
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
132
+ """Create an instance of V1TaskTiming from a dict"""
133
+ if obj is None:
134
+ return None
135
+
136
+ if not isinstance(obj, dict):
137
+ return cls.model_validate(obj)
138
+
139
+ _obj = cls.model_validate(
140
+ {
141
+ "metadata": (
142
+ APIResourceMeta.from_dict(obj["metadata"])
143
+ if obj.get("metadata") is not None
144
+ else None
145
+ ),
146
+ "depth": obj.get("depth"),
147
+ "status": obj.get("status"),
148
+ "taskDisplayName": obj.get("taskDisplayName"),
149
+ "taskExternalId": obj.get("taskExternalId"),
150
+ "taskId": obj.get("taskId"),
151
+ "taskInsertedAt": obj.get("taskInsertedAt"),
152
+ "tenantId": obj.get("tenantId"),
153
+ "parentTaskExternalId": obj.get("parentTaskExternalId"),
154
+ "queuedAt": obj.get("queuedAt"),
155
+ "startedAt": obj.get("startedAt"),
156
+ "finishedAt": obj.get("finishedAt"),
157
+ }
158
+ )
159
+ return _obj
@@ -0,0 +1,110 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Hatchet API
5
+
6
+ The Hatchet API
7
+
8
+ The version of the OpenAPI document: 1.0.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ import pprint
19
+ import re # noqa: F401
20
+ from typing import Any, ClassVar, Dict, List, Optional, Set
21
+
22
+ from pydantic import BaseModel, ConfigDict, Field
23
+ from typing_extensions import Self
24
+
25
+ from hatchet_sdk.clients.rest.models.pagination_response import PaginationResponse
26
+ from hatchet_sdk.clients.rest.models.v1_task_timing import V1TaskTiming
27
+
28
+
29
+ class V1TaskTimingList(BaseModel):
30
+ """
31
+ V1TaskTimingList
32
+ """ # noqa: E501
33
+
34
+ pagination: PaginationResponse
35
+ rows: List[V1TaskTiming] = Field(description="The list of task timings")
36
+ __properties: ClassVar[List[str]] = ["pagination", "rows"]
37
+
38
+ model_config = ConfigDict(
39
+ populate_by_name=True,
40
+ validate_assignment=True,
41
+ protected_namespaces=(),
42
+ )
43
+
44
+ def to_str(self) -> str:
45
+ """Returns the string representation of the model using alias"""
46
+ return pprint.pformat(self.model_dump(by_alias=True))
47
+
48
+ def to_json(self) -> str:
49
+ """Returns the JSON representation of the model using alias"""
50
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
51
+ return json.dumps(self.to_dict())
52
+
53
+ @classmethod
54
+ def from_json(cls, json_str: str) -> Optional[Self]:
55
+ """Create an instance of V1TaskTimingList from a JSON string"""
56
+ return cls.from_dict(json.loads(json_str))
57
+
58
+ def to_dict(self) -> Dict[str, Any]:
59
+ """Return the dictionary representation of the model using alias.
60
+
61
+ This has the following differences from calling pydantic's
62
+ `self.model_dump(by_alias=True)`:
63
+
64
+ * `None` is only added to the output dict for nullable fields that
65
+ were set at model initialization. Other fields with value `None`
66
+ are ignored.
67
+ """
68
+ excluded_fields: Set[str] = set([])
69
+
70
+ _dict = self.model_dump(
71
+ by_alias=True,
72
+ exclude=excluded_fields,
73
+ exclude_none=True,
74
+ )
75
+ # override the default output from pydantic by calling `to_dict()` of pagination
76
+ if self.pagination:
77
+ _dict["pagination"] = self.pagination.to_dict()
78
+ # override the default output from pydantic by calling `to_dict()` of each item in rows (list)
79
+ _items = []
80
+ if self.rows:
81
+ for _item_rows in self.rows:
82
+ if _item_rows:
83
+ _items.append(_item_rows.to_dict())
84
+ _dict["rows"] = _items
85
+ return _dict
86
+
87
+ @classmethod
88
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
89
+ """Create an instance of V1TaskTimingList from a dict"""
90
+ if obj is None:
91
+ return None
92
+
93
+ if not isinstance(obj, dict):
94
+ return cls.model_validate(obj)
95
+
96
+ _obj = cls.model_validate(
97
+ {
98
+ "pagination": (
99
+ PaginationResponse.from_dict(obj["pagination"])
100
+ if obj.get("pagination") is not None
101
+ else None
102
+ ),
103
+ "rows": (
104
+ [V1TaskTiming.from_dict(_item) for _item in obj["rows"]]
105
+ if obj.get("rows") is not None
106
+ else None
107
+ ),
108
+ }
109
+ )
110
+ return _obj
@@ -73,7 +73,7 @@ class Context:
73
73
  from hatchet_sdk.runnables.types import R
74
74
 
75
75
  if self.was_skipped(task):
76
- raise ValueError("{task.name} was skipped")
76
+ raise ValueError(f"{task.name} was skipped")
77
77
 
78
78
  try:
79
79
  parent_step_data = cast(R, self.data.parents[task.name])
hatchet_sdk/hatchet.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  import logging
3
+ from datetime import timedelta
3
4
  from typing import Any, Callable, Type, Union, cast, overload
4
5
 
5
6
  from hatchet_sdk import Context, DurableContext
@@ -21,8 +22,6 @@ from hatchet_sdk.logger import logger
21
22
  from hatchet_sdk.rate_limit import RateLimit
22
23
  from hatchet_sdk.runnables.standalone import Standalone
23
24
  from hatchet_sdk.runnables.types import (
24
- DEFAULT_EXECUTION_TIMEOUT,
25
- DEFAULT_SCHEDULE_TIMEOUT,
26
25
  ConcurrencyExpression,
27
26
  EmptyModel,
28
27
  R,
@@ -294,8 +293,8 @@ class Hatchet:
294
293
  sticky: StickyStrategy | None = None,
295
294
  default_priority: int = 1,
296
295
  concurrency: ConcurrencyExpression | list[ConcurrencyExpression] | None = None,
297
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
298
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
296
+ schedule_timeout: Duration = timedelta(minutes=5),
297
+ execution_timeout: Duration = timedelta(seconds=60),
299
298
  retries: int = 0,
300
299
  rate_limits: list[RateLimit] = [],
301
300
  desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
@@ -316,8 +315,8 @@ class Hatchet:
316
315
  sticky: StickyStrategy | None = None,
317
316
  default_priority: int = 1,
318
317
  concurrency: ConcurrencyExpression | list[ConcurrencyExpression] | None = None,
319
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
320
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
318
+ schedule_timeout: Duration = timedelta(minutes=5),
319
+ execution_timeout: Duration = timedelta(seconds=60),
321
320
  retries: int = 0,
322
321
  rate_limits: list[RateLimit] = [],
323
322
  desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
@@ -339,8 +338,8 @@ class Hatchet:
339
338
  sticky: StickyStrategy | None = None,
340
339
  default_priority: int = 1,
341
340
  concurrency: ConcurrencyExpression | list[ConcurrencyExpression] | None = None,
342
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
343
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
341
+ schedule_timeout: Duration = timedelta(minutes=5),
342
+ execution_timeout: Duration = timedelta(seconds=60),
344
343
  retries: int = 0,
345
344
  rate_limits: list[RateLimit] = [],
346
345
  desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
@@ -451,8 +450,8 @@ class Hatchet:
451
450
  sticky: StickyStrategy | None = None,
452
451
  default_priority: int = 1,
453
452
  concurrency: ConcurrencyExpression | None = None,
454
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
455
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
453
+ schedule_timeout: Duration = timedelta(minutes=5),
454
+ execution_timeout: Duration = timedelta(seconds=60),
456
455
  retries: int = 0,
457
456
  rate_limits: list[RateLimit] = [],
458
457
  desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
@@ -475,8 +474,8 @@ class Hatchet:
475
474
  sticky: StickyStrategy | None = None,
476
475
  default_priority: int = 1,
477
476
  concurrency: ConcurrencyExpression | None = None,
478
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
479
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
477
+ schedule_timeout: Duration = timedelta(minutes=5),
478
+ execution_timeout: Duration = timedelta(seconds=60),
480
479
  retries: int = 0,
481
480
  rate_limits: list[RateLimit] = [],
482
481
  desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
@@ -498,8 +497,8 @@ class Hatchet:
498
497
  sticky: StickyStrategy | None = None,
499
498
  default_priority: int = 1,
500
499
  concurrency: ConcurrencyExpression | None = None,
501
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
502
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
500
+ schedule_timeout: Duration = timedelta(minutes=5),
501
+ execution_timeout: Duration = timedelta(seconds=60),
503
502
  retries: int = 0,
504
503
  rate_limits: list[RateLimit] = [],
505
504
  desired_worker_labels: dict[str, DesiredWorkerLabel] = {},
@@ -1,10 +1,10 @@
1
+ from datetime import timedelta
1
2
  from typing import (
2
3
  TYPE_CHECKING,
3
4
  Any,
4
5
  Awaitable,
5
6
  Callable,
6
7
  Generic,
7
- TypeVar,
8
8
  Union,
9
9
  cast,
10
10
  get_type_hints,
@@ -18,8 +18,6 @@ from hatchet_sdk.contracts.v1.workflows_pb2 import (
18
18
  DesiredWorkerLabels,
19
19
  )
20
20
  from hatchet_sdk.runnables.types import (
21
- DEFAULT_EXECUTION_TIMEOUT,
22
- DEFAULT_SCHEDULE_TIMEOUT,
23
21
  ConcurrencyExpression,
24
22
  R,
25
23
  StepType,
@@ -43,18 +41,6 @@ if TYPE_CHECKING:
43
41
  from hatchet_sdk.runnables.workflow import Workflow
44
42
 
45
43
 
46
- T = TypeVar("T")
47
-
48
-
49
- def fall_back_to_default(value: T, default: T, fallback_value: T) -> T:
50
- ## If the value is not the default, it's set
51
- if value != default:
52
- return value
53
-
54
- ## Otherwise, it's unset, so return the fallback value
55
- return fallback_value
56
-
57
-
58
44
  class Task(Generic[TWorkflowInput, R]):
59
45
  def __init__(
60
46
  self,
@@ -68,8 +54,8 @@ class Task(Generic[TWorkflowInput, R]):
68
54
  type: StepType,
69
55
  workflow: "Workflow[TWorkflowInput]",
70
56
  name: str,
71
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
72
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
57
+ execution_timeout: Duration = timedelta(seconds=60),
58
+ schedule_timeout: Duration = timedelta(minutes=5),
73
59
  parents: "list[Task[TWorkflowInput, Any]]" = [],
74
60
  retries: int = 0,
75
61
  rate_limits: list[CreateTaskRateLimit] = [],
@@ -89,12 +75,8 @@ class Task(Generic[TWorkflowInput, R]):
89
75
  self.workflow = workflow
90
76
 
91
77
  self.type = type
92
- self.execution_timeout = fall_back_to_default(
93
- execution_timeout, DEFAULT_EXECUTION_TIMEOUT, DEFAULT_EXECUTION_TIMEOUT
94
- )
95
- self.schedule_timeout = fall_back_to_default(
96
- schedule_timeout, DEFAULT_SCHEDULE_TIMEOUT, DEFAULT_SCHEDULE_TIMEOUT
97
- )
78
+ self.execution_timeout = execution_timeout
79
+ self.schedule_timeout = schedule_timeout
98
80
  self.name = name
99
81
  self.parents = parents
100
82
  self.retries = retries
@@ -1,9 +1,8 @@
1
1
  import asyncio
2
- from datetime import timedelta
3
2
  from enum import Enum
4
3
  from typing import Any, Awaitable, Callable, ParamSpec, Type, TypeGuard, TypeVar, Union
5
4
 
6
- from pydantic import BaseModel, ConfigDict, Field, StrictInt, model_validator
5
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
7
6
 
8
7
  from hatchet_sdk.context.context import Context, DurableContext
9
8
  from hatchet_sdk.contracts.v1.workflows_pb2 import Concurrency
@@ -16,11 +15,6 @@ R = TypeVar("R", bound=Union[ValidTaskReturnType, Awaitable[ValidTaskReturnType]
16
15
  P = ParamSpec("P")
17
16
 
18
17
 
19
- DEFAULT_EXECUTION_TIMEOUT = timedelta(seconds=60)
20
- DEFAULT_SCHEDULE_TIMEOUT = timedelta(minutes=5)
21
- DEFAULT_PRIORITY = 1
22
-
23
-
24
18
  class EmptyModel(BaseModel):
25
19
  model_config = ConfigDict(extra="allow", frozen=True)
26
20
 
@@ -65,9 +59,12 @@ TWorkflowInput = TypeVar("TWorkflowInput", bound=BaseModel)
65
59
 
66
60
 
67
61
  class TaskDefaults(BaseModel):
68
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT
69
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT
70
- priority: StrictInt = Field(gt=0, lt=4, default=DEFAULT_PRIORITY)
62
+ schedule_timeout: Duration | None = None
63
+ execution_timeout: Duration | None = None
64
+ priority: int | None = Field(gt=0, lt=4, default=None)
65
+ retries: int | None = None
66
+ backoff_factor: float | None = None
67
+ backoff_max_seconds: int | None = None
71
68
 
72
69
 
73
70
  class WorkflowConfig(BaseModel):
@@ -1,9 +1,9 @@
1
1
  import asyncio
2
2
  from datetime import datetime, timedelta
3
- from typing import TYPE_CHECKING, Any, Callable, Generic, cast
3
+ from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast
4
4
 
5
5
  from google.protobuf import timestamp_pb2
6
- from pydantic import BaseModel
6
+ from pydantic import BaseModel, model_validator
7
7
 
8
8
  from hatchet_sdk.clients.admin import (
9
9
  ScheduleTriggerWorkflowOptions,
@@ -25,12 +25,11 @@ from hatchet_sdk.logger import logger
25
25
  from hatchet_sdk.rate_limit import RateLimit
26
26
  from hatchet_sdk.runnables.task import Task
27
27
  from hatchet_sdk.runnables.types import (
28
- DEFAULT_EXECUTION_TIMEOUT,
29
- DEFAULT_SCHEDULE_TIMEOUT,
30
28
  ConcurrencyExpression,
31
29
  EmptyModel,
32
30
  R,
33
31
  StepType,
32
+ TaskDefaults,
34
33
  TWorkflowInput,
35
34
  WorkflowConfig,
36
35
  )
@@ -45,6 +44,62 @@ if TYPE_CHECKING:
45
44
  from hatchet_sdk.runnables.standalone import Standalone
46
45
 
47
46
 
47
+ T = TypeVar("T")
48
+
49
+
50
+ def fall_back_to_default(value: T, param_default: T, fallback_value: T | None) -> T:
51
+ ## If the value is not the param default, it's set
52
+ if value != param_default:
53
+ return value
54
+
55
+ ## Otherwise, it's unset, so return the fallback value if it's set
56
+ if fallback_value is not None:
57
+ return fallback_value
58
+
59
+ ## Otherwise return the param value
60
+ return value
61
+
62
+
63
+ class ComputedTaskParameters(BaseModel):
64
+ schedule_timeout: Duration
65
+ execution_timeout: Duration
66
+ retries: int
67
+ backoff_factor: float | None
68
+ backoff_max_seconds: int | None
69
+
70
+ task_defaults: TaskDefaults
71
+
72
+ @model_validator(mode="after")
73
+ def validate_params(self) -> "ComputedTaskParameters":
74
+ self.execution_timeout = fall_back_to_default(
75
+ value=self.execution_timeout,
76
+ param_default=timedelta(seconds=60),
77
+ fallback_value=self.task_defaults.execution_timeout,
78
+ )
79
+ self.schedule_timeout = fall_back_to_default(
80
+ value=self.schedule_timeout,
81
+ param_default=timedelta(minutes=5),
82
+ fallback_value=self.task_defaults.schedule_timeout,
83
+ )
84
+ self.backoff_factor = fall_back_to_default(
85
+ value=self.backoff_factor,
86
+ param_default=None,
87
+ fallback_value=self.task_defaults.backoff_factor,
88
+ )
89
+ self.backoff_max_seconds = fall_back_to_default(
90
+ value=self.backoff_max_seconds,
91
+ param_default=None,
92
+ fallback_value=self.task_defaults.backoff_max_seconds,
93
+ )
94
+ self.retries = fall_back_to_default(
95
+ value=self.retries,
96
+ param_default=0,
97
+ fallback_value=self.task_defaults.retries,
98
+ )
99
+
100
+ return self
101
+
102
+
48
103
  def transform_desired_worker_label(d: DesiredWorkerLabel) -> DesiredWorkerLabels:
49
104
  value = d.value
50
105
  return DesiredWorkerLabels(
@@ -530,8 +585,8 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
530
585
  def task(
531
586
  self,
532
587
  name: str | None = None,
533
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
534
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
588
+ schedule_timeout: Duration = timedelta(minutes=5),
589
+ execution_timeout: Duration = timedelta(seconds=60),
535
590
  parents: list[Task[TWorkflowInput, Any]] = [],
536
591
  retries: int = 0,
537
592
  rate_limits: list[RateLimit] = [],
@@ -575,6 +630,15 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
575
630
  :returns: A decorator which creates a `Task` object.
576
631
  """
577
632
 
633
+ computed_params = ComputedTaskParameters(
634
+ schedule_timeout=schedule_timeout,
635
+ execution_timeout=execution_timeout,
636
+ retries=retries,
637
+ backoff_factor=backoff_factor,
638
+ backoff_max_seconds=backoff_max_seconds,
639
+ task_defaults=self.config.task_defaults,
640
+ )
641
+
578
642
  def inner(
579
643
  func: Callable[[TWorkflowInput, Context], R]
580
644
  ) -> Task[TWorkflowInput, R]:
@@ -584,17 +648,17 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
584
648
  workflow=self,
585
649
  type=StepType.DEFAULT,
586
650
  name=self._parse_task_name(name, func),
587
- execution_timeout=execution_timeout,
588
- schedule_timeout=schedule_timeout,
651
+ execution_timeout=computed_params.execution_timeout,
652
+ schedule_timeout=computed_params.schedule_timeout,
589
653
  parents=parents,
590
- retries=retries,
654
+ retries=computed_params.retries,
591
655
  rate_limits=[r.to_proto() for r in rate_limits],
592
656
  desired_worker_labels={
593
657
  key: transform_desired_worker_label(d)
594
658
  for key, d in desired_worker_labels.items()
595
659
  },
596
- backoff_factor=backoff_factor,
597
- backoff_max_seconds=backoff_max_seconds,
660
+ backoff_factor=computed_params.backoff_factor,
661
+ backoff_max_seconds=computed_params.backoff_max_seconds,
598
662
  concurrency=concurrency,
599
663
  wait_for=wait_for,
600
664
  skip_if=skip_if,
@@ -610,8 +674,8 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
610
674
  def durable_task(
611
675
  self,
612
676
  name: str | None = None,
613
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
614
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
677
+ schedule_timeout: Duration = timedelta(minutes=5),
678
+ execution_timeout: Duration = timedelta(seconds=60),
615
679
  parents: list[Task[TWorkflowInput, Any]] = [],
616
680
  retries: int = 0,
617
681
  rate_limits: list[RateLimit] = [],
@@ -661,6 +725,15 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
661
725
  :returns: A decorator which creates a `Task` object.
662
726
  """
663
727
 
728
+ computed_params = ComputedTaskParameters(
729
+ schedule_timeout=schedule_timeout,
730
+ execution_timeout=execution_timeout,
731
+ retries=retries,
732
+ backoff_factor=backoff_factor,
733
+ backoff_max_seconds=backoff_max_seconds,
734
+ task_defaults=self.config.task_defaults,
735
+ )
736
+
664
737
  def inner(
665
738
  func: Callable[[TWorkflowInput, DurableContext], R]
666
739
  ) -> Task[TWorkflowInput, R]:
@@ -670,17 +743,17 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
670
743
  workflow=self,
671
744
  type=StepType.DEFAULT,
672
745
  name=self._parse_task_name(name, func),
673
- execution_timeout=execution_timeout,
674
- schedule_timeout=schedule_timeout,
746
+ execution_timeout=computed_params.execution_timeout,
747
+ schedule_timeout=computed_params.schedule_timeout,
675
748
  parents=parents,
676
- retries=retries,
749
+ retries=computed_params.retries,
677
750
  rate_limits=[r.to_proto() for r in rate_limits],
678
751
  desired_worker_labels={
679
752
  key: transform_desired_worker_label(d)
680
753
  for key, d in desired_worker_labels.items()
681
754
  },
682
- backoff_factor=backoff_factor,
683
- backoff_max_seconds=backoff_max_seconds,
755
+ backoff_factor=computed_params.backoff_factor,
756
+ backoff_max_seconds=computed_params.backoff_max_seconds,
684
757
  concurrency=concurrency,
685
758
  wait_for=wait_for,
686
759
  skip_if=skip_if,
@@ -696,8 +769,8 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
696
769
  def on_failure_task(
697
770
  self,
698
771
  name: str | None = None,
699
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
700
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
772
+ schedule_timeout: Duration = timedelta(minutes=5),
773
+ execution_timeout: Duration = timedelta(seconds=60),
701
774
  retries: int = 0,
702
775
  rate_limits: list[RateLimit] = [],
703
776
  backoff_factor: float | None = None,
@@ -756,8 +829,8 @@ class Workflow(BaseWorkflow[TWorkflowInput]):
756
829
  def on_success_task(
757
830
  self,
758
831
  name: str | None = None,
759
- schedule_timeout: Duration = DEFAULT_SCHEDULE_TIMEOUT,
760
- execution_timeout: Duration = DEFAULT_EXECUTION_TIMEOUT,
832
+ schedule_timeout: Duration = timedelta(minutes=5),
833
+ execution_timeout: Duration = timedelta(seconds=60),
761
834
  retries: int = 0,
762
835
  rate_limits: list[RateLimit] = [],
763
836
  backoff_factor: float | None = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hatchet-sdk
3
- Version: 1.7.0
3
+ Version: 1.8.1
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Alexander Belanger
@@ -9,7 +9,7 @@ hatchet_sdk/clients/listeners/durable_event_listener.py,sha256=jpqnbZsuouWk3XaOI
9
9
  hatchet_sdk/clients/listeners/pooled_listener.py,sha256=1rodfIeqmHRF-u-PB6cBJbOU8NrvToLTyGigJMydpGo,8496
10
10
  hatchet_sdk/clients/listeners/run_event_listener.py,sha256=rIjBLRF7d7FBoEq7RKbmbOA84lX_hHSU26trwnthqV8,10230
11
11
  hatchet_sdk/clients/listeners/workflow_listener.py,sha256=EhBZZnHiidDLvAc4r54Re_LJXVypinbgTE9qKBybxj8,2054
12
- hatchet_sdk/clients/rest/__init__.py,sha256=Bee4HPFiMGDHx5xbHkxxVbLBz_mDgSZUqh-nIhvsD1k,16511
12
+ hatchet_sdk/clients/rest/__init__.py,sha256=5lTVCDrwielWr5A_dnCL4xNiVWnyS1zLXLNxINM_p4Y,16664
13
13
  hatchet_sdk/clients/rest/api/__init__.py,sha256=XWlkH9iwpQvJHDqKe7kWl3MUzcTOaH-JiFZbki_fg_U,1200
14
14
  hatchet_sdk/clients/rest/api/api_token_api.py,sha256=xzqMH_-wajBA0qLLs5Ta7tYg4FOLq0NjATyhZ1SV9jo,33433
15
15
  hatchet_sdk/clients/rest/api/default_api.py,sha256=Y0jEhatVpdIX_W2MCt_n40K6iKvVegDB70qxexkeZDI,88677
@@ -22,18 +22,18 @@ hatchet_sdk/clients/rest/api/rate_limits_api.py,sha256=e3CIX35R8SkV8LrgLMPCAy6Kz
22
22
  hatchet_sdk/clients/rest/api/slack_api.py,sha256=0xIUw3_1_3hSTn2yw7fLRO5yb38nYLu5aLM7IE2pnwk,21894
23
23
  hatchet_sdk/clients/rest/api/sns_api.py,sha256=1LfhnZEA450uHwtZCoM_wycOeH4UGwfNP1pw4RWSe08,33641
24
24
  hatchet_sdk/clients/rest/api/step_run_api.py,sha256=rqP4UIJSkw8DwbDnlEgupBDWUL0jlVH_Rm7bNGMUoG8,84505
25
- hatchet_sdk/clients/rest/api/task_api.py,sha256=x2m8VTvpYJuWZ58KWS4EnKItlxJgP0Ch8_89t2yKlF8,86367
25
+ hatchet_sdk/clients/rest/api/task_api.py,sha256=rpppMT70gverBsDYaI9owYUwaDVicxIZRqsCBqPfVi8,87464
26
26
  hatchet_sdk/clients/rest/api/tenant_api.py,sha256=LYUdJSsg-O-Y_7cuCDdtDHP5P0BQ9ch8RFLQKIiIreQ,177493
27
27
  hatchet_sdk/clients/rest/api/user_api.py,sha256=NYuEKLeBjXO4q8gyYq1thtbuRm9m3g0R6-q6LIfv83U,115780
28
28
  hatchet_sdk/clients/rest/api/worker_api.py,sha256=56jRXsyK7SDENly2b019EO80d8xOHU4bZnmOmjKY1iQ,33049
29
29
  hatchet_sdk/clients/rest/api/workflow_api.py,sha256=rpPXy5xZDZWo1GXQGLapTC3A5M_spk1zoK_vu_J7SVA,251652
30
30
  hatchet_sdk/clients/rest/api/workflow_run_api.py,sha256=Jvge80z6DhlqL9OuLzUC49OtojeiCuagrMbNBThMYI4,78120
31
- hatchet_sdk/clients/rest/api/workflow_runs_api.py,sha256=_zFmx0DTztKK2xa5BKBYhYqveIbNBc4g9DkNPIJeUxQ,70192
32
- hatchet_sdk/clients/rest/api_client.py,sha256=g1ECXTfdPHyM2yZuX4FZWZwvl5FZ9dEok0EKyeqLkRA,26813
31
+ hatchet_sdk/clients/rest/api/workflow_runs_api.py,sha256=NiDZXDUM7VapgjQ68z8MWPqZKTfz7rPBvPwGG5AJyZg,81997
32
+ hatchet_sdk/clients/rest/api_client.py,sha256=25vNKzpKVhvrGrU8T2YBLbz0Y7K0pKZwiLXF3Oc7tt0,27435
33
33
  hatchet_sdk/clients/rest/api_response.py,sha256=rSuCVGY-HE8X_WwteQP5wyANIuS-L5AmtZEUOwTicak,641
34
34
  hatchet_sdk/clients/rest/configuration.py,sha256=ijGxGorVe8OEikJruwJ0hPk1Rc0OAKOqeUrfcoEiYH8,19333
35
35
  hatchet_sdk/clients/rest/exceptions.py,sha256=5PTEjyGxLeGP8U_qqc79QzR-sN7SOhzBwknSUC-BU4c,6365
36
- hatchet_sdk/clients/rest/models/__init__.py,sha256=BAwgrsAKYGiS9A3ZtK2ROF9xjiKa3qA7Z_NqBOGgzXI,14931
36
+ hatchet_sdk/clients/rest/models/__init__.py,sha256=5Tse5Ljxu7tONV7ePuf9aFWM2oc1ehBaH90BiiAgdYA,15084
37
37
  hatchet_sdk/clients/rest/models/accept_invite_request.py,sha256=_otOis3SuTHl0F_hhYD-rYqgyxCXRn83CK_eU9oMdn4,2427
38
38
  hatchet_sdk/clients/rest/models/api_error.py,sha256=KodK1_cc28CgYGvX1WhIhTN0pAAkgq8PJXReIrMnqBA,3068
39
39
  hatchet_sdk/clients/rest/models/api_errors.py,sha256=RNmnWn1GWlG9xTvpvrTmKq-Pr70x9mcJ4-dNFBemxa8,2917
@@ -165,8 +165,10 @@ hatchet_sdk/clients/rest/models/v1_task_point_metrics.py,sha256=shKqLFLgNAKua865
165
165
  hatchet_sdk/clients/rest/models/v1_task_run_metric.py,sha256=8trEgJ_7AHAmUQi2Qty-v5XVjgN3g7VZ6gzMTjeZ1tY,2504
166
166
  hatchet_sdk/clients/rest/models/v1_task_run_status.py,sha256=tjipWHHNx7g4lUZBdu_DDZwEqSpxPKv06YiE2Q17cXo,753
167
167
  hatchet_sdk/clients/rest/models/v1_task_status.py,sha256=4Hqczjth228k8Y23vIaxAIzTpLaS9mh9I0PrTjY8JRY,742
168
- hatchet_sdk/clients/rest/models/v1_task_summary.py,sha256=GbHZN4fCkysTgfZKjaaWS-8bAFwgX7l5u4hAKLhDlw4,8371
168
+ hatchet_sdk/clients/rest/models/v1_task_summary.py,sha256=Unbtm9n-NexT37F0S0af2mYxYtWhcbuYDlk4EYh15c0,8330
169
169
  hatchet_sdk/clients/rest/models/v1_task_summary_list.py,sha256=0m-xf_lY9BwwbLky9i6fkTYUwh2K9mADHVZoRyF66o4,3510
170
+ hatchet_sdk/clients/rest/models/v1_task_timing.py,sha256=cYO73DfWGPzxvM7hUF-CXiTHfKVsGtgQalcVKoveBwo,5299
171
+ hatchet_sdk/clients/rest/models/v1_task_timing_list.py,sha256=1LFoKqFn11EJ_t7ZeWUFldWOWfG09tN_wTZu3a8e_SM,3509
170
172
  hatchet_sdk/clients/rest/models/v1_trigger_workflow_run_request.py,sha256=P-dC3O7dPr6mGJ2UZYcl3lSQoxKcX-GlYOiWkmNRMj0,3080
171
173
  hatchet_sdk/clients/rest/models/v1_workflow_run.py,sha256=0kgHJ35XjXgNfaJfb1p0KLS1Jw6VAMeMYSdts8EvuYc,5895
172
174
  hatchet_sdk/clients/rest/models/v1_workflow_run_details.py,sha256=vMnc50mT-tjfFlg2BJ58s2HhFvqvuGJaPGYAlTrLVI4,5040
@@ -221,7 +223,7 @@ hatchet_sdk/clients/v1/api_client.py,sha256=mJQUZ3cOxlFJiwWKK5F8jBxcpNZ7A2292Huc
221
223
  hatchet_sdk/config.py,sha256=jJA76BOvVdfOQHy6TKclAvr2qyblcM-Pz5J-hVAdpQ4,3588
222
224
  hatchet_sdk/connection.py,sha256=B5gT5NL9BBB5-l9U_cN6pMlraQk880rEYMnqaK_dgL0,2590
223
225
  hatchet_sdk/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
224
- hatchet_sdk/context/context.py,sha256=djzppHK3VINAtnrmPwLJhpIqzSMA5qKAVd6qB1r6gfM,9518
226
+ hatchet_sdk/context/context.py,sha256=c45AadcE4mm-1ahSoj2khjcdUcYZzqYBQkndxbs2ock,9519
225
227
  hatchet_sdk/context/worker_context.py,sha256=OVcEWvdT_Kpd0nlg61VAPUgIPSFzSLs0aSrXWj-1GX4,974
226
228
  hatchet_sdk/contracts/dispatcher_pb2.py,sha256=wO-x-NiHjMuC55RArpcvQX7QAjpSrjq1n70mFVwOD0Q,14543
227
229
  hatchet_sdk/contracts/dispatcher_pb2.pyi,sha256=iOcGfGtoyvmT58yCrQDvst_o0VPbq1-9rir-0jH_140,18559
@@ -250,7 +252,7 @@ hatchet_sdk/features/runs.py,sha256=9kmn2AM1XVFZS9P_lR-hh6SXwW42Kh73l0WUBl5VJh8,
250
252
  hatchet_sdk/features/scheduled.py,sha256=1kNR8AxN1UlabNroU9TtVbptZEXfqTVE25Gxmh2lABs,8928
251
253
  hatchet_sdk/features/workers.py,sha256=vD6j7GCttu0fm23_XmBMdE0IuX4mUbL0adgMoC8Sk_E,2571
252
254
  hatchet_sdk/features/workflows.py,sha256=PFJsGXTHVfdDBDQ9WcQXcAzr7u-dN7vUpwbZ9fH0ZD8,3976
253
- hatchet_sdk/hatchet.py,sha256=kIRcvHiLgyOc1OY1uytNatUZ8qaYA4beqoKEiqFcRpE,21873
255
+ hatchet_sdk/hatchet.py,sha256=HRa__owQMeSRhtXzEfObap3ZKxUeNq2FJKOZEUVZ_CI,21795
254
256
  hatchet_sdk/labels.py,sha256=nATgxWE3lFxRTnfISEpoIRLGbMfAZsHF4lZTuG4Mfic,182
255
257
  hatchet_sdk/logger.py,sha256=5uOr52T4mImSQm1QvWT8HvZFK5WfPNh3Y1cBQZRFgUQ,333
256
258
  hatchet_sdk/metadata.py,sha256=XkRbhnghJJGCdVvF-uzyGBcNaTqpeQ3uiQvNNP1wyBc,107
@@ -259,9 +261,9 @@ hatchet_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
261
  hatchet_sdk/rate_limit.py,sha256=TwbCuggiZaWpYuo4mjVLlE-z1OfQ2mRBiVvCSaG3lv4,3919
260
262
  hatchet_sdk/runnables/contextvars.py,sha256=6MDocAMmlyiRW37oQ1jyx10tAlJs-xgDjR3xPoPz05g,426
261
263
  hatchet_sdk/runnables/standalone.py,sha256=pCAIS40q9ltkK7K97ff79MzE73_k22ymZdrLdFdFwD8,15233
262
- hatchet_sdk/runnables/task.py,sha256=nZPclBbNaYRMlCLOYi91YU503MiTcGSp92Unh3_nKvs,7533
263
- hatchet_sdk/runnables/types.py,sha256=hF_8kcSWIVXgYspp67RwSfi-CFZJFTbb8mL8BHR8tG8,4889
264
- hatchet_sdk/runnables/workflow.py,sha256=blkUagpVa-zqEpXYk_MXKz3c5uhKPse_0o2L_48nGZo,37221
264
+ hatchet_sdk/runnables/task.py,sha256=5VOgi413eH8Gz9_XBxFTfbfLITTpPJYwRB2ZXshysW8,7014
265
+ hatchet_sdk/runnables/types.py,sha256=OBhqa6rvEaY4ypKtUpKHHyQxOXKYvxao_-Hknu5jVns,4802
266
+ hatchet_sdk/runnables/workflow.py,sha256=Ucjguf3SxyJzYe7R427U76iUOLDoHQMzwOQ7g9xYuQA,39765
265
267
  hatchet_sdk/token.py,sha256=KjIiInwG5Kqd_FO4BSW1x_5Uc7PFbnzIVJqr50-ZldE,779
266
268
  hatchet_sdk/utils/backoff.py,sha256=6B5Rb5nLKw_TqqgpJMYjIBV1PTTtbOMRZCveisVhg_I,353
267
269
  hatchet_sdk/utils/proto_enums.py,sha256=0UybwE3s7TcqmzoQSO8YnhgAKOS8WZXsyPchB8-eksw,1247
@@ -506,7 +508,7 @@ hatchet_sdk/worker/runner/runner.py,sha256=z8ri-viK_avAfF6zgbVNBc-rztFDbxSwng3RH
506
508
  hatchet_sdk/worker/runner/utils/capture_logs.py,sha256=nHRPSiDBqzhObM7i2X7t03OupVFnE7kQBdR2Ckgg-2w,2709
507
509
  hatchet_sdk/worker/worker.py,sha256=SfUeYYGfPDVa7Hr1Tdgrzn_A0T-e_apIzW26BhsiB70,16101
508
510
  hatchet_sdk/workflow_run.py,sha256=ZwH0HLFGFVXz6jbiqSv4w0Om2XuR52Tzzw6LH4y65jQ,2765
509
- hatchet_sdk-1.7.0.dist-info/METADATA,sha256=-bxsuAlZWUGADJ4lSl2TaRvobNsFujBDtHSik2_JYog,3635
510
- hatchet_sdk-1.7.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
511
- hatchet_sdk-1.7.0.dist-info/entry_points.txt,sha256=Un_76pcLse-ZGBlwebhQpnTPyQrripeHW8J7qmEpGOk,1400
512
- hatchet_sdk-1.7.0.dist-info/RECORD,,
511
+ hatchet_sdk-1.8.1.dist-info/METADATA,sha256=OGkuC1TmJprUiDEHQ9i1eDjhDS6SxMsaX7A22oApNSA,3635
512
+ hatchet_sdk-1.8.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
513
+ hatchet_sdk-1.8.1.dist-info/entry_points.txt,sha256=Un_76pcLse-ZGBlwebhQpnTPyQrripeHW8J7qmEpGOk,1400
514
+ hatchet_sdk-1.8.1.dist-info/RECORD,,