base.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # base.py 修改后
  2. import os
  3. from dotenv import load_dotenv
  4. from core.utils.path_utils import project_root, log_dir
  5. from pydantic import Field, AnyUrl, field_validator, ConfigDict
  6. from pydantic_settings import BaseSettings # 注意:BaseSettings 现在在 pydantic_settings 中
  7. load_dotenv(os.path.join(project_root, ".env"))
  8. class Settings(BaseSettings):
  9. # Pydantic 2.x 使用 ConfigDict 替代内部 Config 类
  10. model_config = ConfigDict(
  11. env_file=".env",
  12. env_file_encoding='utf-8',
  13. case_sensitive=False,
  14. env_prefix="", # 明确指定环境变量前缀
  15. )
  16. # 环境标识
  17. ENV: str = "prod"
  18. ENABLE_ALIYUN_LOG: bool = True
  19. # 日志配置
  20. LOG_DIR: str = log_dir
  21. LOG_LEVEL: str = "INFO"
  22. # 阿里云数据库配置
  23. DB_HOST: str = Field(..., validation_alias="DB_HOST")
  24. DB_PORT: int = Field(3306, validation_alias="DB_PORT")
  25. DB_USER: str = Field(..., validation_alias="DB_USER")
  26. DB_PASSWORD: str = Field(..., validation_alias="DB_PASSWORD")
  27. DB_NAME: str = Field(..., validation_alias="DB_NAME")
  28. DB_CHARSET: str = Field(..., validation_alias="DB_CHARSET")
  29. DB_POOL_SIZE: int = 12
  30. DB_POOL_RECYCLE: int = 3600
  31. # 垂直 spider 查询 API
  32. API_HOST: str = "127.0.0.1"
  33. API_PORT: int = 8888
  34. API_MAX_LIMIT: int = 500
  35. API_MAX_CONCURRENT_REQUESTS: int = 8
  36. API_QUERY_TIMEOUT: int = 30
  37. API_QUEUE_TIMEOUT: float = 2.0
  38. API_LOG_QUEUE_SIZE: int = 1000
  39. API_LOG_FLUSH_TIMEOUT: float = 5.0
  40. API_ALIYUN_LOG_PROJECT: str = "crawler-log-prod"
  41. API_ALIYUN_LOGSTORE: str = "crawler-api-access"
  42. API_ALIYUN_LOG_ENDPOINT: str = "cn-hangzhou.log.aliyuncs.com"
  43. # 兼容旧部署环境变量;API已不再读取或校验该值。
  44. CHUI_ZHI_API_TOKEN: str = ""
  45. # 阿里云RocketMQ配置
  46. ROCKETMQ_ENDPOINT: str = Field(..., validation_alias="ROCKETMQ_ENDPOINT")
  47. ROCKETMQ_ACCESS_KEY_ID: str = Field(..., validation_alias="ROCKETMQ_ACCESS_KEY_ID")
  48. ROCKETMQ_ACCESS_KEY_SECRET: str = Field(..., validation_alias="ROCKETMQ_ACCESS_KEY_SECRET")
  49. ROCKETMQ_INSTANCE_ID: str = Field(..., validation_alias="ROCKETMQ_INSTANCE_ID")
  50. ROCKETMQ_WAIT_SECONDS: int = 30
  51. ROCKETMQ_BATCH: int = 1
  52. # 飞书配置
  53. FEISHU_APPID: str = Field(..., validation_alias="FEISHU_APPID")
  54. FEISHU_APPSECRET: str = Field(..., validation_alias="FEISHU_APPSECRET")
  55. # 连接池配置
  56. CONNECTION_TIMEOUT: int = 10
  57. REQUEST_TIMEOUT: int = 30
  58. # 阿里云日志
  59. ALIYUN_ACCESS_KEY_ID: str = Field(..., validation_alias="ALIYUN_ACCESS_KEY_ID")
  60. ALIYUN_ACCESS_KEY_SECRET: str = Field(..., validation_alias="ALIYUN_ACCESS_KEY_SECRET")
  61. # redis
  62. REDIS_HOST: str = Field(..., validation_alias="REDIS_HOST")
  63. REDIS_PORT: int = Field(..., validation_alias="REDIS_PORT")
  64. REDIS_PASSWORD: str = Field(..., validation_alias="REDIS_PASSWORD")
  65. REDIS_DB: int = Field(0, validation_alias="REDIS_DB")
  66. REDIS_MAX_CONNECTIONS: int = Field(20, validation_alias="REDIS_MAX_CONNECTIONS")
  67. @property
  68. def redis_url(self) -> str:
  69. return f"redis://:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
  70. # Pydantic 2.x 验证器语法
  71. @field_validator('DB_PORT', 'REDIS_PORT', 'API_PORT')
  72. @classmethod
  73. def validate_port(cls, v: int) -> int:
  74. if not 1 <= v <= 65535:
  75. raise ValueError('Port must be between 1 and 65535')
  76. return v
  77. @field_validator(
  78. 'DB_POOL_SIZE',
  79. 'DB_POOL_RECYCLE',
  80. 'REDIS_MAX_CONNECTIONS',
  81. 'API_MAX_LIMIT',
  82. 'API_MAX_CONCURRENT_REQUESTS',
  83. 'API_QUERY_TIMEOUT',
  84. 'API_LOG_QUEUE_SIZE',
  85. )
  86. @classmethod
  87. def validate_positive_int(cls, v: int) -> int:
  88. if v <= 0:
  89. raise ValueError('Value must be positive')
  90. return v
  91. @field_validator('API_QUEUE_TIMEOUT', 'API_LOG_FLUSH_TIMEOUT')
  92. @classmethod
  93. def validate_positive_float(cls, v: float) -> float:
  94. if v <= 0:
  95. raise ValueError('Value must be positive')
  96. return v
  97. @field_validator('ROCKETMQ_WAIT_SECONDS')
  98. @classmethod
  99. def validate_rocketmq_wait_seconds(cls, v: int) -> int:
  100. if not 1 <= v <= 30:
  101. raise ValueError('ROCKETMQ_WAIT_SECONDS must be between 1 and 30')
  102. return v
  103. @field_validator('ROCKETMQ_BATCH')
  104. @classmethod
  105. def validate_rocketmq_batch(cls, v: int) -> int:
  106. if not 1 <= v <= 16:
  107. raise ValueError('ROCKETMQ_BATCH must be between 1 and 16')
  108. return v
  109. @field_validator('CONNECTION_TIMEOUT', 'REQUEST_TIMEOUT')
  110. @classmethod
  111. def validate_timeouts(cls, v: int) -> int:
  112. if v <= 0:
  113. raise ValueError('Timeout must be positive')
  114. return v
  115. settings = Settings()