modal 1.1.4.dev15__tar.gz → 1.1.4.dev17__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.
Files changed (190) hide show
  1. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/PKG-INFO +1 -1
  2. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/client.pyi +2 -2
  3. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/experimental/flash.py +33 -12
  4. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal.egg-info/PKG-INFO +1 -1
  5. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/api.proto +1 -0
  6. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/api_pb2.py +546 -546
  7. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/api_pb2.pyi +6 -1
  8. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_version/__init__.py +1 -1
  9. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/LICENSE +0 -0
  10. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/README.md +0 -0
  11. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/__init__.py +0 -0
  12. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/__main__.py +0 -0
  13. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_clustered_functions.py +0 -0
  14. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_clustered_functions.pyi +0 -0
  15. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_container_entrypoint.py +0 -0
  16. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_functions.py +0 -0
  17. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_ipython.py +0 -0
  18. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_location.py +0 -0
  19. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_object.py +0 -0
  20. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_output.py +0 -0
  21. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_partial_function.py +0 -0
  22. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_pty.py +0 -0
  23. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_resolver.py +0 -0
  24. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_resources.py +0 -0
  25. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/__init__.py +0 -0
  26. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/asgi.py +0 -0
  27. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/container_io_manager.py +0 -0
  28. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/container_io_manager.pyi +0 -0
  29. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/execution_context.py +0 -0
  30. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/execution_context.pyi +0 -0
  31. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  32. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/telemetry.py +0 -0
  33. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_runtime/user_code_imports.py +0 -0
  34. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_serialization.py +0 -0
  35. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_traceback.py +0 -0
  36. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_tunnel.py +0 -0
  37. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_tunnel.pyi +0 -0
  38. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_type_manager.py +0 -0
  39. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/__init__.py +0 -0
  40. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/app_utils.py +0 -0
  41. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/async_utils.py +0 -0
  42. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/auth_token_manager.py +0 -0
  43. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/blob_utils.py +0 -0
  44. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/bytes_io_segment_payload.py +0 -0
  45. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/deprecation.py +0 -0
  46. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/docker_utils.py +0 -0
  47. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/function_utils.py +0 -0
  48. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/git_utils.py +0 -0
  49. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/grpc_testing.py +0 -0
  50. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/grpc_utils.py +0 -0
  51. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/hash_utils.py +0 -0
  52. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/http_utils.py +0 -0
  53. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/jwt_utils.py +0 -0
  54. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/logger.py +0 -0
  55. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/mount_utils.py +0 -0
  56. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/name_utils.py +0 -0
  57. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/package_utils.py +0 -0
  58. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/pattern_utils.py +0 -0
  59. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/rand_pb_testing.py +0 -0
  60. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/shell_utils.py +0 -0
  61. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_utils/time_utils.py +0 -0
  62. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_vendor/__init__.py +0 -0
  63. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  64. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_vendor/cloudpickle.py +0 -0
  65. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_vendor/tblib.py +0 -0
  66. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/_watcher.py +0 -0
  67. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/app.py +0 -0
  68. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/app.pyi +0 -0
  69. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/2023.12.312.txt +0 -0
  70. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/2023.12.txt +0 -0
  71. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/2024.04.txt +0 -0
  72. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/2024.10.txt +0 -0
  73. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/2025.06.txt +0 -0
  74. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/PREVIEW.txt +0 -0
  75. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/README.md +0 -0
  76. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/builder/base-images.json +0 -0
  77. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/call_graph.py +0 -0
  78. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/__init__.py +0 -0
  79. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/_download.py +0 -0
  80. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/_traceback.py +0 -0
  81. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/app.py +0 -0
  82. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/cluster.py +0 -0
  83. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/config.py +0 -0
  84. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/container.py +0 -0
  85. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/dict.py +0 -0
  86. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/entry_point.py +0 -0
  87. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/environment.py +0 -0
  88. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/import_refs.py +0 -0
  89. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/launch.py +0 -0
  90. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/network_file_system.py +0 -0
  91. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/profile.py +0 -0
  92. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/programs/__init__.py +0 -0
  93. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/programs/launch_instance_ssh.py +0 -0
  94. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/programs/run_jupyter.py +0 -0
  95. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/programs/run_marimo.py +0 -0
  96. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/programs/vscode.py +0 -0
  97. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/queues.py +0 -0
  98. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/run.py +0 -0
  99. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/secret.py +0 -0
  100. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/token.py +0 -0
  101. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/utils.py +0 -0
  102. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cli/volume.py +0 -0
  103. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/client.py +0 -0
  104. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cloud_bucket_mount.py +0 -0
  105. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cloud_bucket_mount.pyi +0 -0
  106. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cls.py +0 -0
  107. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/cls.pyi +0 -0
  108. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/config.py +0 -0
  109. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/container_process.py +0 -0
  110. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/container_process.pyi +0 -0
  111. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/dict.py +0 -0
  112. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/dict.pyi +0 -0
  113. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/environments.py +0 -0
  114. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/environments.pyi +0 -0
  115. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/exception.py +0 -0
  116. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/experimental/__init__.py +0 -0
  117. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/experimental/flash.pyi +0 -0
  118. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/experimental/ipython.py +0 -0
  119. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/file_io.py +0 -0
  120. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/file_io.pyi +0 -0
  121. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/file_pattern_matcher.py +0 -0
  122. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/functions.py +0 -0
  123. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/functions.pyi +0 -0
  124. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/gpu.py +0 -0
  125. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/image.py +0 -0
  126. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/image.pyi +0 -0
  127. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/io_streams.py +0 -0
  128. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/io_streams.pyi +0 -0
  129. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/mount.py +0 -0
  130. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/mount.pyi +0 -0
  131. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/network_file_system.py +0 -0
  132. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/network_file_system.pyi +0 -0
  133. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/object.py +0 -0
  134. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/object.pyi +0 -0
  135. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/output.py +0 -0
  136. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/parallel_map.py +0 -0
  137. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/parallel_map.pyi +0 -0
  138. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/partial_function.py +0 -0
  139. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/partial_function.pyi +0 -0
  140. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/proxy.py +0 -0
  141. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/proxy.pyi +0 -0
  142. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/py.typed +0 -0
  143. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/queue.py +0 -0
  144. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/queue.pyi +0 -0
  145. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/retries.py +0 -0
  146. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/runner.py +0 -0
  147. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/runner.pyi +0 -0
  148. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/running_app.py +0 -0
  149. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/sandbox.py +0 -0
  150. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/sandbox.pyi +0 -0
  151. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/schedule.py +0 -0
  152. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/scheduler_placement.py +0 -0
  153. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/secret.py +0 -0
  154. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/secret.pyi +0 -0
  155. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/serving.py +0 -0
  156. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/serving.pyi +0 -0
  157. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/snapshot.py +0 -0
  158. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/snapshot.pyi +0 -0
  159. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/stream_type.py +0 -0
  160. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/token_flow.py +0 -0
  161. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/token_flow.pyi +0 -0
  162. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/volume.py +0 -0
  163. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal/volume.pyi +0 -0
  164. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal.egg-info/SOURCES.txt +0 -0
  165. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal.egg-info/dependency_links.txt +0 -0
  166. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal.egg-info/entry_points.txt +0 -0
  167. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal.egg-info/requires.txt +0 -0
  168. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal.egg-info/top_level.txt +0 -0
  169. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_docs/__init__.py +0 -0
  170. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_docs/gen_cli_docs.py +0 -0
  171. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_docs/gen_reference_docs.py +0 -0
  172. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_docs/mdmd/__init__.py +0 -0
  173. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_docs/mdmd/mdmd.py +0 -0
  174. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_docs/mdmd/signatures.py +0 -0
  175. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/__init__.py +0 -0
  176. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/api_grpc.py +0 -0
  177. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/api_pb2_grpc.py +0 -0
  178. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/api_pb2_grpc.pyi +0 -0
  179. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/modal_api_grpc.py +0 -0
  180. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/modal_options_grpc.py +0 -0
  181. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/options.proto +0 -0
  182. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/options_grpc.py +0 -0
  183. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/options_pb2.py +0 -0
  184. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/options_pb2.pyi +0 -0
  185. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/options_pb2_grpc.py +0 -0
  186. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/options_pb2_grpc.pyi +0 -0
  187. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_proto/py.typed +0 -0
  188. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/modal_version/__main__.py +0 -0
  189. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/pyproject.toml +0 -0
  190. {modal-1.1.4.dev15 → modal-1.1.4.dev17}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.4.dev15
