# استراتژی دیتابیس - انعطاف و مقیاس‌پذیری ## مشکل: انعطاف vs ثبات با توجه به اینکه پروژه قرار است: - کلی feature جدید بگیره - Options و configurations متنوع داشته باشه - قابل توسعه سریع باشه آیا PostgreSQL محدودیت ایجاد می‌کنه؟ ## ✅ راه حل: Hybrid Database Architecture ### لایه‌بندی داده بر اساس نوع: ``` ┌──────────────────────────────────────────────┐ │ Application Layer │ └────┬─────────────┬──────────────┬────────────┘ │ │ │ ┌────▼─────┐ ┌───▼────┐ ┌───▼────┐ │PostgreSQL│ │MongoDB │ │ Redis │ │ │ │ │ │ │ │Critical │ │Flexible│ │ Cache │ │Structured│ │Dynamic │ │Session │ └──────────┘ └────────┘ └────────┘ ``` ### Tier 1: PostgreSQL - Critical Business Data **چی بریزیم توی PostgreSQL:** - User accounts - Financial data (invoices, transactions, wallet) - Service subscriptions - Audit logs - Anything که نیاز به ACID داره ```python # ❌ این‌ها رو NEVER توی MongoDB نذاریم class Invoice(BaseModel): id: int user_id: int amount: Decimal # MUST be ACID status: str paid_at: datetime ``` **چرا PostgreSQL؟** - ✅ ACID Transactions - ✅ Data Integrity - ✅ Complex Joins - ✅ Proven for financial data ### Tier 2: PostgreSQL JSONB - Flexible Structured **چی بریزیم توی JSONB:** - Service configurations - User preferences - Feature flags - Custom metadata - Plugin settings ```python from sqlalchemy.dialects.postgresql import JSONB class Service(BaseModel): # Structured id = Column(Integer, primary_key=True) user_id = Column(Integer) type = Column(String) # 'vps', 'hosting', etc. # Flexible - هر چیزی می‌تونه باشه! config = Column(JSONB, default={}) metadata = Column(JSONB, default={}) # Example 1: VPS vps = Service( type="vps", config={ "cpu": 4, "ram": 8, "disk": 100, "os": "ubuntu-22.04" } ) # Example 2: WordPress Hosting wp = Service( type="wordpress", config={ "domain": "example.com", "php_version": "8.2", "auto_update": True, "cdn_enabled": True, # Future features - بدون migration! "new_feature_2025": {"enabled": True} } ) ``` **Query کردن JSONB:** ```python # پیدا کردن VPS های بالای 4 CPU services = session.query(Service).filter( Service.config['cpu'].astext.cast(Integer) >= 4 ).all() # پیدا کردن WordPress با CDN enabled services = session.query(Service).filter( Service.config['cdn_enabled'].astext == 'true' ).all() # Index روی JSONB برای performance from sqlalchemy import Index Index( 'idx_service_config_cpu', Service.config['cpu'].astext.cast(Integer) ) ``` ### Tier 3: MongoDB - Completely Dynamic **چی بریزیم توی MongoDB:** - Logs و events - Analytics data - User activity tracking - System metrics - Unstructured data ```python # MongoDB - No schema! { "_id": "service_log_123", "service_id": 123, "timestamp": "2025-01-24T...", "events": [ { "type": "cpu_spike", "value": 95, "custom_field_1": "...", # هر چیزی که بخوایم! } ], "metrics": { # Structure آزاد "anything": "goes here" } } ``` ## پیاده‌سازی در کد ### 1. Service با JSONB: ```python # src/infrastructure/database/models/service_model.py from sqlalchemy import Column, Integer, String, ForeignKey, Enum as SQLEnum from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import relationship import enum class ServiceType(enum.Enum): VPS = "vps" HOSTING = "hosting" WORDPRESS = "wordpress" DOMAIN = "domain" class ServiceModel(BaseModel): __tablename__ = "services" id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey('users.id'), nullable=False) type = Column(SQLEnum(ServiceType), nullable=False) status = Column(String(20), nullable=False) # Flexible configuration config = Column(JSONB, nullable=False, default={}) metadata = Column(JSONB, nullable=False, default={}) # Relationships user = relationship("UserModel", back_populates="services") ``` ### 2. Repository با JSONB support: ```python # src/infrastructure/database/repositories/service_repository.py from typing import Dict, Any, List from sqlalchemy.orm import Session class ServiceRepository: def __init__(self, session: Session): self._session = session def find_by_config( self, json_path: str, value: Any ) -> List[ServiceModel]: """Query by JSONB field. Example: repo.find_by_config('cpu', 4) repo.find_by_config('cdn_enabled', True) """ return self._session.query(ServiceModel).filter( ServiceModel.config[json_path].astext == str(value) ).all() def update_config( self, service_id: int, config_updates: Dict[str, Any] ) -> ServiceModel: """Update service config partially.""" service = self.get_by_id(service_id) if service: # Merge configs new_config = {**service.config, **config_updates} service.config = new_config self._session.commit() return service ``` ### 3. Domain Entity که flexible هست: ```python # src/core/domain/entities/service.py from typing import Dict, Any, Optional from src.core.domain.entities.base import BaseEntity class Service(BaseEntity): """Service domain entity with flexible configuration.""" def __init__( self, id: Optional[int] = None, user_id: int = None, type: str = None, status: str = None, config: Dict[str, Any] = None, metadata: Dict[str, Any] = None, **kwargs ): super().__init__(id=id, **kwargs) self.user_id = user_id self.type = type self.status = status self.config = config or {} self.metadata = metadata or {} def get_config(self, key: str, default: Any = None) -> Any: """Get config value safely.""" return self.config.get(key, default) def set_config(self, key: str, value: Any) -> None: """Set config value.""" self.config[key] = value def update_config(self, updates: Dict[str, Any]) -> None: """Update multiple config values.""" self.config.update(updates) ``` ## مقایسه روش‌ها ### Migration-based (Traditional SQL) ```python # ❌ هر feature جدید = migration جدید # Migration 001 ALTER TABLE services ADD COLUMN cpu INTEGER; # Migration 002 ALTER TABLE services ADD COLUMN ram INTEGER; # Migration 003 ALTER TABLE services ADD COLUMN new_feature VARCHAR(255); # بعد از 100 feature = 100 migration! 😱 ``` ### JSONB-based (Flexible SQL) ```python # ✅ هیچ migration لازم نیست! # روز اول service.config = {"cpu": 4} # یک ماه بعد service.config = {"cpu": 4, "ram": 8} # یک سال بعد service.config = { "cpu": 4, "ram": 8, "new_feature_2025": True, "another_feature": {"nested": "data"} } # بدون هیچ migration! 🎉 ``` ## Best Practices ### 1. تصمیم‌گیری: PostgreSQL vs MongoDB vs JSONB ```python # PostgreSQL (Structured) ✅ User authentication ✅ Financial transactions ✅ Invoices ✅ Core business entities # PostgreSQL JSONB ✅ Service configurations ✅ User preferences ✅ Feature flags ✅ Plugin settings ✅ Custom fields # MongoDB ✅ Logs & Events ✅ Analytics ✅ User activity ✅ System metrics ✅ Temporary data ``` ### 2. JSONB Schema Validation (در Application) ```python from pydantic import BaseModel from typing import Optional class VPSConfig(BaseModel): """Schema for VPS service config.""" cpu: int ram: int disk: int os: str backups: Optional[bool] = False class WordPressConfig(BaseModel): """Schema for WordPress service config.""" domain: str php_version: str auto_update: bool cdn_enabled: Optional[bool] = False # Validation def validate_service_config(service_type: str, config: dict): """Validate config based on service type.""" schemas = { "vps": VPSConfig, "wordpress": WordPressConfig, } schema = schemas.get(service_type) if schema: return schema(**config) # Validates return config ``` ### 3. Indexing برای Performance ```python # در migration from alembic import op def upgrade(): # Create GIN index on JSONB op.execute(""" CREATE INDEX idx_services_config_gin ON services USING GIN (config); """) # Index specific keys op.execute(""" CREATE INDEX idx_services_config_cpu ON services ((config->>'cpu')); """) ``` ## مزایا و معایب ### PostgreSQL + JSONB (پیشنهاد من) **مزایا:** - ✅ انعطاف بالا (مثل MongoDB) - ✅ ACID transactions (برای billing امن) - ✅ Query قدرتمند - ✅ یک database کمتر = ساده‌تر - ✅ Performance خوب با indexing - ✅ Data integrity **معایب:** - ❌ JSONB query ها کمی پیچیده‌تر از SQL معمولی - ❌ نیاز به validation در application layer ### Hybrid (PostgreSQL + MongoDB) **مزایا:** - ✅ Best of both worlds - ✅ Separation of concerns - ✅ Optimal performance **معایب:** - ❌ پیچیدگی بیشتر - ❌ دو database = maintenance بیشتر - ❌ Consistency بین دو DB ## نتیجه‌گیری **پیشنهاد برای پیکربند:** ```python """ Tier 1: PostgreSQL - Critical - Users, Auth - Invoices, Transactions - Wallet, Payments Tier 2: PostgreSQL JSONB - Flexible - Service configs - User preferences - Custom settings Tier 3: Redis - Cache - Sessions - Cache - Rate limiting (Optional) Tier 4: MongoDB - Logs - Activity logs - System metrics - Analytics """ ``` **در عمل:** - شروع با PostgreSQL + JSONB - اگر لازم شد، MongoDB اضافه می‌کنیم - ساده، flexible، و قابل توسعه **PostgreSQL دست و پای ما رو نمی‌بنده، اگر از JSONB استفاده کنیم!** ✨