digitalkin 1.0.0.dev18__tar.gz → 1.0.0.dev19__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.
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/PKG-INFO +1 -1
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/pyproject.toml +1 -1
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/__version__.py +1 -1
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/module_runner.py +12 -1
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/gateway_servicer.py +102 -17
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/utils/circuit_breaker.py +16 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +62 -53
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/grpc_servers/stream_error_codes.py +1 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin.egg-info/PKG-INFO +1 -1
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/LICENSE +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/README.md +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/mock/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/mock/mock_pb2.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_async_insecure.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_async_secure.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_sync_insecure.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_sync_secure.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/echo_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/models/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/models/input.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/models/output.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/models/secret.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/models/setup.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/server.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/triggers/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/triggers/message_trigger.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/archetype_with_tools_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/cpu_intensive_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/dynamic_setup_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/minimal_llm_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/text_transform_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/monitoring/digitalkin_observability/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/monitoring/digitalkin_observability/http_server.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/monitoring/digitalkin_observability/interceptors.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/monitoring/digitalkin_observability/metrics.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/monitoring/digitalkin_observability/prometheus.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/monitoring/tests/test_metrics.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/client.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/echo_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/models/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/models/input.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/models/output.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/models/secret.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/models/setup.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/server.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/triggers/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/triggers/message_trigger.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/services/filesystem_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/services/storage_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/setup.cfg +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/agno_adapter.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/agui_tools.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/hitl.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/models.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/common/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/common/factories.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/job_manager/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/job_manager/base_job_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/job_manager/single_job_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/profiling/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/profiling/step_timer.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/profiling/task_profiler.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/resilience/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/resilience/bulkhead.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/resilience/task_supervisor.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/base_task_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/local_task_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/proto_streams.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/redis_client.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/redis_idempotency.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/redis_signal.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/redis_state.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/remote_task_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/task_executor.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/task_session.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/_base_server.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/interceptors/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/interceptors/request_ids.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/m2m_call_registry.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/module_server.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/module_servicer.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/stream_registry.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/stream_session.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/utils/grpc_error_handler.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/utils/utility_schema_extender.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/utils/validators.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/logger.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/agui_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/base_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/cost_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/file_history_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/filesystem_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/logger_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/mixins/storage_mixin.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/core/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/core/job_manager_models.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/core/redis.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/core/task_monitor.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/events/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/events/agent_events.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/grpc_servers/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/grpc_servers/circuit_breaker.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/grpc_servers/m2m.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/grpc_servers/models.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/grpc_servers/types.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/ag_ui.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/base_types.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/module_context.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/module_types.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/request_metadata.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/select_schema.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/setup_types.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/tool_cache.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/tool_reference.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/module/utility.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/services/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/services/cost.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/services/registry.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/services/services.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/services/storage.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/gateway.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/grpc_client.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/log.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/profiling.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/queue.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/redis.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/resilience.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/server/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/server/channel.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/server/grpc.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/server/server.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/server/servicer.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/task_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/settings/utils/channel.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/models/utils/dynamic_schema.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/_base_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/archetype_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/tool_module.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/trigger_handler.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/triggers/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/triggers/healthcheck_ping_trigger.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/triggers/healthcheck_services_trigger.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/modules/triggers/healthcheck_status_trigger.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/py.typed +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/base_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/communication/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/communication/communication_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/communication/default_communication.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/communication/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/communication/grpc_communication.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/cost/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/cost/cost_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/cost/default_cost.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/cost/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/cost/grpc_cost.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/filesystem/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/filesystem/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/identity/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/identity/default_identity.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/identity/identity_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/registry/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/registry/default_registry.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/registry/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/registry/grpc_registry.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/registry/registry_models.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/registry/registry_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/services_config.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/services_models.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/setup/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/setup/default_setup.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/setup/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/setup/grpc_setup.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/setup/setup_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/storage/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/storage/default_storage.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/storage/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/storage/grpc_storage.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/storage/storage_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/task_manager/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/task_manager/default_task_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/task_manager/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/task_manager/redis_task_manager.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/task_manager/task_manager_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/user_profile/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/user_profile/default_user_profile.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/user_profile/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/user_profile/grpc_user_profile.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/services/user_profile/user_profile_strategy.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/__init__.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/arg_parser.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/conditional_schema.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/development_mode_action.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/dynamic_schema.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/exceptions.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/llm_ready_schema.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/package_discover.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/proto_utils.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/utils/schema_splitter.py +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin.egg-info/SOURCES.txt +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin.egg-info/dependency_links.txt +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin.egg-info/requires.txt +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin.egg-info/top_level.txt +0 -0
- {digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/tests/test_exceptions.py +0 -0
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/module_runner.py
RENAMED
|
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
8
8
|
|
|
9
9
|
from google.protobuf import json_format, struct_pb2
|
|
10
10
|
from pydantic import ValidationError
|
|
11
|
+
from redis.exceptions import RedisError
|
|
11
12
|
|
|
12
13
|
from digitalkin.core.exceptions import BackpressureTimeoutError
|
|
13
14
|
from digitalkin.core.profiling.step_timer import StepTimer
|
|
@@ -41,7 +42,7 @@ class ModuleRunner:
|
|
|
41
42
|
self._redis_client = redis_client
|
|
42
43
|
self._servicer = servicer
|
|
43
44
|
|
|
44
|
-
async def run( # noqa: PLR0914, PLR0915
|
|
45
|
+
async def run( # noqa: C901, PLR0914, PLR0915
|
|
45
46
|
self,
|
|
46
47
|
query: struct_pb2.Struct,
|
|
47
48
|
*,
|
|
@@ -215,6 +216,16 @@ class ModuleRunner:
|
|
|
215
216
|
except BackpressureTimeoutError as exc:
|
|
216
217
|
logger.exception("ModuleRunner: backpressure timeout", extra=log_extra)
|
|
217
218
|
await on_fatal(StreamErrorCode.BACKPRESSURE_TIMEOUT.value, str(exc))
|
|
219
|
+
except RedisError as exc:
|
|
220
|
+
logger.error(
|
|
221
|
+
"[VALIDATE R2] ModuleRunner: Redis unavailable writing output: task_id=%s",
|
|
222
|
+
task_id,
|
|
223
|
+
extra=log_extra,
|
|
224
|
+
) # TODO(validate): remove after prod validation
|
|
225
|
+
await on_fatal(
|
|
226
|
+
StreamErrorCode.REDIS_UNAVAILABLE.value,
|
|
227
|
+
f"redis unavailable: {type(exc).__name__}: {exc}",
|
|
228
|
+
)
|
|
218
229
|
except Exception as exc:
|
|
219
230
|
logger.exception("ModuleRunner: module job failed", extra=log_extra)
|
|
220
231
|
await on_fatal(
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/gateway_servicer.py
RENAMED
|
@@ -157,7 +157,7 @@ class GatewayServicer:
|
|
|
157
157
|
await self._m2m.stop()
|
|
158
158
|
await self._registry.shutdown()
|
|
159
159
|
|
|
160
|
-
async def StartStream( # noqa: PLR0911, PLR0915
|
|
160
|
+
async def StartStream( # noqa: C901, PLR0911, PLR0915
|
|
161
161
|
self,
|
|
162
162
|
request: Any,
|
|
163
163
|
context: grpc.aio.ServicerContext,
|
|
@@ -215,14 +215,30 @@ class GatewayServicer:
|
|
|
215
215
|
# Durable at-most-once guard: survives session teardown and spans replicas.
|
|
216
216
|
# A re-issued StartStream for an already-run task is accepted but does NOT
|
|
217
217
|
# re-dial/re-execute — the caller resumes the existing output via Stream/from_seq.
|
|
218
|
-
|
|
218
|
+
try:
|
|
219
|
+
claim = await self._idempotency.claim(task_id, SharedRedisListener.PROCESS_ID)
|
|
220
|
+
except RedisError:
|
|
221
|
+
logger.warning(
|
|
222
|
+
"[VALIDATE R2] StartStream claim Redis failure → accepted=False",
|
|
223
|
+
extra=log_extra,
|
|
224
|
+
exc_info=True,
|
|
225
|
+
) # TODO(validate): remove after prod validation
|
|
226
|
+
return gateway_pb2.StartStreamResponse(accepted=False, task_id=task_id)
|
|
219
227
|
timer.mark("idempotency_claim")
|
|
220
228
|
if claim is not ClaimResult.CLAIMED:
|
|
221
229
|
# Re-issued StartStream for an already-claimed task. The prior dial-back
|
|
222
230
|
# is dead (the dedup branch above returned if its session were still live),
|
|
223
231
|
# so re-dial in resume mode to re-attach the restarted consumer from its
|
|
224
232
|
# cursor — as long as the durable stream is still retained.
|
|
225
|
-
|
|
233
|
+
try:
|
|
234
|
+
stream_len = await self._redis_client.xlen(f"task:{task_id}:stream")
|
|
235
|
+
except RedisError:
|
|
236
|
+
logger.warning(
|
|
237
|
+
"[VALIDATE R2] StartStream xlen Redis failure → accepted=False",
|
|
238
|
+
extra=log_extra,
|
|
239
|
+
exc_info=True,
|
|
240
|
+
) # TODO(validate): remove after prod validation
|
|
241
|
+
return gateway_pb2.StartStreamResponse(accepted=False, task_id=task_id)
|
|
226
242
|
if stream_len == 0:
|
|
227
243
|
logger.info(
|
|
228
244
|
"[VALIDATE IDEM1] no live stream to resume (TTL expired) task_id=%s (%s)",
|
|
@@ -274,7 +290,8 @@ class GatewayServicer:
|
|
|
274
290
|
if not accepted:
|
|
275
291
|
logger.warning("Session rejected (capacity)", extra=log_extra)
|
|
276
292
|
# Release the claim so this task can be retried once capacity frees up.
|
|
277
|
-
|
|
293
|
+
with contextlib.suppress(RedisError):
|
|
294
|
+
await self._idempotency.release(task_id)
|
|
278
295
|
return gateway_pb2.StartStreamResponse(accepted=False, task_id=task_id)
|
|
279
296
|
|
|
280
297
|
# Seed stream.start so the consumer's first XREAD finds data immediately.
|
|
@@ -289,10 +306,22 @@ class GatewayServicer:
|
|
|
289
306
|
},
|
|
290
307
|
})
|
|
291
308
|
timer.mark("build_start_info")
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
309
|
+
try:
|
|
310
|
+
await self._redis_client.xadd(
|
|
311
|
+
f"task:{task_id}:stream",
|
|
312
|
+
{"pb": start_info.SerializeToString(), "seq": "0"},
|
|
313
|
+
)
|
|
314
|
+
except RedisError:
|
|
315
|
+
logger.warning(
|
|
316
|
+
"[VALIDATE R2] StartStream xadd(stream.start) Redis failure → accepted=False",
|
|
317
|
+
extra=log_extra,
|
|
318
|
+
exc_info=True,
|
|
319
|
+
) # TODO(validate): remove after prod validation
|
|
320
|
+
# Claimed + registered but the stream couldn't be seeded: undo both so a retry re-runs.
|
|
321
|
+
with contextlib.suppress(RedisError):
|
|
322
|
+
await self._idempotency.release(task_id)
|
|
323
|
+
await self._registry.unregister(task_id)
|
|
324
|
+
return gateway_pb2.StartStreamResponse(accepted=False, task_id=task_id)
|
|
296
325
|
timer.mark("xadd_stream_start")
|
|
297
326
|
|
|
298
327
|
logger.info("→ Dial-back scheduled to consumer %s", client_address, extra=log_extra)
|
|
@@ -424,7 +453,14 @@ class GatewayServicer:
|
|
|
424
453
|
|
|
425
454
|
# Late client: session finished but data still in Redis.
|
|
426
455
|
if session is None:
|
|
427
|
-
|
|
456
|
+
try:
|
|
457
|
+
stream_len = await self._redis_client.xlen(f"task:{task_id}:stream")
|
|
458
|
+
except RedisError:
|
|
459
|
+
async for out in self._fatal_close(
|
|
460
|
+
task_id, StreamErrorCode.REDIS_UNAVAILABLE.value, "redis unavailable"
|
|
461
|
+
):
|
|
462
|
+
yield out
|
|
463
|
+
return
|
|
428
464
|
if stream_len > 0:
|
|
429
465
|
async for resp in self._consume_guarded(task_id, from_seq):
|
|
430
466
|
yield resp
|
|
@@ -436,10 +472,17 @@ class GatewayServicer:
|
|
|
436
472
|
# First message's data is the query.
|
|
437
473
|
input_key = f"task:{task_id}:input"
|
|
438
474
|
if first_msg.data and len(first_msg.data.fields) > 0:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
475
|
+
try:
|
|
476
|
+
await self._redis_client.xadd(
|
|
477
|
+
input_key,
|
|
478
|
+
{"pb": first_msg.data.SerializeToString()},
|
|
479
|
+
)
|
|
480
|
+
except RedisError:
|
|
481
|
+
async for out in self._fatal_close(
|
|
482
|
+
task_id, StreamErrorCode.REDIS_UNAVAILABLE.value, "redis unavailable"
|
|
483
|
+
):
|
|
484
|
+
yield out
|
|
485
|
+
return
|
|
443
486
|
|
|
444
487
|
upstream_task = self._spawn(
|
|
445
488
|
self._read_peer_upstream(request_iterator, task_id, session),
|
|
@@ -703,6 +746,21 @@ class GatewayServicer:
|
|
|
703
746
|
)
|
|
704
747
|
yield self._sentinel(0, task_id, "stream.end")
|
|
705
748
|
return
|
|
749
|
+
except RedisError:
|
|
750
|
+
logger.warning(
|
|
751
|
+
"[VALIDATE R2] stream read Redis failure — closing stream: task_id=%s",
|
|
752
|
+
task_id,
|
|
753
|
+
) # TODO(validate): remove after prod validation
|
|
754
|
+
yield self._sentinel(
|
|
755
|
+
0,
|
|
756
|
+
task_id,
|
|
757
|
+
"stream.error",
|
|
758
|
+
code=StreamErrorCode.REDIS_UNAVAILABLE.value,
|
|
759
|
+
message="redis unavailable during stream read",
|
|
760
|
+
fatal=True,
|
|
761
|
+
)
|
|
762
|
+
yield self._sentinel(0, task_id, "stream.end")
|
|
763
|
+
return
|
|
706
764
|
yield resp
|
|
707
765
|
|
|
708
766
|
async def _dial_consumer( # noqa: C901, PLR0912, PLR0914, PLR0915
|
|
@@ -869,6 +927,25 @@ class GatewayServicer:
|
|
|
869
927
|
f"dial-back idle timeout: no module output in {idle_timeout:.0f}s",
|
|
870
928
|
)
|
|
871
929
|
return
|
|
930
|
+
except RedisError:
|
|
931
|
+
logger.warning(
|
|
932
|
+
"[VALIDATE R2] dial-back stream read Redis failure — closing BiDi: task_id=%s",
|
|
933
|
+
task_id,
|
|
934
|
+
extra=log_extra,
|
|
935
|
+
) # TODO(validate): remove after prod validation
|
|
936
|
+
for sc in (
|
|
937
|
+
self._sentinel(
|
|
938
|
+
0,
|
|
939
|
+
task_id,
|
|
940
|
+
"stream.error",
|
|
941
|
+
code=StreamErrorCode.REDIS_UNAVAILABLE.value,
|
|
942
|
+
message="redis unavailable during stream read",
|
|
943
|
+
fatal=True,
|
|
944
|
+
),
|
|
945
|
+
self._sentinel(0, task_id, "stream.end"),
|
|
946
|
+
):
|
|
947
|
+
yield gateway_pb2.StreamServer(task_id=task_id, seq=sc.from_seq, data=sc.data)
|
|
948
|
+
return
|
|
872
949
|
yield gateway_pb2.StreamServer(
|
|
873
950
|
task_id=task_id,
|
|
874
951
|
seq=cli_msg.from_seq,
|
|
@@ -968,10 +1045,18 @@ class GatewayServicer:
|
|
|
968
1045
|
first = False
|
|
969
1046
|
continue
|
|
970
1047
|
# Follow-up multi-turn input → task's input stream.
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1048
|
+
try:
|
|
1049
|
+
await self._redis_client.xadd(
|
|
1050
|
+
f"task:{task_id}:input",
|
|
1051
|
+
{"pb": upstream.data.SerializeToString()},
|
|
1052
|
+
)
|
|
1053
|
+
except RedisError:
|
|
1054
|
+
logger.warning(
|
|
1055
|
+
"[VALIDATE R2] dropped follow-up input (redis unavailable): task_id=%s data=%s",
|
|
1056
|
+
task_id,
|
|
1057
|
+
str(upstream.data)[:512],
|
|
1058
|
+
extra=log_extra,
|
|
1059
|
+
) # TODO(validate): remove after prod validation
|
|
975
1060
|
except grpc.aio.AioRpcError as exc:
|
|
976
1061
|
code_name = exc.code().name
|
|
977
1062
|
details = exc.details() or ""
|
|
@@ -134,6 +134,22 @@ class CircuitBreaker:
|
|
|
134
134
|
self._failure_count,
|
|
135
135
|
)
|
|
136
136
|
|
|
137
|
+
def release_probe(self) -> bool:
|
|
138
|
+
"""Release a half-open probe slot without recording an outcome.
|
|
139
|
+
|
|
140
|
+
Called when an in-flight probe is abandoned (e.g. the caller was
|
|
141
|
+
cancelled) so the breaker cannot wedge with the lock held. A cancelled
|
|
142
|
+
probe is neither success nor failure — the slot simply frees for the
|
|
143
|
+
next caller. No-op unless a probe lock is currently held.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
True if a held probe lock was released; False if none was held.
|
|
147
|
+
"""
|
|
148
|
+
if self._state == CBState.HALF_OPEN and self._half_open_lock:
|
|
149
|
+
self._half_open_lock = False
|
|
150
|
+
return True
|
|
151
|
+
return False
|
|
152
|
+
|
|
137
153
|
def reset(self) -> None:
|
|
138
154
|
"""Force reset to CLOSED state."""
|
|
139
155
|
self._state = CBState.CLOSED
|
|
@@ -224,7 +224,7 @@ class GrpcClientWrapper:
|
|
|
224
224
|
cls._stub_cache.clear()
|
|
225
225
|
CircuitBreaker.clear_all()
|
|
226
226
|
|
|
227
|
-
async def exec_grpc_query( # noqa: C901, PLR0914
|
|
227
|
+
async def exec_grpc_query( # noqa: C901, PLR0912, PLR0914, PLR0915
|
|
228
228
|
self,
|
|
229
229
|
query_endpoint: str,
|
|
230
230
|
request: Any,
|
|
@@ -284,57 +284,66 @@ class GrpcClientWrapper:
|
|
|
284
284
|
backoff_delays = tuple(backoff_base_ms / 1000 * (2**i) for i in range(max_retries))
|
|
285
285
|
last_error: grpc.RpcError | None = None
|
|
286
286
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
287
|
+
try:
|
|
288
|
+
for attempt in range(max_retries + 1):
|
|
289
|
+
if attempt > 0:
|
|
290
|
+
await asyncio.sleep(backoff_delays[attempt - 1])
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
response = await rpc_method(request, timeout=eff_timeout)
|
|
294
|
+
except grpc.RpcError as e:
|
|
295
|
+
last_error = e
|
|
296
|
+
if e.code() in self._RETRYABLE_CODES and attempt < max_retries:
|
|
297
|
+
logger.warning(
|
|
298
|
+
"gRPC transient error on %s.%s [%s] (attempt %d/%d), retrying in %.0fms",
|
|
299
|
+
self.service_name,
|
|
300
|
+
query_endpoint,
|
|
301
|
+
e.code().name,
|
|
302
|
+
attempt + 1,
|
|
303
|
+
max_retries + 1,
|
|
304
|
+
backoff_delays[attempt] * 1000,
|
|
305
|
+
)
|
|
306
|
+
continue
|
|
307
|
+
if e.code() in self._CIRCUIT_FAILURE_CODES:
|
|
308
|
+
logger.warning(
|
|
309
|
+
"circuit-breaker tick: %s.%s [%s]",
|
|
310
|
+
self.service_name,
|
|
311
|
+
query_endpoint,
|
|
312
|
+
e.code().name,
|
|
313
|
+
)
|
|
314
|
+
cb.record_failure()
|
|
315
|
+
else:
|
|
316
|
+
cb.record_success()
|
|
317
|
+
break
|
|
314
318
|
else:
|
|
315
319
|
cb.record_success()
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
details
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
320
|
+
return response
|
|
321
|
+
|
|
322
|
+
if last_error is None:
|
|
323
|
+
msg = f"[gRPC-client:{self.service_name}.{query_endpoint}] Retry loop exited without response or error"
|
|
324
|
+
raise ServerError(msg)
|
|
325
|
+
status_code = last_error.code().name
|
|
326
|
+
details = last_error.details()
|
|
327
|
+
retried = last_error.code() in self._RETRYABLE_CODES
|
|
328
|
+
suffix = f" (after {max_retries + 1} attempts)" if retried else ""
|
|
329
|
+
|
|
330
|
+
log_level = logging.DEBUG if last_error.code() == grpc.StatusCode.NOT_FOUND else logging.ERROR
|
|
331
|
+
logger.log(
|
|
332
|
+
log_level,
|
|
333
|
+
"gRPC call failed: %s.%s [%s] %s (%s)",
|
|
334
|
+
self.service_name,
|
|
335
|
+
query_endpoint,
|
|
336
|
+
status_code,
|
|
337
|
+
details,
|
|
338
|
+
type(request).__name__,
|
|
339
|
+
)
|
|
340
|
+
error_msg = f"[gRPC-client:{self.service_name}.{query_endpoint}] [{status_code}] {details}{suffix}"
|
|
341
|
+
raise ServerError(error_msg) from last_error
|
|
342
|
+
finally:
|
|
343
|
+
# Free a half-open probe the loop never resolved (e.g. CancelledError mid-call or backoff).
|
|
344
|
+
if cb.release_probe():
|
|
345
|
+
logger.info(
|
|
346
|
+
"[VALIDATE R1] released abandoned circuit probe: %s.%s",
|
|
347
|
+
self.service_name,
|
|
348
|
+
query_endpoint,
|
|
349
|
+
) # TODO(validate): remove after prod validation
|
|
@@ -19,6 +19,7 @@ class StreamErrorCode(str, Enum):
|
|
|
19
19
|
DIAL_BACK_NO_QUERY = "DIAL_BACK_NO_QUERY"
|
|
20
20
|
DIAL_BACK_IDLE_TIMEOUT = "DIAL_BACK_IDLE_TIMEOUT"
|
|
21
21
|
STREAM_IDLE_TIMEOUT = "STREAM_IDLE_TIMEOUT"
|
|
22
|
+
REDIS_UNAVAILABLE = "REDIS_UNAVAILABLE"
|
|
22
23
|
MODULE_RUNTIME_ERROR = "MODULE_RUNTIME_ERROR"
|
|
23
24
|
INPUT_VALIDATION_ERROR = "INPUT_VALIDATION_ERROR"
|
|
24
25
|
BACKPRESSURE_TIMEOUT = "BACKPRESSURE_TIMEOUT"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/mock/mock_pb2_grpc.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_async_insecure.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_async_secure.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_sync_insecure.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/base_server/server_sync_secure.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
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/triggers/__init__.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/bench_module/triggers/message_trigger.py
RENAMED
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/modules/archetype_with_tools_module.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/examples/redis_demo/triggers/message_trigger.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/agno_adapter.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/community/agno/agui_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/job_manager/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/profiling/step_timer.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/profiling/task_profiler.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/resilience/__init__.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/resilience/bulkhead.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/resilience/task_supervisor.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/redis/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/task_executor.py
RENAMED
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/core/task_manager/task_session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{digitalkin-1.0.0.dev18 → digitalkin-1.0.0.dev19}/src/digitalkin/grpc_servers/_base_server.py
RENAMED
|
File without changes
|