Skip to main content

Backend code review — kioskgaming_backend

FieldValue
Repokioskgaming_backend
Review date2026-06-20
StackNode.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 docsFinance 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)

PatternMô tảRủi ro
MớiBootstrap → setRepositories / setDependencies trên service singletonTest được một phần
Legacyglobal.db = { ...models } + setModels(db) trên controllerBypass 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ữ

  1. Bootstrap composition root — tách database, repositories, services, routes, workers.
  2. Repository pattern — class nhận model qua constructor (src/bootstrap/repositories.js).
  3. Phân tầng service có ý địnhbiz orchestration, core entity, infra cross-cutting, payment gateway.
  4. Cashier modulesrc/modules/cashier-management/ có ports/adapters, core/biz/repo riêng → mẫu cho refactor domain khác.
  5. Architecture CI gatenpm run architecture:check so với baseline 417 vi phạm; không cho regression mới.
  6. Quy tắc dev trong repo.cursor/rules/ARCHITECTURE_AND_DEV_RULES.md.
  7. Worker tách khỏi request path — deposit/withdrawal timeout, queue consumers, stats report.
  8. Game provider adaptersgameProviderAdapters/ + thirdpartyapi/ tách integration.
  9. Migration discipline — 207 migrations; không dùng sequelize.sync() cho schema production.
  10. 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~LinesVấn đề
controllers/user/paymentUserController.js4.311Deposit/withdraw/webhook/player payment; 35+ import; transaction trong controller
controllers/admin/paymentAdminController.js3.272Approve/reject, fee config, cache in-memory + setInterval
controllers/user/authController.js1.285Auth/register/session
controllers/admin/gameWalletManagementController.js1.226Game 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:

RuleCount
controller-direct-db122
repository-conditional-logic267
service-or-biz-to-repository-import28
Total417

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~LinesVấn đề
services/core/depositSettlementCoreService.js1.635Core layer gọi wallet, game, gamify, fee — vượt boundary
services/infra/emailService.js~1.968Multi-provider email
services/infra/telegramService.js~1.695Notify hub
services/payment/zeroxProcessingWebhookService.js~902Webhook + settlement lẫn lộn
services/biz/creditTransactionsLedgerBizService.js~958Ledger + nhiều global.db

D. Duplicate / parallel implementations

