Backend code review — kioskgaming_backend
| Field | Value |
|---|---|
| Repo | kioskgaming_backend |
| Review date | 2026-06-20 |
| Stack | Node.js ≥18 · Express · Sequelize · PostgreSQL · Redis · RabbitMQ |
| Quy mô (ước lượng) | ~1.004 file JS trong src/ · ~162k dòng · 76 models · 207 migrations · 160 test files |
| Related docs | Finance System · Database code review · Architecture rules: kioskgaming_backend/.cursor/rules/ARCHITECTURE_AND_DEV_RULES.md (trong repo) |
1. Executive summary
Backend KioskGaming là monolith Express có chủ đích, đang chuyển đổi dần từ pattern legacy (controller dày + global.db) sang composition root + repository + biz/core/infra services. Domain payment được test kỹ và có nhiều worker bảo vệ timeout/retry; domain CDN hierarchy (agent/shop/super agent) và cashier module còn lệch chuẩn kiến trúc mới.
| Tiêu chí | Đánh giá |
|---|---|
| Nghiệp vụ tài chính (wallet, settlement, withdrawal) | ✅ Mạnh — logic phức tạp nhưng có test payment sâu |
| Kiến trúc mục tiêu (layering, DI) | ⚠️ Đang migrate — 417 vi phạm baseline, chưa siết xuống |
| Maintainability | ❌ Rủi ro cao — 2 mega-controller payment ~7.5k dòng |
| API consistency | ⚠️ Response envelope / validation không đồng nhất giữa actor |
| Security | ⚠️ Building blocks tốt; có fallback secret hardcoded |
| Test coverage | ⚠️ Payment tốt; CDN/cashier/controller mỏng |
Verdict: Codebase vận hành được và có hướng refactor rõ (src/bootstrap/, cashier module, architecture CI). Ưu tiên ngắn hạn: tách mega-controller payment, cấm global.db mới, xóa secret fallback, chuẩn hóa response + transaction boundary.
2. Cấu trúc thư mục & phân tầng
2.1 Bản đồ layer
src/
├── server.js # Entry, graceful shutdown
├── bootstrap/ # Composition root (database → repos → services → routes → workers)
├── controllers/ # HTTP theo actor: user, admin, shop, agent, superAgent, portal*, cashier*, payment
├── routes/ # Mount Express, middleware, validation (không đồng đều)
├── services/
│ ├── biz/ # Orchestration use-case
│ ├── core/ # Entity / aggregate ops (nên mỏng)
│ ├── infra/ # Wallet, email, telegram, fraud…
│ ├── payment/ # Gateway, webhook, withdrawal pipeline
│ ├── display/ # Presentation enrich (mới, mỏng)
│ ├── gameProviderAdapters/
│ └── queues/, ops/, outbound/
├── repositories/ # Sequelize access (45 file)
├── database/ # connection, models, migrations, migrate.js
├── middleware/ # Auth đa role, signing, CORS, error
├── workers/ # Timeout, queue consumers, stats report
├── modules/cashier-management/ # Bounded context tách (ports/adapters)
├── thirdpartyapi/ # Client game / payment bên ngoài
└── utils/, constants/
2.2 Luồng khởi động chuẩn
// src/bootstrap/index.js
async function buildAppWithRoutes() {
const db = await initDatabase();
const repos = createRepositories(db);
const services = initServices(db, repos);
const { app, authLimiter, portalAuthLimiter } = buildApp();
mountRoutes(app, authLimiter, db, repos, services, portalAuthLimiter);
return { app, db, repos };
}
Đây là hướng đi đúng: một composition root, inject dependency qua factory thay vì require vòng.
2.3 Hai “thế giới” song song (technical debt)
| Pattern | Mô tả | Rủi ro |
|---|---|---|
| Mới | Bootstrap → setRepositories / setDependencies trên service singleton | Test được một phần |
| Legacy | global.db = { ...models } + setModels(db) trên controller | Bypass repository, khó mock, 122 vi phạm controller-direct-db |
Hệ thống không thống nhất — code mới và cũ cùng tồn tại; reviewer dễ nhầm convention khi thêm feature.
3. Architecture patterns
3.1 Điểm mạnh nên giữ
- Bootstrap composition root — tách
database,repositories,services,routes,workers. - Repository pattern — class nhận model qua constructor (
src/bootstrap/repositories.js). - Phân tầng service có ý định —
bizorchestration,coreentity,infracross-cutting,paymentgateway. - Cashier module —
src/modules/cashier-management/có ports/adapters, core/biz/repo riêng → mẫu cho refactor domain khác. - Architecture CI gate —
npm run architecture:checkso với baseline 417 vi phạm; không cho regression mới. - Quy tắc dev trong repo —
.cursor/rules/ARCHITECTURE_AND_DEV_RULES.md. - Worker tách khỏi request path — deposit/withdrawal timeout, queue consumers, stats report.
- Game provider adapters —
gameProviderAdapters/+thirdpartyapi/tách integration. - Migration discipline — 207 migrations; không dùng
sequelize.sync()cho schema production. - Security primitives — Helmet, rate limit, HMAC request signing, role-based JWT secrets, log redaction.
3.2 Anti-patterns hệ thống
A. Fat controller (HTTP layer chứa nghiệp vụ)
| File | ~Lines | Vấn đề |
|---|---|---|
controllers/user/paymentUserController.js | 4.311 | Deposit/withdraw/webhook/player payment; 35+ import; transaction trong controller |
controllers/admin/paymentAdminController.js | 3.272 | Approve/reject, fee config, cache in-memory + setInterval |
controllers/user/authController.js | 1.285 | Auth/register/session |
controllers/admin/gameWalletManagementController.js | 1.226 | Game wallet admin |
Hệ quả: Khó test, khó review PR, bug fix dễ regression chéo use-case.
B. global.db / bypass repository
Baseline architecture-violation-baseline.json:
| Rule | Count |
|---|---|
controller-direct-db | 122 |
repository-conditional-logic | 267 |
service-or-biz-to-repository-import | 28 |
| Total | 417 |
Ví dụ: modules/cashier-management/controllers/shop/cashierController.js, controllers/agent/agentShopController.js (nhiều query trực tiếp global.db.Shop).
C. God service / cross-layer imports
| File | ~Lines | Vấn đề |
|---|---|---|
services/core/depositSettlementCoreService.js | 1.635 | Core layer gọi wallet, game, gamify, fee — vượt boundary |
services/infra/emailService.js | ~1.968 | Multi-provider email |
services/infra/telegramService.js | ~1.695 | Notify hub |
services/payment/zeroxProcessingWebhookService.js | ~902 | Webhook + settlement lẫn lộn |
services/biz/creditTransactionsLedgerBizService.js | ~958 | Ledger + nhiều global.db |
D. Duplicate / parallel implementations
| Cặp trùng | Ghi chú |
|---|---|
services/gameWalletSyncService.js vs services/infra/gameWalletSyncService.js | Hai bản ~900 dòng |
services/core/cashierCoreService.js vs modules/cashier-management/services/core/ | Cashier logic song song |
routes/cashier.js + module routes | Hai entry cashier |
Legacy src/services/balanceService.js, reconciliationService.js | Nằm ngoài biz/core/infra chuẩn |
E. Service singleton + setter injection
Hầu hết export module.exports = new X() + setRepositories() / setDependencies() thay vì constructor DI thuần. Chấp nhận được trong migration, nhưng khó unit test khi quên gọi setter trước khi chạy.
4. Code quality
4.1 Naming & conventions
| Vấn đề | Ví dụ |
|---|---|
| Tên service không đồng nhất | playerServiceBiz.js vs *BizService.js |
| Controller export lẫn lộn | Class vs module.exports = { fn } |
| Snake vs camel trong API/DB | Sequelize field mapping OK; DTO đôi khi lẫn created_at / createdAt |
4.2 Response envelope không thống nhất
- User API:
COMMON_SUCCESS/COMMON_ERRORS(utils/httpStatus.js) - Admin/portal:
{ success: false, message }ad-hoc - Một số controller: hàng chục literal
success: true/falsekhông qua helper
Khắc phục: Một envelope chuẩn per actor (hoặc một envelope toàn hệ thống) + middleware format response.
4.3 Validation không đồng đều
- Payment routes có
express-validatortập trung (routes/payment/validations.js) - Nhiều route CDN/portal/admin không có validator tương đương
- Chỉ ~7 controller file dùng
validationResult
4.4 Error handling
- Global
middleware/errorHandler.jsmap Sequelize/JWT tốt - Nhiều controller
catchtrả JSON riêng, khôngnext(err)→ bypass centralized logging/mapping - Một số adapter: empty
catch(vd. game provider adapters) — nuốt lỗi
4.5 Transaction boundary
sequelize.transaction xuất hiện trong controller (payment, game wallet, USD wallet reject) thay vì biz service.
Quy tắc nên áp dụng: Controller chỉ parse input + gọi service; mọi transaction nằm trong service (một use-case = một transaction scope).
4.6 Lint & CI scope hẹp
// package.json — lint chỉ services biz/core/infra + architecture scripts
"lint": "eslint \"scripts/architecture/**/*.js\" \"src/services/biz/**/*.js\" ..."
Controllers, routes, workers, modules không nằm trong ESLint scope → style/bug pattern không bị gate.
4.7 Dependencies
bcryptvàbcryptjscùng trongpackage.json; code thực tế chủ yếubcryptjs(nativebcryptcó thể dead weight)- Package
crypto(^1.0.1) — Node built-in, dependency npm không cần thiết
5. File phức tạp nhất (hotspots)
| # | File | Lines | Domain |
|---|---|---|---|
| 1 | controllers/user/paymentUserController.js | 4.311 | Player payment |
| 2 | controllers/admin/paymentAdminController.js | 3.272 | Admin payment |
| 3 | services/infra/emailService.js | ~1.968 | Notify |
| 4 | services/infra/telegramService.js | ~1.695 | Notify |
| 5 | services/core/depositSettlementCoreService.js | 1.635 | Settlement |
| 6 | controllers/user/authController.js | ~1.285 | Auth |
| 7 | controllers/admin/gameWalletManagementController.js | ~1.226 | Game wallet |
| 8 | services/biz/adminTransactionDetailBizService.js | ~1.003 | Detail aggregation |
| 9 | services/biz/creditTransactionsLedgerBizService.js | ~958 | Credit ledger |
| 10 | workers/pendingDepositTimeoutWorker.js | ~911 | Worker |
Refactor nên cắt theo vertical slice (deposit, withdrawal, webhook, admin approve…) chứ không “đọc hết file rồi tách”.
6. Testing
6.1 Thống kê thô
| Metric | Value |
|---|---|
| Test files | ~160 (136 unit, 13 integration) |
Production JS files in src/ | ~1.004 |
| Tỷ lệ file có test (thô) | ~16% |
6.2 Được test tốt
- Payment: withdrawal approve/reject, webhooks (ZeroX, Meld, BTCPay), deposit guard, fee math
- Wallet: balance/debit, balance conversion, reservation
- Auth/security: portal 2FA, request signing integration test
- Biz mới:
portalLedgerDetailBizService,financeCorrectionBizService, hierarchy withdrawal
6.3 Yếu / thiếu
| Area | Gap |
|---|---|
| Mega-controllers | paymentUserController / paymentAdminController — không test trực tiếp theo file |
| CDN controllers | agent/shop/superAgent — hầu như không unit test |
| Cashier module | ~66 file module, ~2 test file |
| Controllers nói chung | ~114 controllers, ~15 file test tên *Controller* |
| Integration | 13 file, maxWorkers: 1 — phù hợp DB serial nhưng mỏng so surface area |
6.4 Khuyến nghị test strategy
- Không viết test 4k-line controller — extract biz service trước, test service.
- Mỗi “hot path” CDN (shop credit transfer, agent adjust) → ít nhất 1 biz service test.
- Giữ integration test cho money movement end-to-end (deposit → settlement → game wallet).
- Ratchet: PR mới touch payment phải có test cho logic mới.
7. Security
| Mức | Vấn đề | Evidence |
|---|---|---|
| P0 | Hardcoded DB password fallback | connection.js: password: process.env.DB_PASSWORD || '@Linux121314' (lặp ở migrate/config) |
| P1 | global.db trong controller | Khó audit query; bypass repository |
| P1 | CORS có thể tắt | DISABLE_CORS / CORS_DISABLED trong bootstrap |
| P2 | JWT secret fallback chain | Nhiều role dùng secret riêng (tốt) nhưng fallback JWT_SECRET nếu thiếu env |
| OK | Helmet, rate limit, request signing HMAC, raw body capture | bootstrap/app.js |
| OK | Log redaction secrets | Bootstrap redact list |
| OK | Multi-role auth middleware | user/admin/agent/shop/superAgent/cashier |
| OK | rejectUnknownBodyFields whitelist | Giảm mass assignment |
| Note | bcryptjs vs native bcrypt | bcryptjs chậm hơn; cân nhắc thống nhất native cho production |
P0 action: Fail fast nếu thiếu DB_PASSWORD ở mọi environment non-local; xóa fallback string khỏi repo.
8. Database
Đánh giá chi tiết PostgreSQL/Sequelize (schema, migrations, partitioning, idempotency, integrity) nằm ở doc riêng:
→ Database code review — kioskgaming_backend
Tóm tắt nhanh:
| Tiêu chí | Đánh giá |
|---|---|
| Schema & ledger design | ✅ Mạnh |
| Migration-first + partitioning | ✅ Tốt |
| Config / secrets / model drift | ❌ Cần siết (P0) |
| JSONB + DECIMAL consistency | ⚠️ Cần governance |
Ưu tiên P0: gỡ password fallback, đăng ký orphan models, verify unique wallet_transactions, automate partition N+1. Chi tiết DB-1 → DB-14 trong doc database.
9. Domain-by-domain snapshot
| Domain | Trạng thái kiến trúc | Test | Ghi chú |
|---|---|---|---|
| Payment / withdrawal | Biz services tăng nhưng controller vẫn khổng lồ | ✅ Mạnh | Ưu tiên tách controller |
| Deposit settlement | God service depositSettlementCoreService | ⚠️ Một phần | Tách step pipeline |
| USD wallet | Infra service tốt (usdWalletService); enrich display đang thêm | ⚠️ Unit infra | Optimistic lock + idempotency OK |
| Credit / master wallet | walletService, walletTransferService | ✅ Khá | Reservation pattern tốt |
| Game wallet / sync | Duplicate sync service | ⚠️ | Gộp một source |
| CDN hierarchy | Controllers dày + global.db | ❌ Yếu | Copy pattern agent/shop |
| Cashier | Module mới tốt; song song legacy routes | ❌ Yếu | Migrate dần sang module |
| Auth / portal | Middleware tốt; controller response lệch | ⚠️ | Chuẩn hóa envelope |
| Notify (email/telegram/bell) | Infra lớn, nhiều copy | ⚠️ | Tách template + i18n sau |
| Workers | Tách file rõ | ⚠️ | Test worker logic riêng |
| Third-party API | Adapter per provider | ⚠️ | Empty catch cần audit |
10. Top 10 khuyến nghị ưu tiên
| # | Priority | Hành động | Impact | Effort |
|---|---|---|---|---|
| 1 | P0 | Tách paymentUserController + paymentAdminController thành biz services theo use-case | Giảm bug, enable test | L (2–4 tuần incremental) |
| 2 | P0 | Cấm global.db mới trong controller — ratchet baseline xuống | 122 vi phạm hiện tại | M |
| 3 | P0 | Xóa hardcoded DB password — require env | Security | S |
| 3b | P0 | Database — xem Database code review (DB-1→DB-4) | Data integrity | M |
| 4 | P1 | Chuẩn hóa response envelope (admin/portal/CDN → common helper) | Client consistency | M |
| 5 | P1 | Di chuyển sequelize.transaction từ controller → service | Data integrity | M |
| 6 | P1 | Gộp duplicate services (gameWalletSyncService, cashier core) | Maintenance | M |
| 7 | P1 | Mở ESLint + architecture check lên controllers/routes/workers | Enforce layering | S |
| 8 | P2 | Test pyramid CDN + cashier — biz test per hot path | Regression safety | M |
| 9 | P2 | Hoàn thiện constructor DI — giảm setModels / global.db | Testability | L |
| 10 | P2 | Refactor depositSettlementCoreService — pipeline steps + inject deps | Payment stability | L |
Size: S ≈ 0.5–1 ngày · M ≈ 2–5 ngày · L ≈ 1–4 tuần (incremental PR).
11. Lộ trình refactor đề xuất
Phase 0 — Safety (1 sprint)
- P0 security (DB password)
- P0 database — xem Database code review
- Document transaction boundary rule + dual-wallet invariant
- Không tăng architecture baseline
Phase 1 — Payment vertical slice (2–3 sprint)
- Extract từ
paymentUserController: deposit, withdrawal request, webhook handlers →*BizService - Extract từ
paymentAdminController: approve, reject, refund → existing + new biz services - Test theo service mới; controller còn <300 LOC/file
Phase 2 — Layering ratchet (ongoing)
- Migrate CDN controllers off
global.db(1 controller / PR) - Gộp duplicate sync/cashier services
- Mở lint scope
Phase 3 — Platform consistency
- Unified response + validation middleware per route group
- Constructor DI factory từ bootstrap
- Settlement pipeline refactor
Template kiến trúc: src/modules/cashier-management/ — ports, adapters, biz/core/repo tách, self-bootstrap.
12. Checklist PR reviewer (backend)
- Controller không import Sequelize model /
global.dbtrực tiếp - Transaction nằm trong biz service, không trong controller
- Response qua helper chuẩn của actor (không literal
success:rải rác) - Input validation (express-validator hoặc schema) cho route mới
- Idempotency key cho money movement
- Unit test cho logic mới (biz layer)
-
npm run architecture:checkpass (không tăng baseline) - Không thêm secret fallback hardcoded
- Migration / model / partition — xem checklist trong Database code review
13. Definition of Done — health target (6 tháng)
-
paymentUserController+paymentAdminControllereach < 500 LOC (delegate to biz) - Architecture baseline < 200 violations (từ 417)
- Zero hardcoded credentials in repo
- ESLint covers controllers + routes
- CDN hot paths có biz unit test
- Single
gameWalletSyncServicesource of truth - Response envelope documented per API surface (admin/user/portal)
- Database health targets — xem Database code review §13
14. Changelog
| Date | Author | Notes |
|---|---|---|
| 2026-06-20 | Code review | Tạo doc — full backend review (không gắn task cụ thể) |
| 2026-06-20 | Code review | Mở rộng §8 Database — schema, migration, partition, idempotency, khuyến nghị DB-1→DB-14 |
| 2026-06-20 | Code review | Tách database sang kioskgaming-backend-database-review |