Some checks failed
CD - Build & Deploy / build-and-push (push) Has been cancelled
CD - Build & Deploy / package-helm (push) Has been cancelled
CD - Build & Deploy / deploy-staging (push) Has been cancelled
CD - Build & Deploy / deploy-production (push) Has been cancelled
CD - Build & Deploy / release (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / security (push) Has been cancelled
- Implemented Clean Architecture with Domain, Application, Infrastructure, Presentation layers - Added comprehensive project structure following SOLID principles - Created Kubernetes deployment with Helm charts (HPA, PDB, NetworkPolicy) - Configured ArgoCD for automated deployment (production + staging) - Implemented CI/CD pipeline with GitHub Actions - Added comprehensive documentation (handbook, architecture, coding standards) - Configured PostgreSQL, Redis, Celery for backend services - Created modern landing page with Persian fonts (Vazirmatn) - Added Docker multi-stage build for production - Configured development tools (pytest, black, flake8, mypy, isort) - Added pre-commit hooks for code quality - Implemented Makefile for common operations
23 KiB
23 KiB
پروژه پیکربند - Handbook جامع
نسخه: 1.0.0
آخرین بروزرسانی: 2025-01-24
نویسنده: تیم توسعه پیکربند
فهرست مطالب
- معرفی پروژه
- معماری کلی
- قوانین و استانداردها
- راهاندازی محیط توسعه
- ساختار پروژه
- Design Patterns
- Best Practices
- Testing Strategy
- Deployment Guide
- Troubleshooting
- مستندسازی تغییرات
1. معرفی پروژه
1.1 هدف
پیکربند یک پلتفرم جامع مدیریت هاستینگ و زیرساخت ابری است که شامل:
- هاستینگ وردپرس: مدیریت حرفهای سایتهای WordPress
- فروش دامین: ثبت و مدیریت دامینها
- سرورهای اختصاصی: VPS و Dedicated Servers
- خدمات DevOps: مشاوره و پیادهسازی
- پنل مدیریت: پنل کنترل سفارشی شبیه cPanel
1.2 تکنولوژیهای استفاده شده
| تکنولوژی | نسخه | کاربرد |
|---|---|---|
| Python | 3.11+ | زبان اصلی |
| Reflex | 0.4.0 | Frontend/Backend Framework |
| PostgreSQL | 14+ | Database اصلی |
| Redis | 7+ | Cache & Sessions |
| SQLAlchemy | 2.0+ | ORM |
| Celery | 5.3+ | Task Queue |
| pytest | 7.4+ | Testing |
1.3 اصول طراحی
Clean Architecture
پروژه بر اساس معماری تمیز طراحی شده که شامل 4 لایه اصلی است:
- Domain Layer: منطق کسبوکار خالص
- Application Layer: موارد استفاده (Use Cases)
- Infrastructure Layer: جزئیات فنی
- Presentation Layer: رابط کاربری
SOLID Principles
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
سایر اصول
- DRY: Don't Repeat Yourself
- KISS: Keep It Simple, Stupid
- YAGNI: You Aren't Gonna Need It
- Convention over Configuration
2. معماری کلی
2.1 نمای کلی لایهها
┌─────────────────────────────────────────┐
│ Presentation Layer (Reflex UI) │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │Landing │ │Dashboard│ │ Admin │ │
│ └────────┘ └────────┘ └────────┘ │
└──────────────────┬──────────────────────┘
│
┌──────────────────┴──────────────────────┐
│ Application Layer (Use Cases) │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ Auth │ │Billing│ │Server│ │Ticket│ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
└──────────────────┬──────────────────────┘
│
┌──────────────────┴──────────────────────┐
│ Domain Layer (Business Logic) │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │Entities│ │ Values │ │Services│ │
│ └────────┘ └────────┘ └────────┘ │
└──────────────────┬──────────────────────┘
│
┌──────────────────┴──────────────────────┐
│ Infrastructure Layer (Technical) │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ DB │ │Cache│ │ API │ │Tasks│ │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────────┘
2.2 جریان داده
User Request → Presentation → Application → Domain
↓
Infrastructure ← Application ← Domain Logic
↓
External APIs
2.3 Layer های جزئی
Domain Layer
- Entities: موجودیتهای اصلی (User, Service, Invoice, etc.)
- Value Objects: اشیاء ارزشی (Email, Money, Phone)
- Domain Services: منطق پیچیده دامین
- Enums: مقادیر ثابت
- Exceptions: خطاهای دامین
Application Layer
- Use Cases: موارد استفاده سیستم
- DTOs: Data Transfer Objects
- Interfaces: تعریف رابطهای سرویسها
- Validators: اعتبارسنجی ورودیها
Infrastructure Layer
- Database: Models و Repositories
- Cache: Redis implementation
- External: API های خارجی
- Tasks: Background jobs
- Security: Authentication & Authorization
- Logging: Structured logging
Presentation Layer
- Web: Reflex components و pages
- API: REST endpoints (optional)
- State: Reflex state management
3. قوانین و استانداردها
3.1 Python Code Style (PEP 8)
Naming Conventions
# Classes: PascalCase
class UserService:
pass
class PaymentGateway:
pass
# Functions & Methods: snake_case
def create_user(email: str) -> User:
pass
def process_payment(amount: Decimal) -> PaymentResult:
pass
# Constants: UPPER_SNAKE_CASE
MAX_LOGIN_ATTEMPTS = 3
DEFAULT_TIMEOUT = 30
API_VERSION = "v1"
# Private methods: _leading_underscore
def _internal_helper():
pass
# Protected: __double_underscore (name mangling)
class BaseClass:
def __private_method(self):
pass
# Variables: snake_case
user_email = "test@example.com"
total_amount = Decimal("100.00")
3.2 Type Hints (الزامی)
from typing import Optional, List, Dict, Any, Union
from decimal import Decimal
# Function signatures
def get_user_by_id(user_id: int) -> Optional[User]:
pass
def create_invoice(
user_id: int,
amount: Decimal,
items: List[InvoiceItem]
) -> Invoice:
pass
# Return types
def get_users(limit: int = 10) -> List[User]:
pass
def find_service(service_id: int) -> Optional[Service]:
pass
# Complex types
def process_config(config: Dict[str, Any]) -> bool:
pass
UserOrNone = Optional[User]
ServiceList = List[Service]
3.3 Docstrings (Google Style - الزامی)
def create_user(
email: str,
password: str,
full_name: str,
phone: Optional[str] = None
) -> User:
"""Create a new user account.
This function creates a new user in the system with the provided
information. Password is automatically hashed before storage.
Args:
email: User's email address (must be unique)
password: Plain text password (will be hashed)
full_name: User's full name
phone: Optional phone number
Returns:
User: Created user object
Raises:
EmailAlreadyExistsException: If email is already registered
InvalidEmailException: If email format is invalid
WeakPasswordException: If password doesn't meet requirements
Example:
>>> user = create_user(
... email="test@example.com",
... password="SecurePass123!",
... full_name="John Doe",
... phone="+989123456789"
... )
>>> print(user.id)
1
"""
pass
3.4 Import Order (با isort)
# 1. Standard library imports
import os
import sys
from typing import Optional, List
from decimal import Decimal
from datetime import datetime
# 2. Third-party imports
import redis
from sqlalchemy import Column, Integer, String
from pydantic import BaseModel
# 3. Local application imports
from src.config.settings import settings
from src.core.domain.entities.user import User
from src.infrastructure.database.repositories.user_repository import UserRepository
3.5 Error Handling
# ✅ GOOD: Specific exceptions
try:
user = user_repository.get_by_id(user_id)
if not user:
raise UserNotFoundException(f"User {user_id} not found")
except DatabaseException as e:
logger.error("database_error", error=str(e), user_id=user_id)
raise
except Exception as e:
logger.critical("unexpected_error", error=str(e))
raise InfrastructureException("Internal server error") from e
# ❌ BAD: Generic exceptions
try:
# code
except: # Never do this!
pass
# ❌ BAD: Too broad
try:
# code
except Exception:
pass
3.6 Logging Best Practices
import structlog
logger = structlog.get_logger(__name__)
# ✅ GOOD: Structured logging with context
logger.info(
"user_created",
user_id=user.id,
email=user.email,
registration_source="web",
ip_address=request.ip
)
logger.error(
"payment_failed",
user_id=user.id,
invoice_id=invoice.id,
amount=str(invoice.amount),
gateway="zarinpal",
error_code=response.code,
error_message=response.message
)
# ❌ BAD: String concatenation
logger.info("User " + str(user.id) + " created")
4. راهاندازی محیط توسعه
4.1 پیشنیازها
# Check Python version (3.11+)
python --version
# Check PostgreSQL (14+)
psql --version
# Check Redis (7+)
redis-cli --version
# Check Node.js (18+)
node --version
4.2 نصب وابستگیها
# Clone repository
git clone https://github.com/yourusername/peikarband.git
cd peikarband
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Install pre-commit hooks
pre-commit install
4.3 تنظیم Environment Variables
# Copy example env file
cp .env.example .env
# Edit .env file
nano .env
# Required variables:
# - DATABASE_URL
# - REDIS_URL
# - SECRET_KEY
# - JWT_SECRET_KEY
4.4 راهاندازی دیتابیس
# Create database
createdb peikarband
# Or using psql
psql -U postgres
CREATE DATABASE peikarband;
\q
# Run migrations
alembic upgrade head
# (Optional) Seed database
python scripts/seed_database.py
4.5 اجرای پروژه
# Development mode
python -m reflex run
# With auto-reload
python -m reflex run --reload
# Production mode
python -m reflex run --env production
5. ساختار پروژه
5.1 نمای کلی
peikarband/
├── docs/ # Documentation
├── src/ # Source code
├── tests/ # Tests
├── scripts/ # Utility scripts
├── .github/workflows/ # CI/CD
└── [config files] # Configuration
5.2 src/ Structure
src/
├── config/ # Configuration
│ ├── settings.py # Main settings
│ ├── database.py # DB config
│ ├── cache.py # Redis config
│ └── logging.py # Log config
│
├── core/ # Core business logic
│ ├── domain/ # Domain layer
│ │ ├── entities/ # Business entities
│ │ ├── value_objects/ # Value objects
│ │ ├── enums/ # Enumerations
│ │ └── exceptions/ # Domain exceptions
│ │
│ ├── application/ # Application layer
│ │ ├── use_cases/ # Use cases
│ │ ├── dto/ # DTOs
│ │ ├── interfaces/ # Service interfaces
│ │ └── validators/ # Validators
│ │
│ └── utils/ # Core utilities
│
├── infrastructure/ # Infrastructure layer
│ ├── database/ # Database implementation
│ ├── cache/ # Cache implementation
│ ├── external/ # External APIs
│ ├── tasks/ # Background tasks
│ ├── security/ # Security utilities
│ └── logging/ # Logging setup
│
├── presentation/ # Presentation layer
│ ├── web/ # Reflex web app
│ │ ├── pages/ # Pages
│ │ ├── components/ # Components
│ │ ├── state/ # State management
│ │ └── styles/ # Styling
│ │
│ └── api/ # REST API (optional)
│
└── shared/ # Shared code
├── events/ # Domain events
└── messaging/ # Event bus
6. Design Patterns
6.1 Repository Pattern
from abc import ABC, abstractmethod
from typing import Optional, List
# Interface (in core/application/interfaces/repositories/)
class IUserRepository(ABC):
@abstractmethod
def get_by_id(self, user_id: int) -> Optional[User]:
"""Get user by ID."""
pass
@abstractmethod
def get_by_email(self, email: str) -> Optional[User]:
"""Get user by email."""
pass
@abstractmethod
def save(self, user: User) -> User:
"""Save or update user."""
pass
@abstractmethod
def delete(self, user_id: int) -> bool:
"""Delete user."""
pass
# Implementation (in infrastructure/database/repositories/)
class UserRepository(IUserRepository):
def __init__(self, session: Session):
self._session = session
def get_by_id(self, user_id: int) -> Optional[User]:
model = self._session.query(UserModel).filter_by(id=user_id).first()
return self._to_entity(model) if model else None
def save(self, user: User) -> User:
model = self._to_model(user)
self._session.add(model)
self._session.commit()
self._session.refresh(model)
return self._to_entity(model)
6.2 Unit of Work Pattern
from contextlib import contextmanager
class UnitOfWork:
"""Manages database transactions."""
def __init__(self, session_factory):
self.session_factory = session_factory
self._session = None
def __enter__(self):
self._session = self.session_factory()
self.users = UserRepository(self._session)
self.services = ServiceRepository(self._session)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
self._session.rollback()
else:
self._session.commit()
self._session.close()
# Usage
with UnitOfWork(SessionLocal) as uow:
user = uow.users.get_by_id(1)
user.email = "new@email.com"
uow.users.save(user)
# Automatically commits on success
6.3 Factory Pattern
from abc import ABC, abstractmethod
class ICloudProvider(ABC):
@abstractmethod
def create_server(self, config: ServerConfig) -> Server:
pass
class DigitalOceanProvider(ICloudProvider):
def create_server(self, config: ServerConfig) -> Server:
# Implementation
pass
class HetznerProvider(ICloudProvider):
def create_server(self, config: ServerConfig) -> Server:
# Implementation
pass
class CloudProviderFactory:
@staticmethod
def create(provider_type: str) -> ICloudProvider:
providers = {
"digitalocean": DigitalOceanProvider,
"hetzner": HetznerProvider,
"ovh": OVHProvider,
}
provider_class = providers.get(provider_type)
if not provider_class:
raise ValueError(f"Unknown provider: {provider_type}")
return provider_class()
# Usage
provider = CloudProviderFactory.create("digitalocean")
server = provider.create_server(config)
6.4 Strategy Pattern
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount: Decimal) -> PaymentResult:
pass
class ZarinpalPayment(PaymentStrategy):
def pay(self, amount: Decimal) -> PaymentResult:
# Zarinpal implementation
pass
class IdPayPayment(PaymentStrategy):
def pay(self, amount: Decimal) -> PaymentResult:
# IdPay implementation
pass
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self._strategy = strategy
def process(self, amount: Decimal) -> PaymentResult:
return self._strategy.pay(amount)
# Usage
processor = PaymentProcessor(ZarinpalPayment())
result = processor.process(Decimal("100.00"))
7. Best Practices
7.1 کد تمیز
# ✅ GOOD: Clear and simple
def calculate_total_price(items: List[Item]) -> Decimal:
"""Calculate total price of items."""
return sum(item.price * item.quantity for item in items)
# ❌ BAD: Too complex
def calc(i):
t = 0
for x in i:
t += x[0] * x[1]
return t
7.2 Don't Repeat Yourself (DRY)
# ❌ BAD: Repetition
def get_user_name(user_id: int) -> str:
session = SessionLocal()
user = session.query(User).filter_by(id=user_id).first()
session.close()
return user.name
def get_user_email(user_id: int) -> str:
session = SessionLocal()
user = session.query(User).filter_by(id=user_id).first()
session.close()
return user.email
# ✅ GOOD: Reusable
def get_user(user_id: int) -> User:
with get_db_context() as session:
return session.query(User).filter_by(id=user_id).first()
def get_user_name(user_id: int) -> str:
user = get_user(user_id)
return user.name if user else None
7.3 Single Responsibility
# ❌ BAD: Multiple responsibilities
class User:
def save(self):
# Saves to database
pass
def send_email(self):
# Sends email
pass
def calculate_discount(self):
# Business logic
pass
# ✅ GOOD: Separated
class User:
# Just entity
pass
class UserRepository:
def save(self, user: User):
pass
class EmailService:
def send_welcome_email(self, user: User):
pass
class DiscountService:
def calculate_user_discount(self, user: User):
pass
8. Testing Strategy
8.1 Test Pyramid
/\
/E2E\ 10% - End-to-End Tests
/------\
/Integr-\ 20% - Integration Tests
/----------\
/ Unit \ 70% - Unit Tests
8.2 Unit Test Example
import pytest
from decimal import Decimal
class TestInvoiceCalculation:
def test_calculate_total_with_items(self):
# Arrange
items = [
InvoiceItem(name="Item 1", price=Decimal("10.00"), quantity=2),
InvoiceItem(name="Item 2", price=Decimal("5.00"), quantity=3),
]
invoice = Invoice(items=items)
# Act
total = invoice.calculate_total()
# Assert
assert total == Decimal("35.00")
def test_calculate_total_empty(self):
invoice = Invoice(items=[])
assert invoice.calculate_total() == Decimal("0.00")
8.3 Integration Test Example
@pytest.mark.integration
class TestUserRepository:
def test_save_and_retrieve_user(self, db_session):
# Arrange
repository = UserRepository(db_session)
user = User(email="test@example.com", name="Test User")
# Act
saved_user = repository.save(user)
retrieved_user = repository.get_by_id(saved_user.id)
# Assert
assert retrieved_user is not None
assert retrieved_user.email == "test@example.com"
9. Deployment Guide
9.1 Production Checklist
- همه تستها pass شدند
- Code coverage بالای 80%
- Security audit انجام شد
- Environment variables set شدند
- Database migrations اجرا شدند
- Monitoring setup شد
- Backup strategy تعریف شد
- SSL certificates نصب شدند
- Firewall rules تنظیم شدند
10. Troubleshooting
10.1 مشکلات رایج
Database Connection Error
Problem: sqlalchemy.exc.OperationalError
Solution:
- Check DATABASE_URL in .env
- Verify PostgreSQL is running
- Check firewall rules
- Test connection:
psql $DATABASE_URL
Redis Connection Error
Problem: redis.exceptions.ConnectionError
Solution:
- Check REDIS_URL in .env
- Verify Redis is running:
redis-cli ping - Check Redis password if set
11. مستندسازی تغییرات
11.1 Commit Message Format
<type>(<scope>): <subject>
<body>
<footer>
Types:
- feat: ویژگی جدید
- fix: رفع باگ
- docs: تغییرات مستندات
- style: فرمتبندی
- refactor: بازنویسی
- test: اضافه کردن تست
- chore: کارهای نگهداری
Example:
feat(auth): add two-factor authentication
- Implement TOTP-based 2FA
- Add QR code generation for authenticator apps
- Add backup codes feature
Closes #123
11.2 CHANGELOG.md
تمام تغییرات باید در CHANGELOG.md ثبت شود:
# Changelog
## [Unreleased]
## [1.0.0] - 2025-01-24
### Added
- User authentication system
- Two-factor authentication
- Password reset functionality
### Changed
- Improved database schema
- Updated UI components
### Fixed
- Payment gateway timeout issue
- Email verification bug
پیوستها
A. فایلهای مهم
docs/architecture/: معماری سیستمdocs/development/: راهنمای توسعهdocs/changelog/: تاریخچه تغییراتdocs/api/: مستندات API
B. لینکهای مفید
این handbook باید همیشه بهروز نگه داشته شود.