sycommon-python-lib 0.2.5a24__tar.gz → 0.2.5a26__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.
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/pyproject.toml +1 -1
- sycommon_python_lib-0.2.5a26/src/sycommon/database/async_base_db_service.py +114 -0
- sycommon_python_lib-0.2.5a26/src/sycommon/database/base_db_service.py +114 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/kafka_log.py +58 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/mqlistener_config.py +2 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_client.py +125 -14
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +4 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +2 -1
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/services.py +8 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon_python_lib.egg-info/SOURCES.txt +1 -0
- sycommon_python_lib-0.2.5a26/tests/test_asyncio_logging.py +116 -0
- sycommon_python_lib-0.2.5a24/src/sycommon/database/async_base_db_service.py +0 -36
- sycommon_python_lib-0.2.5a24/src/sycommon/database/base_db_service.py +0 -30
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/README.md +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/core/console.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/core/models.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/core/project.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/core/utils.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/api/query.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/db/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/db/service.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/model/parse.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/agent/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/.env.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/.gitignore.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/Dockerfile.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/app.yaml.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/model/file_info.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/base/requirements.txt.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/commands/hello.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/pyproject.toml.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/api/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/command/templates/web/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/nexus/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/__main__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/agents/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/agents/factory.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/agents/prompts.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/browser.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/console.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/dom.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/network.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/page_errors.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/performance.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/capabilities/screenshot.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/client.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/protocol.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cdp/repl.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/cli.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/cdp_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/chat_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/create_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/evaluate_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/init_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/memory_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/resume_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/rollback_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/commands/run_cmd.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/backend.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/display.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/git_integration.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/llm.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/core/state.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/evaluate/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/evaluate/api_evaluator.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/memory/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/memory/compressor.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/memory/full.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/memory/hot.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/memory/manager.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/memory/warm.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/mode/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/mode/create.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/mode/optimize.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/models/config_models.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/baseline_tests.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/checkpoint.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/convergence.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/diagnosis.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/engine.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/environment.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/experience.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/harness_prompts.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/history.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/optimization_logger.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/pre_validation.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/reward.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/strategy_bandit.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/strategy_generator.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/rl/strategy_prompts.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycli/skills/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/agent_manager.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/chat_events.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/deep_agent.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/mcp/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/mcp/models.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/mcp/tool_loader.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/multi_agent_team.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/file_ops.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/http_sandbox_backend.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/minio_sync.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/sandbox/session.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/agent/summarization_utils.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/auth/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/auth/ldap_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/auth/oa_cache.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/auth/oa_crypto.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/auth/oa_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/auth/wecom_ldap_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/Config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/ElasticsearchConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/PgConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/RedisConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/XxlJobConfig.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/database/async_database_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/database/elasticsearch_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/database/pg_checkpoint_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/database/redis_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/database/token_usage_db_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/heartbeat_process/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/output_fixing_runnable.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/struct_token.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/token_usage_es_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/llm/usage_token.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/process_logger.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/mcp_server/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/mcp_server/server.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/sandbox.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/token_tracking.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/tool_result_truncation.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/middleware/traceid.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/mcp_server_config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/sandbox.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/token_usage.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/token_usage_mysql.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/models/xxljob_handler_config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/notice/wecom_message.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/deep_agent_server.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_consumer_recovery.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_deep_agent.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_dynamic_max_tokens.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_encoding_cache.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_mcp_server.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_minimax_reasoning.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_oa_login.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_real_summarization.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_summarization_config.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tests/test_summarization_real.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/xxljob/__init__.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/xxljob/xxljob_service.py +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
- {sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/tests/test_sycli.py +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from contextlib import asynccontextmanager
|
|
3
|
+
from sqlalchemy.exc import OperationalError, InterfaceError, InternalError
|
|
4
|
+
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
|
5
|
+
from sycommon.config.Config import SingletonMeta
|
|
6
|
+
from sycommon.database.async_database_service import AsyncDatabaseService
|
|
7
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
8
|
+
|
|
9
|
+
# 连接级错误:连接已断,事务必定已丢失,重试安全
|
|
10
|
+
_CONNECTION_ERROR_CODES = {2006, 2013}
|
|
11
|
+
# 事务级错误:死锁、锁等待超时,由调用方决定是否重试
|
|
12
|
+
_RETRYABLE_TX_ERROR_CODES = {1205, 1213, 1206}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _is_connection_error(exc: Exception) -> bool:
|
|
16
|
+
"""判断是否为连接级错误(断开、宕机),可安全重试"""
|
|
17
|
+
if isinstance(exc, (OperationalError, InterfaceError)):
|
|
18
|
+
if exc.orig and hasattr(exc.orig, 'errno'):
|
|
19
|
+
return exc.orig.errno in _CONNECTION_ERROR_CODES
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _is_retryable_tx_error(exc: Exception) -> bool:
|
|
24
|
+
"""判断是否为可重试的事务级错误(死锁、锁超时)"""
|
|
25
|
+
if isinstance(exc, (OperationalError, InternalError)):
|
|
26
|
+
if exc.orig and hasattr(exc.orig, 'errno'):
|
|
27
|
+
return exc.orig.errno in _RETRYABLE_TX_ERROR_CODES
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AsyncBaseDBService(metaclass=SingletonMeta):
|
|
32
|
+
"""数据库操作基础服务类,封装异步会话管理功能"""
|
|
33
|
+
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self.engine = AsyncDatabaseService.engine()
|
|
36
|
+
self.Session = async_sessionmaker(
|
|
37
|
+
bind=self.engine,
|
|
38
|
+
class_=AsyncSession,
|
|
39
|
+
expire_on_commit=False
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@asynccontextmanager
|
|
43
|
+
async def session(self):
|
|
44
|
+
"""
|
|
45
|
+
异步数据库会话上下文管理器
|
|
46
|
+
自动处理会话的创建、提交、回滚和关闭
|
|
47
|
+
"""
|
|
48
|
+
async with self.Session() as session:
|
|
49
|
+
try:
|
|
50
|
+
yield session
|
|
51
|
+
await session.commit()
|
|
52
|
+
except Exception as e:
|
|
53
|
+
await session.rollback()
|
|
54
|
+
SYLogger.error(f"Database operation failed: {str(e)}")
|
|
55
|
+
raise
|
|
56
|
+
|
|
57
|
+
async def execute(self, fn, retry: int = 0):
|
|
58
|
+
"""
|
|
59
|
+
执行异步数据库操作,支持自动重试
|
|
60
|
+
|
|
61
|
+
连接级错误(连接断开 2006/2013)始终自动重试1次。
|
|
62
|
+
事务级错误(死锁 1213、锁超时 1205)按 retry 参数重试。
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
fn: 接收 session 参数的异步可调用对象,例如:
|
|
66
|
+
async def query(session): return (await session.execute(select(User))).scalars().all()
|
|
67
|
+
retry: 事务级错误最大重试次数,默认0不重试
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
fn 的返回值
|
|
71
|
+
|
|
72
|
+
Usage:
|
|
73
|
+
result = await self.execute(
|
|
74
|
+
lambda session: session.execute(select(User)),
|
|
75
|
+
retry=3
|
|
76
|
+
)
|
|
77
|
+
"""
|
|
78
|
+
attempt = 0
|
|
79
|
+
max_attempts = 1 + max(retry, 0)
|
|
80
|
+
connection_retried = False
|
|
81
|
+
last_exc = None
|
|
82
|
+
|
|
83
|
+
while True:
|
|
84
|
+
async with self.Session() as session:
|
|
85
|
+
try:
|
|
86
|
+
result = await fn(session)
|
|
87
|
+
await session.commit()
|
|
88
|
+
return result
|
|
89
|
+
except Exception as e:
|
|
90
|
+
await session.rollback()
|
|
91
|
+
last_exc = e
|
|
92
|
+
|
|
93
|
+
# 连接级错误:始终自动重试1次(不计入 max_attempts)
|
|
94
|
+
if _is_connection_error(e) and not connection_retried:
|
|
95
|
+
connection_retried = True
|
|
96
|
+
SYLogger.warning(
|
|
97
|
+
f"DB connection lost (errno={getattr(e.orig, 'errno', None)}), retrying..."
|
|
98
|
+
)
|
|
99
|
+
attempt += 1
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
# 事务级错误:按 retry 参数重试
|
|
103
|
+
if retry > 0 and _is_retryable_tx_error(e) and attempt < max_attempts - 1:
|
|
104
|
+
attempt += 1
|
|
105
|
+
backoff = min(0.5 * (2 ** (attempt - 1)), 2.0)
|
|
106
|
+
SYLogger.warning(
|
|
107
|
+
f"DB retryable error (errno={getattr(e.orig, 'errno', None)}), "
|
|
108
|
+
f"attempt {attempt}/{max_attempts}, backoff {backoff}s"
|
|
109
|
+
)
|
|
110
|
+
await asyncio.sleep(backoff)
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
SYLogger.error(f"Database operation failed: {str(e)}")
|
|
114
|
+
raise
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from sqlalchemy.orm import sessionmaker
|
|
4
|
+
from sqlalchemy.exc import OperationalError, InterfaceError, InternalError
|
|
5
|
+
from sycommon.config.Config import SingletonMeta
|
|
6
|
+
from sycommon.database.database_service import DatabaseService
|
|
7
|
+
from sycommon.logging.kafka_log import SYLogger
|
|
8
|
+
|
|
9
|
+
# 连接级错误:连接已断,事务必定已丢失,重试安全
|
|
10
|
+
_CONNECTION_ERROR_CODES = {2006, 2013}
|
|
11
|
+
# 事务级错误:死锁、锁等待超时,由调用方决定是否重试
|
|
12
|
+
_RETRYABLE_TX_ERROR_CODES = {1205, 1213, 1206}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _is_connection_error(exc: Exception) -> bool:
|
|
16
|
+
"""判断是否为连接级错误(断开、宕机),可安全重试"""
|
|
17
|
+
if isinstance(exc, (OperationalError, InterfaceError)):
|
|
18
|
+
if exc.orig and hasattr(exc.orig, 'errno'):
|
|
19
|
+
return exc.orig.errno in _CONNECTION_ERROR_CODES
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _is_retryable_tx_error(exc: Exception) -> bool:
|
|
24
|
+
"""判断是否为可重试的事务级错误(死锁、锁超时)"""
|
|
25
|
+
if isinstance(exc, (OperationalError, InternalError)):
|
|
26
|
+
if exc.orig and hasattr(exc.orig, 'errno'):
|
|
27
|
+
return exc.orig.errno in _RETRYABLE_TX_ERROR_CODES
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class BaseDBService(metaclass=SingletonMeta):
|
|
32
|
+
"""数据库操作基础服务类,封装会话管理功能"""
|
|
33
|
+
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self.engine = DatabaseService.engine()
|
|
36
|
+
self.Session = sessionmaker(bind=self.engine)
|
|
37
|
+
|
|
38
|
+
@contextmanager
|
|
39
|
+
def session(self):
|
|
40
|
+
"""
|
|
41
|
+
数据库会话上下文管理器
|
|
42
|
+
自动处理会话的创建、提交、回滚和关闭
|
|
43
|
+
"""
|
|
44
|
+
session = self.Session()
|
|
45
|
+
try:
|
|
46
|
+
yield session
|
|
47
|
+
session.commit()
|
|
48
|
+
except Exception as e:
|
|
49
|
+
session.rollback()
|
|
50
|
+
SYLogger.error(f"Database operation failed: {str(e)}")
|
|
51
|
+
raise
|
|
52
|
+
finally:
|
|
53
|
+
session.close()
|
|
54
|
+
|
|
55
|
+
def execute(self, fn, retry: int = 0):
|
|
56
|
+
"""
|
|
57
|
+
执行数据库操作,支持自动重试
|
|
58
|
+
|
|
59
|
+
连接级错误(连接断开 2006/2013)始终自动重试1次。
|
|
60
|
+
事务级错误(死锁 1213、锁超时 1205)按 retry 参数重试。
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
fn: 接收 session 参数的可调用对象,例如:
|
|
64
|
+
lambda session: session.query(User).all()
|
|
65
|
+
retry: 事务级错误最大重试次数,默认0不重试
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
fn 的返回值
|
|
69
|
+
|
|
70
|
+
Usage:
|
|
71
|
+
result = self.execute(
|
|
72
|
+
lambda session: session.query(User).all(),
|
|
73
|
+
retry=3
|
|
74
|
+
)
|
|
75
|
+
"""
|
|
76
|
+
attempt = 0
|
|
77
|
+
max_attempts = 1 + max(retry, 0)
|
|
78
|
+
connection_retried = False
|
|
79
|
+
last_exc = None
|
|
80
|
+
|
|
81
|
+
while True:
|
|
82
|
+
session = self.Session()
|
|
83
|
+
try:
|
|
84
|
+
result = fn(session)
|
|
85
|
+
session.commit()
|
|
86
|
+
return result
|
|
87
|
+
except Exception as e:
|
|
88
|
+
session.rollback()
|
|
89
|
+
last_exc = e
|
|
90
|
+
|
|
91
|
+
# 连接级错误:始终自动重试1次(不计入 max_attempts)
|
|
92
|
+
if _is_connection_error(e) and not connection_retried:
|
|
93
|
+
connection_retried = True
|
|
94
|
+
SYLogger.warning(
|
|
95
|
+
f"DB connection lost (errno={getattr(e.orig, 'errno', None)}), retrying..."
|
|
96
|
+
)
|
|
97
|
+
attempt += 1
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
# 事务级错误:按 retry 参数重试
|
|
101
|
+
if retry > 0 and _is_retryable_tx_error(e) and attempt < max_attempts - 1:
|
|
102
|
+
attempt += 1
|
|
103
|
+
backoff = min(0.5 * (2 ** (attempt - 1)), 2.0)
|
|
104
|
+
SYLogger.warning(
|
|
105
|
+
f"DB retryable error (errno={getattr(e.orig, 'errno', None)}), "
|
|
106
|
+
f"attempt {attempt}/{max_attempts}, backoff {backoff}s"
|
|
107
|
+
)
|
|
108
|
+
time.sleep(backoff)
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
SYLogger.error(f"Database operation failed: {str(e)}")
|
|
112
|
+
raise
|
|
113
|
+
finally:
|
|
114
|
+
session.close()
|
{sycommon_python_lib-0.2.5a24 → sycommon_python_lib-0.2.5a26}/src/sycommon/logging/kafka_log.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
import json
|
|
4
|
+
import logging
|
|
4
5
|
import socket
|
|
5
6
|
import threading
|
|
6
7
|
import traceback
|
|
@@ -176,6 +177,23 @@ class KafkaSink:
|
|
|
176
177
|
pass
|
|
177
178
|
|
|
178
179
|
|
|
180
|
+
class _InterceptHandler(logging.Handler):
|
|
181
|
+
"""将 stdlib logging 日志桥接到 Loguru,使 asyncio 等第三方库的日志进入 Kafka 管道"""
|
|
182
|
+
|
|
183
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
184
|
+
try:
|
|
185
|
+
level = logger.level(record.levelname).name
|
|
186
|
+
except ValueError:
|
|
187
|
+
level = record.levelno
|
|
188
|
+
|
|
189
|
+
frame, depth = logging.currentframe(), 2
|
|
190
|
+
while frame and frame.f_code.co_filename == logging.__file__:
|
|
191
|
+
frame = frame.f_back
|
|
192
|
+
depth += 1
|
|
193
|
+
|
|
194
|
+
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
|
|
195
|
+
|
|
196
|
+
|
|
179
197
|
class KafkaLogger(metaclass=SingletonMeta):
|
|
180
198
|
_sink_instance = None
|
|
181
199
|
|
|
@@ -206,8 +224,48 @@ class KafkaLogger(metaclass=SingletonMeta):
|
|
|
206
224
|
diagnose=True
|
|
207
225
|
)
|
|
208
226
|
|
|
227
|
+
# 桥接 stdlib logging → Loguru,捕获 asyncio 等第三方库的日志
|
|
228
|
+
intercept_handler = _InterceptHandler()
|
|
229
|
+
logging.root.handlers = [intercept_handler]
|
|
230
|
+
logging.root.setLevel(logging.WARNING)
|
|
231
|
+
|
|
209
232
|
sys.excepthook = KafkaLogger._handle_exception
|
|
210
233
|
|
|
234
|
+
# 注册 asyncio 异常处理器,捕获未处理的 Task 异常
|
|
235
|
+
KafkaLogger._setup_asyncio_exception_handler()
|
|
236
|
+
|
|
237
|
+
@staticmethod
|
|
238
|
+
def _setup_asyncio_exception_handler():
|
|
239
|
+
"""注册 asyncio 事件循环异常处理器,将未处理的 Task 异常导入 Kafka"""
|
|
240
|
+
try:
|
|
241
|
+
loop = asyncio.get_running_loop()
|
|
242
|
+
loop.set_exception_handler(KafkaLogger._asyncio_exception_handler)
|
|
243
|
+
except RuntimeError:
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
@staticmethod
|
|
247
|
+
def _asyncio_exception_handler(loop, context):
|
|
248
|
+
"""asyncio 未处理异常回调,通过 SYLogger 记录到 Kafka"""
|
|
249
|
+
message = context.get("exception", context.get("message", "Unknown asyncio error"))
|
|
250
|
+
exception = context.get("exception")
|
|
251
|
+
|
|
252
|
+
if exception:
|
|
253
|
+
tb_str = "".join(traceback.format_exception(
|
|
254
|
+
type(exception), exception, exception.__traceback__
|
|
255
|
+
))
|
|
256
|
+
else:
|
|
257
|
+
tb_str = str(message)
|
|
258
|
+
|
|
259
|
+
trace_id = current_trace_id.get() or str(Snowflake.id)
|
|
260
|
+
error_msg = json.dumps({
|
|
261
|
+
"trace_id": trace_id,
|
|
262
|
+
"message": f"asyncio unhandled: {message}",
|
|
263
|
+
"level": "ERROR",
|
|
264
|
+
"detail": tb_str,
|
|
265
|
+
}, ensure_ascii=False)
|
|
266
|
+
|
|
267
|
+
logger.opt(exception=True).error(error_msg)
|
|
268
|
+
|
|
211
269
|
@staticmethod
|
|
212
270
|
def _handle_exception(exc_type, exc_value, exc_traceback):
|
|
213
271
|
if issubclass(exc_type, KeyboardInterrupt):
|
|
@@ -32,6 +32,8 @@ class RabbitMQListenerConfig(BaseModel):
|
|
|
32
32
|
auto_delete: bool = Field(False, description="是否自动删除队列")
|
|
33
33
|
auto_parse_json: bool = Field(True, description="是否自动解析JSON消息")
|
|
34
34
|
prefetch_count: int = Field(2, description="同时消费并发数(控制MQ预取与handler并发上限)")
|
|
35
|
+
max_priority: Optional[int] = Field(
|
|
36
|
+
10, description="队列支持的最大优先级(对应 x-max-priority)")
|
|
35
37
|
|
|
36
38
|
class Config:
|
|
37
39
|
"""模型配置"""
|
|
@@ -42,6 +42,7 @@ class RabbitMQClient:
|
|
|
42
42
|
auto_delete: bool = False,
|
|
43
43
|
auto_parse_json: bool = True,
|
|
44
44
|
create_if_not_exists: bool = True,
|
|
45
|
+
max_priority: Optional[int] = 10,
|
|
45
46
|
**kwargs,
|
|
46
47
|
):
|
|
47
48
|
self.connection_pool = connection_pool
|
|
@@ -60,6 +61,7 @@ class RabbitMQClient:
|
|
|
60
61
|
self.auto_delete = auto_delete
|
|
61
62
|
self.auto_parse_json = auto_parse_json
|
|
62
63
|
self.create_if_not_exists = create_if_not_exists
|
|
64
|
+
self.max_priority = max_priority
|
|
63
65
|
|
|
64
66
|
# 资源状态
|
|
65
67
|
self._channel: Optional[AbstractChannel] = None
|
|
@@ -91,6 +93,97 @@ class RabbitMQClient:
|
|
|
91
93
|
except Exception:
|
|
92
94
|
return False
|
|
93
95
|
|
|
96
|
+
async def _try_migrate_queue(self, original_error: Exception) -> bool:
|
|
97
|
+
"""尝试迁移队列以支持 x-max-priority。
|
|
98
|
+
|
|
99
|
+
当队列已存在但参数不匹配(PRECONDITION_FAILED)时,检查队列是否为空,
|
|
100
|
+
为空则删除重建,否则跳过迁移。
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
True 迁移成功,False 未迁移(需由调用方处理)
|
|
104
|
+
"""
|
|
105
|
+
from aiormq.exceptions import ChannelPreconditionFailed
|
|
106
|
+
|
|
107
|
+
if not isinstance(original_error, ChannelPreconditionFailed):
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
if self.max_priority is None:
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
# PRECONDITION_FAILED 会关闭当前 channel,需要用新 channel 检查队列状态
|
|
115
|
+
channel, _ = await self.connection_pool.acquire_channel()
|
|
116
|
+
try:
|
|
117
|
+
queue = await channel.declare_queue(
|
|
118
|
+
name=self.queue_name, passive=True
|
|
119
|
+
)
|
|
120
|
+
if queue.declaration_result:
|
|
121
|
+
message_count = queue.declaration_result.message_count
|
|
122
|
+
consumer_count = queue.declaration_result.consumer_count
|
|
123
|
+
else:
|
|
124
|
+
message_count = 0
|
|
125
|
+
consumer_count = 0
|
|
126
|
+
finally:
|
|
127
|
+
await channel.close()
|
|
128
|
+
|
|
129
|
+
if message_count > 0:
|
|
130
|
+
logger.warning(
|
|
131
|
+
f"队列 '{self.queue_name}' 迁移跳过: "
|
|
132
|
+
f"存在 {message_count} 条消息"
|
|
133
|
+
)
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
logger.info(
|
|
137
|
+
f"开始迁移队列 '{self.queue_name}',添加 x-max-priority={self.max_priority}")
|
|
138
|
+
|
|
139
|
+
# 删除旧队列
|
|
140
|
+
channel, _ = await self.connection_pool.acquire_channel()
|
|
141
|
+
try:
|
|
142
|
+
await channel.queue_delete(
|
|
143
|
+
queue_name=self.queue_name,
|
|
144
|
+
if_unused=False,
|
|
145
|
+
if_empty=False,
|
|
146
|
+
)
|
|
147
|
+
finally:
|
|
148
|
+
await channel.close()
|
|
149
|
+
|
|
150
|
+
# 清理旧 channel(被 PRECONDITION_FAILED 关闭后残留)
|
|
151
|
+
if self._channel and not self._channel.is_closed:
|
|
152
|
+
try:
|
|
153
|
+
await self._channel.close()
|
|
154
|
+
except Exception:
|
|
155
|
+
pass
|
|
156
|
+
self._channel = None
|
|
157
|
+
self._exchange = None
|
|
158
|
+
self._queue = None
|
|
159
|
+
|
|
160
|
+
# 重建 self._channel(旧 channel 已被 PRECONDITION_FAILED 关闭)
|
|
161
|
+
self._channel, self._channel_conn = await self.connection_pool.acquire_channel()
|
|
162
|
+
|
|
163
|
+
# 重新声明交换机
|
|
164
|
+
self._exchange = await self._channel.declare_exchange(
|
|
165
|
+
name=self.exchange_name,
|
|
166
|
+
type=self.exchange_type,
|
|
167
|
+
durable=self.durable,
|
|
168
|
+
auto_delete=self.auto_delete,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# 重新声明带 priority 的队列
|
|
172
|
+
self._queue = await self._channel.declare_queue(
|
|
173
|
+
name=self.queue_name,
|
|
174
|
+
durable=self.durable,
|
|
175
|
+
auto_delete=self.auto_delete,
|
|
176
|
+
arguments={"x-max-priority": self.max_priority},
|
|
177
|
+
)
|
|
178
|
+
await self._queue.bind(exchange=self._exchange, routing_key=self.routing_key)
|
|
179
|
+
logger.info(
|
|
180
|
+
f"队列 '{self.queue_name}' 迁移成功,已添加 x-max-priority={self.max_priority}")
|
|
181
|
+
return True
|
|
182
|
+
|
|
183
|
+
except Exception as migrate_error:
|
|
184
|
+
logger.error(f"队列 '{self.queue_name}' 迁移失败: {migrate_error}")
|
|
185
|
+
return False
|
|
186
|
+
|
|
94
187
|
async def _rebuild_resources(self) -> None:
|
|
95
188
|
if not self._channel or self._channel.is_closed:
|
|
96
189
|
raise RuntimeError("无有效通道,无法重建资源")
|
|
@@ -112,26 +205,32 @@ class RabbitMQClient:
|
|
|
112
205
|
# 2. 声明队列 (仅消费者需要)
|
|
113
206
|
# 【核心保留逻辑】只有当 queue_name 存在且符合消费者命名规范时,才初始化队列
|
|
114
207
|
if self.queue_name and self.queue_name.endswith(f".{self.app_name}"):
|
|
208
|
+
queue_args = {}
|
|
209
|
+
if self.max_priority is not None:
|
|
210
|
+
queue_args["x-max-priority"] = self.max_priority
|
|
211
|
+
|
|
115
212
|
try:
|
|
116
213
|
self._queue = await self._channel.declare_queue(
|
|
117
214
|
name=self.queue_name,
|
|
118
215
|
durable=self.durable,
|
|
119
216
|
auto_delete=self.auto_delete,
|
|
120
217
|
passive=not self.create_if_not_exists,
|
|
218
|
+
arguments=queue_args or None,
|
|
121
219
|
)
|
|
122
220
|
await self._queue.bind(exchange=self._exchange, routing_key=self.routing_key)
|
|
123
221
|
logger.debug(f"队列就绪: {self.queue_name}")
|
|
124
222
|
except Exception as e:
|
|
125
|
-
|
|
126
|
-
if self.create_if_not_exists:
|
|
127
|
-
# 模式:自动创建。如果失败说明权限不足或服务器限制,属于严重错误
|
|
128
|
-
logger.error(f"❌ 无法自动创建队列 '{self.queue_name}': {e}")
|
|
129
|
-
raise
|
|
130
|
-
else:
|
|
131
|
-
# 模式:仅检查。队列不存在是预期内的(如生产者启动时队列未创建),跳过
|
|
223
|
+
if not self.create_if_not_exists:
|
|
132
224
|
self._queue = None
|
|
133
225
|
logger.warning(
|
|
134
226
|
f"⚠️ 队列 '{self.queue_name}' 不存在或无权访问 (Passive模式),跳过绑定。")
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
# 尝试自动迁移:参数不匹配时删除重建
|
|
230
|
+
migrated = await self._try_migrate_queue(e)
|
|
231
|
+
if not migrated:
|
|
232
|
+
# 迁移失败(非参数不匹配 / 队列非空 / 有消费者),抛出原始异常
|
|
233
|
+
raise
|
|
135
234
|
else:
|
|
136
235
|
# 不符合命名规范或无队列名,清空队列引用
|
|
137
236
|
self._queue = None
|
|
@@ -145,7 +244,8 @@ class RabbitMQClient:
|
|
|
145
244
|
t.cancel()
|
|
146
245
|
try:
|
|
147
246
|
await asyncio.wait_for(
|
|
148
|
-
asyncio.gather(*self._running_tasks,
|
|
247
|
+
asyncio.gather(*self._running_tasks,
|
|
248
|
+
return_exceptions=True),
|
|
149
249
|
timeout=5.0
|
|
150
250
|
)
|
|
151
251
|
except asyncio.TimeoutError:
|
|
@@ -350,16 +450,21 @@ class RabbitMQClient:
|
|
|
350
450
|
if not self._queue and self.queue_name and self.queue_name.endswith(f".{self.app_name}"):
|
|
351
451
|
logger.warning(f"队列对象在消费前为空,尝试强制初始化: {self.queue_name}")
|
|
352
452
|
try:
|
|
453
|
+
queue_args = {}
|
|
454
|
+
if self.max_priority is not None:
|
|
455
|
+
queue_args["x-max-priority"] = self.max_priority
|
|
353
456
|
self._queue = await self._channel.declare_queue(
|
|
354
457
|
name=self.queue_name,
|
|
355
458
|
durable=self.durable,
|
|
356
459
|
auto_delete=self.auto_delete,
|
|
357
|
-
passive=False,
|
|
460
|
+
passive=False,
|
|
461
|
+
arguments=queue_args or None,
|
|
358
462
|
)
|
|
359
463
|
await self._queue.bind(exchange=self._exchange, routing_key=self.routing_key)
|
|
360
464
|
except Exception as e:
|
|
361
|
-
|
|
362
|
-
|
|
465
|
+
migrated = await self._try_migrate_queue(e)
|
|
466
|
+
if not migrated:
|
|
467
|
+
raise RuntimeError(f"无法初始化队列 {self.queue_name}")
|
|
363
468
|
|
|
364
469
|
if not self._queue:
|
|
365
470
|
raise RuntimeError("未配置队列名或队列初始化失败")
|
|
@@ -396,6 +501,7 @@ class RabbitMQClient:
|
|
|
396
501
|
content_type: str = "application/json",
|
|
397
502
|
delivery_mode: DeliveryMode = DeliveryMode.PERSISTENT,
|
|
398
503
|
retry_count: int = 3,
|
|
504
|
+
priority: Optional[int] = None,
|
|
399
505
|
) -> None:
|
|
400
506
|
if self._closed:
|
|
401
507
|
raise RuntimeError("客户端已关闭,无法发布消息")
|
|
@@ -415,8 +521,11 @@ class RabbitMQClient:
|
|
|
415
521
|
logger.error(f"消息体序列化失败: {e}")
|
|
416
522
|
raise
|
|
417
523
|
|
|
418
|
-
|
|
524
|
+
msg_kwargs = dict(body=body, headers=headers or {},
|
|
419
525
|
content_type=content_type, delivery_mode=delivery_mode)
|
|
526
|
+
if priority is not None:
|
|
527
|
+
msg_kwargs["priority"] = priority
|
|
528
|
+
message = Message(**msg_kwargs)
|
|
420
529
|
last_exception = None
|
|
421
530
|
|
|
422
531
|
for attempt in range(retry_count):
|
|
@@ -471,11 +580,13 @@ class RabbitMQClient:
|
|
|
471
580
|
logger.info(f"等待 {len(self._running_tasks)} 个后台任务完成...")
|
|
472
581
|
try:
|
|
473
582
|
await asyncio.wait_for(
|
|
474
|
-
asyncio.gather(*self._running_tasks,
|
|
583
|
+
asyncio.gather(*self._running_tasks,
|
|
584
|
+
return_exceptions=True),
|
|
475
585
|
timeout=15.0
|
|
476
586
|
)
|
|
477
587
|
except asyncio.TimeoutError:
|
|
478
|
-
logger.warning(
|
|
588
|
+
logger.warning(
|
|
589
|
+
f"等待后台任务超时,剩余 {len(self._running_tasks)} 个任务将被丢弃")
|
|
479
590
|
self._running_tasks.clear()
|
|
480
591
|
|
|
481
592
|
if self._channel and not self._channel.is_closed:
|
|
@@ -183,6 +183,7 @@ class RabbitMQClientManager(RabbitMQCoreService):
|
|
|
183
183
|
auto_parse_json=kwargs.get('auto_parse_json', True),
|
|
184
184
|
create_if_not_exists=create_if_not_exists,
|
|
185
185
|
prefetch_count=kwargs.get('prefetch_count', 2),
|
|
186
|
+
max_priority=kwargs.get('max_priority'),
|
|
186
187
|
)
|
|
187
188
|
|
|
188
189
|
# 4. 连接客户端
|
|
@@ -238,6 +239,9 @@ class RabbitMQClientManager(RabbitMQCoreService):
|
|
|
238
239
|
client.queue_name = input_qn
|
|
239
240
|
|
|
240
241
|
if await client.is_connected:
|
|
242
|
+
# 更新 max_priority(发送器先创建客户端时没有此参数)
|
|
243
|
+
if client_type == "listener" and 'max_priority' in kwargs:
|
|
244
|
+
client.max_priority = kwargs['max_priority']
|
|
241
245
|
return client
|
|
242
246
|
else:
|
|
243
247
|
logger.info(f"客户端 '{client_name}' 连接已断开,重新创建")
|
|
@@ -218,7 +218,8 @@ class RabbitMQProducerManager(RabbitMQClientManager):
|
|
|
218
218
|
await sender.publish(
|
|
219
219
|
message_body=mq_message.model_dump_json(),
|
|
220
220
|
headers=mq_header,
|
|
221
|
-
content_type="application/json"
|
|
221
|
+
content_type="application/json",
|
|
222
|
+
priority=kwargs.get('priority')
|
|
222
223
|
)
|
|
223
224
|
logger.info(f"消息发送成功 (队列: {queue_name})")
|
|
224
225
|
except Exception as e:
|
|
@@ -265,6 +265,14 @@ class Services(metaclass=SingletonMeta):
|
|
|
265
265
|
sandbox_cleanup_task = None
|
|
266
266
|
|
|
267
267
|
try:
|
|
268
|
+
# 注册 asyncio 异常处理器(需在事件循环运行后)
|
|
269
|
+
try:
|
|
270
|
+
from sycommon.logging.kafka_log import KafkaLogger
|
|
271
|
+
loop = asyncio.get_running_loop()
|
|
272
|
+
loop.set_exception_handler(KafkaLogger._asyncio_exception_handler)
|
|
273
|
+
except Exception as e:
|
|
274
|
+
logging.debug(f"注册 asyncio 异常处理器失败: {e}")
|
|
275
|
+
|
|
268
276
|
# 1. 处理数据库服务
|
|
269
277
|
if database_service:
|
|
270
278
|
instance._pending_async_db_setup = []
|
|
@@ -286,4 +286,5 @@ src/sycommon_python_lib.egg-info/dependency_links.txt
|
|
|
286
286
|
src/sycommon_python_lib.egg-info/entry_points.txt
|
|
287
287
|
src/sycommon_python_lib.egg-info/requires.txt
|
|
288
288
|
src/sycommon_python_lib.egg-info/top_level.txt
|
|
289
|
+
tests/test_asyncio_logging.py
|
|
289
290
|
tests/test_sycli.py
|