Files
pos-system/services/mining-service-net/docs/vi/ARCHITECTURE.md

12 KiB
Raw Blame History

Kiến Trúc Mining Service

Tổng Quan

Mining Service cung cấp hệ thống đào điểm game hóa lấy cảm hứng từ Pi Network, cho phép người dùng tích lũy Mining Points thông qua hoạt động hàng ngày và xây dựng cộng đồng.

%%{init: {'theme':'dark'}}%%
graph TD
    subgraph API["🌐 Tầng API"]
        Controllers[Controllers]
        Commands[Commands]
        Queries[Queries]
    end
    
    subgraph Domain["⚙️ Tầng Domain"]
        Miner[Miner Aggregate]
        Circle[Circle Aggregate]
        Referral[Referral Aggregate]
    end
    
    subgraph Infra["💾 Tầng Infrastructure"]
        EF[EF Core]
        Redis[(Redis Cache)]
        RabbitMQ[RabbitMQ]
    end
    
    subgraph Data["🗄️ Lưu Trữ Dữ Liệu"]
        DB[(PostgreSQL)]
    end
    
    API --> Domain
    Domain --> Infra
    EF --> DB
    
    style API fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
    style Domain fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style Infra fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px
    style Data fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px

Các Mẫu Kiến Trúc

Domain-Driven Design (DDD)

  • Aggregates: Miner, Circle, Referral
  • Entities: MiningSession, MiningHistory, CircleMember
  • Value Objects: MiningRate, MiningPoints, MiningSession
  • Domain Events: MiningSessionStarted, PointsMined, CircleCompleted, ReferralActivated

CQRS Pattern

%%{init: {'theme':'dark'}}%%
flowchart LR
    subgraph Write["📝 Commands (Ghi)"]
        C1[StartMiningCommand]
        C2[ClaimRewardCommand]
        C3[CreateCircleCommand]
        C4[InviteToCircleCommand]
        C5[ApplyReferralCommand]
    end
    
    subgraph Read["📖 Queries (Đọc)"]
        Q1[GetMinerStatusQuery]
        Q2[GetMiningHistoryQuery]
        Q3[GetCircleQuery]
        Q4[GetReferralsQuery]
        Q5[GetLeaderboardQuery]
    end
    
    style Write fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
    style Read fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px

Domain Model

Miner Aggregate

%%{init: {'theme':'dark'}}%%
classDiagram
    class Miner {
        +Guid Id
        +Guid UserId
        +MinerRole Role
        +decimal TotalMinedPoints
        +MiningRate CurrentRate
        +MiningSession ActiveSession
        +MiningStreak Streak
        +string ReferralCode
        +Guid ReferredBy
        +MinerStatus Status
        +StartMiningSession()
        +ClaimMiningReward()
        +UpgradeRole()
        +RecalculateMiningRate()
    }
    
    class MiningSession {
        +Guid SessionId
        +DateTime StartTime
        +DateTime EndTime
        +decimal AccumulatedPoints
        +SessionStatus Status
    }
    
    class MiningRate {
        +decimal BaseRate
        +decimal CircleBonus
        +decimal ReferralBonus
        +decimal RoleBonus
        +decimal StreakBonus
        +decimal TotalRate
    }
    
    class MiningStreak {
        +int CurrentStreak
        +int LongestStreak
        +DateTime LastMiningDate
        +int FreezeTokens
        +bool IsGracePeriod
        +decimal BonusMultiplier
    }
    
    class MiningHistory {
        +Guid Id
        +decimal PointsEarned
        +string Source
        +DateTime EarnedAt
    }
    
    Miner "1" --> "0..1" MiningSession : có
    Miner --> MiningRate : sử dụng
    Miner --> MiningStreak : theo dõi
    Miner "1" --> "*" MiningHistory : theo dõi

Circle Aggregate

%%{init: {'theme':'dark'}}%%
classDiagram
    class Circle {
        +Guid Id
        +Guid OwnerId
        +string Name
        +List~CircleMember~ Members
        +decimal TrustScore
        +decimal BonusMultiplier
        +CircleStatus Status
        +AddMember()
        +RemoveMember()
        +CalculateTrustScore()
        +Validate()
    }
    
    class CircleMember {
        +Guid Id
        +Guid MinerId
        +DateTime JoinedAt
        +bool IsActive
    }
    
    Circle "1" --> "3..5" CircleMember : chứa

Referral Aggregate

