mirror of
http://172.20.10.11:3000/gitadmin/INSIGHT-MVP.git
synced 2026-06-25 09:06:40 +02:00
- Phase 2.3 Forecast: probability-Feld in PipelineStage, GET /crm/deals/forecast Endpoint - Phase 2.2 Import: ImportModule mit preview/execute/history Endpoints (CSV, XLSX, vCard) - Phase 2.4 Enrichment: EnrichmentModule mit /enrich + /settings/integrations/north-data - Contracts: ContractsModule mit CRUD + File-Upload Endpoints (Multer, max 25MB) - Migrations: 20260312_contract_files, 20260312_phase23_forecast - docker-compose.crm.yml: uploads Volume für Vertragsdokumente Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
import { Controller, Get, Inject, Optional } from '@nestjs/common';
|
|
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
|
import { Public } from '../common/decorators/public.decorator';
|
|
import { CrmPrismaService } from '../prisma/crm-prisma.service';
|
|
import { RedisService } from '../redis/redis.service';
|
|
import { LexwareClientService } from '../lexware/lexware-client.service';
|
|
import { EnrichmentService } from '../enrichment/enrichment.service';
|
|
|
|
interface HealthResponse {
|
|
status: 'ok' | 'error';
|
|
service: string;
|
|
timestamp: string;
|
|
version: string;
|
|
services: {
|
|
database: 'up' | 'down';
|
|
redis: 'up' | 'down';
|
|
lexware: 'up' | 'down' | 'unconfigured';
|
|
enrichment: 'up' | 'down' | 'unconfigured';
|
|
};
|
|
}
|
|
|
|
@ApiTags('Health')
|
|
@Controller('health')
|
|
export class HealthController {
|
|
constructor(
|
|
private readonly prisma: CrmPrismaService,
|
|
private readonly redis: RedisService,
|
|
@Optional() @Inject(LexwareClientService)
|
|
private readonly lexwareClient?: LexwareClientService,
|
|
@Optional() @Inject(EnrichmentService)
|
|
private readonly enrichmentService?: EnrichmentService,
|
|
) {}
|
|
|
|
@Get()
|
|
@Public()
|
|
@ApiOperation({ summary: 'Health-Check fuer CRM-Service' })
|
|
async check(): Promise<HealthResponse> {
|
|
const [dbStatus, redisStatus, lexwareStatus, enrichmentStatus] =
|
|
await Promise.allSettled([
|
|
this.checkDatabase(),
|
|
this.checkRedis(),
|
|
this.checkLexware(),
|
|
this.checkEnrichment(),
|
|
]);
|
|
|
|
const dbOk = dbStatus.status === 'fulfilled' && dbStatus.value;
|
|
const redisOk = redisStatus.status === 'fulfilled' && redisStatus.value;
|
|
const lexwareResult: 'up' | 'down' | 'unconfigured' =
|
|
lexwareStatus.status === 'fulfilled'
|
|
? lexwareStatus.value
|
|
: 'down';
|
|
const enrichmentResult: 'up' | 'down' | 'unconfigured' =
|
|
enrichmentStatus.status === 'fulfilled'
|
|
? enrichmentStatus.value
|
|
: 'down';
|
|
|
|
// "unconfigured" ist kein Fehler
|
|
const allUp = dbOk && redisOk
|
|
&& lexwareResult !== 'down'
|
|
&& enrichmentResult !== 'down';
|
|
|
|
return {
|
|
status: allUp ? 'ok' : 'error',
|
|
service: 'crm-service',
|
|
timestamp: new Date().toISOString(),
|
|
version: '0.3.0',
|
|
services: {
|
|
database: dbOk ? 'up' : 'down',
|
|
redis: redisOk ? 'up' : 'down',
|
|
lexware: lexwareResult,
|
|
enrichment: enrichmentResult,
|
|
},
|
|
};
|
|
}
|
|
|
|
private async checkDatabase(): Promise<boolean> {
|
|
try {
|
|
await this.prisma.$queryRaw`SELECT 1`;
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private async checkRedis(): Promise<boolean> {
|
|
try {
|
|
const pong = await this.redis.ping();
|
|
return pong === 'PONG';
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private async checkLexware(): Promise<'up' | 'down' | 'unconfigured'> {
|
|
if (!this.lexwareClient) return 'unconfigured';
|
|
return this.lexwareClient.isHealthy();
|
|
}
|
|
|
|
private async checkEnrichment(): Promise<'up' | 'down' | 'unconfigured'> {
|
|
if (!this.enrichmentService) return 'unconfigured';
|
|
return this.enrichmentService.isHealthy();
|
|
}
|
|
}
|