3
+ Version: 1.1.4.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -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.4.dev15",
36
+ version: str = "1.1.4.dev17",
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.4.dev15",
167
+ version: str = "1.1.4.dev17",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -213,8 +213,8 @@ class _FlashPrometheusAutoscaler:
213
213
  )
214
214
 
215
215
  logger.warning(
216
- f"[Modal Flash] Scaling to {actual_target_containers} containers. Autoscaling decision "
217
- f"made in {time.time() - autoscaling_time} seconds."
216
+ f"[Modal Flash] Scaling to {actual_target_containers=} containers. "
217
+ f" Autoscaling decision made in {time.time() - autoscaling_time} seconds."
218
218
  )
219
219
 
220
220
  await self.autoscaling_decisions_dict.put(
@@ -223,9 +223,7 @@ class _FlashPrometheusAutoscaler:
223
223
  )
224
224
  await self.autoscaling_decisions_dict.put("current_replicas", actual_target_containers)
225
225
 
226
- await self.cls.update_autoscaler(
227
- min_containers=actual_target_containers,
228
- )
226
+ await self.cls.update_autoscaler(min_containers=actual_target_containers)
229
227
 
230
228
  if time.time() - autoscaling_time < self.autoscaling_interval_seconds:
231
229
  await asyncio.sleep(self.autoscaling_interval_seconds - (time.time() - autoscaling_time))
