@eventista/ticketing-common 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -3
- package/dist/cluster/config/cluster.config.d.ts +0 -8
- package/dist/cluster/config/cluster.config.js +0 -8
- package/dist/cluster/config/cluster.config.js.map +0 -1
- package/dist/cluster/index.d.ts +0 -2
- package/dist/cluster/index.js +0 -19
- package/dist/cluster/index.js.map +0 -1
- package/dist/cluster/modules/cluster.module.d.ts +0 -2
- package/dist/cluster/modules/cluster.module.js +0 -22
- package/dist/cluster/modules/cluster.module.js.map +0 -1
- package/dist/cluster/services/cluster.service.d.ts +0 -7
- package/dist/cluster/services/cluster.service.js +0 -63
- package/dist/cluster/services/cluster.service.js.map +0 -1
- package/dist/database/index.d.ts +0 -2
- package/dist/database/index.js +0 -19
- package/dist/database/index.js.map +0 -1
- package/dist/database/mongodb/index.d.ts +0 -2
- package/dist/database/mongodb/index.js +0 -19
- package/dist/database/mongodb/index.js.map +0 -1
- package/dist/database/mongodb/mongodb.module.d.ts +0 -2
- package/dist/database/mongodb/mongodb.module.js +0 -50
- package/dist/database/mongodb/mongodb.module.js.map +0 -1
- package/dist/database/mongodb/mongodb.service.d.ts +0 -29
- package/dist/database/mongodb/mongodb.service.js +0 -114
- package/dist/database/mongodb/mongodb.service.js.map +0 -1
- package/dist/database/redis/index.d.ts +0 -2
- package/dist/database/redis/index.js +0 -19
- package/dist/database/redis/index.js.map +0 -1
- package/dist/database/redis/redis.module.d.ts +0 -2
- package/dist/database/redis/redis.module.js +0 -52
- package/dist/database/redis/redis.module.js.map +0 -1
- package/dist/database/redis/redis.service.d.ts +0 -26
- package/dist/database/redis/redis.service.js +0 -126
- package/dist/database/redis/redis.service.js.map +0 -1
- package/dist/exception/exception.filter.d.ts +0 -4
- package/dist/exception/exception.filter.js +0 -35
- package/dist/exception/exception.filter.js.map +0 -1
- package/dist/generic-repository/index.d.ts +0 -4
- package/dist/generic-repository/index.js +0 -21
- package/dist/generic-repository/index.js.map +0 -1
- package/dist/generic-repository/repositories/base.repository.d.ts +0 -39
- package/dist/generic-repository/repositories/base.repository.interface.d.ts +0 -36
- package/dist/generic-repository/repositories/base.repository.interface.js +0 -3
- package/dist/generic-repository/repositories/base.repository.interface.js.map +0 -1
- package/dist/generic-repository/repositories/base.repository.js +0 -96
- package/dist/generic-repository/repositories/base.repository.js.map +0 -1
- package/dist/generic-repository/services/base.service.d.ts +0 -42
- package/dist/generic-repository/services/base.service.interface.d.ts +0 -36
- package/dist/generic-repository/services/base.service.interface.js +0 -3
- package/dist/generic-repository/services/base.service.interface.js.map +0 -1
- package/dist/generic-repository/services/base.service.js +0 -57
- package/dist/generic-repository/services/base.service.js.map +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -24
- package/dist/index.js.map +0 -1
- package/dist/logger/custom.logger.d.ts +0 -14
- package/dist/logger/custom.logger.js +0 -76
- package/dist/logger/custom.logger.js.map +0 -1
- package/dist/logger/index.d.ts +0 -2
- package/dist/logger/index.js +0 -19
- package/dist/logger/index.js.map +0 -1
- package/dist/logger/logger.module.d.ts +0 -2
- package/dist/logger/logger.module.js +0 -27
- package/dist/logger/logger.module.js.map +0 -1
- package/dist/pipes/custom-validation.pipe.d.ts +0 -7
- package/dist/pipes/custom-validation.pipe.js +0 -69
- package/dist/pipes/custom-validation.pipe.js.map +0 -1
- package/dist/response/response.interceptor.d.ts +0 -5
- package/dist/response/response.interceptor.js +0 -29
- package/dist/response/response.interceptor.js.map +0 -1
- package/dist/schemas/base.schema.d.ts +0 -11
- package/dist/schemas/base.schema.js +0 -29
- package/dist/schemas/base.schema.js.map +0 -1
- package/dist/schemas/event/event.interfaces.d.ts +0 -69
- package/dist/schemas/event/event.interfaces.js +0 -9
- package/dist/schemas/event/event.interfaces.js.map +0 -1
- package/dist/schemas/event/event.schema.d.ts +0 -70
- package/dist/schemas/event/event.schema.js +0 -242
- package/dist/schemas/event/event.schema.js.map +0 -1
- package/dist/schemas/index.d.ts +0 -14
- package/dist/schemas/index.js +0 -31
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/order/order.interfaces.d.ts +0 -72
- package/dist/schemas/order/order.interfaces.js +0 -31
- package/dist/schemas/order/order.interfaces.js.map +0 -1
- package/dist/schemas/order/order.schema.d.ts +0 -39
- package/dist/schemas/order/order.schema.js +0 -162
- package/dist/schemas/order/order.schema.js.map +0 -1
- package/dist/schemas/promotions/promotions.interfaces.d.ts +0 -30
- package/dist/schemas/promotions/promotions.interfaces.js +0 -14
- package/dist/schemas/promotions/promotions.interfaces.js.map +0 -1
- package/dist/schemas/promotions/promotions.schema.d.ts +0 -25
- package/dist/schemas/promotions/promotions.schema.js +0 -92
- package/dist/schemas/promotions/promotions.schema.js.map +0 -1
- package/dist/schemas/rows/rows.interfaces.d.ts +0 -14
- package/dist/schemas/rows/rows.interfaces.js +0 -3
- package/dist/schemas/rows/rows.interfaces.js.map +0 -1
- package/dist/schemas/rows/rows.schema.d.ts +0 -22
- package/dist/schemas/rows/rows.schema.js +0 -65
- package/dist/schemas/rows/rows.schema.js.map +0 -1
- package/dist/schemas/schema.helper.d.ts +0 -4
- package/dist/schemas/schema.helper.js +0 -84
- package/dist/schemas/schema.helper.js.map +0 -1
- package/dist/schemas/ticket-classes/ticket-classes.interfaces.d.ts +0 -18
- package/dist/schemas/ticket-classes/ticket-classes.interfaces.js +0 -3
- package/dist/schemas/ticket-classes/ticket-classes.interfaces.js.map +0 -1
- package/dist/schemas/ticket-classes/ticket-classes.schemas.d.ts +0 -26
- package/dist/schemas/ticket-classes/ticket-classes.schemas.js +0 -75
- package/dist/schemas/ticket-classes/ticket-classes.schemas.js.map +0 -1
- package/dist/schemas/ticket-summary/ticket-summary.interfaces.d.ts +0 -19
- package/dist/schemas/ticket-summary/ticket-summary.interfaces.js +0 -9
- package/dist/schemas/ticket-summary/ticket-summary.interfaces.js.map +0 -1
- package/dist/schemas/ticket-summary/ticket-summary.schema.d.ts +0 -23
- package/dist/schemas/ticket-summary/ticket-summary.schema.js +0 -65
- package/dist/schemas/ticket-summary/ticket-summary.schema.js.map +0 -1
- package/dist/schemas/user-fanpass/user-fanpass.interfaces.d.ts +0 -26
- package/dist/schemas/user-fanpass/user-fanpass.interfaces.js +0 -9
- package/dist/schemas/user-fanpass/user-fanpass.interfaces.js.map +0 -1
- package/dist/schemas/user-fanpass/user-fanpass.schemas.d.ts +0 -29
- package/dist/schemas/user-fanpass/user-fanpass.schemas.js +0 -113
- package/dist/schemas/user-fanpass/user-fanpass.schemas.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/cluster/config/cluster.config.ts +0 -6
- package/src/cluster/index.ts +0 -2
- package/src/cluster/modules/cluster.module.ts +0 -9
- package/src/cluster/services/cluster.service.ts +0 -76
- package/src/database/index.ts +0 -2
- package/src/database/mongodb/index.ts +0 -2
- package/src/database/mongodb/mongodb.module.ts +0 -42
- package/src/database/mongodb/mongodb.service.ts +0 -111
- package/src/database/redis/index.ts +0 -2
- package/src/database/redis/redis.module.ts +0 -45
- package/src/database/redis/redis.service.ts +0 -142
- package/src/exception/exception.filter.ts +0 -36
- package/src/generic-repository/index.ts +0 -7
- package/src/generic-repository/repositories/base.repository.interface.ts +0 -78
- package/src/generic-repository/repositories/base.repository.ts +0 -199
- package/src/generic-repository/services/base.service.interface.ts +0 -78
- package/src/generic-repository/services/base.service.ts +0 -165
- package/src/index.ts +0 -11
- package/src/logger/custom.logger.ts +0 -83
- package/src/logger/index.ts +0 -2
- package/src/logger/logger.module.ts +0 -14
- package/src/pipes/custom-validation.pipe.ts +0 -61
- package/src/response/response.interceptor.ts +0 -26
- package/src/schemas/base.schema.ts +0 -19
- package/src/schemas/event/event.interfaces.ts +0 -74
- package/src/schemas/event/event.schema.ts +0 -195
- package/src/schemas/index.ts +0 -16
- package/src/schemas/order/order.interfaces.ts +0 -78
- package/src/schemas/order/order.schema.ts +0 -120
- package/src/schemas/promotions/promotions.interfaces.ts +0 -34
- package/src/schemas/promotions/promotions.schema.ts +0 -71
- package/src/schemas/rows/rows.interfaces.ts +0 -14
- package/src/schemas/rows/rows.schema.ts +0 -47
- package/src/schemas/schema.helper.ts +0 -103
- package/src/schemas/ticket-classes/ticket-classes.interfaces.ts +0 -18
- package/src/schemas/ticket-classes/ticket-classes.schemas.ts +0 -51
- package/src/schemas/ticket-summary/ticket-summary.interfaces.ts +0 -20
- package/src/schemas/ticket-summary/ticket-summary.schema.ts +0 -46
- package/src/schemas/user-fanpass/user-fanpass.interfaces.ts +0 -28
- package/src/schemas/user-fanpass/user-fanpass.schemas.ts +0 -86
- package/tsconfig.json +0 -17
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
2
|
-
import { CustomLogger } from 'src/logger';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// Import node:cluster và node:os
|
|
6
|
-
const cluster = require('node:cluster');
|
|
7
|
-
const { cpus } = require('node:os');
|
|
8
|
-
|
|
9
|
-
@Injectable()
|
|
10
|
-
export class ClusterService {
|
|
11
|
-
private logger: CustomLogger;
|
|
12
|
-
|
|
13
|
-
constructor() {
|
|
14
|
-
this.logger = new CustomLogger('ClusterService');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Khởi động ứng dụng với chế độ cluster hoặc đơn luồng dựa trên cấu hình
|
|
19
|
-
* @param bootstrapFunction Hàm khởi động ứng dụng
|
|
20
|
-
*/
|
|
21
|
-
public startApplication(bootstrapFunction: () => Promise<void>): void {
|
|
22
|
-
// Lấy giá trị ENABLE_CLUSTER từ biến môi trường, mặc định là 'false'
|
|
23
|
-
const enableCluster = process.env.ENABLE_CLUSTER?.toLowerCase() === 'true';
|
|
24
|
-
|
|
25
|
-
if (enableCluster && cluster.isPrimary) {
|
|
26
|
-
this.startClusterMode();
|
|
27
|
-
} else {
|
|
28
|
-
this.startSingleProcessMode(bootstrapFunction, enableCluster);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Khởi động ứng dụng trong chế độ cluster
|
|
34
|
-
*/
|
|
35
|
-
private startClusterMode(): void {
|
|
36
|
-
this.logger.log(`Cluster mode enabled. Primary ${process.pid} is running`);
|
|
37
|
-
|
|
38
|
-
// Fork workers for each CPU
|
|
39
|
-
const numCPUs = cpus().length;
|
|
40
|
-
|
|
41
|
-
// Có thể giới hạn số lượng worker thông qua biến môi trường
|
|
42
|
-
const maxWorkers = parseInt(process.env.MAX_WORKERS || String(numCPUs), 10);
|
|
43
|
-
const workerCount = Math.min(numCPUs, maxWorkers);
|
|
44
|
-
|
|
45
|
-
this.logger.log(`Starting ${workerCount} workers out of ${numCPUs} available CPUs`);
|
|
46
|
-
|
|
47
|
-
for (let i = 0; i < workerCount; i++) {
|
|
48
|
-
cluster.fork();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
cluster.on('exit', (worker, code, signal) => {
|
|
52
|
-
this.logger.warn(`Worker ${worker.process.pid} died with code ${code} and signal ${signal}`);
|
|
53
|
-
// Thay thế worker đã chết
|
|
54
|
-
this.logger.log('Forking a new worker...');
|
|
55
|
-
cluster.fork();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Khởi động ứng dụng trong chế độ đơn luồng hoặc như một worker
|
|
61
|
-
* @param bootstrapFunction Hàm khởi động ứng dụng
|
|
62
|
-
* @param isWorker Có phải là worker trong chế độ cluster không
|
|
63
|
-
*/
|
|
64
|
-
private startSingleProcessMode(bootstrapFunction: () => Promise<void>, isWorker: boolean): void {
|
|
65
|
-
bootstrapFunction().catch(err => {
|
|
66
|
-
this.logger.error('Failed to start application', err);
|
|
67
|
-
process.exit(1);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (isWorker) {
|
|
71
|
-
this.logger.log(`Worker ${process.pid} started`);
|
|
72
|
-
} else {
|
|
73
|
-
this.logger.log(`Running in single process mode. Process ${process.pid} started`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
package/src/database/index.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Module, Global } from '@nestjs/common';
|
|
2
|
-
import { MongooseModule } from '@nestjs/mongoose';
|
|
3
|
-
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
4
|
-
import { MongodbService } from './mongodb.service';
|
|
5
|
-
|
|
6
|
-
@Global()
|
|
7
|
-
@Module({
|
|
8
|
-
imports: [
|
|
9
|
-
MongooseModule.forRootAsync({
|
|
10
|
-
imports: [ConfigModule],
|
|
11
|
-
inject: [ConfigService],
|
|
12
|
-
useFactory: async (configService: ConfigService) => {
|
|
13
|
-
const uri = configService.get<string>('MONGODB_URI');
|
|
14
|
-
return {
|
|
15
|
-
uri,
|
|
16
|
-
// Cấu hình connection pool tối ưu cho production
|
|
17
|
-
maxPoolSize: configService.get<number>('MONGODB_MAX_POOL_SIZE', 100),
|
|
18
|
-
minPoolSize: configService.get<number>('MONGODB_MIN_POOL_SIZE', 5),
|
|
19
|
-
maxConnecting: configService.get<number>('MONGODB_MAX_CONNECTING', 5),
|
|
20
|
-
maxIdleTimeMS: configService.get<number>('MONGODB_MAX_IDLE_TIME_MS', 60000),
|
|
21
|
-
waitQueueTimeoutMS: 5000,
|
|
22
|
-
// Cấu hình timeout và retry tối ưu
|
|
23
|
-
connectTimeoutMS: 30000,
|
|
24
|
-
socketTimeoutMS: 45000,
|
|
25
|
-
heartbeatFrequencyMS: 10000,
|
|
26
|
-
serverSelectionTimeoutMS: 30000,
|
|
27
|
-
retryWrites: true,
|
|
28
|
-
retryReads: true,
|
|
29
|
-
// Cấu hình bảo mật và hiệu suất
|
|
30
|
-
compressors: 'zlib',
|
|
31
|
-
zlibCompressionLevel: 6,
|
|
32
|
-
// Cấu hình monitoring
|
|
33
|
-
monitorCommands: true,
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
},
|
|
37
|
-
}),
|
|
38
|
-
],
|
|
39
|
-
providers: [MongodbService],
|
|
40
|
-
exports: [MongodbService, MongooseModule],
|
|
41
|
-
})
|
|
42
|
-
export class MongodbModule {}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
|
2
|
-
import { InjectConnection } from '@nestjs/mongoose';
|
|
3
|
-
import { Connection } from 'mongoose';
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class MongodbService implements OnModuleInit {
|
|
7
|
-
private readonly logger = new Logger(MongodbService.name);
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
10
|
-
@InjectConnection()
|
|
11
|
-
private readonly connection: Connection,
|
|
12
|
-
) {}
|
|
13
|
-
|
|
14
|
-
async onModuleInit() {
|
|
15
|
-
try {
|
|
16
|
-
// Kiểm tra kết nối khi khởi động
|
|
17
|
-
if (this.connection.readyState === 1) {
|
|
18
|
-
this.logger.log('MongoDB connected successfully');
|
|
19
|
-
|
|
20
|
-
// Log thông tin về connection pool
|
|
21
|
-
const poolInfo = this.getConnectionPoolInfo();
|
|
22
|
-
this.logger.log(`MongoDB connection pool initialized: ${JSON.stringify(poolInfo)}`);
|
|
23
|
-
} else {
|
|
24
|
-
this.logger.warn(`MongoDB connection state: ${this.getReadyStateText(this.connection.readyState)}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Thiết lập event listeners
|
|
28
|
-
this.setupConnectionListeners();
|
|
29
|
-
} catch (error) {
|
|
30
|
-
this.logger.error('Failed to initialize MongoDB connection', error.stack);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
private setupConnectionListeners() {
|
|
35
|
-
this.connection.on('connected', () => {
|
|
36
|
-
this.logger.log('MongoDB connected');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
this.connection.on('disconnected', () => {
|
|
40
|
-
this.logger.warn('MongoDB disconnected');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
this.connection.on('reconnected', () => {
|
|
44
|
-
this.logger.log('MongoDB reconnected');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
this.connection.on('error', (error) => {
|
|
48
|
-
this.logger.error('MongoDB connection error', error.stack);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getConnection(): Connection {
|
|
53
|
-
return this.connection;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
getConnectionStatus(): string {
|
|
57
|
-
return this.getReadyStateText(this.connection.readyState);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async ping(): Promise<boolean> {
|
|
61
|
-
try {
|
|
62
|
-
await this.connection.db.admin().ping();
|
|
63
|
-
return true;
|
|
64
|
-
} catch (error) {
|
|
65
|
-
this.logger.error('MongoDB ping failed', error.stack);
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getConnectionPoolInfo() {
|
|
71
|
-
// Sửa lại cách truy cập thông tin connection pool
|
|
72
|
-
try {
|
|
73
|
-
// Cách 1: Truy cập thông qua mongoose driver
|
|
74
|
-
if (this.connection.getClient) {
|
|
75
|
-
const client = this.connection.getClient();
|
|
76
|
-
return {
|
|
77
|
-
maxPoolSize: client.options?.maxPoolSize || 'default',
|
|
78
|
-
minPoolSize: client.options?.minPoolSize || 'default',
|
|
79
|
-
readyState: this.getReadyStateText(this.connection.readyState),
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Cách 2: Nếu không có getClient, sử dụng cách khác
|
|
84
|
-
return {
|
|
85
|
-
readyState: this.getReadyStateText(this.connection.readyState),
|
|
86
|
-
// Thêm các thông tin khác nếu có thể truy cập
|
|
87
|
-
};
|
|
88
|
-
} catch (error) {
|
|
89
|
-
this.logger.warn('Could not retrieve connection pool info', error.message);
|
|
90
|
-
return {
|
|
91
|
-
readyState: this.getReadyStateText(this.connection.readyState),
|
|
92
|
-
error: 'Could not retrieve pool information',
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private getReadyStateText(state: number): string {
|
|
98
|
-
switch (state) {
|
|
99
|
-
case 0:
|
|
100
|
-
return 'disconnected';
|
|
101
|
-
case 1:
|
|
102
|
-
return 'connected';
|
|
103
|
-
case 2:
|
|
104
|
-
return 'connecting';
|
|
105
|
-
case 3:
|
|
106
|
-
return 'disconnecting';
|
|
107
|
-
default:
|
|
108
|
-
return 'unknown';
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Module, Global } from '@nestjs/common';
|
|
2
|
-
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
3
|
-
import { RedisService } from './redis.service';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@Global()
|
|
7
|
-
@Module({
|
|
8
|
-
imports: [ConfigModule],
|
|
9
|
-
providers: [
|
|
10
|
-
{
|
|
11
|
-
provide: 'REDIS_CLIENT',
|
|
12
|
-
useFactory: (configService: ConfigService) => {
|
|
13
|
-
const Redis = require('ioredis');
|
|
14
|
-
return new Redis({
|
|
15
|
-
host: configService.get('REDIS_HOST', 'localhost'),
|
|
16
|
-
port: configService.get('REDIS_PORT', 6379),
|
|
17
|
-
password: configService.get('REDIS_PASSWORD', 'StrongRedisPassword123'),
|
|
18
|
-
db: configService.get('REDIS_DB', 0),
|
|
19
|
-
// Tối ưu connection pool
|
|
20
|
-
maxRetriesPerRequest: 3,
|
|
21
|
-
connectTimeout: 10000,
|
|
22
|
-
// Tăng số lượng kết nối trong pool
|
|
23
|
-
connectionName: 'ticket-service',
|
|
24
|
-
// Tối ưu hóa retry strategy
|
|
25
|
-
retryStrategy: (times) => {
|
|
26
|
-
if (times > 3) {
|
|
27
|
-
return null; // stop retrying
|
|
28
|
-
}
|
|
29
|
-
return Math.min(times * 50, 1000);
|
|
30
|
-
},
|
|
31
|
-
// Tối ưu hóa các tùy chọn khác
|
|
32
|
-
enableReadyCheck: false,
|
|
33
|
-
enableOfflineQueue: true,
|
|
34
|
-
// Tối ưu hóa TCP keepalive
|
|
35
|
-
keepAlive: 10000,
|
|
36
|
-
noDelay: true,
|
|
37
|
-
});
|
|
38
|
-
},
|
|
39
|
-
inject: [ConfigService],
|
|
40
|
-
},
|
|
41
|
-
RedisService,
|
|
42
|
-
],
|
|
43
|
-
exports: [RedisService],
|
|
44
|
-
})
|
|
45
|
-
export class RedisModule {}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { Injectable, Inject, OnModuleDestroy } from '@nestjs/common';
|
|
2
|
-
import { Redis } from 'ioredis';
|
|
3
|
-
|
|
4
|
-
@Injectable()
|
|
5
|
-
export class RedisService implements OnModuleDestroy {
|
|
6
|
-
constructor(
|
|
7
|
-
@Inject('REDIS_CLIENT')
|
|
8
|
-
private readonly redis: Redis,
|
|
9
|
-
) {}
|
|
10
|
-
|
|
11
|
-
getClient(): Redis {
|
|
12
|
-
return this.redis;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async get(key: string): Promise<string | null> {
|
|
16
|
-
return this.redis.get(key);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async set(key: string, value: string, ttl?: number): Promise<'OK'> {
|
|
20
|
-
if (ttl) {
|
|
21
|
-
return this.redis.set(key, value, 'EX', ttl);
|
|
22
|
-
}
|
|
23
|
-
return this.redis.set(key, value);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async del(key: string): Promise<number> {
|
|
27
|
-
return this.redis.del(key);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async incr(key: string): Promise<number> {
|
|
31
|
-
return this.redis.incr(key);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async decr(key: string): Promise<number> {
|
|
35
|
-
return this.redis.decr(key);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async incrby(key: string, increment: number): Promise<number> {
|
|
39
|
-
return this.redis.incrby(key, increment);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async decrby(key: string, decrement: number): Promise<number> {
|
|
43
|
-
return this.redis.decrby(key, decrement);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Thêm phương thức để thực hiện nhiều lệnh Redis trong một pipeline
|
|
47
|
-
async pipeline(commands: Array<[string, ...any[]]>): Promise<any[]> {
|
|
48
|
-
const pipeline = this.redis.pipeline();
|
|
49
|
-
|
|
50
|
-
for (const [command, ...args] of commands) {
|
|
51
|
-
pipeline[command](...args);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return pipeline.exec();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Tối ưu phương thức executeScript
|
|
58
|
-
async executeScript(script: string, keys: string[], args: string[]): Promise<any> {
|
|
59
|
-
// Sử dụng defineCommand để tối ưu hiệu suất cho các script được sử dụng nhiều lần
|
|
60
|
-
const scriptHash = require('crypto').createHash('sha1').update(script).digest('hex');
|
|
61
|
-
|
|
62
|
-
// Kiểm tra xem script đã được cache chưa
|
|
63
|
-
try {
|
|
64
|
-
return await this.redis.evalsha(scriptHash, keys.length, ...keys, ...args);
|
|
65
|
-
} catch (err) {
|
|
66
|
-
if (err.message.includes('NOSCRIPT')) {
|
|
67
|
-
// Script chưa được cache, thực thi và cache
|
|
68
|
-
return this.redis.eval(script, keys.length, ...keys, ...args);
|
|
69
|
-
}
|
|
70
|
-
throw err;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async releaseLock(lockKey: string, value: string): Promise<boolean> {
|
|
75
|
-
const script = `
|
|
76
|
-
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
77
|
-
return redis.call("del", KEYS[1])
|
|
78
|
-
else
|
|
79
|
-
return 0
|
|
80
|
-
end
|
|
81
|
-
`;
|
|
82
|
-
const result = await this.redis.eval(script, 1, lockKey, value);
|
|
83
|
-
return result === 1;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Thêm phương thức zadd để hỗ trợ sorted sets
|
|
87
|
-
async zadd(key: string, ...args: string[]): Promise<number> {
|
|
88
|
-
return this.redis.zadd(key, ...args);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Thêm các phương thức khác cho sorted sets
|
|
92
|
-
async zrevrange(key: string, start: number, stop: number, withScores?: boolean): Promise<string[]> {
|
|
93
|
-
if (withScores) {
|
|
94
|
-
return this.redis.zrevrange(key, start, stop, 'WITHSCORES');
|
|
95
|
-
}
|
|
96
|
-
return this.redis.zrevrange(key, start, stop);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async zrange(key: string, start: number, stop: number, withScores?: boolean): Promise<string[]> {
|
|
100
|
-
if (withScores) {
|
|
101
|
-
return this.redis.zrange(key, start, stop, 'WITHSCORES');
|
|
102
|
-
}
|
|
103
|
-
return this.redis.zrange(key, start, stop);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async zrem(key: string, ...members: string[]): Promise<number> {
|
|
107
|
-
return this.redis.zrem(key, ...members);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async zscore(key: string, member: string): Promise<string | null> {
|
|
111
|
-
return this.redis.zscore(key, member);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Thêm phương thức hỗ trợ hash maps
|
|
115
|
-
async hmset(key: string, hash: Record<string, string>): Promise<'OK'> {
|
|
116
|
-
return this.redis.hmset(key, hash);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async hgetall(key: string): Promise<Record<string, string>> {
|
|
120
|
-
return this.redis.hgetall(key);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Lấy nhiều giá trị từ Redis
|
|
125
|
-
* @param keys Danh sách các key cần lấy
|
|
126
|
-
* @returns Danh sách các giá trị tương ứng
|
|
127
|
-
*/
|
|
128
|
-
async mget(...keys: string[]): Promise<(string | null)[]> {
|
|
129
|
-
try {
|
|
130
|
-
const client = this.getClient();
|
|
131
|
-
const values = await client.mget(keys);
|
|
132
|
-
return values;
|
|
133
|
-
} catch (error) {
|
|
134
|
-
// Trả về mảng null với độ dài bằng số lượng key
|
|
135
|
-
return Array(keys.length).fill(null);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
onModuleDestroy() {
|
|
140
|
-
this.redis.disconnect();
|
|
141
|
-
}
|
|
142
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ArgumentsHost,
|
|
3
|
-
Catch,
|
|
4
|
-
ExceptionFilter,
|
|
5
|
-
HttpException,
|
|
6
|
-
HttpStatus,
|
|
7
|
-
} from '@nestjs/common';
|
|
8
|
-
|
|
9
|
-
@Catch()
|
|
10
|
-
export class GlobalExceptionFilter implements ExceptionFilter {
|
|
11
|
-
catch(exception: any, host: ArgumentsHost) {
|
|
12
|
-
const ctx = host.switchToHttp();
|
|
13
|
-
const response = ctx.getResponse();
|
|
14
|
-
const request = ctx.getRequest();
|
|
15
|
-
// Lấy mã trạng thái
|
|
16
|
-
const status =
|
|
17
|
-
exception instanceof HttpException
|
|
18
|
-
? exception.getStatus()
|
|
19
|
-
: HttpStatus.INTERNAL_SERVER_ERROR;
|
|
20
|
-
|
|
21
|
-
const errorResponse = {
|
|
22
|
-
errorCode:
|
|
23
|
-
exception instanceof HttpException
|
|
24
|
-
? exception.getResponse()['code']
|
|
25
|
-
: status,
|
|
26
|
-
message: exception.message || 'Internal Server Error',
|
|
27
|
-
data: exception instanceof HttpException ? exception.getResponse()['data'] : null,
|
|
28
|
-
|
|
29
|
-
path: request.url,
|
|
30
|
-
timestamp: new Date().toISOString(),
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// Sử dụng phương thức Fastify để trả về phản hồi
|
|
34
|
-
response.status(status).send(errorResponse); // Fastify sử dụng `send` để trả về JSON
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { Document, FilterQuery, UpdateQuery, QueryOptions, PipelineStage } from 'mongoose';
|
|
2
|
-
|
|
3
|
-
export interface IBaseRepository<T extends Document> {
|
|
4
|
-
findOne(
|
|
5
|
-
filterQuery: FilterQuery<T>,
|
|
6
|
-
projection?: Record<string, unknown>,
|
|
7
|
-
options?: QueryOptions,
|
|
8
|
-
): Promise<T | null>;
|
|
9
|
-
|
|
10
|
-
findOneOrFail(
|
|
11
|
-
filterQuery: FilterQuery<T>,
|
|
12
|
-
projection?: Record<string, unknown>,
|
|
13
|
-
options?: QueryOptions,
|
|
14
|
-
): Promise<T>;
|
|
15
|
-
|
|
16
|
-
find(
|
|
17
|
-
filterQuery: FilterQuery<T>,
|
|
18
|
-
projection?: Record<string, unknown>,
|
|
19
|
-
options?: QueryOptions,
|
|
20
|
-
): Promise<T[]>;
|
|
21
|
-
|
|
22
|
-
create(createDto: Partial<T>): Promise<T>;
|
|
23
|
-
|
|
24
|
-
createMany(createDtos: Partial<T>[]): Promise<T[]>;
|
|
25
|
-
|
|
26
|
-
findOneAndUpdate(
|
|
27
|
-
filterQuery: FilterQuery<T>,
|
|
28
|
-
updateQuery: UpdateQuery<T>,
|
|
29
|
-
options?: QueryOptions,
|
|
30
|
-
): Promise<T | null>;
|
|
31
|
-
|
|
32
|
-
findOneAndUpdateOrFail(
|
|
33
|
-
filterQuery: FilterQuery<T>,
|
|
34
|
-
updateQuery: UpdateQuery<T>,
|
|
35
|
-
options?: QueryOptions,
|
|
36
|
-
): Promise<T>;
|
|
37
|
-
|
|
38
|
-
updateMany(
|
|
39
|
-
filterQuery: FilterQuery<T>,
|
|
40
|
-
updateQuery: UpdateQuery<T>,
|
|
41
|
-
): Promise<{ matchedCount: number; modifiedCount: number }>;
|
|
42
|
-
|
|
43
|
-
findOneAndDelete(
|
|
44
|
-
filterQuery: FilterQuery<T>,
|
|
45
|
-
options?: QueryOptions,
|
|
46
|
-
): Promise<T | null>;
|
|
47
|
-
|
|
48
|
-
findOneAndDeleteOrFail(
|
|
49
|
-
filterQuery: FilterQuery<T>,
|
|
50
|
-
options?: QueryOptions,
|
|
51
|
-
): Promise<T>;
|
|
52
|
-
|
|
53
|
-
deleteMany(filterQuery: FilterQuery<T>): Promise<{ deletedCount: number }>;
|
|
54
|
-
|
|
55
|
-
count(filterQuery: FilterQuery<T>): Promise<number>;
|
|
56
|
-
|
|
57
|
-
exists(filterQuery: FilterQuery<T>): Promise<boolean>;
|
|
58
|
-
|
|
59
|
-
aggregate(pipeline: PipelineStage[]): Promise<any[]>;
|
|
60
|
-
|
|
61
|
-
paginate(
|
|
62
|
-
filterQuery: FilterQuery<T>,
|
|
63
|
-
options?: {
|
|
64
|
-
page?: number;
|
|
65
|
-
limit?: number;
|
|
66
|
-
sort?: Record<string, 1 | -1>;
|
|
67
|
-
projection?: Record<string, unknown>;
|
|
68
|
-
},
|
|
69
|
-
): Promise<{
|
|
70
|
-
data: T[];
|
|
71
|
-
pagination: {
|
|
72
|
-
total: number;
|
|
73
|
-
page: number;
|
|
74
|
-
limit: number;
|
|
75
|
-
pages: number;
|
|
76
|
-
};
|
|
77
|
-
}>;
|
|
78
|
-
}
|