modal 1.1.3.dev1__py3-none-any.whl → 1.1.3.dev3__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.
- modal/_functions.py +47 -25
- modal/client.pyi +2 -2
- {modal-1.1.3.dev1.dist-info → modal-1.1.3.dev3.dist-info}/METADATA +1 -1
- {modal-1.1.3.dev1.dist-info → modal-1.1.3.dev3.dist-info}/RECORD +11 -11
- modal_proto/api.proto +1 -1
- modal_proto/api_pb2.pyi +1 -2
- modal_version/__init__.py +1 -1
- {modal-1.1.3.dev1.dist-info → modal-1.1.3.dev3.dist-info}/WHEEL +0 -0
- {modal-1.1.3.dev1.dist-info → modal-1.1.3.dev3.dist-info}/entry_points.txt +0 -0
- {modal-1.1.3.dev1.dist-info → modal-1.1.3.dev3.dist-info}/licenses/LICENSE +0 -0
- {modal-1.1.3.dev1.dist-info → modal-1.1.3.dev3.dist-info}/top_level.txt +0 -0
modal/_functions.py
CHANGED
@@ -100,6 +100,10 @@ if TYPE_CHECKING:
|
|
100
100
|
import modal.partial_function
|
101
101
|
|
102
102
|
MAX_INTERNAL_FAILURE_COUNT = 8
|
103
|
+
TERMINAL_STATUSES = (
|
104
|
+
api_pb2.GenericResult.GENERIC_STATUS_SUCCESS,
|
105
|
+
api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
|
106
|
+
)
|
103
107
|
|
104
108
|
|
105
109
|
@dataclasses.dataclass
|
@@ -300,11 +304,7 @@ class _Invocation:
|
|
300
304
|
|
301
305
|
while True:
|
302
306
|
item = await self._get_single_output(ctx.input_jwt)
|
303
|
-
if item.result.status in
|
304
|
-
api_pb2.GenericResult.GENERIC_STATUS_SUCCESS,
|
305
|
-
api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
|
306
|
-
):
|
307
|
-
# success or cancellations are "final" results
|
307
|
+
if item.result.status in TERMINAL_STATUSES:
|
308
308
|
return await _process_result(item.result, item.data_format, self.stub, self.client)
|
309
309
|
|
310
310
|
if item.result.status != api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
|
@@ -411,6 +411,7 @@ class _InputPlaneInvocation:
|
|
411
411
|
client: _Client,
|
412
412
|
input_item: api_pb2.FunctionPutInputsItem,
|
413
413
|
function_id: str,
|
414
|
+
retry_policy: api_pb2.FunctionRetryPolicy,
|
414
415
|
input_plane_region: str,
|
415
416
|
):
|
416
417
|
self.stub = stub
|
@@ -418,6 +419,7 @@ class _InputPlaneInvocation:
|
|
418
419
|
self.attempt_token = attempt_token
|
419
420
|
self.input_item = input_item
|
420
421
|
self.function_id = function_id
|
422
|
+
self.retry_policy = retry_policy
|
421
423
|
self.input_plane_region = input_plane_region
|
422
424
|
|
423
425
|
@staticmethod
|
@@ -453,11 +455,15 @@ class _InputPlaneInvocation:
|
|
453
455
|
response = await retry_transient_errors(stub.AttemptStart, request, metadata=metadata)
|
454
456
|
attempt_token = response.attempt_token
|
455
457
|
|
456
|
-
return _InputPlaneInvocation(
|
458
|
+
return _InputPlaneInvocation(
|
459
|
+
stub, attempt_token, client, input_item, function_id, response.retry_policy, input_plane_region
|
460
|
+
)
|
457
461
|
|
458
462
|
async def run_function(self) -> Any:
|
463
|
+
# User errors including timeouts are managed by the user-specified retry policy.
|
464
|
+
user_retry_manager = RetryManager(self.retry_policy)
|
465
|
+
|
459
466
|
# This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
|
460
|
-
# TODO(ryan): add logic to retry for user defined retry policy
|
461
467
|
internal_failure_count = 0
|
462
468
|
while True:
|
463
469
|
await_request = api_pb2.AttemptAwaitRequest(
|
@@ -474,32 +480,48 @@ class _InputPlaneInvocation:
|
|
474
480
|
)
|
475
481
|
|
476
482
|
if await_response.HasField("output"):
|
483
|
+
if await_response.output.result.status in TERMINAL_STATUSES:
|
484
|
+
return await _process_result(
|
485
|
+
await_response.output.result, await_response.output.data_format, self.client.stub, self.client
|
486
|
+
)
|
487
|
+
|
477
488
|
if await_response.output.result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
|
478
489
|
internal_failure_count += 1
|
479
490
|
# Limit the number of times we retry
|
480
491
|
if internal_failure_count < MAX_INTERNAL_FAILURE_COUNT:
|
481
492
|
# For system failures on the server, we retry immediately,
|
482
493
|
# and the failure does not count towards the retry policy.
|
483
|
-
|
484
|
-
function_id=self.function_id,
|
485
|
-
parent_input_id=current_input_id() or "",
|
486
|
-
input=self.input_item,
|
487
|
-
attempt_token=self.attempt_token,
|
488
|
-
)
|
489
|
-
# TODO(ryan): Add exponential backoff?
|
490
|
-
retry_response = await retry_transient_errors(
|
491
|
-
self.stub.AttemptRetry,
|
492
|
-
retry_request,
|
493
|
-
metadata=metadata,
|
494
|
-
)
|
495
|
-
self.attempt_token = retry_response.attempt_token
|
494
|
+
self.attempt_token = await self._retry_input(metadata)
|
496
495
|
continue
|
497
496
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
497
|
+
# We add delays between retries for non-internal failures.
|
498
|
+
delay_ms = user_retry_manager.get_delay_ms()
|
499
|
+
if delay_ms is None:
|
500
|
+
# No more retries either because we reached the retry limit or user didn't set a retry policy
|
501
|
+
# and the limit defaulted to 0.
|
502
|
+
# An unsuccessful status should raise an error when it's converted to an exception.
|
503
|
+
# Note: Blob download is done on the control plane stub not the input plane stub!
|
504
|
+
return await _process_result(
|
505
|
+
await_response.output.result, await_response.output.data_format, self.client.stub, self.client
|
506
|
+
)
|
507
|
+
await asyncio.sleep(delay_ms / 1000)
|
508
|
+
|
509
|
+
await self._retry_input(metadata)
|
510
|
+
|
511
|
+
async def _retry_input(self, metadata: list[tuple[str, str]]) -> str:
|
512
|
+
retry_request = api_pb2.AttemptRetryRequest(
|
513
|
+
function_id=self.function_id,
|
514
|
+
parent_input_id=current_input_id() or "",
|
515
|
+
input=self.input_item,
|
516
|
+
attempt_token=self.attempt_token,
|
517
|
+
)
|
518
|
+
# TODO(ryan): Add exponential backoff?
|
519
|
+
retry_response = await retry_transient_errors(
|
520
|
+
self.stub.AttemptRetry,
|
521
|
+
retry_request,
|
522
|
+
metadata=metadata,
|
523
|
+
)
|
524
|
+
return retry_response.attempt_token
|
503
525
|
|
504
526
|
async def run_generator(self):
|
505
527
|
items_received = 0
|
modal/client.pyi
CHANGED
@@ -33,7 +33,7 @@ class _Client:
|
|
33
33
|
server_url: str,
|
34
34
|
client_type: int,
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
36
|
-
version: str = "1.1.3.
|
36
|
+
version: str = "1.1.3.dev3",
|
37
37
|
):
|
38
38
|
"""mdmd:hidden
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
@@ -164,7 +164,7 @@ class Client:
|
|
164
164
|
server_url: str,
|
165
165
|
client_type: int,
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
167
|
-
version: str = "1.1.3.
|
167
|
+
version: str = "1.1.3.dev3",
|
168
168
|
):
|
169
169
|
"""mdmd:hidden
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
@@ -3,7 +3,7 @@ modal/__main__.py,sha256=45H-GtwzaDfN-1nP4_HYvzN3s7AG_HXR4-ynrsjO_OI,2803
|
|
3
3
|
modal/_clustered_functions.py,sha256=zmrKbptRbqp4euS3LWncKaLXb8Kjj4YreusOzpEpRMk,2856
|
4
4
|
modal/_clustered_functions.pyi,sha256=_wtFjWocGf1WgI-qYBpbJPArNkg2H9JV7BVaGgMesEQ,1103
|
5
5
|
modal/_container_entrypoint.py,sha256=a1HAQYh1gGpqHuhSw6AW7XDYHztbeYr5a8iNnfCnoks,29023
|
6
|
-
modal/_functions.py,sha256=
|
6
|
+
modal/_functions.py,sha256=dEUtjBxPxMfS-HW98JCXxSJbeSAVcIHQTWzojWZQIcY,88862
|
7
7
|
modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
|
8
8
|
modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
|
9
9
|
modal/_object.py,sha256=gwsLdXb-Ecd8nH8LVCo8oVZPzzdyo9BrN1DjgQmsSuM,11967
|
@@ -22,7 +22,7 @@ modal/app.py,sha256=hJU3DGzP5GwYRmBj57XajljkQtLxkKftxXih2TYRcKo,48047
|
|
22
22
|
modal/app.pyi,sha256=0U2xVKD3yfHe5l2bcihTDjPl__tzOvx1AIYOTebu-5o,43375
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
24
24
|
modal/client.py,sha256=kyAIVB3Ay-XKJizQ_1ufUFB__EagV0MLmHJpyYyJ7J0,18636
|
25
|
-
modal/client.pyi,sha256=
|
25
|
+
modal/client.pyi,sha256=F0rZ98XW0UFZ-AReWqLTuvub4N5TiXZxJT369UTg330,15829
|
26
26
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=-qSfYAQvIoO_l2wsCCGTG5ZUwQieNKXdAO00yP1-LYU,7394
|
28
28
|
modal/cls.py,sha256=1mBcExFrLDTZwkD3Dzu8F26_CL0CGktOV9pE60Y8g_E,40689
|
@@ -153,7 +153,7 @@ modal/experimental/__init__.py,sha256=dPBPpxsmjZMLF3YjRrXoTvT01pl65wxi4UdFZsOem3
|
|
153
153
|
modal/experimental/flash.py,sha256=viXQumCIFp5VFsPFURdFTBTjP_QnsAi8nSWXAMmfjeQ,19744
|
154
154
|
modal/experimental/flash.pyi,sha256=A8_qJGtGoXEzKDdHbvhmCw7oqfneFEvJQK3ZdTOvUdU,10830
|
155
155
|
modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
|
156
|
-
modal-1.1.3.
|
156
|
+
modal-1.1.3.dev3.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
157
157
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
158
158
|
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
159
159
|
modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
|
@@ -161,10 +161,10 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
|
|
161
161
|
modal_docs/mdmd/mdmd.py,sha256=tUTImNd4UMFk1opkaw8J672gX8AkBO5gbY2S_NMxsxs,7140
|
162
162
|
modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
|
163
163
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
164
|
-
modal_proto/api.proto,sha256=
|
164
|
+
modal_proto/api.proto,sha256=COEYvEVL-RpN0laad0PAhVHP0ChZNGAnjimqPQ6pwlw,104712
|
165
165
|
modal_proto/api_grpc.py,sha256=AWsKZFdXr_T6LpWGlMM6BDY30RdOPjqgoPMijR-R1lI,127964
|
166
166
|
modal_proto/api_pb2.py,sha256=yoKWv2SoqnPhZ4cwb6bxoljOvDJeoBI9-TMLgd6PZ0c,366803
|
167
|
-
modal_proto/api_pb2.pyi,sha256
|
167
|
+
modal_proto/api_pb2.pyi,sha256=9BnK5J8cmqeKgo57jW4WS5qlGVJfyVLP-AeuA__tWmU,506001
|
168
168
|
modal_proto/api_pb2_grpc.py,sha256=kDZBX6i1KdRpm4P3c2wdRbGe3XOFtqGHSbWE0vOe4F4,276062
|
169
169
|
modal_proto/api_pb2_grpc.pyi,sha256=s1hjXmqaB3jGCSgnOouzncdfMVX0umPZd4TC1zObhgU,64579
|
170
170
|
modal_proto/modal_api_grpc.py,sha256=faBxtXAqoz6ei8ntNu1MQTL859FFHH_LZww_FP9wubw,19311
|
@@ -176,10 +176,10 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
|
|
176
176
|
modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
177
177
|
modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
|
178
178
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
179
|
-
modal_version/__init__.py,sha256=
|
179
|
+
modal_version/__init__.py,sha256=cXuBYyPLeQ0NDGD3GpT3f4jI8wrH0Ydql9I7MV77hTg,120
|
180
180
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
181
|
-
modal-1.1.3.
|
182
|
-
modal-1.1.3.
|
183
|
-
modal-1.1.3.
|
184
|
-
modal-1.1.3.
|
185
|
-
modal-1.1.3.
|
181
|
+
modal-1.1.3.dev3.dist-info/METADATA,sha256=TxKaMMdWS6VkASan7YRw_yFFFKAn-OCMViJvA7N2RHA,2459
|
182
|
+
modal-1.1.3.dev3.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
183
|
+
modal-1.1.3.dev3.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
184
|
+
modal-1.1.3.dev3.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
185
|
+
modal-1.1.3.dev3.dist-info/RECORD,,
|
modal_proto/api.proto
CHANGED
@@ -618,7 +618,7 @@ message AttemptStartRequest {
|
|
618
618
|
|
619
619
|
message AttemptStartResponse {
|
620
620
|
string attempt_token = 1;
|
621
|
-
FunctionRetryPolicy retry_policy = 2;
|
621
|
+
FunctionRetryPolicy retry_policy = 2;
|
622
622
|
}
|
623
623
|
|
624
624
|
message AuthTokenGetRequest {
|
modal_proto/api_pb2.pyi
CHANGED
@@ -1959,8 +1959,7 @@ class AttemptStartResponse(google.protobuf.message.Message):
|
|
1959
1959
|
RETRY_POLICY_FIELD_NUMBER: builtins.int
|
1960
1960
|
attempt_token: builtins.str
|
1961
1961
|
@property
|
1962
|
-
def retry_policy(self) -> global___FunctionRetryPolicy:
|
1963
|
-
"""TODO(ben-okeefe) TODO(nathan): Not currently used"""
|
1962
|
+
def retry_policy(self) -> global___FunctionRetryPolicy: ...
|
1964
1963
|
def __init__(
|
1965
1964
|
self,
|
1966
1965
|
*,
|
modal_version/__init__.py
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|