@@ -239,6 +237,8 @@ class _FlashPrometheusAutoscaler:
239
237
  await asyncio.sleep(self.autoscaling_interval_seconds)
240
238
 
241
239
  async def _compute_target_containers(self, current_replicas: int) -> int:
240
+ # current_replicas is the number of live containers + cold starting containers (not yet live)
241
+ # containers is the number of live containers that are registered in flash dns
242
242
  containers = await self._get_all_containers()
243
243
  if len(containers) > current_replicas:
244
244
  logger.info(
@@ -271,11 +271,17 @@ class _FlashPrometheusAutoscaler:
271
271
  sum_metric += container_metrics[target_metric][0].value
272
272
  containers_with_metrics += 1
273
273
 
274
+ # n_containers_missing_metric is the number of unhealthy containers + number of cold starting containers
274
275
  n_containers_missing_metric = current_replicas - containers_with_metrics
276
+ # n_containers_unhealthy is the number of live containers that are not emitting metrics i.e. unhealthy
277
+ n_containers_unhealthy = len(containers) - containers_with_metrics
278
+
279
+ # Scale up assuming that every unhealthy container is at 2x the target metric value.
280
+ scale_up_target_metric_value = (sum_metric + n_containers_unhealthy * target_metric_value) / (
281
+ (containers_with_metrics + n_containers_unhealthy) or 1
282
+ )
275
283
 
276
- # Scale up / down conservatively: Any container that is missing the metric is assumed to be at the minimum
277
- # value of the metric when scaling up and the maximum value of the metric when scaling down.
278
- scale_up_target_metric_value = sum_metric / (containers_with_metrics or 1)
284
+ # Scale down assuming that every container (including cold starting containers) are at the target metric value.
279
285
  scale_down_target_metric_value = (
280
286
  sum_metric + n_containers_missing_metric * target_metric_value
281
287
  ) / current_replicas
@@ -290,9 +296,14 @@ class _FlashPrometheusAutoscaler:
290
296
  desired_replicas = math.ceil(current_replicas * scale_down_ratio)
291
297
 
292
298
  logger.warning(
293
- f"[Modal Flash] Current replicas: {current_replicas}, target metric value: {target_metric_value}, "
294
- f"current sum of metric values: {sum_metric}, number of containers missing metric: "
295
- f"{n_containers_missing_metric}, scale up ratio: {scale_up_ratio}, scale down ratio: {scale_down_ratio}, "
299
+ f"[Modal Flash] Current replicas: {current_replicas}, "
300
+ f"target metric value: {target_metric_value}, "
301
+ f"current sum of metric values: {sum_metric}, "
302
+ f"number of containers with metrics: {containers_with_metrics}, "
303
+ f"number of containers unhealthy: {n_containers_unhealthy}, "
304
+ f"number of containers missing metric (includes unhealthy): {n_containers_missing_metric}, "
305
+ f"scale up ratio: {scale_up_ratio}, "
306
+ f"scale down ratio: {scale_down_ratio}, "
296
307
  f"desired replicas: {desired_replicas}"
297
308
  )
298
309
 
@@ -312,9 +323,19 @@ class _FlashPrometheusAutoscaler:
312
323
  logger.warning(f"[Modal Flash] Error getting metrics from {url}: {e}")
313
324
  return None
314
325
 
326
+ # Read body with timeout/error handling and parse Prometheus metrics
327
+ try:
328
+ text_body = await response.text()
329
+ except asyncio.TimeoutError:
330
+ logger.warning(f"[Modal Flash] Timeout reading metrics body from {url}")
331
+ return None
332
+ except Exception as e:
333
+ logger.warning(f"[Modal Flash] Error reading metrics body from {url}: {e}")
334
+ return None
335
+
315
336
  # Parse the text-based Prometheus metrics format
316
337
  metrics: dict[str, list[Sample]] = defaultdict(list)
317
- for family in text_string_to_metric_families(await response.text()):
338
+ for family in text_string_to_metric_families(text_body):
318
339
  for sample in family.samples:
319
340
  metrics[sample.name] += [sample]
320
341
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.4.dev15
3
+ Version: 1.1.4.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1798,6 +1798,7 @@ message FunctionHandleMetadata {
1798
1798
  optional string input_plane_region = 47;
1799
1799
  // Use optional to ensure unset values default to None instead of 0
1800
1800
  optional uint64 max_object_size_bytes = 48;
1801
+ repeated string _experimental_flash_urls = 49; // (Optional) urls for flash services
1801
1802
  }
1802
1803
 
1803
1804
  message FunctionInput {