251125:0000 Phase 6 wait start dev Check
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
import { IsBoolean, IsOptional, IsString } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class SetMaintenanceDto {
|
||||
@ApiProperty({ description: 'สถานะ Maintenance (true = เปิด, false = ปิด)' })
|
||||
@IsBoolean()
|
||||
enabled!: boolean; // ✅ เพิ่ม ! ตรงนี้
|
||||
|
||||
@ApiProperty({
|
||||
description: 'เหตุผลที่ปิดปรับปรุง (แสดงให้ User เห็น)',
|
||||
required: false,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
reason?: string; // Optional (?) ไม่ต้องใส่ !
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { MonitoringService } from './monitoring.service';
|
||||
import { SetMaintenanceDto } from './dto/set-maintenance.dto';
|
||||
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
||||
import { RequirePermission } from '../../common/decorators/require-permission.decorator';
|
||||
import { BypassMaintenance } from '../../common/decorators/bypass-maintenance.decorator';
|
||||
|
||||
@ApiTags('System Monitoring')
|
||||
@Controller('monitoring')
|
||||
export class MonitoringController {
|
||||
constructor(private readonly monitoringService: MonitoringService) {}
|
||||
|
||||
@Get('maintenance')
|
||||
@ApiOperation({ summary: 'Check maintenance status (Public)' })
|
||||
@BypassMaintenance() // API นี้ต้องเรียกได้แม้ระบบปิดอยู่
|
||||
getMaintenanceStatus() {
|
||||
return this.monitoringService.getMaintenanceStatus();
|
||||
}
|
||||
|
||||
@Post('maintenance')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@RequirePermission('system.manage_all') // เฉพาะ Superadmin เท่านั้น
|
||||
@BypassMaintenance() // Admin ต้องยิงเปิด/ปิดได้แม้ระบบจะปิดอยู่
|
||||
@ApiOperation({ summary: 'Toggle Maintenance Mode (Admin Only)' })
|
||||
setMaintenanceMode(@Body() dto: SetMaintenanceDto) {
|
||||
return this.monitoringService.setMaintenanceMode(dto);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,34 @@
|
||||
// File: src/modules/monitoring/monitoring.module.ts
|
||||
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { TerminusModule } from '@nestjs/terminus';
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
import { APP_INTERCEPTOR } from '@nestjs/core';
|
||||
|
||||
// Existing Components
|
||||
import { HealthController } from './controllers/health.controller';
|
||||
import { MetricsService } from './services/metrics.service';
|
||||
import { PerformanceInterceptor } from '../../common/interceptors/performance.interceptor';
|
||||
|
||||
@Global() // ทำให้ Module นี้ใช้งานได้ทั่วทั้ง App โดยไม่ต้อง Import ซ้ำ
|
||||
// [NEW] Maintenance Mode Components
|
||||
import { MonitoringController } from './monitoring.controller';
|
||||
import { MonitoringService } from './monitoring.service';
|
||||
|
||||
@Global() // Module นี้เป็น Global (ดีแล้วครับ)
|
||||
@Module({
|
||||
imports: [TerminusModule, HttpModule],
|
||||
controllers: [HealthController],
|
||||
controllers: [
|
||||
HealthController, // ✅ ของเดิม: /health
|
||||
MonitoringController, // ✅ ของใหม่: /monitoring/maintenance
|
||||
],
|
||||
providers: [
|
||||
MetricsService,
|
||||
MetricsService, // ✅ ของเดิม
|
||||
MonitoringService, // ✅ ของใหม่ (Logic เปิด/ปิด Maintenance)
|
||||
{
|
||||
provide: APP_INTERCEPTOR, // Register Global Interceptor
|
||||
useClass: PerformanceInterceptor,
|
||||
provide: APP_INTERCEPTOR,
|
||||
useClass: PerformanceInterceptor, // ✅ ของเดิม (จับเวลา Response Time)
|
||||
},
|
||||
],
|
||||
exports: [MetricsService],
|
||||
exports: [MetricsService, MonitoringService],
|
||||
})
|
||||
export class MonitoringModule {}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// File: src/modules/monitoring/monitoring.service.ts
|
||||
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRedis } from '@nestjs-modules/ioredis';
|
||||
import Redis from 'ioredis';
|
||||
import { SetMaintenanceDto } from './dto/set-maintenance.dto';
|
||||
|
||||
@Injectable()
|
||||
export class MonitoringService {
|
||||
private readonly logger = new Logger(MonitoringService.name);
|
||||
private readonly MAINTENANCE_KEY = 'system:maintenance_mode';
|
||||
|
||||
constructor(@InjectRedis() private readonly redis: Redis) {}
|
||||
|
||||
/**
|
||||
* ตรวจสอบสถานะปัจจุบัน
|
||||
*/
|
||||
async getMaintenanceStatus() {
|
||||
const status = await this.redis.get(this.MAINTENANCE_KEY);
|
||||
return {
|
||||
isEnabled: status === 'true',
|
||||
message:
|
||||
status === 'true' ? 'System is under maintenance' : 'System is normal',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ตั้งค่า Maintenance Mode
|
||||
*/
|
||||
async setMaintenanceMode(dto: SetMaintenanceDto) {
|
||||
if (dto.enabled) {
|
||||
await this.redis.set(this.MAINTENANCE_KEY, 'true');
|
||||
// เก็บเหตุผลไว้ใน Key อื่นก็ได้ถ้าต้องการ แต่เบื้องต้น Guard เช็คแค่ Key นี้
|
||||
this.logger.warn(
|
||||
`⚠️ SYSTEM ENTERED MAINTENANCE MODE: ${dto.reason || 'No reason provided'}`,
|
||||
);
|
||||
} else {
|
||||
await this.redis.del(this.MAINTENANCE_KEY);
|
||||
this.logger.log('✅ System exited maintenance mode');
|
||||
}
|
||||
|
||||
return this.getMaintenanceStatus();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user