12 KiB
12 KiB
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