modAL 1.1.3__tar.gz → 1.1.3.dev0__tar.gz
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-1.1.3 → modal-1.1.3.dev0}/PKG-INFO +1 -1
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_functions.py +25 -48
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/client.pyi +10 -2
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/functions.pyi +6 -6
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/image.py +1 -2
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/image.pyi +2 -4
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/parallel_map.py +2 -21
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/parallel_map.pyi +0 -3
- {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api.proto +3 -8
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2.py +493 -493
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2.pyi +6 -15
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_version/__init__.py +1 -1
- {modal-1.1.3 → modal-1.1.3.dev0}/LICENSE +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/README.md +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/__main__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_clustered_functions.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_clustered_functions.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_container_entrypoint.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_ipython.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_location.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_object.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_output.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_partial_function.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_pty.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_resolver.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_resources.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/asgi.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/execution_context.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/telemetry.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_serialization.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_traceback.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_tunnel.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_tunnel.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_type_manager.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/app_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/async_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/blob_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/deprecation.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/docker_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/function_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/git_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/hash_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/http_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/logger.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/mount_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/name_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/package_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/shell_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/time_utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/tblib.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/_watcher.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/app.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/app.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2023.12.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2024.04.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2024.10.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2025.06.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/README.md +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/base-images.json +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/call_graph.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/_download.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/_traceback.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/app.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/cluster.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/config.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/container.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/dict.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/entry_point.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/environment.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/import_refs.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/launch.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/network_file_system.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/profile.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/launch_instance_ssh.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/run_marimo.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/vscode.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/queues.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/run.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/secret.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/token.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/utils.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/volume.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/client.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cls.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/cls.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/config.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/container_process.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/container_process.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/dict.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/dict.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/environments.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/environments.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/exception.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/flash.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/flash.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/ipython.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/file_io.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/file_io.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/file_pattern_matcher.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/functions.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/gpu.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/io_streams.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/io_streams.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/mount.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/mount.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/network_file_system.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/network_file_system.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/object.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/object.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/output.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/partial_function.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/partial_function.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/proxy.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/proxy.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/py.typed +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/queue.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/queue.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/retries.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/runner.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/runner.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/running_app.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/sandbox.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/sandbox.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/schedule.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/scheduler_placement.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/secret.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/secret.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/serving.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/serving.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/snapshot.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/snapshot.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/stream_type.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/token_flow.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/token_flow.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/volume.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal/volume.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/requires.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/top_level.txt +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/__init__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_grpc.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options.proto +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_grpc.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/py.typed +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/modal_version/__main__.py +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/pyproject.toml +0 -0
- {modal-1.1.3 → modal-1.1.3.dev0}/setup.cfg +0 -0
|
@@ -100,10 +100,6 @@ 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
|
-
)
|
|
107
103
|
|
|
108
104
|
|
|
109
105
|
@dataclasses.dataclass
|
|
@@ -304,7 +300,11 @@ class _Invocation:
|
|
|
304
300
|
|
|
305
301
|
while True:
|
|
306
302
|
item = await self._get_single_output(ctx.input_jwt)
|
|
307
|
-
if item.result.status in
|
|
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
|
|
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,7 +411,6 @@ class _InputPlaneInvocation:
|
|
|
411
411
|
client: _Client,
|
|
412
412
|
input_item: api_pb2.FunctionPutInputsItem,
|
|
413
413
|
function_id: str,
|
|
414
|
-
retry_policy: api_pb2.FunctionRetryPolicy,
|
|
415
414
|
input_plane_region: str,
|
|
416
415
|
):
|
|
417
416
|
self.stub = stub
|
|
@@ -419,7 +418,6 @@ class _InputPlaneInvocation:
|
|
|
419
418
|
self.attempt_token = attempt_token
|
|
420
419
|
self.input_item = input_item
|
|
421
420
|
self.function_id = function_id
|
|
422
|
-
self.retry_policy = retry_policy
|
|
423
421
|
self.input_plane_region = input_plane_region
|
|
424
422
|
|
|
425
423
|
@staticmethod
|
|
@@ -455,15 +453,11 @@ class _InputPlaneInvocation:
|
|
|
455
453
|
response = await retry_transient_errors(stub.AttemptStart, request, metadata=metadata)
|
|
456
454
|
attempt_token = response.attempt_token
|
|
457
455
|
|
|
458
|
-
return _InputPlaneInvocation(
|
|
459
|
-
stub, attempt_token, client, input_item, function_id, response.retry_policy, input_plane_region
|
|
460
|
-
)
|
|
456
|
+
return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id, input_plane_region)
|
|
461
457
|
|
|
462
458
|
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
|
-
|
|
466
459
|
# 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
|
|
467
461
|
internal_failure_count = 0
|
|
468
462
|
while True:
|
|
469
463
|
await_request = api_pb2.AttemptAwaitRequest(
|
|
@@ -480,48 +474,32 @@ class _InputPlaneInvocation:
|
|
|
480
474
|
)
|
|
481
475
|
|
|
482
476
|
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
|
-
|
|
488
477
|
if await_response.output.result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
|
|
489
478
|
internal_failure_count += 1
|
|
490
479
|
# Limit the number of times we retry
|
|
491
480
|
if internal_failure_count < MAX_INTERNAL_FAILURE_COUNT:
|
|
492
481
|
# For system failures on the server, we retry immediately,
|
|
493
482
|
# and the failure does not count towards the retry policy.
|
|
494
|
-
|
|
483
|
+
retry_request = api_pb2.AttemptRetryRequest(
|
|
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
|
|
495
496
|
continue
|
|
496
497
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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
|
|
498
|
+
control_plane_stub = self.client.stub
|
|
499
|
+
# Note: Blob download is done on the control plane stub, not the input plane stub!
|
|
500
|
+
return await _process_result(
|
|
501
|
+
await_response.output.result, await_response.output.data_format, control_plane_stub, self.client
|
|
502
|
+
)
|
|
525
503
|
|
|
526
504
|
async def run_generator(self):
|
|
527
505
|
items_received = 0
|
|
@@ -2015,7 +1993,6 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2015
1993
|
fc: _FunctionCall[Any] = _FunctionCall._from_loader(_load, rep, hydrate_lazily=True)
|
|
2016
1994
|
# We already know the object ID, so we can set it directly
|
|
2017
1995
|
fc._object_id = function_call_id
|
|
2018
|
-
fc._client = client
|
|
2019
1996
|
return fc
|
|
2020
1997
|
|
|
2021
1998
|
@staticmethod
|
|
@@ -29,7 +29,11 @@ class _Client:
|
|
|
29
29
|
_snapshotted: bool
|
|
30
30
|
|
|
31
31
|
def __init__(
|
|
32
|
-
self,
|
|
32
|
+
self,
|
|
33
|
+
server_url: str,
|
|
34
|
+
client_type: int,
|
|
35
|
+
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
+
version: str = "1.1.3.dev0",
|
|
33
37
|
):
|
|
34
38
|
"""mdmd:hidden
|
|
35
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -156,7 +160,11 @@ class Client:
|
|
|
156
160
|
_snapshotted: bool
|
|
157
161
|
|
|
158
162
|
def __init__(
|
|
159
|
-
self,
|
|
163
|
+
self,
|
|
164
|
+
server_url: str,
|
|
165
|
+
client_type: int,
|
|
166
|
+
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
+
version: str = "1.1.3.dev0",
|
|
160
168
|
):
|
|
161
169
|
"""mdmd:hidden
|
|
162
170
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -433,7 +433,7 @@ class Function(
|
|
|
433
433
|
|
|
434
434
|
_call_generator: ___call_generator_spec[typing_extensions.Self]
|
|
435
435
|
|
|
436
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
436
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
437
437
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
438
438
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
439
439
|
...
|
|
@@ -442,7 +442,7 @@ class Function(
|
|
|
442
442
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
443
443
|
...
|
|
444
444
|
|
|
445
|
-
remote: __remote_spec[modal._functions.
|
|
445
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
446
446
|
|
|
447
447
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
448
448
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -469,7 +469,7 @@ class Function(
|
|
|
469
469
|
"""
|
|
470
470
|
...
|
|
471
471
|
|
|
472
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
472
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
473
473
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
474
474
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
475
475
|
|
|
@@ -493,7 +493,7 @@ class Function(
|
|
|
493
493
|
...
|
|
494
494
|
|
|
495
495
|
_experimental_spawn: ___experimental_spawn_spec[
|
|
496
|
-
modal._functions.
|
|
496
|
+
modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
|
|
497
497
|
]
|
|
498
498
|
|
|
499
499
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
|
|
@@ -502,7 +502,7 @@ class Function(
|
|
|
502
502
|
|
|
503
503
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
|
|
504
504
|
|
|
505
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
505
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
506
506
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
507
507
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
508
508
|
|
|
@@ -523,7 +523,7 @@ class Function(
|
|
|
523
523
|
"""
|
|
524
524
|
...
|
|
525
525
|
|
|
526
|
-
spawn: __spawn_spec[modal._functions.
|
|
526
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
527
527
|
|
|
528
528
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
529
529
|
"""Return the inner Python object wrapped by this Modal Function."""
|
|
@@ -1356,8 +1356,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
1356
1356
|
image = modal.Image.debian_slim().uv_sync()
|
|
1357
1357
|
```
|
|
1358
1358
|
|
|
1359
|
-
The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
|
|
1360
|
-
`uv_project_dir` is relative to the current working directory of where `modal` is called.
|
|
1359
|
+
The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
|
|
1361
1360
|
|
|
1362
1361
|
Added in v1.1.0.
|
|
1363
1362
|
"""
|
|
@@ -524,8 +524,7 @@ class _Image(modal._object._Object):
|
|
|
524
524
|
image = modal.Image.debian_slim().uv_sync()
|
|
525
525
|
```
|
|
526
526
|
|
|
527
|
-
The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
|
|
528
|
-
`uv_project_dir` is relative to the current working directory of where `modal` is called.
|
|
527
|
+
The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
|
|
529
528
|
|
|
530
529
|
Added in v1.1.0.
|
|
531
530
|
"""
|
|
@@ -1369,8 +1368,7 @@ class Image(modal.object.Object):
|
|
|
1369
1368
|
image = modal.Image.debian_slim().uv_sync()
|
|
1370
1369
|
```
|
|
1371
1370
|
|
|
1372
|
-
The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
|
|
1373
|
-
`uv_project_dir` is relative to the current working directory of where `modal` is called.
|
|
1371
|
+
The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
|
|
1374
1372
|
|
|
1375
1373
|
Added in v1.1.0.
|
|
1376
1374
|
"""
|
|
@@ -673,11 +673,9 @@ async def _map_invocation_inputplane(
|
|
|
673
673
|
# any reason).
|
|
674
674
|
max_inputs_outstanding = MAX_INPUTS_OUTSTANDING_DEFAULT
|
|
675
675
|
|
|
676
|
-
#
|
|
677
|
-
# We'll update the retry policy with the actual user-specified retry policy
|
|
678
|
-
# from the server in the first MapStartOrContinue response.
|
|
676
|
+
# Input plane does not yet return a retry policy. So we currently disable retries.
|
|
679
677
|
retry_policy = api_pb2.FunctionRetryPolicy(
|
|
680
|
-
retries=0,
|
|
678
|
+
retries=0, # Input plane does not yet return a retry policy. So only retry server failures for now.
|
|
681
679
|
initial_delay_ms=1000,
|
|
682
680
|
max_delay_ms=1000,
|
|
683
681
|
backoff_coefficient=1.0,
|
|
@@ -773,17 +771,10 @@ async def _map_invocation_inputplane(
|
|
|
773
771
|
|
|
774
772
|
map_items_manager.handle_put_continue_response(response_items_idx_tuple)
|
|
775
773
|
|
|
776
|
-
# Set the function call id and actual retry policy with the data from the first response.
|
|
777
|
-
# This conditional is skipped for subsequent iterations of this for-loop.
|
|
778
774
|
if function_call_id is None:
|
|
779
775
|
function_call_id = response.function_call_id
|
|
780
776
|
function_call_id_received.set()
|
|
781
777
|
max_inputs_outstanding = response.max_inputs_outstanding or MAX_INPUTS_OUTSTANDING_DEFAULT
|
|
782
|
-
map_items_manager.set_retry_policy(response.retry_policy)
|
|
783
|
-
# Update the retry policy for the first batch of inputs.
|
|
784
|
-
# Subsequent batches will have the correct user-specified retry policy
|
|
785
|
-
# set by the updated _MapItemsManager.
|
|
786
|
-
map_items_manager.update_items_retry_policy(response.retry_policy)
|
|
787
778
|
yield
|
|
788
779
|
|
|
789
780
|
async def check_lost_inputs():
|
|
@@ -1484,9 +1475,6 @@ class _MapItemContext:
|
|
|
1484
1475
|
retry_count=self.retry_manager.retry_count,
|
|
1485
1476
|
)
|
|
1486
1477
|
|
|
1487
|
-
def set_retry_policy(self, retry_policy: api_pb2.FunctionRetryPolicy):
|
|
1488
|
-
self.retry_manager = RetryManager(retry_policy)
|
|
1489
|
-
|
|
1490
1478
|
def handle_retry_response(self, input_jwt: str):
|
|
1491
1479
|
self.input_jwt.set_result(input_jwt)
|
|
1492
1480
|
self.state = _MapItemState.WAITING_FOR_OUTPUT
|
|
@@ -1523,9 +1511,6 @@ class _MapItemsManager:
|
|
|
1523
1511
|
self._sync_client_retries_enabled = sync_client_retries_enabled
|
|
1524
1512
|
self._is_input_plane_instance = is_input_plane_instance
|
|
1525
1513
|
|
|
1526
|
-
def set_retry_policy(self, retry_policy: api_pb2.FunctionRetryPolicy):
|
|
1527
|
-
self._retry_policy = retry_policy
|
|
1528
|
-
|
|
1529
1514
|
async def add_items(self, items: list[api_pb2.FunctionPutInputsItem]):
|
|
1530
1515
|
for item in items:
|
|
1531
1516
|
# acquire semaphore to limit the number of inputs in progress
|
|
@@ -1555,10 +1540,6 @@ class _MapItemsManager:
|
|
|
1555
1540
|
async def prepare_items_for_retry(self, retriable_idxs: list[int]) -> list[api_pb2.FunctionRetryInputsItem]:
|
|
1556
1541
|
return [await self._item_context[idx].prepare_item_for_retry() for idx in retriable_idxs]
|
|
1557
1542
|
|
|
1558
|
-
def update_items_retry_policy(self, retry_policy: api_pb2.FunctionRetryPolicy):
|
|
1559
|
-
for ctx in self._item_context.values():
|
|
1560
|
-
ctx.set_retry_policy(retry_policy)
|
|
1561
|
-
|
|
1562
1543
|
def get_input_jwts_waiting_for_output(self) -> list[str]:
|
|
1563
1544
|
"""
|
|
1564
1545
|
Returns a list of input_jwts for inputs that are waiting for output.
|
|
@@ -406,7 +406,6 @@ class _MapItemContext:
|
|
|
406
406
|
...
|
|
407
407
|
|
|
408
408
|
async def prepare_item_for_retry(self) -> modal_proto.api_pb2.FunctionRetryInputsItem: ...
|
|
409
|
-
def set_retry_policy(self, retry_policy: modal_proto.api_pb2.FunctionRetryPolicy): ...
|
|
410
409
|
def handle_retry_response(self, input_jwt: str): ...
|
|
411
410
|
async def create_map_start_or_continue_item(self, idx: int) -> modal_proto.api_pb2.MapStartOrContinueItem: ...
|
|
412
411
|
|
|
@@ -423,13 +422,11 @@ class _MapItemsManager:
|
|
|
423
422
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
424
423
|
...
|
|
425
424
|
|
|
426
|
-
def set_retry_policy(self, retry_policy: modal_proto.api_pb2.FunctionRetryPolicy): ...
|
|
427
425
|
async def add_items(self, items: list[modal_proto.api_pb2.FunctionPutInputsItem]): ...
|
|
428
426
|
async def add_items_inputplane(self, items: list[modal_proto.api_pb2.MapStartOrContinueItem]): ...
|
|
429
427
|
async def prepare_items_for_retry(
|
|
430
428
|
self, retriable_idxs: list[int]
|
|
431
429
|
) -> list[modal_proto.api_pb2.FunctionRetryInputsItem]: ...
|
|
432
|
-
def update_items_retry_policy(self, retry_policy: modal_proto.api_pb2.FunctionRetryPolicy): ...
|
|
433
430
|
def get_input_jwts_waiting_for_output(self) -> list[str]:
|
|
434
431
|
"""Returns a list of input_jwts for inputs that are waiting for output."""
|
|
435
432
|
...
|
|
@@ -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; // TODO(ben-okeefe) TODO(nathan): Not currently used
|
|
622
622
|
}
|
|
623
623
|
|
|
624
624
|
message AuthTokenGetRequest {
|
|
@@ -1976,8 +1976,6 @@ message GenericResult { // Used for both tasks and function outputs
|
|
|
1976
1976
|
// Terminates the function and all remaining inputs.
|
|
1977
1977
|
GENERIC_STATUS_INIT_FAILURE = 5;
|
|
1978
1978
|
GENERIC_STATUS_INTERNAL_FAILURE = 6;
|
|
1979
|
-
// Used when sandboxes are terminated due to idle_timeout
|
|
1980
|
-
GENERIC_STATUS_IDLE_TIMEOUT = 7;
|
|
1981
1979
|
}
|
|
1982
1980
|
|
|
1983
1981
|
GenericStatus status = 1; // Status of the task or function output.
|
|
@@ -2169,7 +2167,7 @@ message MapStartOrContinueResponse {
|
|
|
2169
2167
|
string function_call_id = 2;
|
|
2170
2168
|
uint32 max_inputs_outstanding = 3;
|
|
2171
2169
|
repeated string attempt_tokens = 4;
|
|
2172
|
-
FunctionRetryPolicy retry_policy = 5;
|
|
2170
|
+
FunctionRetryPolicy retry_policy = 5; // TODO(ben-okeefe): Not currently used
|
|
2173
2171
|
}
|
|
2174
2172
|
|
|
2175
2173
|
message MethodDefinition {
|
|
@@ -2575,7 +2573,7 @@ message Sandbox {
|
|
|
2575
2573
|
Resources resources = 5;
|
|
2576
2574
|
CloudProvider cloud_provider = 6; // Deprecated at some point
|
|
2577
2575
|
|
|
2578
|
-
uint32 timeout_secs = 7;
|
|
2576
|
+
uint32 timeout_secs = 7;
|
|
2579
2577
|
|
|
2580
2578
|
optional string workdir = 8;
|
|
2581
2579
|
|
|
@@ -2637,9 +2635,6 @@ message Sandbox {
|
|
|
2637
2635
|
map<string, bool> experimental_options = 31;
|
|
2638
2636
|
|
|
2639
2637
|
repeated string preload_path_prefixes = 32; // Internal use only.
|
|
2640
|
-
|
|
2641
|
-
// Optional idle timeout in seconds. If set, the sandbox will be terminated after being idle for this duration.
|
|
2642
|
-
optional uint32 idle_timeout_secs = 33;
|
|
2643
2638
|
}
|
|
2644
2639
|
|
|
2645
2640
|
message SandboxCreateRequest {
|