fal 1.9.3__tar.gz → 1.10.0__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 fal might be problematic. Click here for more details.
- {fal-1.9.3/fal.egg-info → fal-1.10.0}/PKG-INFO +2 -2
- {fal-1.9.3 → fal-1.10.0/fal.egg-info}/PKG-INFO +2 -2
- {fal-1.9.3 → fal-1.10.0}/fal.egg-info/SOURCES.txt +2 -0
- {fal-1.9.3 → fal-1.10.0}/fal.egg-info/requires.txt +1 -1
- {fal-1.9.3 → fal-1.10.0}/pyproject.toml +1 -1
- {fal-1.9.3 → fal-1.10.0}/src/fal/_fal_version.py +2 -2
- {fal-1.9.3 → fal-1.10.0}/src/fal/api.py +12 -0
- fal-1.10.0/src/fal/cli/api.py +72 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/apps.py +39 -1
- fal-1.10.0/src/fal/cli/cli_nested_json.py +421 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/deploy.py +3 -3
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/main.py +14 -1
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/profile.py +14 -6
- {fal-1.9.3 → fal-1.10.0}/src/fal/sdk.py +10 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/providers/fal.py +292 -2
- {fal-1.9.3 → fal-1.10.0}/tests/cli/test_apps.py +3 -0
- {fal-1.9.3 → fal-1.10.0}/tests/test_apps.py +40 -14
- {fal-1.9.3 → fal-1.10.0}/.gitignore +0 -0
- {fal-1.9.3 → fal-1.10.0}/Makefile +0 -0
- {fal-1.9.3 → fal-1.10.0}/README.md +0 -0
- {fal-1.9.3 → fal-1.10.0}/docs/conf.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/docs/index.rst +0 -0
- {fal-1.9.3 → fal-1.10.0}/fal.egg-info/dependency_links.txt +0 -0
- {fal-1.9.3 → fal-1.10.0}/fal.egg-info/entry_points.txt +0 -0
- {fal-1.9.3 → fal-1.10.0}/fal.egg-info/top_level.txt +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/README.md +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi-fal-rest/pyproject.toml +0 -0
- {fal-1.9.3 → fal-1.10.0}/openapi_rest.config.yaml +0 -0
- {fal-1.9.3 → fal-1.10.0}/setup.cfg +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/__main__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/_serialization.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/_version.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/app.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/apps.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/auth/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/auth/auth0.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/auth/local.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/_utils.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/auth.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/create.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/debug.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/doctor.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/keys.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/parser.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/run.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/runners.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/cli/secrets.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/config.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/console/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/console/icons.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/console/ux.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/container.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/exceptions/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/exceptions/_base.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/exceptions/_cuda.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/exceptions/auth.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/files.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/flags.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/logging/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/logging/isolate.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/logging/style.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/logging/trace.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/logging/user.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/py.typed +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/rest_client.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/sync.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/exceptions.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/file.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/providers/gcp.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/providers/r2.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/providers/s3.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/file/types.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/image.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/image/safety_checker.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/optimize.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/types.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/utils/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/utils/download_utils.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/toolkit/utils/retry.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/utils.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/src/fal/workflows.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/assets/cat.png +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/cli/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/cli/test_auth.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/cli/test_deploy.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/cli/test_keys.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/cli/test_run.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/cli/test_secrets.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/conftest.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/integration_test.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/mainify_package/__init__.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/mainify_package/impl.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/mainify_package/utils.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/mainify_target.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/test_stability.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/toolkit/file_test.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/toolkit/image_test.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/toolkit/test_types.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tests/toolkit/utils/retry.py +0 -0
- {fal-1.9.3 → fal-1.10.0}/tools/demo_script.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.0
|
|
4
4
|
Summary: fal is an easy-to-use Serverless Python Framework
|
|
5
5
|
Author: Features & Labels <support@fal.ai>
|
|
6
6
|
Requires-Python: >=3.8
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: isolate[build]<0.17.0,>=0.16.1
|
|
9
|
-
Requires-Dist: isolate-proto<0.
|
|
9
|
+
Requires-Dist: isolate-proto<0.8.0,>=0.7.0
|
|
10
10
|
Requires-Dist: grpcio==1.64.0
|
|
11
11
|
Requires-Dist: dill==0.3.7
|
|
12
12
|
Requires-Dist: cloudpickle==3.0.0
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.0
|
|
4
4
|
Summary: fal is an easy-to-use Serverless Python Framework
|
|
5
5
|
Author: Features & Labels <support@fal.ai>
|
|
6
6
|
Requires-Python: >=3.8
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: isolate[build]<0.17.0,>=0.16.1
|
|
9
|
-
Requires-Dist: isolate-proto<0.
|
|
9
|
+
Requires-Dist: isolate-proto<0.8.0,>=0.7.0
|
|
10
10
|
Requires-Dist: grpcio==1.64.0
|
|
11
11
|
Requires-Dist: dill==0.3.7
|
|
12
12
|
Requires-Dist: cloudpickle==3.0.0
|
|
@@ -99,8 +99,10 @@ src/fal/auth/auth0.py
|
|
|
99
99
|
src/fal/auth/local.py
|
|
100
100
|
src/fal/cli/__init__.py
|
|
101
101
|
src/fal/cli/_utils.py
|
|
102
|
+
src/fal/cli/api.py
|
|
102
103
|
src/fal/cli/apps.py
|
|
103
104
|
src/fal/cli/auth.py
|
|
105
|
+
src/fal/cli/cli_nested_json.py
|
|
104
106
|
src/fal/cli/create.py
|
|
105
107
|
src/fal/cli/debug.py
|
|
106
108
|
src/fal/cli/deploy.py
|
|
@@ -53,6 +53,7 @@ from fal.exceptions import (
|
|
|
53
53
|
from fal.exceptions._cuda import _is_cuda_oom_exception
|
|
54
54
|
from fal.logging.isolate import IsolateLogPrinter
|
|
55
55
|
from fal.sdk import (
|
|
56
|
+
FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
56
57
|
FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
57
58
|
FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
58
59
|
FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
@@ -400,6 +401,7 @@ class FalServerlessHost(Host):
|
|
|
400
401
|
"keep_alive",
|
|
401
402
|
"max_concurrency",
|
|
402
403
|
"min_concurrency",
|
|
404
|
+
"concurrency_buffer",
|
|
403
405
|
"max_multiplexing",
|
|
404
406
|
"setup_function",
|
|
405
407
|
"metadata",
|
|
@@ -451,6 +453,7 @@ class FalServerlessHost(Host):
|
|
|
451
453
|
scheduler_options = options.host.get("_scheduler_options", None)
|
|
452
454
|
max_concurrency = options.host.get("max_concurrency")
|
|
453
455
|
min_concurrency = options.host.get("min_concurrency")
|
|
456
|
+
concurrency_buffer = options.host.get("concurrency_buffer")
|
|
454
457
|
max_multiplexing = options.host.get("max_multiplexing")
|
|
455
458
|
exposed_port = options.get_exposed_port()
|
|
456
459
|
request_timeout = options.host.get("request_timeout")
|
|
@@ -466,6 +469,7 @@ class FalServerlessHost(Host):
|
|
|
466
469
|
max_multiplexing=max_multiplexing,
|
|
467
470
|
max_concurrency=max_concurrency,
|
|
468
471
|
min_concurrency=min_concurrency,
|
|
472
|
+
concurrency_buffer=concurrency_buffer,
|
|
469
473
|
request_timeout=request_timeout,
|
|
470
474
|
startup_timeout=startup_timeout,
|
|
471
475
|
)
|
|
@@ -523,6 +527,7 @@ class FalServerlessHost(Host):
|
|
|
523
527
|
keep_alive = options.host.get("keep_alive", FAL_SERVERLESS_DEFAULT_KEEP_ALIVE)
|
|
524
528
|
max_concurrency = options.host.get("max_concurrency")
|
|
525
529
|
min_concurrency = options.host.get("min_concurrency")
|
|
530
|
+
concurrency_buffer = options.host.get("concurrency_buffer")
|
|
526
531
|
max_multiplexing = options.host.get("max_multiplexing")
|
|
527
532
|
base_image = options.host.get("_base_image", None)
|
|
528
533
|
scheduler = options.host.get("_scheduler", None)
|
|
@@ -542,6 +547,7 @@ class FalServerlessHost(Host):
|
|
|
542
547
|
max_multiplexing=max_multiplexing,
|
|
543
548
|
max_concurrency=max_concurrency,
|
|
544
549
|
min_concurrency=min_concurrency,
|
|
550
|
+
concurrency_buffer=concurrency_buffer,
|
|
545
551
|
request_timeout=request_timeout,
|
|
546
552
|
startup_timeout=startup_timeout,
|
|
547
553
|
)
|
|
@@ -709,6 +715,7 @@ def function(
|
|
|
709
715
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
710
716
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
711
717
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
718
|
+
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
712
719
|
request_timeout: int | None = None,
|
|
713
720
|
startup_timeout: int | None = None,
|
|
714
721
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -737,6 +744,7 @@ def function(
|
|
|
737
744
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
738
745
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
739
746
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
747
|
+
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
740
748
|
request_timeout: int | None = None,
|
|
741
749
|
startup_timeout: int | None = None,
|
|
742
750
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -815,6 +823,7 @@ def function(
|
|
|
815
823
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
816
824
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
817
825
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
826
|
+
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
818
827
|
request_timeout: int | None = None,
|
|
819
828
|
startup_timeout: int | None = None,
|
|
820
829
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -848,6 +857,7 @@ def function(
|
|
|
848
857
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
849
858
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
850
859
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
860
|
+
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
851
861
|
request_timeout: int | None = None,
|
|
852
862
|
startup_timeout: int | None = None,
|
|
853
863
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -875,6 +885,7 @@ def function(
|
|
|
875
885
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
876
886
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
877
887
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
888
|
+
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
878
889
|
request_timeout: int | None = None,
|
|
879
890
|
startup_timeout: int | None = None,
|
|
880
891
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -902,6 +913,7 @@ def function(
|
|
|
902
913
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
903
914
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
904
915
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
916
|
+
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
905
917
|
request_timeout: int | None = None,
|
|
906
918
|
startup_timeout: int | None = None,
|
|
907
919
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
import rich
|
|
4
|
+
|
|
5
|
+
import fal.apps
|
|
6
|
+
|
|
7
|
+
# = or := only
|
|
8
|
+
KV_SPLIT_RE = re.compile(r"(=|:=)")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _api(args):
|
|
12
|
+
"""Handle the api command execution."""
|
|
13
|
+
from rich.console import Group
|
|
14
|
+
from rich.live import Live
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
from rich.text import Text
|
|
17
|
+
|
|
18
|
+
from . import cli_nested_json
|
|
19
|
+
|
|
20
|
+
params = [KV_SPLIT_RE.split(param) for param in args.params]
|
|
21
|
+
params = cli_nested_json.interpret_nested_json( # type: ignore
|
|
22
|
+
[(key, value) for key, _, value in params]
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
handle = fal.apps.submit(args.model_id, params) # type: ignore
|
|
26
|
+
logs = [] # type: ignore
|
|
27
|
+
|
|
28
|
+
with Live(auto_refresh=False) as live:
|
|
29
|
+
for event in handle.iter_events(logs=True):
|
|
30
|
+
if isinstance(event, fal.apps.Queued):
|
|
31
|
+
status = Text(f"⏳ Queued (position: {event.position})", style="yellow")
|
|
32
|
+
elif isinstance(event, fal.apps.InProgress):
|
|
33
|
+
status = Text("🔄 In Progress", style="blue")
|
|
34
|
+
if event.logs:
|
|
35
|
+
logs.extend(log.get("message", str(log)) for log in event.logs)
|
|
36
|
+
logs = logs[-10:] # Keep only last 10 logs
|
|
37
|
+
else:
|
|
38
|
+
status = Text("✅ Done", style="green")
|
|
39
|
+
|
|
40
|
+
status_panel = Panel(status, title="Status")
|
|
41
|
+
logs_panel = Panel("\n".join(logs), title="Logs")
|
|
42
|
+
|
|
43
|
+
live.update(Group(status_panel, logs_panel))
|
|
44
|
+
live.refresh()
|
|
45
|
+
|
|
46
|
+
# Show final result
|
|
47
|
+
result = handle.get()
|
|
48
|
+
live.update(rich.pretty.Pretty(result))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def add_parser(main_subparsers, parents):
|
|
52
|
+
"""Add the api command to the main parser."""
|
|
53
|
+
api_help = "Call a fal API endpoint directly"
|
|
54
|
+
parser = main_subparsers.add_parser(
|
|
55
|
+
"api",
|
|
56
|
+
description=api_help,
|
|
57
|
+
help=api_help,
|
|
58
|
+
parents=parents,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"model_id",
|
|
63
|
+
help="Name of the Model ID to call",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"params",
|
|
68
|
+
nargs="*",
|
|
69
|
+
help="Key-value pairs (e.g. key=value or nested[a][b]=value)",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
parser.set_defaults(func=_api)
|
|
@@ -17,6 +17,7 @@ def _apps_table(apps: list[AliasInfo]):
|
|
|
17
17
|
table.add_column("Auth")
|
|
18
18
|
table.add_column("Min Concurrency")
|
|
19
19
|
table.add_column("Max Concurrency")
|
|
20
|
+
table.add_column("Concurrency Buffer")
|
|
20
21
|
table.add_column("Max Multiplexing")
|
|
21
22
|
table.add_column("Keep Alive")
|
|
22
23
|
table.add_column("Request Timeout")
|
|
@@ -32,6 +33,7 @@ def _apps_table(apps: list[AliasInfo]):
|
|
|
32
33
|
app.auth_mode,
|
|
33
34
|
str(app.min_concurrency),
|
|
34
35
|
str(app.max_concurrency),
|
|
36
|
+
str(app.concurrency_buffer),
|
|
35
37
|
str(app.max_multiplexing),
|
|
36
38
|
str(app.keep_alive),
|
|
37
39
|
str(app.request_timeout),
|
|
@@ -50,6 +52,15 @@ def _list(args):
|
|
|
50
52
|
client = FalServerlessClient(args.host)
|
|
51
53
|
with client.connect() as connection:
|
|
52
54
|
apps = connection.list_aliases()
|
|
55
|
+
|
|
56
|
+
if args.filter:
|
|
57
|
+
apps = [app for app in apps if args.filter in app.alias]
|
|
58
|
+
|
|
59
|
+
if args.sort_by_runners:
|
|
60
|
+
apps.sort(key=lambda x: x.active_runners)
|
|
61
|
+
else:
|
|
62
|
+
apps.sort(key=lambda x: x.alias)
|
|
63
|
+
|
|
53
64
|
table = _apps_table(apps)
|
|
54
65
|
|
|
55
66
|
args.console.print(table)
|
|
@@ -63,6 +74,16 @@ def _add_list_parser(subparsers, parents):
|
|
|
63
74
|
help=list_help,
|
|
64
75
|
parents=parents,
|
|
65
76
|
)
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
"--sort-by-runners",
|
|
79
|
+
action="store_true",
|
|
80
|
+
help="Sort by number of runners ascending",
|
|
81
|
+
)
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
"--filter",
|
|
84
|
+
type=str,
|
|
85
|
+
help="Filter applications by alias contents",
|
|
86
|
+
)
|
|
66
87
|
parser.set_defaults(func=_list)
|
|
67
88
|
|
|
68
89
|
|
|
@@ -130,6 +151,7 @@ def _scale(args):
|
|
|
130
151
|
and args.max_multiplexing is None
|
|
131
152
|
and args.max_concurrency is None
|
|
132
153
|
and args.min_concurrency is None
|
|
154
|
+
and args.concurrency_buffer is None
|
|
133
155
|
and args.request_timeout is None
|
|
134
156
|
and args.startup_timeout is None
|
|
135
157
|
and args.machine_types is None
|
|
@@ -144,6 +166,7 @@ def _scale(args):
|
|
|
144
166
|
max_multiplexing=args.max_multiplexing,
|
|
145
167
|
max_concurrency=args.max_concurrency,
|
|
146
168
|
min_concurrency=args.min_concurrency,
|
|
169
|
+
concurrency_buffer=args.concurrency_buffer,
|
|
147
170
|
request_timeout=args.request_timeout,
|
|
148
171
|
startup_timeout=args.startup_timeout,
|
|
149
172
|
machine_types=args.machine_types,
|
|
@@ -186,6 +209,11 @@ def _add_scale_parser(subparsers, parents):
|
|
|
186
209
|
type=int,
|
|
187
210
|
help="Minimum concurrency",
|
|
188
211
|
)
|
|
212
|
+
parser.add_argument(
|
|
213
|
+
"--concurrency-buffer",
|
|
214
|
+
type=int,
|
|
215
|
+
help="Concurrency buffer",
|
|
216
|
+
)
|
|
189
217
|
parser.add_argument(
|
|
190
218
|
"--request-timeout",
|
|
191
219
|
type=int,
|
|
@@ -258,13 +286,23 @@ def _runners(args):
|
|
|
258
286
|
table = Table()
|
|
259
287
|
table.add_column("Runner ID")
|
|
260
288
|
table.add_column("In Flight Requests")
|
|
261
|
-
table.add_column("
|
|
289
|
+
table.add_column("Missing Leases")
|
|
290
|
+
table.add_column("Expires In")
|
|
262
291
|
table.add_column("Uptime")
|
|
263
292
|
|
|
264
293
|
for runner in runners:
|
|
294
|
+
num_leases_with_request = len(
|
|
295
|
+
[
|
|
296
|
+
lease
|
|
297
|
+
for lease in runner.external_metadata.get("leases", [])
|
|
298
|
+
if lease.get("request_id") is not None
|
|
299
|
+
]
|
|
300
|
+
)
|
|
301
|
+
|
|
265
302
|
table.add_row(
|
|
266
303
|
runner.runner_id,
|
|
267
304
|
str(runner.in_flight_requests),
|
|
305
|
+
str(runner.in_flight_requests - num_leases_with_request),
|
|
268
306
|
(
|
|
269
307
|
"N/A (active)"
|
|
270
308
|
if runner.expiration_countdown is None
|