opensandbox 0.1.8.dev1__tar.gz → 0.1.8.dev2__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.
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/.gitignore +2 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/PKG-INFO +3 -2
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/README.md +2 -1
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/pyproject.toml +1 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/__init__.py +0 -4
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/snapshots/delete_snapshots_snapshot_id.py +28 -8
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/snapshots/post_sandboxes_sandbox_id_snapshots.py +16 -8
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/async_redis_pool_store.py +101 -42
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/pool.py +0 -4
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/pool_async.py +8 -1
- opensandbox-0.1.8.dev2/src/opensandbox/pool_redis.py +27 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/redis_pool_store.py +47 -7
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/pool.py +8 -1
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/LICENSE +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/_async_pool_reconciler.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/_async_pool_store.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/_pool_reconciler.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/_pool_store.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/command_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/command_model_converter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/event_node.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/exception_converter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/execution_converter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/execution_event_dispatcher.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/filesystem_model_converter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/metrics_model_converter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/response_handler.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/sandbox_model_converter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/egress_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/factory.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/filesystem_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/health_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/metrics_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/sandboxes_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/api/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/api/policy/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/api/policy/get_policy.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/api/policy/patch_policy.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/client.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/errors.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/models/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/models/network_policy.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/models/network_policy_default_action.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/models/network_rule.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/models/network_rule_action.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/models/policy_status_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/py.typed +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/types.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/create_code_context.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/delete_context.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/delete_contexts_by_language.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/get_context.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/interrupt_code.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/list_contexts.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/code_interpreting/run_code.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/create_session.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/delete_session.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/get_background_command_logs.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/get_command_status.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/interrupt_command.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/run_command.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/command/run_in_session.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/chmod_files.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/download_file.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/get_files_info.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/make_dirs.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/remove_dirs.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/remove_files.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/rename_files.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/replace_content.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/search_files.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/filesystem/upload_file.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/health/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/health/ping.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/metric/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/metric/get_metrics.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/api/metric/watch_metrics.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/client.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/errors.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/chmod_files_body.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/code_context.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/code_context_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/command_status_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/create_session_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/create_session_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/error_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/file_info.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/file_metadata.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/get_files_info_response_200.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/make_dirs_body.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/metrics.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/permission.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/rename_file_item.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/replace_content_body.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/replace_file_content_item.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/run_code_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/run_command_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/run_command_request_envs.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/run_in_session_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/server_stream_event.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/server_stream_event_error.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/server_stream_event_results.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/server_stream_event_type.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/models/upload_file_body.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/py.typed +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/execd/types.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/delete_sandboxes_sandbox_id.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/get_sandboxes.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/get_sandboxes_sandbox_id.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/get_sandboxes_sandbox_id_endpoints_port.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/post_sandboxes.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/post_sandboxes_sandbox_id_pause.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/post_sandboxes_sandbox_id_renew_expiration.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/sandboxes/post_sandboxes_sandbox_id_resume.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/snapshots/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/snapshots/get_snapshots.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/api/snapshots/get_snapshots_snapshot_id.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/client.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/errors.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_sandbox_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_sandbox_request_env.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_sandbox_request_extensions.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_sandbox_request_metadata.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_sandbox_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_sandbox_response_metadata.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/create_snapshot_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/endpoint.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/endpoint_headers.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/error_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/host.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/image_spec.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/image_spec_auth.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/list_sandboxes_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/list_snapshots_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/network_policy.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/network_policy_default_action.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/network_rule.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/network_rule_action.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/ossfs.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/ossfs_version.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/pagination_info.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/platform_spec.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/platform_spec_arch.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/platform_spec_os.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/pvc.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/renew_sandbox_expiration_request.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/renew_sandbox_expiration_response.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/resource_limits.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/sandbox.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/sandbox_metadata.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/sandbox_status.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/snapshot.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/snapshot_status.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/models/volume.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/py.typed +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/lifecycle/types.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/config/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/config/connection.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/config/connection_sync.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/constants.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/exceptions/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/exceptions/sandbox.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/manager.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/models/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/models/execd.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/models/execd_sync.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/models/filesystem.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/models/sandboxes.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/pool_types.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/py.typed +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sandbox.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/command.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/egress.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/filesystem.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/health.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/metrics.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/services/sandbox.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/command_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/converter/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/converter/execution_event_dispatcher.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/egress_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/factory.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/filesystem_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/health_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/metrics_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/adapters/sandboxes_adapter.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/manager.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/sandbox.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/__init__.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/command.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/egress.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/filesystem.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/health.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/metrics.py +0 -0
- {opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/sync/services/sandbox.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensandbox
|
|
3
|
-
Version: 0.1.8.
|
|
3
|
+
Version: 0.1.8.dev2
|
|
4
4
|
Summary: OpenSandbox Python SDK - Secure, isolated execution environments
|
|
5
5
|
Project-URL: Homepage, https://open-sandbox.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/alibaba/OpenSandbox
|
|
@@ -420,8 +420,9 @@ The store does not create or close Redis clients.
|
|
|
420
420
|
```python
|
|
421
421
|
import redis
|
|
422
422
|
|
|
423
|
-
from opensandbox import PoolCreationSpec,
|
|
423
|
+
from opensandbox import PoolCreationSpec, SandboxPoolSync
|
|
424
424
|
from opensandbox.config import ConnectionConfigSync
|
|
425
|
+
from opensandbox.pool_redis import RedisPoolStateStore
|
|
425
426
|
|
|
426
427
|
redis_client = redis.Redis.from_url(
|
|
427
428
|
"redis://user:password@redis.example.com:6379/0",
|
|
@@ -187,8 +187,9 @@ The store does not create or close Redis clients.
|
|
|
187
187
|
```python
|
|
188
188
|
import redis
|
|
189
189
|
|
|
190
|
-
from opensandbox import PoolCreationSpec,
|
|
190
|
+
from opensandbox import PoolCreationSpec, SandboxPoolSync
|
|
191
191
|
from opensandbox.config import ConnectionConfigSync
|
|
192
|
+
from opensandbox.pool_redis import RedisPoolStateStore
|
|
192
193
|
|
|
193
194
|
redis_client = redis.Redis.from_url(
|
|
194
195
|
"redis://user:password@redis.example.com:6379/0",
|
|
@@ -102,12 +102,10 @@ from importlib.metadata import version as _pkg_version
|
|
|
102
102
|
from opensandbox.manager import SandboxManager
|
|
103
103
|
from opensandbox.pool import (
|
|
104
104
|
AcquirePolicy,
|
|
105
|
-
AsyncRedisPoolStateStore,
|
|
106
105
|
AsyncSandboxPool,
|
|
107
106
|
InMemoryAsyncPoolStateStore,
|
|
108
107
|
InMemoryPoolStateStore,
|
|
109
108
|
PoolCreationSpec,
|
|
110
|
-
RedisPoolStateStore,
|
|
111
109
|
SandboxPool,
|
|
112
110
|
SandboxPoolAsync,
|
|
113
111
|
)
|
|
@@ -133,6 +131,4 @@ __all__ = [
|
|
|
133
131
|
"PoolCreationSpec",
|
|
134
132
|
"InMemoryAsyncPoolStateStore",
|
|
135
133
|
"InMemoryPoolStateStore",
|
|
136
|
-
"AsyncRedisPoolStateStore",
|
|
137
|
-
"RedisPoolStateStore",
|
|
138
134
|
]
|
|
@@ -91,8 +91,13 @@ def sync_detailed(
|
|
|
91
91
|
) -> Response[Any | ErrorResponse]:
|
|
92
92
|
"""Delete a snapshot
|
|
93
93
|
|
|
94
|
-
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
95
|
-
deleted.
|
|
94
|
+
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
95
|
+
being created cannot be deleted.
|
|
96
|
+
|
|
97
|
+
For Kubernetes-backed snapshots, deletion removes OpenSandbox metadata
|
|
98
|
+
and Kubernetes coordination resources, but does not guarantee removal
|
|
99
|
+
of pushed OCI images from the configured registry. Use registry
|
|
100
|
+
retention or garbage collection policies for image lifecycle cleanup.
|
|
96
101
|
|
|
97
102
|
Args:
|
|
98
103
|
snapshot_id (str):
|
|
@@ -123,8 +128,13 @@ def sync(
|
|
|
123
128
|
) -> Any | ErrorResponse | None:
|
|
124
129
|
"""Delete a snapshot
|
|
125
130
|
|
|
126
|
-
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
127
|
-
deleted.
|
|
131
|
+
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
132
|
+
being created cannot be deleted.
|
|
133
|
+
|
|
134
|
+
For Kubernetes-backed snapshots, deletion removes OpenSandbox metadata
|
|
135
|
+
and Kubernetes coordination resources, but does not guarantee removal
|
|
136
|
+
of pushed OCI images from the configured registry. Use registry
|
|
137
|
+
retention or garbage collection policies for image lifecycle cleanup.
|
|
128
138
|
|
|
129
139
|
Args:
|
|
130
140
|
snapshot_id (str):
|
|
@@ -150,8 +160,13 @@ async def asyncio_detailed(
|
|
|
150
160
|
) -> Response[Any | ErrorResponse]:
|
|
151
161
|
"""Delete a snapshot
|
|
152
162
|
|
|
153
|
-
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
154
|
-
deleted.
|
|
163
|
+
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
164
|
+
being created cannot be deleted.
|
|
165
|
+
|
|
166
|
+
For Kubernetes-backed snapshots, deletion removes OpenSandbox metadata
|
|
167
|
+
and Kubernetes coordination resources, but does not guarantee removal
|
|
168
|
+
of pushed OCI images from the configured registry. Use registry
|
|
169
|
+
retention or garbage collection policies for image lifecycle cleanup.
|
|
155
170
|
|
|
156
171
|
Args:
|
|
157
172
|
snapshot_id (str):
|
|
@@ -180,8 +195,13 @@ async def asyncio(
|
|
|
180
195
|
) -> Any | ErrorResponse | None:
|
|
181
196
|
"""Delete a snapshot
|
|
182
197
|
|
|
183
|
-
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
184
|
-
deleted.
|
|
198
|
+
Delete a persistent sandbox snapshot by id. Snapshots that are still
|
|
199
|
+
being created cannot be deleted.
|
|
200
|
+
|
|
201
|
+
For Kubernetes-backed snapshots, deletion removes OpenSandbox metadata
|
|
202
|
+
and Kubernetes coordination resources, but does not guarantee removal
|
|
203
|
+
of pushed OCI images from the configured registry. Use registry
|
|
204
|
+
retention or garbage collection policies for image lifecycle cleanup.
|
|
185
205
|
|
|
186
206
|
Args:
|
|
187
207
|
snapshot_id (str):
|
|
@@ -115,8 +115,10 @@ def sync_detailed(
|
|
|
115
115
|
"""Create a snapshot from a sandbox
|
|
116
116
|
|
|
117
117
|
Create a persistent point-in-time snapshot from the sandbox's current state.
|
|
118
|
-
The
|
|
119
|
-
|
|
118
|
+
The source sandbox must be `Running`. The returned snapshot id identifies
|
|
119
|
+
the created artifact. Snapshot creation may temporarily pause the sandbox
|
|
120
|
+
while the runtime captures provider-supported state, then the source
|
|
121
|
+
sandbox continues running.
|
|
120
122
|
|
|
121
123
|
Args:
|
|
122
124
|
sandbox_id (str):
|
|
@@ -151,8 +153,10 @@ def sync(
|
|
|
151
153
|
"""Create a snapshot from a sandbox
|
|
152
154
|
|
|
153
155
|
Create a persistent point-in-time snapshot from the sandbox's current state.
|
|
154
|
-
The
|
|
155
|
-
|
|
156
|
+
The source sandbox must be `Running`. The returned snapshot id identifies
|
|
157
|
+
the created artifact. Snapshot creation may temporarily pause the sandbox
|
|
158
|
+
while the runtime captures provider-supported state, then the source
|
|
159
|
+
sandbox continues running.
|
|
156
160
|
|
|
157
161
|
Args:
|
|
158
162
|
sandbox_id (str):
|
|
@@ -182,8 +186,10 @@ async def asyncio_detailed(
|
|
|
182
186
|
"""Create a snapshot from a sandbox
|
|
183
187
|
|
|
184
188
|
Create a persistent point-in-time snapshot from the sandbox's current state.
|
|
185
|
-
The
|
|
186
|
-
|
|
189
|
+
The source sandbox must be `Running`. The returned snapshot id identifies
|
|
190
|
+
the created artifact. Snapshot creation may temporarily pause the sandbox
|
|
191
|
+
while the runtime captures provider-supported state, then the source
|
|
192
|
+
sandbox continues running.
|
|
187
193
|
|
|
188
194
|
Args:
|
|
189
195
|
sandbox_id (str):
|
|
@@ -216,8 +222,10 @@ async def asyncio(
|
|
|
216
222
|
"""Create a snapshot from a sandbox
|
|
217
223
|
|
|
218
224
|
Create a persistent point-in-time snapshot from the sandbox's current state.
|
|
219
|
-
The
|
|
220
|
-
|
|
225
|
+
The source sandbox must be `Running`. The returned snapshot id identifies
|
|
226
|
+
the created artifact. Snapshot creation may temporarily pause the sandbox
|
|
227
|
+
while the runtime captures provider-supported state, then the source
|
|
228
|
+
sandbox continues running.
|
|
221
229
|
|
|
222
230
|
Args:
|
|
223
231
|
sandbox_id (str):
|
|
@@ -20,17 +20,26 @@ from __future__ import annotations
|
|
|
20
20
|
import base64
|
|
21
21
|
from collections.abc import Awaitable, Callable
|
|
22
22
|
from datetime import datetime, timedelta, timezone
|
|
23
|
-
from typing import Any, TypeVar
|
|
23
|
+
from typing import Any, TypeVar, cast
|
|
24
24
|
|
|
25
25
|
from opensandbox.exceptions import PoolStateStoreUnavailableException
|
|
26
26
|
from opensandbox.pool_types import IdleEntry, StoreCounters
|
|
27
27
|
from opensandbox.redis_pool_store import (
|
|
28
|
+
_REQUIRED_REDIS_METHODS,
|
|
29
|
+
Redis,
|
|
28
30
|
RedisPoolStateStore,
|
|
29
31
|
_decode,
|
|
30
32
|
_millis,
|
|
31
33
|
_validate_owner_and_ttl,
|
|
32
34
|
)
|
|
33
35
|
|
|
36
|
+
try:
|
|
37
|
+
from redis.asyncio import Redis as AsyncRedis
|
|
38
|
+
except ImportError as exc: # pragma: no cover
|
|
39
|
+
raise ImportError(
|
|
40
|
+
'Install opensandbox[pool-redis] to use opensandbox.pool_redis'
|
|
41
|
+
) from exc
|
|
42
|
+
|
|
34
43
|
T = TypeVar("T")
|
|
35
44
|
|
|
36
45
|
|
|
@@ -39,7 +48,8 @@ class AsyncRedisPoolStateStore:
|
|
|
39
48
|
|
|
40
49
|
DEFAULT_KEY_PREFIX = RedisPoolStateStore.DEFAULT_KEY_PREFIX
|
|
41
50
|
|
|
42
|
-
def __init__(self, redis:
|
|
51
|
+
def __init__(self, redis: AsyncRedis, key_prefix: str = DEFAULT_KEY_PREFIX) -> None:
|
|
52
|
+
_validate_async_redis_client(redis)
|
|
43
53
|
self._redis = redis
|
|
44
54
|
self._key_prefix = key_prefix
|
|
45
55
|
self._default_idle_ttl = timedelta(hours=24)
|
|
@@ -48,11 +58,14 @@ class AsyncRedisPoolStateStore:
|
|
|
48
58
|
result = await self._execute(
|
|
49
59
|
"try_take_idle",
|
|
50
60
|
pool_name,
|
|
51
|
-
lambda:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
lambda: cast(
|
|
62
|
+
Awaitable[Any],
|
|
63
|
+
self._redis.eval(
|
|
64
|
+
RedisPoolStateStore._TAKE_IDLE_SCRIPT,
|
|
65
|
+
2,
|
|
66
|
+
self._idle_list_key(pool_name),
|
|
67
|
+
self._idle_expires_key(pool_name),
|
|
68
|
+
),
|
|
56
69
|
),
|
|
57
70
|
)
|
|
58
71
|
return _decode(result) if result is not None else None
|
|
@@ -64,13 +77,16 @@ class AsyncRedisPoolStateStore:
|
|
|
64
77
|
await self._execute(
|
|
65
78
|
"put_idle",
|
|
66
79
|
pool_name,
|
|
67
|
-
lambda:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
lambda: cast(
|
|
81
|
+
Awaitable[Any],
|
|
82
|
+
self._redis.eval(
|
|
83
|
+
RedisPoolStateStore._PUT_IDLE_SCRIPT,
|
|
84
|
+
2,
|
|
85
|
+
self._idle_list_key(pool_name),
|
|
86
|
+
self._idle_expires_key(pool_name),
|
|
87
|
+
sandbox_id,
|
|
88
|
+
str(ttl_millis),
|
|
89
|
+
),
|
|
74
90
|
),
|
|
75
91
|
)
|
|
76
92
|
|
|
@@ -79,8 +95,14 @@ class AsyncRedisPoolStateStore:
|
|
|
79
95
|
"remove_idle",
|
|
80
96
|
pool_name,
|
|
81
97
|
lambda: _gather_tuple(
|
|
82
|
-
|
|
83
|
-
|
|
98
|
+
cast(
|
|
99
|
+
Awaitable[Any],
|
|
100
|
+
self._redis.hdel(self._idle_expires_key(pool_name), sandbox_id),
|
|
101
|
+
),
|
|
102
|
+
cast(
|
|
103
|
+
Awaitable[Any],
|
|
104
|
+
self._redis.lrem(self._idle_list_key(pool_name), 0, sandbox_id),
|
|
105
|
+
),
|
|
84
106
|
),
|
|
85
107
|
)
|
|
86
108
|
|
|
@@ -109,12 +131,15 @@ class AsyncRedisPoolStateStore:
|
|
|
109
131
|
result = await self._execute(
|
|
110
132
|
"renew_primary_lock",
|
|
111
133
|
pool_name,
|
|
112
|
-
lambda:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
lambda: cast(
|
|
135
|
+
Awaitable[Any],
|
|
136
|
+
self._redis.eval(
|
|
137
|
+
RedisPoolStateStore._RENEW_LOCK_SCRIPT,
|
|
138
|
+
1,
|
|
139
|
+
self._primary_lock_key(pool_name),
|
|
140
|
+
owner_id,
|
|
141
|
+
str(max(1, _millis(ttl))),
|
|
142
|
+
),
|
|
118
143
|
),
|
|
119
144
|
)
|
|
120
145
|
return result == 1 or result == b"1"
|
|
@@ -123,11 +148,14 @@ class AsyncRedisPoolStateStore:
|
|
|
123
148
|
await self._execute(
|
|
124
149
|
"release_primary_lock",
|
|
125
150
|
pool_name,
|
|
126
|
-
lambda:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
151
|
+
lambda: cast(
|
|
152
|
+
Awaitable[Any],
|
|
153
|
+
self._redis.eval(
|
|
154
|
+
RedisPoolStateStore._RELEASE_LOCK_SCRIPT,
|
|
155
|
+
1,
|
|
156
|
+
self._primary_lock_key(pool_name),
|
|
157
|
+
owner_id,
|
|
158
|
+
),
|
|
131
159
|
),
|
|
132
160
|
)
|
|
133
161
|
|
|
@@ -135,35 +163,52 @@ class AsyncRedisPoolStateStore:
|
|
|
135
163
|
await self._execute(
|
|
136
164
|
"reap_expired_idle",
|
|
137
165
|
pool_name,
|
|
138
|
-
lambda:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
166
|
+
lambda: cast(
|
|
167
|
+
Awaitable[Any],
|
|
168
|
+
self._redis.eval(
|
|
169
|
+
RedisPoolStateStore._REAP_EXPIRED_SCRIPT,
|
|
170
|
+
2,
|
|
171
|
+
self._idle_list_key(pool_name),
|
|
172
|
+
self._idle_expires_key(pool_name),
|
|
173
|
+
),
|
|
143
174
|
),
|
|
144
175
|
)
|
|
145
176
|
|
|
146
177
|
async def snapshot_counters(self, pool_name: str) -> StoreCounters:
|
|
147
178
|
async def op() -> StoreCounters:
|
|
148
|
-
|
|
179
|
+
idle_count = cast(
|
|
180
|
+
int,
|
|
181
|
+
await cast(
|
|
182
|
+
Awaitable[Any],
|
|
183
|
+
self._redis.hlen(self._idle_expires_key(pool_name)),
|
|
184
|
+
),
|
|
185
|
+
)
|
|
149
186
|
return StoreCounters(
|
|
150
|
-
idle_count=
|
|
187
|
+
idle_count=idle_count
|
|
151
188
|
)
|
|
152
189
|
|
|
153
190
|
return await self._execute("snapshot_counters", pool_name, op)
|
|
154
191
|
|
|
155
192
|
async def snapshot_idle_entries(self, pool_name: str) -> list[IdleEntry]:
|
|
156
193
|
async def op() -> list[IdleEntry]:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
194
|
+
raw_ids = cast(
|
|
195
|
+
list[Any],
|
|
196
|
+
await cast(
|
|
197
|
+
Awaitable[Any],
|
|
198
|
+
self._redis.lrange(self._idle_list_key(pool_name), 0, -1),
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
ids = [_decode(v) for v in raw_ids]
|
|
202
|
+
raw_expires_by_id = cast(
|
|
203
|
+
dict[Any, Any],
|
|
204
|
+
await cast(
|
|
205
|
+
Awaitable[Any],
|
|
206
|
+
self._redis.hgetall(self._idle_expires_key(pool_name)),
|
|
207
|
+
),
|
|
208
|
+
)
|
|
162
209
|
expires_by_id = {
|
|
163
210
|
_decode(k): _decode(v)
|
|
164
|
-
for k, v in (
|
|
165
|
-
await self._redis.hgetall(self._idle_expires_key(pool_name))
|
|
166
|
-
).items()
|
|
211
|
+
for k, v in raw_expires_by_id.items()
|
|
167
212
|
}
|
|
168
213
|
entries: list[IdleEntry] = []
|
|
169
214
|
for sandbox_id in ids:
|
|
@@ -267,3 +312,17 @@ async def _gather_tuple(*awaitables: Awaitable[Any]) -> tuple[Any, ...]:
|
|
|
267
312
|
import asyncio
|
|
268
313
|
|
|
269
314
|
return tuple(await asyncio.gather(*awaitables))
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _validate_async_redis_client(redis: Any) -> None:
|
|
318
|
+
if isinstance(redis, Redis) or not isinstance(redis, AsyncRedis):
|
|
319
|
+
raise TypeError(
|
|
320
|
+
"AsyncRedisPoolStateStore requires a redis.asyncio.Redis client; "
|
|
321
|
+
"use RedisPoolStateStore for redis.Redis"
|
|
322
|
+
)
|
|
323
|
+
for method_name in _REQUIRED_REDIS_METHODS:
|
|
324
|
+
method = getattr(redis, method_name, None)
|
|
325
|
+
if not callable(method):
|
|
326
|
+
raise TypeError(
|
|
327
|
+
f"AsyncRedisPoolStateStore requires a Redis client with callable {method_name}()"
|
|
328
|
+
)
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
from opensandbox._async_pool_store import InMemoryAsyncPoolStateStore
|
|
19
19
|
from opensandbox._pool_store import InMemoryPoolStateStore
|
|
20
|
-
from opensandbox.async_redis_pool_store import AsyncRedisPoolStateStore
|
|
21
20
|
from opensandbox.pool_async import AsyncSandboxPool, SandboxPoolAsync
|
|
22
21
|
from opensandbox.pool_types import (
|
|
23
22
|
AcquirePolicy,
|
|
@@ -32,7 +31,6 @@ from opensandbox.pool_types import (
|
|
|
32
31
|
PoolStateStore,
|
|
33
32
|
StoreCounters,
|
|
34
33
|
)
|
|
35
|
-
from opensandbox.redis_pool_store import RedisPoolStateStore
|
|
36
34
|
from opensandbox.sync.pool import SandboxPoolSync
|
|
37
35
|
|
|
38
36
|
SandboxPool = SandboxPoolSync
|
|
@@ -41,7 +39,6 @@ __all__ = [
|
|
|
41
39
|
"AcquirePolicy",
|
|
42
40
|
"AsyncPoolConfig",
|
|
43
41
|
"AsyncPoolStateStore",
|
|
44
|
-
"AsyncRedisPoolStateStore",
|
|
45
42
|
"AsyncSandboxPool",
|
|
46
43
|
"IdleEntry",
|
|
47
44
|
"InMemoryAsyncPoolStateStore",
|
|
@@ -52,7 +49,6 @@ __all__ = [
|
|
|
52
49
|
"PoolSnapshot",
|
|
53
50
|
"PoolState",
|
|
54
51
|
"PoolStateStore",
|
|
55
|
-
"RedisPoolStateStore",
|
|
56
52
|
"SandboxPoolAsync",
|
|
57
53
|
"SandboxPool",
|
|
58
54
|
"SandboxPoolSync",
|
|
@@ -428,7 +428,14 @@ class SandboxPoolAsync:
|
|
|
428
428
|
skip_health_check=self._config.acquire_skip_health_check,
|
|
429
429
|
)
|
|
430
430
|
if sandbox_timeout is not None:
|
|
431
|
-
|
|
431
|
+
try:
|
|
432
|
+
await sandbox.renew(sandbox_timeout)
|
|
433
|
+
except BaseException:
|
|
434
|
+
try:
|
|
435
|
+
await sandbox.kill()
|
|
436
|
+
finally:
|
|
437
|
+
await sandbox.close()
|
|
438
|
+
raise
|
|
432
439
|
return sandbox
|
|
433
440
|
|
|
434
441
|
async def _resolve_max_idle(self) -> int:
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2025 Alibaba Group Holding Ltd.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#
|
|
16
|
+
"""Redis-backed sandbox pool state stores.
|
|
17
|
+
|
|
18
|
+
Install ``opensandbox[pool-redis]`` and pass a caller-managed redis-py client.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from opensandbox.async_redis_pool_store import AsyncRedisPoolStateStore
|
|
22
|
+
from opensandbox.redis_pool_store import RedisPoolStateStore
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"AsyncRedisPoolStateStore",
|
|
26
|
+
"RedisPoolStateStore",
|
|
27
|
+
]
|
|
@@ -19,11 +19,29 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import base64
|
|
21
21
|
from datetime import datetime, timedelta, timezone
|
|
22
|
-
from typing import Any
|
|
22
|
+
from typing import Any, cast
|
|
23
23
|
|
|
24
24
|
from opensandbox.exceptions import PoolStateStoreUnavailableException
|
|
25
25
|
from opensandbox.pool_types import IdleEntry, StoreCounters
|
|
26
26
|
|
|
27
|
+
try:
|
|
28
|
+
from redis import Redis
|
|
29
|
+
except ImportError as exc: # pragma: no cover
|
|
30
|
+
raise ImportError(
|
|
31
|
+
'Install opensandbox[pool-redis] to use opensandbox.pool_redis'
|
|
32
|
+
) from exc
|
|
33
|
+
|
|
34
|
+
_REQUIRED_REDIS_METHODS = (
|
|
35
|
+
"eval",
|
|
36
|
+
"get",
|
|
37
|
+
"set",
|
|
38
|
+
"hdel",
|
|
39
|
+
"lrem",
|
|
40
|
+
"hlen",
|
|
41
|
+
"lrange",
|
|
42
|
+
"hgetall",
|
|
43
|
+
)
|
|
44
|
+
|
|
27
45
|
|
|
28
46
|
class RedisPoolStateStore:
|
|
29
47
|
"""Distributed pool store backed by a caller-managed Redis client."""
|
|
@@ -91,7 +109,8 @@ end
|
|
|
91
109
|
return 1
|
|
92
110
|
"""
|
|
93
111
|
|
|
94
|
-
def __init__(self, redis:
|
|
112
|
+
def __init__(self, redis: Redis, key_prefix: str = DEFAULT_KEY_PREFIX) -> None:
|
|
113
|
+
_validate_sync_redis_client(redis)
|
|
95
114
|
self._redis = redis
|
|
96
115
|
self._key_prefix = key_prefix
|
|
97
116
|
self._default_idle_ttl = timedelta(hours=24)
|
|
@@ -195,18 +214,25 @@ return 1
|
|
|
195
214
|
|
|
196
215
|
def snapshot_counters(self, pool_name: str) -> StoreCounters:
|
|
197
216
|
def op() -> StoreCounters:
|
|
198
|
-
|
|
199
|
-
return StoreCounters(idle_count=
|
|
217
|
+
idle_count = cast(int, self._redis.hlen(self._idle_expires_key(pool_name)))
|
|
218
|
+
return StoreCounters(idle_count=idle_count)
|
|
200
219
|
|
|
201
220
|
return self._execute("snapshot_counters", pool_name, op)
|
|
202
221
|
|
|
203
222
|
def snapshot_idle_entries(self, pool_name: str) -> list[IdleEntry]:
|
|
204
223
|
def op() -> list[IdleEntry]:
|
|
205
|
-
|
|
206
|
-
|
|
224
|
+
raw_ids = cast(
|
|
225
|
+
list[Any],
|
|
226
|
+
self._redis.lrange(self._idle_list_key(pool_name), 0, -1),
|
|
227
|
+
)
|
|
228
|
+
ids = [_decode(v) for v in raw_ids]
|
|
229
|
+
raw_expires_by_id = cast(
|
|
230
|
+
dict[Any, Any],
|
|
231
|
+
self._redis.hgetall(self._idle_expires_key(pool_name)),
|
|
232
|
+
)
|
|
207
233
|
expires_by_id = {
|
|
208
234
|
_decode(k): _decode(v)
|
|
209
|
-
for k, v in
|
|
235
|
+
for k, v in raw_expires_by_id.items()
|
|
210
236
|
}
|
|
211
237
|
entries: list[IdleEntry] = []
|
|
212
238
|
for sandbox_id in ids:
|
|
@@ -317,3 +343,17 @@ def _validate_owner_and_ttl(owner_id: str, ttl: timedelta) -> None:
|
|
|
317
343
|
raise ValueError("owner_id must not be blank")
|
|
318
344
|
if ttl.total_seconds() <= 0:
|
|
319
345
|
raise ValueError("ttl must be positive")
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _validate_sync_redis_client(redis: Any) -> None:
|
|
349
|
+
if not isinstance(redis, Redis):
|
|
350
|
+
raise TypeError(
|
|
351
|
+
"RedisPoolStateStore requires a redis.Redis client; "
|
|
352
|
+
"use AsyncRedisPoolStateStore for redis.asyncio.Redis"
|
|
353
|
+
)
|
|
354
|
+
for method_name in _REQUIRED_REDIS_METHODS:
|
|
355
|
+
method = getattr(redis, method_name, None)
|
|
356
|
+
if not callable(method):
|
|
357
|
+
raise TypeError(
|
|
358
|
+
f"RedisPoolStateStore requires a Redis client with callable {method_name}()"
|
|
359
|
+
)
|
|
@@ -410,7 +410,14 @@ class SandboxPoolSync:
|
|
|
410
410
|
skip_health_check=self._config.acquire_skip_health_check,
|
|
411
411
|
)
|
|
412
412
|
if sandbox_timeout is not None:
|
|
413
|
-
|
|
413
|
+
try:
|
|
414
|
+
sandbox.renew(sandbox_timeout)
|
|
415
|
+
except BaseException:
|
|
416
|
+
try:
|
|
417
|
+
sandbox.kill()
|
|
418
|
+
finally:
|
|
419
|
+
sandbox.close()
|
|
420
|
+
raise
|
|
414
421
|
return sandbox
|
|
415
422
|
|
|
416
423
|
def _resolve_max_idle(self) -> int:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/command_adapter.py
RENAMED
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/converter/event_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/egress_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/filesystem_adapter.py
RENAMED
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/health_adapter.py
RENAMED
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/metrics_adapter.py
RENAMED
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/adapters/sandboxes_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensandbox-0.1.8.dev1 → opensandbox-0.1.8.dev2}/src/opensandbox/api/egress/api/__init__.py
RENAMED
|
File without changes
|