|  | @@ -1,6 +1,6 @@
 | 
	
		
			
				|  |  | -from typing import Optional
 | 
	
		
			
				|  |  | +from typing import Any, Optional
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -from pydantic import BaseModel, Field
 | 
	
		
			
				|  |  | +from pydantic import BaseModel, Field, NonNegativeInt, PositiveInt, computed_field
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  from configs.middleware.redis_config import RedisConfig
 | 
	
		
			
				|  |  |  from configs.middleware.storage.aliyun_oss_storage_config import AliyunOSSStorageConfig
 | 
	
	
		
			
				|  | @@ -49,8 +49,114 @@ class KeywordStoreConfigs(BaseModel):
 | 
	
		
			
				|  |  |      )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +class DatabaseConfigs:
 | 
	
		
			
				|  |  | +    DB_HOST: str = Field(
 | 
	
		
			
				|  |  | +        description='db host',
 | 
	
		
			
				|  |  | +        default='localhost',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    DB_PORT: PositiveInt = Field(
 | 
	
		
			
				|  |  | +        description='db port',
 | 
	
		
			
				|  |  | +        default=5432,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    DB_USERNAME: str = Field(
 | 
	
		
			
				|  |  | +        description='db username',
 | 
	
		
			
				|  |  | +        default='postgres',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    DB_PASSWORD: str = Field(
 | 
	
		
			
				|  |  | +        description='db password',
 | 
	
		
			
				|  |  | +        default='',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    DB_DATABASE: str = Field(
 | 
	
		
			
				|  |  | +        description='db database',
 | 
	
		
			
				|  |  | +        default='dify',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    DB_CHARSET: str = Field(
 | 
	
		
			
				|  |  | +        description='db charset',
 | 
	
		
			
				|  |  | +        default='',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SQLALCHEMY_DATABASE_URI_SCHEME: str = Field(
 | 
	
		
			
				|  |  | +        description='db uri scheme',
 | 
	
		
			
				|  |  | +        default='postgresql',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @computed_field
 | 
	
		
			
				|  |  | +    @property
 | 
	
		
			
				|  |  | +    def SQLALCHEMY_DATABASE_URI(self) -> str:
 | 
	
		
			
				|  |  | +        db_extras = f"?client_encoding={self.DB_CHARSET}" if self.DB_CHARSET else ""
 | 
	
		
			
				|  |  | +        return (f"{self.SQLALCHEMY_DATABASE_URI_SCHEME}://"
 | 
	
		
			
				|  |  | +                f"{self.DB_USERNAME}:{self.DB_PASSWORD}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_DATABASE}"
 | 
	
		
			
				|  |  | +                f"{db_extras}")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SQLALCHEMY_POOL_SIZE: NonNegativeInt = Field(
 | 
	
		
			
				|  |  | +        description='pool size of SqlAlchemy',
 | 
	
		
			
				|  |  | +        default=30,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SQLALCHEMY_MAX_OVERFLOW: NonNegativeInt = Field(
 | 
	
		
			
				|  |  | +        description='max overflows for SqlAlchemy',
 | 
	
		
			
				|  |  | +        default=10,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SQLALCHEMY_POOL_RECYCLE: NonNegativeInt = Field(
 | 
	
		
			
				|  |  | +        description='SqlAlchemy pool recycle',
 | 
	
		
			
				|  |  | +        default=3600,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SQLALCHEMY_POOL_PRE_PING: bool = Field(
 | 
	
		
			
				|  |  | +        description='whether to enable pool pre-ping in SqlAlchemy',
 | 
	
		
			
				|  |  | +        default=False,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SQLALCHEMY_ECHO: bool = Field(
 | 
	
		
			
				|  |  | +        description='whether to enable SqlAlchemy echo',
 | 
	
		
			
				|  |  | +        default=False,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @computed_field
 | 
	
		
			
				|  |  | +    @property
 | 
	
		
			
				|  |  | +    def SQLALCHEMY_ENGINE_OPTIONS(self) -> dict[str, Any]:
 | 
	
		
			
				|  |  | +        return {
 | 
	
		
			
				|  |  | +            'pool_size': self.SQLALCHEMY_POOL_SIZE,
 | 
	
		
			
				|  |  | +            'max_overflow': self.SQLALCHEMY_MAX_OVERFLOW,
 | 
	
		
			
				|  |  | +            'pool_recycle': self.SQLALCHEMY_POOL_RECYCLE,
 | 
	
		
			
				|  |  | +            'pool_pre_ping': self.SQLALCHEMY_POOL_PRE_PING,
 | 
	
		
			
				|  |  | +            'connect_args': {'options': '-c timezone=UTC'},
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class CeleryConfigs(DatabaseConfigs):
 | 
	
		
			
				|  |  | +    CELERY_BACKEND: str = Field(
 | 
	
		
			
				|  |  | +        description='Celery backend, available values are `database`, `redis`',
 | 
	
		
			
				|  |  | +        default='database',
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    CELERY_BROKER_URL: Optional[str] = Field(
 | 
	
		
			
				|  |  | +        description='CELERY_BROKER_URL',
 | 
	
		
			
				|  |  | +        default=None,
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @computed_field
 | 
	
		
			
				|  |  | +    @property
 | 
	
		
			
				|  |  | +    def CELERY_RESULT_BACKEND(self) -> str:
 | 
	
		
			
				|  |  | +        return 'db+{}'.format(self.SQLALCHEMY_DATABASE_URI) \
 | 
	
		
			
				|  |  | +            if self.CELERY_BACKEND == 'database' else self.CELERY_BROKER_URL
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @computed_field
 | 
	
		
			
				|  |  | +    @property
 | 
	
		
			
				|  |  | +    def BROKER_USE_SSL(self) -> bool:
 | 
	
		
			
				|  |  | +        return self.CELERY_BROKER_URL.startswith('rediss://') if self.CELERY_BROKER_URL else False
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class MiddlewareConfig(
 | 
	
		
			
				|  |  |      # place the configs in alphabet order
 | 
	
		
			
				|  |  | +    CeleryConfigs,
 | 
	
		
			
				|  |  | +    DatabaseConfigs,
 | 
	
		
			
				|  |  |      KeywordStoreConfigs,
 | 
	
		
			
				|  |  |      RedisConfig,
 | 
	
		
			
				|  |  |  
 |