sycommon-python-lib 0.2.0b20__tar.gz → 0.2.0b22__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.0b20 → sycommon_python_lib-0.2.0b22}/PKG-INFO +3 -1
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/pyproject.toml +3 -1
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/Config.py +17 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/config/ElasticsearchConfig.py +65 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/config/RedisConfig.py +150 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/database/elasticsearch_service.py +104 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/database/redis_service.py +767 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/struct_token.py +69 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/llm/token_usage_es_service.py +539 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/llm/token_usage_mysql_service.py +727 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/usage_token.py +87 -4
- sycommon_python_lib-0.2.0b22/src/sycommon/models/token_usage.py +25 -0
- sycommon_python_lib-0.2.0b22/src/sycommon/models/token_usage_mysql.py +58 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_pool.py +29 -9
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/services.py +38 -4
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/nacos_heartbeat_manager.py +25 -5
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/nacos_service_discovery.py +14 -9
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon_python_lib.egg-info/PKG-INFO +3 -1
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon_python_lib.egg-info/SOURCES.txt +8 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon_python_lib.egg-info/requires.txt +2 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/README.md +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/command/console.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/command/models.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/command/project.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/command/utils.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/01_basic_agent.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/02_tool_agent.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/03_structured_output.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/04_memory_agent.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/05_streaming.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/06_multi_agent.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/07_skills_agent.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/08_middleware.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/09_interrupt.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/10_custom_llm.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/11_complex_workflow.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/12_batch_processing.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/01_basic_monitoring.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/02_permission_control.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/03_tool_skill_filter.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/04_caching_retry.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/05_sanitization.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/06_tracking.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/07_advanced.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/08_progressive_skills.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/examples/middleware/override_examples.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/agent/get_agent.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/database/async_base_db_service.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/database/async_database_service.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/database/base_db_service.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/logging/kafka_log.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/middleware/traceid.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/mqlistener_config.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.0b20 → sycommon_python_lib-0.2.0b22}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sycommon-python-lib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0b22
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -10,6 +10,7 @@ Requires-Dist: aiomysql>=0.3.2
|
|
|
10
10
|
Requires-Dist: anyio>=4.12.1
|
|
11
11
|
Requires-Dist: decorator>=5.2.1
|
|
12
12
|
Requires-Dist: deepagents>=0.4.5
|
|
13
|
+
Requires-Dist: elasticsearch>=9.3.0
|
|
13
14
|
Requires-Dist: fastapi>=0.133.1
|
|
14
15
|
Requires-Dist: jinja2>=3.1.6
|
|
15
16
|
Requires-Dist: kafka-python>=2.3.0
|
|
@@ -26,6 +27,7 @@ Requires-Dist: pydantic>=2.12.5
|
|
|
26
27
|
Requires-Dist: python-dotenv>=1.2.1
|
|
27
28
|
Requires-Dist: python-multipart>=0.0.22
|
|
28
29
|
Requires-Dist: pyyaml>=6.0.3
|
|
30
|
+
Requires-Dist: redis>=7.3.0
|
|
29
31
|
Requires-Dist: sentry-sdk[fastapi]>=2.53.0
|
|
30
32
|
Requires-Dist: sqlalchemy[asyncio]>=2.0.47
|
|
31
33
|
Requires-Dist: starlette>=0.52.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sycommon-python-lib"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.0b22"
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -11,6 +11,7 @@ dependencies = [
|
|
|
11
11
|
"anyio>=4.12.1",
|
|
12
12
|
"decorator>=5.2.1",
|
|
13
13
|
"deepagents>=0.4.5",
|
|
14
|
+
"elasticsearch>=9.3.0",
|
|
14
15
|
"fastapi>=0.133.1",
|
|
15
16
|
"jinja2>=3.1.6",
|
|
16
17
|
"kafka-python>=2.3.0",
|
|
@@ -27,6 +28,7 @@ dependencies = [
|
|
|
27
28
|
"python-dotenv>=1.2.1",
|
|
28
29
|
"python-multipart>=0.0.22",
|
|
29
30
|
"pyyaml>=6.0.3",
|
|
31
|
+
"redis>=7.3.0",
|
|
30
32
|
"sentry-sdk[fastapi]>=2.53.0",
|
|
31
33
|
"sqlalchemy[asyncio]>=2.0.47",
|
|
32
34
|
"starlette>=0.52.1",
|
|
@@ -22,6 +22,7 @@ class Config(metaclass=SingletonMeta):
|
|
|
22
22
|
self.reranker_configs = []
|
|
23
23
|
self.sentry_configs = []
|
|
24
24
|
self.langfuse_configs = []
|
|
25
|
+
self.elasticsearch_configs = []
|
|
25
26
|
self._process_config()
|
|
26
27
|
|
|
27
28
|
def get_llm_config(self, model_name):
|
|
@@ -54,6 +55,12 @@ class Config(metaclass=SingletonMeta):
|
|
|
54
55
|
return langfuse
|
|
55
56
|
raise ValueError(f"No configuration found for server: {name}")
|
|
56
57
|
|
|
58
|
+
def get_elasticsearch_config(self, name="default"):
|
|
59
|
+
for es in self.elasticsearch_configs:
|
|
60
|
+
if es.get('name') == name:
|
|
61
|
+
return es
|
|
62
|
+
raise ValueError(f"No configuration found for elasticsearch: {name}")
|
|
63
|
+
|
|
57
64
|
def _process_config(self):
|
|
58
65
|
llm_config_list = self.config.get('LLMConfig', [])
|
|
59
66
|
for llm_config in llm_config_list:
|
|
@@ -92,6 +99,16 @@ class Config(metaclass=SingletonMeta):
|
|
|
92
99
|
except ValueError as e:
|
|
93
100
|
print(f"Invalid Sentry configuration: {e}")
|
|
94
101
|
|
|
102
|
+
elasticsearch_config_list = self.config.get('ElasticsearchConfig', [])
|
|
103
|
+
for es_config in elasticsearch_config_list:
|
|
104
|
+
try:
|
|
105
|
+
from sycommon.config.ElasticsearchConfig import ElasticsearchConfig
|
|
106
|
+
validated_config = ElasticsearchConfig(**es_config)
|
|
107
|
+
self.elasticsearch_configs.append(
|
|
108
|
+
validated_config.model_dump())
|
|
109
|
+
except ValueError as e:
|
|
110
|
+
print(f"Invalid Elasticsearch configuration: {e}")
|
|
111
|
+
|
|
95
112
|
def set_attr(self, share_configs: dict):
|
|
96
113
|
self.config = {**self.config, **
|
|
97
114
|
share_configs.get('llm', {}), **share_configs}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import List
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ElasticsearchConfig(BaseModel):
|
|
7
|
+
"""Elasticsearch 配置"""
|
|
8
|
+
name: str = Field(default="default", description="配置名称")
|
|
9
|
+
uris: str = Field(..., description="ES节点地址,多个用英文逗号分隔")
|
|
10
|
+
username: str = Field(default="elastic", description="用户名")
|
|
11
|
+
password: str = Field(..., description="密码")
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def uri_list(self) -> List[str]:
|
|
15
|
+
"""获取 URI 列表,自动补全 scheme 和 port"""
|
|
16
|
+
uris = [uri.strip() for uri in self.uris.split(",") if uri.strip()]
|
|
17
|
+
normalized = []
|
|
18
|
+
for uri in uris:
|
|
19
|
+
normalized.append(self._normalize_uri(uri))
|
|
20
|
+
return normalized
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def _normalize_uri(uri: str) -> str:
|
|
24
|
+
"""
|
|
25
|
+
标准化 ES URI,确保包含 scheme、host 和 port
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
localhost:9200 -> http://localhost:9200
|
|
29
|
+
localhost -> http://localhost:9200
|
|
30
|
+
10.10.6.202:9200 -> http://10.10.6.202:9200
|
|
31
|
+
http://localhost:9200 -> http://localhost:9200
|
|
32
|
+
https://localhost:9200 -> https://localhost:9200
|
|
33
|
+
"""
|
|
34
|
+
uri = uri.strip()
|
|
35
|
+
|
|
36
|
+
# 已有 scheme
|
|
37
|
+
if uri.startswith("http://") or uri.startswith("https://"):
|
|
38
|
+
# 检查是否有 port
|
|
39
|
+
# http://localhost -> http://localhost:9200
|
|
40
|
+
parsed = re.match(r'(https?://)([^:/]+)(:\d+)?(.*)$', uri)
|
|
41
|
+
if parsed:
|
|
42
|
+
scheme = parsed.group(1)
|
|
43
|
+
host = parsed.group(2)
|
|
44
|
+
port = parsed.group(3)
|
|
45
|
+
if not port:
|
|
46
|
+
port = ":9200"
|
|
47
|
+
return f"{scheme}{host}{port}"
|
|
48
|
+
return uri
|
|
49
|
+
|
|
50
|
+
# 没有 scheme,默认 http
|
|
51
|
+
# localhost:9200 -> http://localhost:9200
|
|
52
|
+
# localhost -> http://localhost:9200
|
|
53
|
+
if ":" in uri:
|
|
54
|
+
# 有端口
|
|
55
|
+
return f"http://{uri}"
|
|
56
|
+
else:
|
|
57
|
+
# 没有端口,默认 9200
|
|
58
|
+
return f"http://{uri}:9200"
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def from_config(cls, name: str = "default"):
|
|
62
|
+
"""从配置文件获取 ES 配置"""
|
|
63
|
+
from sycommon.config.Config import Config
|
|
64
|
+
es_config = Config().get_elasticsearch_config(name)
|
|
65
|
+
return cls(**es_config)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Optional, List
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RedisPoolConfig(BaseModel):
|
|
7
|
+
"""Redis 连接池配置(对应 Spring Lettuce Pool)"""
|
|
8
|
+
max_active: int = Field(default=50, description="最大活跃连接数")
|
|
9
|
+
max_idle: int = Field(default=10, description="最大空闲连接数")
|
|
10
|
+
max_wait: int = Field(default=30, description="最大等待时间(秒)")
|
|
11
|
+
min_idle: int = Field(default=1, description="最小空闲连接数")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RedisSentinelConfig(BaseModel):
|
|
15
|
+
"""Redis Sentinel 配置"""
|
|
16
|
+
master: str = Field(..., description="主节点名称")
|
|
17
|
+
nodes: List[str] = Field(default_factory=list, description="Sentinel 节点列表")
|
|
18
|
+
topology_refresh_interval: Optional[int] = Field(default=None, description="拓扑刷新间隔(秒)")
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_dict(cls, sentinel: dict) -> "RedisSentinelConfig":
|
|
22
|
+
"""从字典解析 Sentinel 配置"""
|
|
23
|
+
nodes_str = sentinel.get("nodes", "")
|
|
24
|
+
# 解析节点列表,支持逗号分隔
|
|
25
|
+
nodes = []
|
|
26
|
+
if nodes_str:
|
|
27
|
+
nodes = [n.strip() for n in nodes_str.split(",") if n.strip()]
|
|
28
|
+
|
|
29
|
+
# 解析拓扑刷新间隔
|
|
30
|
+
topology_refresh_interval = None
|
|
31
|
+
topology_refresh = sentinel.get("topologyRefresh", {})
|
|
32
|
+
if topology_refresh:
|
|
33
|
+
interval = topology_refresh.get("interval")
|
|
34
|
+
if interval:
|
|
35
|
+
topology_refresh_interval = RedisConfig._parse_duration(interval)
|
|
36
|
+
|
|
37
|
+
return cls(
|
|
38
|
+
master=sentinel.get("master", "mymaster"),
|
|
39
|
+
nodes=nodes,
|
|
40
|
+
topology_refresh_interval=topology_refresh_interval
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class RedisConfig(BaseModel):
|
|
45
|
+
"""Redis 配置(对应 Spring Redis YAML 格式)"""
|
|
46
|
+
host: str = Field(default="localhost", description="Redis 主机地址")
|
|
47
|
+
port: int = Field(default=6379, description="Redis 端口")
|
|
48
|
+
password: Optional[str] = Field(default=None, description="密码")
|
|
49
|
+
database: int = Field(default=0, description="数据库索引")
|
|
50
|
+
timeout: int = Field(default=60, description="超时时间(秒)")
|
|
51
|
+
pool: Optional[RedisPoolConfig] = Field(default=None, description="连接池配置")
|
|
52
|
+
sentinel: Optional[RedisSentinelConfig] = Field(default=None, description="Sentinel 配置")
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def from_spring_yaml(cls, config: dict) -> "RedisConfig":
|
|
56
|
+
"""
|
|
57
|
+
从 Spring Redis YAML 格式解析配置
|
|
58
|
+
|
|
59
|
+
支持两种模式:
|
|
60
|
+
1. 单机模式:配置 host/port
|
|
61
|
+
2. Sentinel 模式:配置 sentinel.master/nodes
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
config: Spring Redis 配置字典
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
RedisConfig 实例
|
|
68
|
+
"""
|
|
69
|
+
# 获取 spring.redis 配置
|
|
70
|
+
spring_config = config.get("spring", {})
|
|
71
|
+
redis_config = spring_config.get("redis", {})
|
|
72
|
+
|
|
73
|
+
if not redis_config:
|
|
74
|
+
raise ValueError("未找到 Spring Redis 配置")
|
|
75
|
+
|
|
76
|
+
# 解析超时时间(支持 "60s" 格式)
|
|
77
|
+
timeout = redis_config.get("timeout", 60)
|
|
78
|
+
if isinstance(timeout, str):
|
|
79
|
+
timeout = cls._parse_duration(timeout)
|
|
80
|
+
|
|
81
|
+
# 解析连接池配置
|
|
82
|
+
pool_config = None
|
|
83
|
+
lettuce = redis_config.get("lettuce", {})
|
|
84
|
+
pool = lettuce.get("pool", {})
|
|
85
|
+
if pool:
|
|
86
|
+
max_wait = pool.get("max-wait", 30)
|
|
87
|
+
if isinstance(max_wait, str):
|
|
88
|
+
max_wait = cls._parse_duration(max_wait)
|
|
89
|
+
|
|
90
|
+
pool_config = RedisPoolConfig(
|
|
91
|
+
max_active=pool.get("max-active", 50),
|
|
92
|
+
max_idle=pool.get("max-idle", 10),
|
|
93
|
+
max_wait=max_wait,
|
|
94
|
+
min_idle=pool.get("min-idle", 1)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# 解析 Sentinel 配置
|
|
98
|
+
sentinel_config = None
|
|
99
|
+
sentinel = redis_config.get("sentinel", {})
|
|
100
|
+
if sentinel and sentinel.get("master") and sentinel.get("nodes"):
|
|
101
|
+
sentinel_config = RedisSentinelConfig.from_dict(sentinel)
|
|
102
|
+
|
|
103
|
+
return cls(
|
|
104
|
+
host=redis_config.get("host", "localhost"),
|
|
105
|
+
port=redis_config.get("port", 6379),
|
|
106
|
+
password=redis_config.get("password"),
|
|
107
|
+
database=redis_config.get("database", 0),
|
|
108
|
+
timeout=timeout,
|
|
109
|
+
pool=pool_config,
|
|
110
|
+
sentinel=sentinel_config
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
@staticmethod
|
|
114
|
+
def _parse_duration(duration: str) -> int:
|
|
115
|
+
"""
|
|
116
|
+
解析持续时间字符串为秒数
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
duration: 持续时间字符串,如 "60s", "30s", "1m"
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
秒数
|
|
123
|
+
"""
|
|
124
|
+
if not duration:
|
|
125
|
+
return 60
|
|
126
|
+
|
|
127
|
+
if isinstance(duration, (int, float)):
|
|
128
|
+
return int(duration)
|
|
129
|
+
|
|
130
|
+
# 匹配数字和单位
|
|
131
|
+
match = re.match(r"(\d+)([smh]?)", str(duration).strip())
|
|
132
|
+
if not match:
|
|
133
|
+
return 60
|
|
134
|
+
|
|
135
|
+
value = int(match.group(1))
|
|
136
|
+
unit = match.group(2) or "s"
|
|
137
|
+
|
|
138
|
+
if unit == "s":
|
|
139
|
+
return value
|
|
140
|
+
elif unit == "m":
|
|
141
|
+
return value * 60
|
|
142
|
+
elif unit == "h":
|
|
143
|
+
return value * 3600
|
|
144
|
+
|
|
145
|
+
return value
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def is_sentinel_mode(self) -> bool:
|
|
149
|
+
"""是否为 Sentinel 模式"""
|
|
150
|
+
return self.sentinel is not None and len(self.sentinel.nodes) > 0
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Elasticsearch 异步服务
|
|
3
|
+
管理 ES 客户端连接,供其他业务服务使用
|
|
4
|
+
"""
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Optional, Any, List
|
|
7
|
+
|
|
8
|
+
from sycommon.config.Config import SingletonMeta
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ElasticsearchService(metaclass=SingletonMeta):
|
|
12
|
+
"""Elasticsearch 基础服务(单例)"""
|
|
13
|
+
_client: Optional[Any] = None
|
|
14
|
+
_initialized: bool = False
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def setup(cls, config: Optional[dict] = None):
|
|
21
|
+
"""
|
|
22
|
+
ES 服务初始化函数(用于 Services.plugins 传入)
|
|
23
|
+
|
|
24
|
+
用法:
|
|
25
|
+
Services.plugins(
|
|
26
|
+
app,
|
|
27
|
+
elasticsearch_service=ElasticsearchService.setup
|
|
28
|
+
)
|
|
29
|
+
"""
|
|
30
|
+
cls.init(config)
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def init(cls, config: Optional[dict] = None):
|
|
34
|
+
"""
|
|
35
|
+
初始化 ES 连接
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
config: 配置字典,包含 ElasticsearchConfig 配置
|
|
39
|
+
"""
|
|
40
|
+
if cls._initialized:
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
from sycommon.config.ElasticsearchConfig import ElasticsearchConfig
|
|
45
|
+
from sycommon.config.Config import Config
|
|
46
|
+
|
|
47
|
+
# 获取 ES 配置
|
|
48
|
+
es_configs = Config().config.get('ElasticsearchConfig', [])
|
|
49
|
+
if not es_configs:
|
|
50
|
+
logging.info("未配置 ElasticsearchConfig,ES 服务将禁用")
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
# 使用第一个配置
|
|
54
|
+
es_config = ElasticsearchConfig(**es_configs[0])
|
|
55
|
+
|
|
56
|
+
# 导入 ES 客户端
|
|
57
|
+
try:
|
|
58
|
+
from elasticsearch import AsyncElasticsearch
|
|
59
|
+
except ImportError:
|
|
60
|
+
logging.warning("未安装 elasticsearch 包,请执行: pip install elasticsearch")
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
# 创建异步客户端
|
|
64
|
+
cls._client = AsyncElasticsearch(
|
|
65
|
+
hosts=es_config.uri_list,
|
|
66
|
+
basic_auth=(es_config.username, es_config.password),
|
|
67
|
+
verify_certs=False,
|
|
68
|
+
retry_on_timeout=True,
|
|
69
|
+
max_retries=3
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
cls._initialized = True
|
|
73
|
+
logging.info(f"ElasticsearchService 初始化成功,ES 地址: {es_config.uris}")
|
|
74
|
+
|
|
75
|
+
except Exception as e:
|
|
76
|
+
logging.error(f"ElasticsearchService 初始化失败: {e}", exc_info=True)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def get_client(cls) -> Optional[Any]:
|
|
80
|
+
"""
|
|
81
|
+
获取 ES 客户端
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
AsyncElasticsearch 客户端实例,未初始化返回 None
|
|
85
|
+
"""
|
|
86
|
+
return cls._client
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def is_initialized(cls) -> bool:
|
|
90
|
+
"""检查是否已初始化"""
|
|
91
|
+
return cls._initialized
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
async def close(cls):
|
|
95
|
+
"""关闭 ES 连接"""
|
|
96
|
+
if cls._client:
|
|
97
|
+
try:
|
|
98
|
+
await cls._client.close()
|
|
99
|
+
logging.info("ElasticsearchService ES 连接已关闭")
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logging.error(f"关闭 ES 连接失败: {e}")
|
|
102
|
+
finally:
|
|
103
|
+
cls._client = None
|
|
104
|
+
cls._initialized = False
|