Cặp trùngGhi chú
services/gameWalletSyncService.js vs services/infra/gameWalletSyncService.jsHai bản ~900 dòng
services/core/cashierCoreService.js vs modules/cashier-management/services/core/Cashier logic song song
routes/cashier.js + module routesHai entry cashier
Legacy src/services/balanceService.js, reconciliationService.jsNằ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ấtplayerServiceBiz.js vs *BizService.js
Controller export lẫn lộnClass vs module.exports = { fn }
Snake vs camel trong API/DBSequelize 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/false khô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-validator tậ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.js map Sequelize/JWT tốt
  • Nhiều controller catch trả JSON riêng, không next(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

  • bcryptbcryptjs cùng trong package.json; code thực tế chủ yếu bcryptjs (native bcrypt có 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)

#FileLinesDomain
1controllers/user/paymentUserController.js4.311Player payment
2controllers/admin/paymentAdminController.js3.272Admin payment
3services/infra/emailService.js~1.968Notify
4services/infra/telegramService.js~1.695Notify
5services/core/depositSettlementCoreService.js1.635Settlement
6controllers/user/authController.js~1.285Auth
7controllers/admin/gameWalletManagementController.js~1.226Game wallet
8services/biz/adminTransactionDetailBizService.js~1.003Detail aggregation
9services/biz/creditTransactionsLedgerBizService.js~958Credit ledger
10workers/pendingDepositTimeoutWorker.js~911Worker

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ô

MetricValue
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

AreaGap
Mega-controllerspaymentUserController / paymentAdminController — không test trực tiếp theo file
CDN controllersagent/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*
Integration13 file, maxWorkers: 1 — phù hợp DB serial nhưng mỏng so surface area

6.4 Khuyến nghị test strategy

  1. Không viết test 4k-line controller — extract biz service trước, test service.
  2. Mỗi “hot path” CDN (shop credit transfer, agent adjust) → ít nhất 1 biz service test.
  3. Giữ integration test cho money movement end-to-end (deposit → settlement → game wallet).
  4. Ratchet: PR mới touch payment phải có test cho logic mới.

7. Security

MứcVấn đềEvidence
P0Hardcoded DB password fallbackconnection.js: password: process.env.DB_PASSWORD || '@Linux121314' (lặp ở migrate/config)
P1global.db trong controllerKhó audit query; bypass repository
P1CORS có thể tắtDISABLE_CORS / CORS_DISABLED trong bootstrap
P2JWT secret fallback chainNhiều role dùng secret riêng (tốt) nhưng fallback JWT_SECRET nếu thiếu env
OKHelmet, rate limit, request signing HMAC, raw body capturebootstrap/app.js
OKLog redaction secretsBootstrap redact list
OKMulti-role auth middlewareuser/admin/agent/shop/superAgent/cashier
OKrejectUnknownBodyFields whitelistGiảm mass assignment
Notebcryptjs vs native bcryptbcryptjs 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

DomainTrạng thái kiến trúcTestGhi chú
Payment / withdrawalBiz services tăng nhưng controller vẫn khổng lồ✅ MạnhƯu tiên tách controller
Deposit settlementGod service depositSettlementCoreService⚠️ Một phầnTách step pipeline
USD walletInfra service tốt (usdWalletService); enrich display đang thêm⚠️ Unit infraOptimistic lock + idempotency OK
Credit / master walletwalletService, walletTransferService✅ KháReservation pattern tốt
Game wallet / syncDuplicate sync service⚠️Gộp một source
CDN hierarchyControllers dày + global.db❌ YếuCopy pattern agent/shop
CashierModule mới tốt; song song legacy routes❌ YếuMigrate dần sang module
Auth / portalMiddleware 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
WorkersTách file rõ⚠️Test worker logic riêng
Third-party APIAdapter per provider⚠️Empty catch cần audit

10. Top 10 khuyến nghị ưu tiên

#PriorityHành độngImpactEffort
1P0Tách paymentUserController + paymentAdminController thành biz services theo use-caseGiảm bug, enable testL (2–4 tuần incremental)
2P0Cấm global.db mới trong controller — ratchet baseline xuống122 vi phạm hiện tạiM
3P0Xóa hardcoded DB password — require envSecurityS
3bP0Database — xem Database code review (DB-1→DB-4)Data integrityM
4P1Chuẩn hóa response envelope (admin/portal/CDN → common helper)Client consistencyM
5P1Di chuyển sequelize.transaction từ controller → serviceData integrityM
6P1Gộp duplicate services (gameWalletSyncService, cashier core)MaintenanceM
7P1Mở ESLint + architecture check lên controllers/routes/workersEnforce layeringS
8P2Test pyramid CDN + cashier — biz test per hot pathRegression safetyM
9P2Hoàn thiện constructor DI — giảm setModels / global.dbTestabilityL
10P2Refactor depositSettlementCoreService — pipeline steps + inject depsPayment stabilityL

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.db trự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:check pass (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 + paymentAdminController each < 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 gameWalletSyncService source of truth
  • Response envelope documented per API surface (admin/user/portal)
  • Database health targets — xem Database code review §13

14. Changelog

DateAuthorNotes
2026-06-20Code reviewTạo doc — full backend review (không gắn task cụ thể)
2026-06-20Code reviewMở rộng §8 Database — schema, migration, partition, idempotency, khuyến nghị DB-1→DB-14
2026-06-20Code reviewTách database sang kioskgaming-backend-database-review