Kien truc Core
1. Tong quan
@nx/core trien khai kien truc phan lop duoc xay dung tren nen IGNIS Framework. Moi microservice backend trong monorepo BANA deu mo rong DefaultApplication tu goi nay, ke thua mot tap hop nhat quan cac moi quan tam co so ha tang: xac thuc, CORS, kiem tra suc khoe, tai lieu Swagger, ket noi co so du lieu, va giao tiep lien dich vu.
Tai lieu nay bao gom:
- Kien truc phan lop va cach cac primitive IGNIS anh xa toi tung lop
- Vong doi ung dung va lop
DefaultApplication - Cac mau dependency injection
- Cac mau component, controller, repository, va service
- Kien truc huong su kien (Redis Pub/Sub + hang doi BullMQ)
- Bootstrap helper cho diem truy cap ung dung va migration
- Giao tiep lien dich vu thong qua
IdentityNetworkService - Luong xac thuc (JWT + Basic)
- Chuoi phu thuoc goi
2. Kien truc Phan lop
Tat ca dich vu backend deu tuan theo kien truc nam lop. Moi lop co mot trach nhiem duy nhat va chi giao tiep voi cac lop lan can truc tiep.
| Lop | Thanh phan | Mo ta |
|---|---|---|
| Application | DefaultApplication | Vong doi preConfigure() · CORS · BodyLimit 100 MB · Swagger Scalar |
| Bootstrap Helpers | bootstrapApplication() · bootstrapMigration() · createAppConfig() · createMigrationProcessLoader() | |
| Built-in Components | HealthCheck GET /health · Swagger Scalar /explorer · Xac thuc JWT stateless · Basic → Identity | |
| Package Components | Signal · Payment · Commerce · Finance · Inventory · Search · Asset | |
| Service | Business Services | Logic nghiep vu · Validation · Dieu phoi |
| IdentityNetworkService | signIn() HTTP → Identity service · Uy quyen xac thuc Basic lien dich vu | |
| Event Handlers | Redis Pub/Sub — Kenh Payment · Onboarding · IEventBus · RedisPubSubAdapter | |
| Queue Consumers | BullMQ — 4 he thong · 8 loai · 3 phan vung · Commerce · Finance · Inventory · Sale | |
| BaseSocketEventService | broadcast() · sendToRoom() · sendToClient() · Phan phoi lien instance qua Redis | |
| Repository | SoftDeletableRepository | Xoa mem · Khoi phuc · Bo loc mac dinh deletedAt IS NULL tu dong ap dung |
| DefaultCRUDRepository | find · create · updateById · deleteById · count · withTransaction | |
| Infrastructure | PostgresCoreDataSource | Drizzle ORM · node-postgres Pool · 7 schema · 55 model |
| RedisConnectionFactory | Cache · Pub/Sub · WebSocket · Che do Single · Che do Cluster | |
| BullMQ | Scheduler · Confirmation · Processing · 12 hang doi voi dinh tuyen phan vung hash |
| Lop | Lop Co so IGNIS | Trach nhiem |
|---|---|---|
| Application | BaseApplication | Quan ly vong doi, thiet lap middleware, goc DI container |
| Component | BaseComponent | Dang ky module tinh nang (repository, service, controller) |
| Service | BaseService | Logic nghiep vu, dieu phoi giao dich, giao tiep ben ngoai |
| Repository | DefaultCRUDRepository | Truu tuong truy cap du lieu, thao tac CRUD, xoa mem |
| DataSource | BaseDataSource | Cau hinh driver co so du lieu, quan ly connection pool |
3. Vong doi Ung dung
3.1 DefaultApplication
Moi dich vu backend deu mo rong DefaultApplication, lop nay lai mo rong IGNIS BaseApplication. No cung cap luong khoi tao co cau truc thong qua phuong thuc vong doi preConfigure().
export class DefaultApplication extends BaseApplication {
protected applicationRoles: string[] = [];
preConfigure() {
this.applicationRoles = this.getApplicationRoles();
this.configureDatasources();
this.configureRepositories();
this.configureServices();
this.configureComponents();
this.configureSecurity();
this.configureControllers();
}
async postConfigure() {
// Runs after all components are bound
}
}3.2 Trinh tu Vong doi
So do sau day cho thay toan bo trinh tu khoi dong, tu diem truy cap (index.ts) toi server HTTP dang chay.
3.3 Thu tu Phuong thuc preConfigure()
Thu tu goi phuong thuc ben trong preConfigure() la quan trong. Moi buoc phu thuoc vao buoc truoc da hoan thanh.
| Thu tu | Phuong thuc | Chuc nang |
|---|---|---|
| 1 | configureDatasources() | Dang ky pool ket noi PostgreSQL (mac dinh khong lam gi, datasource tu dong phat hien tu glob) |
| 2 | configureRepositories() | Dang ky cac lop repository vao DI container (mac dinh khong lam gi, repository tu dong phat hien tu glob) |
| 3 | configureServices() | Dang ky IdentityNetworkService cho xac thuc lien dich vu |
| 4 | configureComponents() | Bind HealthCheckComponent tai /health va SwaggerComponent tai /doc |
| 5 | configureSecurity() | Cau hinh chien luoc xac thuc JWT va Basic thong qua AuthenticateComponent |
| 6 | configureControllers() | Dang ky HTTP controller (mac dinh khong lam gi, duoc ghi de theo tung goi) |
3.4 Thiet lap Middleware
setupMiddlewares() cau hinh hai middleware Hono toan cuc:
| Middleware | Cau hinh |
|---|---|
| CORS | Origin: *, tat ca phuong thuc, 86400s max-age, credentials duoc bat |
| Body Limit | Toi da 100 MB, tra ve 413 Content Too Large khi vuot qua |
3.5 Ghi de trong Cac Goi Downstream
Moi dich vu backend tao lop Application rieng mo rong DefaultApplication va ghi de cac phuong thuc configure tuong ung:
// packages/sale/src/application.ts
export class Application extends DefaultApplication {
override preConfigure(): void {
this.configureServices();
this.configureComponents();
this.configureSecurity();
}
override configureComponents(): void {
super.configureComponents(); // HealthCheck + Swagger
this.component(ApplicationSaleComponent);
}
override async postConfigure(): Promise<void> {
// Package-specific post-boot logic
}
}4. Dependency Injection
DI container cua IGNIS su dung constructor injection voi decorator @inject(). Cac phu thuoc duoc xac dinh bang khoa binding dua tren chuoi.
4.1 Mau Injection
import { inject, BaseService } from '@venizia/ignis';
export class SaleOrderService extends BaseService {
constructor(
@inject({ key: 'repositories.SaleOrderRepository' })
private saleOrderRepository: SaleOrderRepository,
@inject({ key: 'repositories.SaleOrderItemRepository' })
private saleOrderItemRepository: SaleOrderItemRepository,
) {
super({ scope: SaleOrderService.name });
}
}4.2 Quy uoc Khoa Binding
Khoa binding tuan theo mau {namespace}.{ClassName}:
| Namespace | Khoa Vi du | Dang ky Thong qua |
|---|---|---|
repositories | repositories.SaleOrderRepository | this.application.repository(SaleOrderRepository) |
services | services.IdentityNetworkService | this.application.service(IdentityNetworkService) |
controllers | controllers.SaleOrderController | this.application.controller(SaleOrderController) |
datasources | datasources.PostgresCoreDataSource | this.application.datasource(PostgresCoreDataSource) |
Ban cung co the xay dung khoa tuong minh su dung tien ich BindingKeys cua IGNIS:
import { BindingKeys, BindingNamespaces } from '@venizia/ignis';
const key = BindingKeys.build({
namespace: BindingNamespaces.REPOSITORY,
key: 'SaleOrderRepository',
});
// Result: 'repositories.SaleOrderRepository'4.3 Value Binding
Doi voi cac doi tuong cau hinh, su dung mau bind().toValue():
this.bind<IHealthCheckOptions>({
key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,
}).toValue({
restOptions: { path: '/health' },
});5. Mau Component
Component la co che chinh de to chuc cac module tinh nang. Moi component mo rong BaseComponent va dang ky cac repository, service, va controller trong phuong thuc vong doi binding().
export class ApplicationSaleComponent extends BaseComponent {
constructor(
@inject({ key: CoreBindings.APPLICATION_INSTANCE })
protected application: BaseApplication,
) {
super({
scope: ApplicationSaleComponent.name,
initDefault: { enable: true, container: application },
bindings: {},
});
}
override async binding(): Promise<void> {
this.application.repository(SaleOrderRepository);
this.application.repository(SaleOrderItemRepository);
this.application.service(SaleOrderService);
this.application.service(CheckoutService);
this.application.controller(SaleOrderController);
}
}Component duoc dang ky vao ung dung thong qua:
this.component(ApplicationSaleComponent);5.1 To hop Component
Component co the tai cac component khac, tao cay to hop:
6. Mau Controller
6.1 ControllerFactory (CRUD Tu dong)
IGNIS ControllerFactory tao ra day du cac endpoint CRUD tu mot khai bao duy nhat. Day la mau chuan cho hau het cac controller trong BANA.
import { controller, inject, ControllerFactory } from '@venizia/ignis';
@controller({ path: '/sale-orders' })
export class SaleOrderController extends ControllerFactory.defineCrudController({
repository: { name: SaleOrderRepository.name },
authenticate: { strategies: ['jwt', 'basic'] },
controller: { name: 'SaleOrderController', basePath: '/sale-orders' },
entity: () => SaleOrderEntity,
}) {
constructor(
@inject({ key: 'repositories.SaleOrderRepository' })
repository: SaleOrderRepository,
) {
super(repository);
}
}Factory tao ra cac endpoint sau:
| Phuong thuc | Duong dan | Mo ta |
|---|---|---|
GET | /sale-orders | Danh sach voi bo loc, phan trang, sap xep |
GET | /sale-orders/:id | Tim theo ID |
GET | /sale-orders/count | Dem theo bo loc |
POST | /sale-orders | Tao moi |
PUT | /sale-orders/:id | Cap nhat theo ID |
DELETE | /sale-orders/:id | Xoa theo ID (xoa mem) |
6.2 Endpoint Controller Tuy chinh
Cac endpoint bo sung duoc dinh nghia cung voi cac endpoint do factory tao bang cach them phuong thuc vao lop controller. He thong Bo loc cua IGNIS co san tren tat ca endpoint list/count.
7. Repository va SoftDeletableRepository
7.1 Khai bao Repository
Repository duoc khai bao voi decorator @repository, lien ket model voi datasource:
import { repository } from '@venizia/ignis';
import { PostgresCoreDataSource } from '@nx/core';
@repository({ dataSource: PostgresCoreDataSource, model: SaleOrderEntity })
export class SaleOrderRepository extends SoftDeletableRepository<
TSaleOrderSchema,
TSaleOrder,
TSaleOrderPersist
> {}7.2 SoftDeletableRepository
Tat ca repository BANA deu mo rong SoftDeletableRepository thay vi DefaultCRUDRepository. Dieu nay dam bao rang cac thao tac DELETE dat dau thoi gian deletedAt thay vi xoa vat ly cac dong.
| Phuong thuc | Hanh vi |
|---|---|
deleteById(id) | Dat deletedAt = NOW() thay vi DELETE FROM |
restoreById(id) | Dat deletedAt = NULL de khoi phuc xoa mem |
find(filter) | Tu dong loai tru cac dong co deletedAt IS NOT NULL |
7.3 Giao dich Co so Du lieu
Repository cung cap datasource de ho tro giao dich:
await this.repository.dataSource.withTransaction(async (tx) => {
await this.saleOrderRepository.create({ data: orderData, options: { transaction: tx } });
await this.saleOrderItemRepository.create({ data: itemData, options: { transaction: tx } });
});7.4 PostgresCoreDataSource
Datasource dung chung su dung node-postgres voi Drizzle ORM. No tu dong phat hien model tu cac binding @repository thong qua getSchema():
@datasource({ driver: 'node-postgres' })
export class PostgresCoreDataSource extends BaseDataSource<IPostgresDataSourceSettings> {
override configure(): void {
const schema = this.getSchema(); // Auto-discovers @repository models
this.pool = new Pool(this.settings);
this.connector = drizzle({ client: this.pool, schema });
}
}Tat ca goi backend deu re-export PostgresCoreDataSource tu datasources/index.ts cuc bo, de repository luon tham chieu toi cung datasource dung chung.
8. Kien truc Huong Su kien
BANA su dung hai he thong su kien bo sung cho giao tiep bat dong bo giua cac dich vu:
| Co che | Cong nghe | Truong hop Su dung | Phan phoi |
|---|---|---|---|
| Event Bus | Redis Pub/Sub | Thong bao thoi gian thuc giua cac dich vu dang chay | At-most-once, fire-and-forget |
| Hang doi Cong viec | BullMQ (Redis) | Xu ly tac vu bat dong bo dang tin cay voi thu lai | At-least-once, voi thu lai va luu tru |
8.1 So do Luong Su kien
8.2 Event Bus (Redis Pub/Sub)
RedisPubSubAdapter trien khai giao dien IEventBus duoc dinh nghia trong @nx/core. No bao boc thong diep trong phong bi chuan hoa:
interface IEventBusMessage<T> {
id: string; // Snowflake ID
type: string; // Channel name
publishedAt: string; // ISO timestamp
data: T; // Event payload
}Kenh Su kien duoc dinh nghia trong @nx/core:
| Kenh | Nha phat hanh | Nguoi tieu thu | Kich hoat |
|---|---|---|---|
payment.order.success | Sale Service | Finance, Inventory | Thanh toan hoan tat |
user.seller.registered | Identity Service | Commerce Service | Dang ky nguoi ban |
commerce.initialized | Commerce Service | Finance, Inventory | Hoan tat onboarding merchant |
8.3 Hang doi Cong viec (BullMQ)
Moi mien hang doi su dung 3 phan vung (P01, P02, P03) de phan phoi tai. Bo chon phan vung dua tren hash dinh tuyen cong viec toi phan vung cu the dua tren khoa (thuong la ID thuc the).
Dinh nghia Hang doi trong @nx/core:
| Mien Hang doi | Loai Hang doi | Nha san xuat | Nguoi tieu thu |
|---|---|---|---|
| Commerce | seller-registered | Identity | Commerce |
| Commerce | commerce-initialized-for-finance | Commerce | Finance |
| Commerce | commerce-initialized-for-inventory | Commerce | Inventory |
| Finance | purchase-order-received | Inventory | Finance |
| Finance | sale-order-completed | Sale | Finance |
| Sale | payment-success-for-finance | Sale | Finance |
| Sale | payment-success-for-inventory | Sale | Inventory |
| Inventory | product_variant_created | Commerce | Inventory |
Quy uoc dat ten hang doi theo mau: @nx/{package}/{queue-type}/{partition}
Vi du: @nx/sale/payment-success-for-finance/01
8.4 Su kien WebSocket
@nx/core cung cap cac lop tien ich de xay dung dinh danh phong va chu de WebSocket, duoc su dung boi dich vu Signal:
| Tien ich | Dinh dang | Vi du |
|---|---|---|
WebSocketRooms.build() | wr:{prefix}/{paths} | wr:observation/merchants/abc-123 |
WebSocketTopics.build() | ws:{paths joined by .} | ws:observation.sale.sale-order |
9. Bootstrap Helper
@nx/core cung cap hai ham bootstrap chuan hoa diem truy cap tren tat ca cac goi. Xem tham chieu Bootstrapping cua IGNIS cho cac khai niem framework co so.
9.1 Bootstrap Ung dung
Duoc su dung trong src/index.ts cua moi goi de khoi dong HTTP server:
// packages/sale/src/index.ts
import { bootstrapApplication } from '@nx/core';
import { Application } from './application';
import { appConfig } from './common/app-config';
import { resolve } from 'node:path';
bootstrapApplication({
ApplicationClass: Application,
config: appConfig,
options: { bannerPath: resolve(__dirname, '../resources/banner.txt') },
});Trinh tu bootstrap la: new Application() --> init() --> boot() --> start().
9.2 Bootstrap Migration
Duoc su dung trong src/migrate.ts cua moi goi de chay seed va migration co so du lieu:
// packages/sale/src/migrate.ts
import { bootstrapMigration } from '@nx/core';
import { Application } from './application';
import { getMigrationProcesses } from './migrations/processes/migration-process';
bootstrapMigration({
ApplicationClass: Application,
getMigrationProcesses,
});9.3 createMigrationProcessLoader
Ham factory tao trinh lay quy trinh migration tu danh sach duong dan file seed:
// packages/sale/src/migrations/processes/migration-process.ts
import { createMigrationProcessLoader } from '@nx/core';
export const getMigrationProcesses = createMigrationProcessLoader({
seedPaths: [
'sale-0001-seed-initial-data',
'sale-0002-seed-tracking-types',
],
importFn: (path) => import(`../processes/${path}.js`),
});Moi quy trinh migration la mot doi tuong voi name, migrateFn, va cleanFn tuy chon. Lop MigrationHelper theo doi trang thai thuc thi trong co so du lieu de ngan chay trung lap.
9.4 createAppConfig
Tap trung cau hinh ung dung de moi goi su dung cung cau truc:
// packages/sale/src/common/app-config.ts
import { createAppConfig } from '@nx/core';
export const appConfig = createAppConfig();Ham nay doc tu bien moi truong va tra ve doi tuong IApplicationConfigs voi host, port, base path, cai dat debug, va boot option (mau glob de tu dong phat hien datasource va repository tu @nx/core).
10. Giao tiep Lien Dich vu
10.1 IdentityNetworkService
Client mang lien dich vu duy nhat trong he thong. No mo rong AxiosNetworkRequest tu @venizia/ignis-helpers/axios va giao tiep voi dich vu Identity de xac minh thong tin dang nhap.
export class IdentityNetworkService extends AxiosNetworkRequest {
constructor() {
super({
name: IdentityNetworkService.name,
networkOptions: {
baseUrl: applicationEnvironment.get<string>(
EnvironmentKeys.APP_ENV_IDENTITY_SERVICE_BASE_URL,
),
},
});
}
async signIn(opts: {
identifier: { scheme: string; value: string };
credential: { scheme: string; value: string };
}) {
const networkService = this.getNetworkService();
const response = await networkService.post({
url: '/auth/sign-in',
body: opts,
});
return response.data;
}
}Dich vu nay duoc dang ky mac dinh trong DefaultApplication.configureServices(), giup no co san cho tat ca goi downstream de xac minh thong tin dang nhap Basic auth.
10.2 Topology Giao tiep
Khong co API gateway. Moi dich vu tu xu ly xac thuc cua rieng minh va cung cap HTTP API truc tiep. Cuoc goi HTTP lien dich vu duy nhat la de xac minh thong tin dang nhap Basic auth.
Tat ca giao tiep lien dich vu khac deu thong qua su kien Redis Pub/Sub hoac hang doi BullMQ (xem Phan 8).
11. Luong Xac thuc
DefaultApplication.configureSecurity() thiet lap IGNIS AuthenticateComponent voi hai chien luoc.
11.1 Chien luoc JWT
Xac thuc dua tren token khong trang thai. Dich vu xac thuc token cuc bo ma khong can lien he dich vu khac.
| Bien Moi truong | Muc dich |
|---|---|
APP_ENV_APPLICATION_SECRET | Secret cap ung dung |
APP_ENV_JWT_SECRET | Secret ky JWT |
APP_ENV_JWT_EXPIRES_IN | Thoi gian het han token tinh bang giay |
11.2 Chien luoc Basic
Uy quyen xac minh thong tin dang nhap cho dich vu Identity thong qua IdentityNetworkService.signIn():
11.3 Dang ky Chien luoc
Ca hai chien luoc deu duoc dang ky trong singleton AuthenticationStrategyRegistry:
AuthenticationStrategyRegistry.getInstance().register({
container: this,
strategies: [
{ name: Authentication.STRATEGY_JWT, strategy: JWTAuthenticationStrategy },
{ name: Authentication.STRATEGY_BASIC, strategy: BasicAuthenticationStrategy },
],
});Controller chi dinh chien luoc nao duoc su dung trong cau hinh authenticate:
authenticate: { strategies: ['jwt', 'basic'] }12. Tien ich Dung chung
@nx/core cung cap mot so tien ich singleton duoc su dung tren tat ca cac goi.
| Tien ich | Muc dich |
|---|---|
IdGenerator | Singleton tao ID Snowflake (bao boc IGNIS SnowflakeUidHelper) |
CryptoUtility | Ma hoa AES-256-GCM va ky HMAC su dung APP_ENV_APPLICATION_SECRET |
useRequestContext() | Trich xuat nguoi dung da xac thuc, vai tro, va cung cap helper dinh dang phan hoi |
@logged decorator | Ghi log do luong hieu suat cap phuong thuc |
RedisConnectionFactory | Tao ket noi Redis che do single hoac cluster |
12.1 IdGenerator
import { IdGenerator } from '@nx/core';
const id = IdGenerator.getInstance().nextId();
// Returns: '7193487234817024' (Snowflake ID string)Cau hinh thong qua bien moi truong:
APP_ENV_SNOWFLAKE_WORKER_ID(0-1023, duy nhat cho moi instance dich vu)APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT(epoch tuy chinh tinh bang mili giay)
12.2 useRequestContext()
Wrapper xung quanh useRequestContext cua IGNIS bo sung cac truong dac thu BANA:
const {
context, // Hono request context
currentUser, // JWT payload with userId, roles
userId, // Shortcut: currentUser.userId
roles, // Shortcut: currentUser.roles[].identifier
isAlwaysAllowed, // true if user has SUPER_ADMIN or ADMIN role
normalizeCountableData, // Format list responses with count/range headers
formatResponse, // Format single-item responses
formatArrayResponse, // Format array responses
} = useRequestContext();13. Chuoi Phu thuoc Goi
Tat ca goi backend deu phu thuoc vao @nx/core. So do sau day cho thay cay phu thuoc day du:
| Goi | Phu thuoc Truc tiep |
|---|---|
@nx/core | Khong (nen tang) |
@nx/asset | @nx/core |
@nx/search | @nx/core |
@nx/inventory | @nx/core |
@nx/identity | @nx/core |
@nx/finance | @nx/core |
@nx/signal | @nx/core |
@nx/payment | @nx/core, @nx/mq-pay |
@nx/sale | @nx/core |
@nx/commerce | @nx/core, @nx/asset, @nx/search, @nx/inventory |
14. Schema Co so Du lieu
@nx/core dinh nghia tat ca Drizzle ORM schema tap trung de moi dich vu truy cap cung cau truc co so du lieu. Schema duoc to chuc tren 7 schema PostgreSQL:
| Schema PostgreSQL | So luong Model | Mien |
|---|---|---|
public | 30 | Nguoi dung, vai tro, san pham, merchant, to chuc, cau hinh |
allocation | 4 | Cho ngoi su kien va bo cuc dia diem |
pricing | 7 | Gia, quy tac dinh gia, chi phi, thue |
inventory | 8 | Ton kho, don dat hang, nha cung cap, theo doi |
finance | 3 | Vi, giao dich, danh muc |
payment | 1 | Cau hinh webhook |
sale | 2 | Don hang va san pham don hang |
Tai lieu schema chi tiet, xem ERD Co so Du lieu.
15. Tai lieu Lien quan
- Tong quan Goi Core -- Gioi thieu goi va cau truc du an
- ERD Co so Du lieu -- So do quan he thuc the
- Thanh phan -- Cac lop co so va component tai su dung
- Tien ich -- Cac ham helper va lop tien ich
- Cau hinh -- Cau hinh moi truong va middleware
- Tham chieu IGNIS Framework -- Tai lieu framework co so