%%{init: {'theme':'dark'}}%%
classDiagram
    class Referral {
        +Guid Id
        +Guid ReferrerId
        +Guid ReferredId
        +string ReferralCode
        +decimal BonusRate
        +bool IsActive
        +int Level
        +DateTime CreatedAt
        +Activate()
        +Deactivate()
        +CalculateBonus()
    }

Công Thức Tỷ Lệ Đào

%%{init: {'theme':'dark'}}%%
flowchart LR
    Base["🎯 Tỷ Lệ Cơ Bản<br/>0.25 MP/giờ"] --> Multiply1((×))
    Role["👤 Thưởng Vai Trò<br/>+0-50%"] --> Multiply1
    Multiply1 --> Multiply2((×))
    Circle["🔵 Thưởng Vòng Tròn<br/>+25%"] --> Multiply2
    Multiply2 --> Multiply3((×))
    Referral["👥 Thưởng Giới Thiệu<br/>+25%/người"] --> Multiply3
    Multiply3 --> Total["✅ Tỷ Lệ Tổng<br/>MP/giờ"]
    
    style Base fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:2px
    style Role fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style Circle fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px
    style Referral fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
    style Total fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:3px

Ví Dụ Tính Toán:

Thành Phần Giá Trị Hệ Số
Tỷ Lệ Cơ Bản 0.25 MP/giờ -
Vai Trò (Ambassador) +25% × 1.25
Vòng Tròn Hợp Lệ +25% × 1.25
2 Giới Thiệu +50% × 1.50
Tổng 0.585 MP/giờ 14.04 MP/ngày

Database Schema

ER Diagram

