# استراتژی دیتابیس - انعطاف و مقیاس‌پذیری

## مشکل: انعطاف 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 استفاده کنیم!** ✨

