modal 1.0.6.dev8__tar.gz → 1.0.6.dev10__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.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/PKG-INFO +1 -1
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/blob_utils.py +22 -9
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/function_utils.py +9 -2
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/client.pyi +2 -2
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/api.proto +9 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/api_grpc.py +16 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/api_pb2.py +711 -691
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/api_pb2.pyi +30 -1
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/api_pb2_grpc.py +33 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/api_pb2_grpc.pyi +10 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/modal_api_grpc.py +1 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_version/__init__.py +1 -1
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/LICENSE +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/README.md +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/__main__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_clustered_functions.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_clustered_functions.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_container_entrypoint.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_functions.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_ipython.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_location.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_object.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_output.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_partial_function.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_pty.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_resolver.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_resources.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/asgi.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/execution_context.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/telemetry.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_serialization.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_traceback.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_tunnel.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_tunnel.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_type_manager.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/app_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/async_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/deprecation.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/docker_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/git_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/hash_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/http_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/logger.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/mount_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/name_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/package_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/shell_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_utils/time_utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_vendor/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_vendor/tblib.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/_watcher.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/app.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/app.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/call_graph.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/_download.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/_traceback.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/app.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/cluster.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/config.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/container.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/dict.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/entry_point.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/environment.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/import_refs.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/launch.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/network_file_system.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/profile.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/programs/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/programs/vscode.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/queues.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/run.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/secret.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/token.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/utils.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cli/volume.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/client.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cls.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/cls.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/config.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/container_process.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/container_process.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/dict.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/dict.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/environments.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/environments.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/exception.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/experimental/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/experimental/ipython.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/file_io.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/file_io.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/file_pattern_matcher.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/functions.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/functions.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/gpu.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/image.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/image.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/io_streams.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/io_streams.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/mount.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/mount.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/network_file_system.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/network_file_system.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/object.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/object.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/output.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/parallel_map.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/parallel_map.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/partial_function.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/partial_function.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/proxy.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/proxy.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/py.typed +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/queue.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/queue.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/2023.12.312.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/2023.12.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/2024.04.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/2024.10.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/PREVIEW.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/README.md +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/requirements/base-images.json +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/retries.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/runner.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/runner.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/running_app.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/sandbox.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/sandbox.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/schedule.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/scheduler_placement.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/secret.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/secret.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/serving.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/serving.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/snapshot.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/snapshot.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/stream_type.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/token_flow.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/token_flow.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/volume.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal/volume.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal.egg-info/requires.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal.egg-info/top_level.txt +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_docs/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/__init__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/options.proto +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/options_grpc.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/options_pb2.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_proto/py.typed +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/modal_version/__main__.py +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/pyproject.toml +0 -0
- {modal-1.0.6.dev8 → modal-1.0.6.dev10}/setup.cfg +0 -0
|
@@ -188,16 +188,23 @@ def get_content_length(data: BinaryIO) -> int:
|
|
|
188
188
|
return content_length - pos
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
async def _blob_upload_with_fallback(items, blob_ids, callback):
|
|
191
|
+
async def _blob_upload_with_fallback(items, blob_ids: list[str], callback) -> tuple[str, bool, int]:
|
|
192
|
+
r2_latency_ms = 0
|
|
193
|
+
r2_failed = False
|
|
192
194
|
for idx, (item, blob_id) in enumerate(zip(items, blob_ids)):
|
|
193
195
|
# We want to default to R2 95% of the time and S3 5% of the time.
|
|
194
196
|
# To ensure the failure path is continuously exercised.
|
|
195
197
|
if idx == 0 and len(items) > 1 and random.random() > HEALTHY_R2_UPLOAD_PERCENTAGE:
|
|
196
198
|
continue
|
|
197
199
|
try:
|
|
200
|
+
init_time = time.monotonic_ns()
|
|
198
201
|
await callback(item)
|
|
199
|
-
|
|
202
|
+
if blob_id.endswith(":r2"):
|
|
203
|
+
r2_latency_ms = (time.monotonic_ns() - init_time) // 1_000_000
|
|
204
|
+
return blob_id, r2_failed, r2_latency_ms
|
|
200
205
|
except Exception as _:
|
|
206
|
+
if blob_id.endswith(":r2"):
|
|
207
|
+
r2_failed = True
|
|
201
208
|
# Ignore all errors except the last one, since we're out of fallback options.
|
|
202
209
|
if idx == len(items) - 1:
|
|
203
210
|
raise
|
|
@@ -206,7 +213,7 @@ async def _blob_upload_with_fallback(items, blob_ids, callback):
|
|
|
206
213
|
|
|
207
214
|
async def _blob_upload(
|
|
208
215
|
upload_hashes: UploadHashes, data: Union[bytes, BinaryIO], stub, progress_report_cb: Optional[Callable] = None
|
|
209
|
-
) -> str:
|
|
216
|
+
) -> tuple[str, bool, int]:
|
|
210
217
|
if isinstance(data, bytes):
|
|
211
218
|
data = BytesIO(data)
|
|
212
219
|
|
|
@@ -232,7 +239,7 @@ async def _blob_upload(
|
|
|
232
239
|
progress_report_cb=progress_report_cb,
|
|
233
240
|
)
|
|
234
241
|
|
|
235
|
-
blob_id = await _blob_upload_with_fallback(
|
|
242
|
+
blob_id, r2_failed, r2_latency_ms = await _blob_upload_with_fallback(
|
|
236
243
|
resp.multiparts.items,
|
|
237
244
|
resp.blob_ids,
|
|
238
245
|
upload_multipart_upload,
|
|
@@ -252,7 +259,7 @@ async def _blob_upload(
|
|
|
252
259
|
content_md5_b64=upload_hashes.md5_base64,
|
|
253
260
|
)
|
|
254
261
|
|
|
255
|
-
blob_id = await _blob_upload_with_fallback(
|
|
262
|
+
blob_id, r2_failed, r2_latency_ms = await _blob_upload_with_fallback(
|
|
256
263
|
resp.upload_urls.items,
|
|
257
264
|
resp.blob_ids,
|
|
258
265
|
upload_to_s3_url,
|
|
@@ -261,10 +268,10 @@ async def _blob_upload(
|
|
|
261
268
|
if progress_report_cb:
|
|
262
269
|
progress_report_cb(complete=True)
|
|
263
270
|
|
|
264
|
-
return blob_id
|
|
271
|
+
return blob_id, r2_failed, r2_latency_ms
|
|
265
272
|
|
|
266
273
|
|
|
267
|
-
async def
|
|
274
|
+
async def blob_upload_with_r2_failure_info(payload: bytes, stub: ModalClientModal) -> tuple[str, bool, int]:
|
|
268
275
|
size_mib = len(payload) / 1024 / 1024
|
|
269
276
|
logger.debug(f"Uploading large blob of size {size_mib:.2f} MiB")
|
|
270
277
|
t0 = time.time()
|
|
@@ -272,12 +279,17 @@ async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
|
|
|
272
279
|
logger.warning("Blob uploading string, not bytes - auto-encoding as utf8")
|
|
273
280
|
payload = payload.encode("utf8")
|
|
274
281
|
upload_hashes = get_upload_hashes(payload)
|
|
275
|
-
blob_id = await _blob_upload(upload_hashes, payload, stub)
|
|
282
|
+
blob_id, r2_failed, r2_latency_ms = await _blob_upload(upload_hashes, payload, stub)
|
|
276
283
|
dur_s = max(time.time() - t0, 0.001) # avoid division by zero
|
|
277
284
|
throughput_mib_s = (size_mib) / dur_s
|
|
278
285
|
logger.debug(
|
|
279
286
|
f"Uploaded large blob of size {size_mib:.2f} MiB ({throughput_mib_s:.2f} MiB/s, total {dur_s:.2f}s). {blob_id}"
|
|
280
287
|
)
|
|
288
|
+
return blob_id, r2_failed, r2_latency_ms
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
|
|
292
|
+
blob_id, _, _ = await blob_upload_with_r2_failure_info(payload, stub)
|
|
281
293
|
return blob_id
|
|
282
294
|
|
|
283
295
|
|
|
@@ -289,7 +301,8 @@ async def blob_upload_file(
|
|
|
289
301
|
md5_hex: Optional[str] = None,
|
|
290
302
|
) -> str:
|
|
291
303
|
upload_hashes = get_upload_hashes(file_obj, sha256_hex=sha256_hex, md5_hex=md5_hex)
|
|
292
|
-
|
|
304
|
+
blob_id, _, _ = await _blob_upload(upload_hashes, file_obj, stub, progress_report_cb)
|
|
305
|
+
return blob_id
|
|
293
306
|
|
|
294
307
|
|
|
295
308
|
@retry(n_attempts=5, base_delay=0.1, timeout=None)
|
|
@@ -32,7 +32,12 @@ from ..exception import (
|
|
|
32
32
|
RemoteError,
|
|
33
33
|
)
|
|
34
34
|
from ..mount import ROOT_DIR, _is_modal_path, _Mount
|
|
35
|
-
from .blob_utils import
|
|
35
|
+
from .blob_utils import (
|
|
36
|
+
MAX_ASYNC_OBJECT_SIZE_BYTES,
|
|
37
|
+
MAX_OBJECT_SIZE_BYTES,
|
|
38
|
+
blob_download,
|
|
39
|
+
blob_upload_with_r2_failure_info,
|
|
40
|
+
)
|
|
36
41
|
from .grpc_utils import RETRYABLE_GRPC_STATUS_CODES
|
|
37
42
|
|
|
38
43
|
|
|
@@ -544,7 +549,7 @@ async def _create_input(
|
|
|
544
549
|
args_serialized = serialize((args, kwargs))
|
|
545
550
|
|
|
546
551
|
if should_upload(len(args_serialized), function_call_invocation_type):
|
|
547
|
-
args_blob_id = await
|
|
552
|
+
args_blob_id, r2_failed, r2_latency_ms = await blob_upload_with_r2_failure_info(args_serialized, stub)
|
|
548
553
|
return api_pb2.FunctionPutInputsItem(
|
|
549
554
|
input=api_pb2.FunctionInput(
|
|
550
555
|
args_blob_id=args_blob_id,
|
|
@@ -552,6 +557,8 @@ async def _create_input(
|
|
|
552
557
|
method_name=method_name,
|
|
553
558
|
),
|
|
554
559
|
idx=idx,
|
|
560
|
+
r2_failed=r2_failed,
|
|
561
|
+
r2_latency_ms=r2_latency_ms,
|
|
555
562
|
)
|
|
556
563
|
else:
|
|
557
564
|
return api_pb2.FunctionPutInputsItem(
|
|
@@ -31,7 +31,7 @@ class _Client:
|
|
|
31
31
|
server_url: str,
|
|
32
32
|
client_type: int,
|
|
33
33
|
credentials: typing.Optional[tuple[str, str]],
|
|
34
|
-
version: str = "1.0.6.
|
|
34
|
+
version: str = "1.0.6.dev10",
|
|
35
35
|
):
|
|
36
36
|
"""mdmd:hidden
|
|
37
37
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -160,7 +160,7 @@ class Client:
|
|
|
160
160
|
server_url: str,
|
|
161
161
|
client_type: int,
|
|
162
162
|
credentials: typing.Optional[tuple[str, str]],
|
|
163
|
-
version: str = "1.0.6.
|
|
163
|
+
version: str = "1.0.6.dev10",
|
|
164
164
|
):
|
|
165
165
|
"""mdmd:hidden
|
|
166
166
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -1013,6 +1013,12 @@ message ContainerLogRequest {
|
|
|
1013
1013
|
repeated TaskLogs logs = 3;
|
|
1014
1014
|
}
|
|
1015
1015
|
|
|
1016
|
+
message ContainerReloadVolumesRequest {
|
|
1017
|
+
string task_id = 1;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
message ContainerReloadVolumesResponse { }
|
|
1021
|
+
|
|
1016
1022
|
message ContainerStopRequest {
|
|
1017
1023
|
string task_id = 1 [ (modal.options.audit_target_attr) = true ];
|
|
1018
1024
|
}
|
|
@@ -1790,6 +1796,8 @@ message FunctionPrecreateResponse {
|
|
|
1790
1796
|
message FunctionPutInputsItem {
|
|
1791
1797
|
int32 idx = 1;
|
|
1792
1798
|
FunctionInput input = 2;
|
|
1799
|
+
bool r2_failed = 3;
|
|
1800
|
+
uint64 r2_latency_ms = 4;
|
|
1793
1801
|
}
|
|
1794
1802
|
|
|
1795
1803
|
message FunctionPutInputsRequest {
|
|
@@ -3279,6 +3287,7 @@ service ModalClient {
|
|
|
3279
3287
|
rpc ContainerHeartbeat(ContainerHeartbeatRequest) returns (ContainerHeartbeatResponse);
|
|
3280
3288
|
rpc ContainerHello(google.protobuf.Empty) returns (google.protobuf.Empty);
|
|
3281
3289
|
rpc ContainerLog(ContainerLogRequest) returns (google.protobuf.Empty);
|
|
3290
|
+
rpc ContainerReloadVolumes(ContainerReloadVolumesRequest) returns (ContainerReloadVolumesResponse);
|
|
3282
3291
|
rpc ContainerStop(ContainerStopRequest) returns (ContainerStopResponse);
|
|
3283
3292
|
|
|
3284
3293
|
// Dicts
|
|
@@ -162,6 +162,10 @@ class ModalClientBase(abc.ABC):
|
|
|
162
162
|
async def ContainerLog(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.ContainerLogRequest, google.protobuf.empty_pb2.Empty]') -> None:
|
|
163
163
|
pass
|
|
164
164
|
|
|
165
|
+
@abc.abstractmethod
|
|
166
|
+
async def ContainerReloadVolumes(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.ContainerReloadVolumesRequest, modal_proto.api_pb2.ContainerReloadVolumesResponse]') -> None:
|
|
167
|
+
pass
|
|
168
|
+
|
|
165
169
|
@abc.abstractmethod
|
|
166
170
|
async def ContainerStop(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.ContainerStopRequest, modal_proto.api_pb2.ContainerStopResponse]') -> None:
|
|
167
171
|
pass
|
|
@@ -860,6 +864,12 @@ class ModalClientBase(abc.ABC):
|
|
|
860
864
|
modal_proto.api_pb2.ContainerLogRequest,
|
|
861
865
|
google.protobuf.empty_pb2.Empty,
|
|
862
866
|
),
|
|
867
|
+
'/modal.client.ModalClient/ContainerReloadVolumes': grpclib.const.Handler(
|
|
868
|
+
self.ContainerReloadVolumes,
|
|
869
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
870
|
+
modal_proto.api_pb2.ContainerReloadVolumesRequest,
|
|
871
|
+
modal_proto.api_pb2.ContainerReloadVolumesResponse,
|
|
872
|
+
),
|
|
863
873
|
'/modal.client.ModalClient/ContainerStop': grpclib.const.Handler(
|
|
864
874
|
self.ContainerStop,
|
|
865
875
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
@@ -1802,6 +1812,12 @@ class ModalClientStub:
|
|
|
1802
1812
|
modal_proto.api_pb2.ContainerLogRequest,
|
|
1803
1813
|
google.protobuf.empty_pb2.Empty,
|
|
1804
1814
|
)
|
|
1815
|
+
self.ContainerReloadVolumes = grpclib.client.UnaryUnaryMethod(
|
|
1816
|
+
channel,
|
|
1817
|
+
'/modal.client.ModalClient/ContainerReloadVolumes',
|
|
1818
|
+
modal_proto.api_pb2.ContainerReloadVolumesRequest,
|
|
1819
|
+
modal_proto.api_pb2.ContainerReloadVolumesResponse,
|
|
1820
|
+
)
|
|
1805
1821
|
self.ContainerStop = grpclib.client.UnaryUnaryMethod(
|
|
1806
1822
|
channel,
|
|
1807
1823
|
'/modal.client.ModalClient/ContainerStop',
|