%%{init: {'theme':'dark'}}%%
erDiagram
    Miner ||--o{ MiningSession : "có"
    Miner ||--o{ MiningHistory : "theo dõi"
    Miner ||--o| Circle : "sở hữu"
    Circle ||--|{ CircleMember : "chứa"
    Miner ||--o{ Referral : "giới thiệu"
    Miner ||--o| Referral : "được giới thiệu bởi"
    
    Miner {
        uuid Id PK
        uuid UserId UK
        string Role
        decimal TotalMinedPoints
        string ReferralCode UK
        uuid ReferredBy FK
        string Status
        datetime CreatedAt
    }
    
    MiningSession {
        uuid Id PK
        uuid MinerId FK
        datetime StartTime
        datetime EndTime
        decimal AccumulatedPoints
        string Status
    }
    
    MiningHistory {
        uuid Id PK
        uuid MinerId FK
        decimal PointsEarned
        string Source
        datetime EarnedAt
    }
    
    Circle {
        uuid Id PK
        uuid OwnerId FK
        string Name
        decimal TrustScore
        decimal BonusMultiplier
        string Status
    }
    
    CircleMember {
        uuid Id PK
        uuid CircleId FK
        uuid MinerId FK
        datetime JoinedAt
        bool IsActive
    }
    
    Referral {
        uuid Id PK
        uuid ReferrerId FK
        uuid ReferredId FK
        string ReferralCode
        decimal BonusRate
        bool IsActive
        int Level
    }

Các Index Quan Trọng

Index Cột Mục Đích
IX_Miners_UserId UserId Tra cứu nhanh theo user
IX_Miners_ReferralCode ReferralCode Tra cứu mã giới thiệu
IX_MiningSessions_MinerId_Status MinerId, Status Kiểm tra phiên hoạt động
IX_Referrals_ReferrerId ReferrerId Danh sách giới thiệu

Luồng API

Bắt Đầu Phiên Đào

%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant Client as 📱 Client
    participant API as 🌐 Mining API
    participant Handler as ⚙️ CommandHandler
    participant Miner as 👤 MinerAggregate
    participant Calc as 🧮 RateCalculator
    participant DB as 💾 PostgreSQL
    participant Cache as ⚡ Redis
    
    Client->>API: POST /api/v1/mining/start
    API->>Handler: StartMiningCommand
    Handler->>Miner: ValidateNoActiveSession()
    Handler->>Calc: CalculateMiningRate()
    Calc-->>Handler: MiningRate
    Handler->>Miner: CreateSession(24 giờ)
    Miner->>DB: SaveSession()
    Miner->>Cache: CacheSessionInfo(ttl: 24h)
    API-->>Client: 200 OK { session_id, rate, end_time }

Nhận Thưởng Đào

%%{init: {'theme':'dark'}}%%
sequenceDiagram
    participant Client as 📱 Client
    participant API as 🌐 Mining API
    participant Handler as ⚙️ CommandHandler
    participant Miner as 👤 MinerAggregate
    participant DB as 💾 PostgreSQL
    participant MQ as 📨 RabbitMQ
    
    Client->>API: POST /api/v1/mining/claim
    API->>Handler: ClaimRewardCommand
    Handler->>Miner: GetActiveSession()
    
    alt Phiên Đã Hoàn Thành
        Miner->>Miner: CalculateEarnedPoints()
        Miner->>Miner: AddToTotalPoints()
        Miner->>DB: SaveMiningHistory()
        Miner->>MQ: Publish PointsMinedEvent
        API-->>Client: 200 OK { earned_points, total_points }
    else Phiên Chưa Sẵn Sàng
        API-->>Client: 400 Bad Request
    end

Giao Tiếp Liên Dịch Vụ

Phụ Thuộc Dịch Vụ

%%{init: {'theme':'dark'}}%%
graph TD
    subgraph External["🔐 Xác Thực"]
        IAM[IAM Service]
    end
    
    subgraph Core["⛏️ Mining Service"]
        Mining[Mining Service]
    end
    
    subgraph Integration["🔗 Tích Hợp"]
        Social[Social Service]
        Wallet[Wallet Service]
    end
    
    IAM -->|Xác thực JWT| Mining
    Social <-->|Dữ liệu bạn bè| Mining
    Mining -->|Chuyển đổi điểm| Wallet
    
    style External fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
    style Core fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:3px
    style Integration fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px

Integration Events (RabbitMQ)

%%{init: {'theme':'dark'}}%%
flowchart LR
    subgraph Publishers["📤 Nhà Xuất Bản"]
        IAM[IAM Service]
        Social[Social Service]
        Mining1[Mining Service]
    end
    
    subgraph Events["📨 Sự Kiện"]
        E1[UserRegisteredEvent]
        E2[FriendAddedEvent]
        E3[PointsMinedEvent]
    end
    
    subgraph Consumers["📥 Người Tiêu Thụ"]
        Mining2[Mining Service]
        Wallet[Wallet Service]
    end
    
    IAM --> E1 --> Mining2
    Social --> E2 --> Mining2
    Mining1 --> E3 --> Wallet
    
    style Events fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px

Triển Khai

Docker Compose

mining-service:
  build:
    context: ../..
    dockerfile: services/mining-service-net/Dockerfile
  environment:
    - DATABASE_URL=${MINING_DATABASE_URL}
    - REDIS_URL=${REDIS_URL}
    - RABBITMQ_URL=${RABBITMQ_URL}
    - JWT_AUTHORITY=${IAM_SERVICE_URL}
  labels:
    - traefik.http.routers.mining.rule=PathPrefix(`/api/v1/mining`)

Health Checks

Endpoint Kiểm Tra
/health/live Service đang chạy
/health/ready DB + Redis đã kết nối
/health Trạng thái đầy đủ

Bảo Mật

Giới Hạn Tốc Độ

  • 1 phiên đào mỗi 24 giờ
  • 10 lời mời vòng tròn mỗi ngày

Chống Gian Lận

%%{init: {'theme':'dark'}}%%
flowchart TD
    Request([🚀 Yêu Cầu]) --> Device{🔍 Kiểm Tra Thiết Bị}
    Device -->|Thiết Bị Mới| Flag[⚠️ Đánh Dấu Xem Xét]
    Device -->|Đã Biết| IP{🌐 Kiểm Tra IP}
    IP -->|Đáng Ngờ| Block[❌ Chặn]
    IP -->|Bình Thường| KYC{🔐 Đã KYC?}
    KYC -->|Chưa| Limited[⚠️ Tính Năng Hạn Chế]
    KYC -->|Rồi| Full[✅ Truy Cập Đầy Đủ]
    
    style Request fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
    style Block fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
    style Full fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
    style Device fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
    style IP fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px
    style KYC fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px

Chiến Lược Cache (Redis)

Mẫu Key TTL Mục Đích
session:{minerId} 24h Cache phiên hoạt động
rate:{minerId} 1h Cache tỷ lệ đào
leaderboard:daily 5m Cache bảng xếp hạng

Giám Sát

Metrics

  • Số phiên đào bắt đầu/ngày
  • Tổng điểm đã đào
  • Số thợ đào hoạt động
  • Tỷ lệ chuyển đổi giới thiệu

Logging

  • Serilog structured logging
  • Correlation IDs để tracing
  • Tích hợp Prometheus + Grafana