From 3a376f4a9cc5f6555f7fb12c204f96e8a67e1ff8 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Tue, 31 Mar 2026 23:12:12 +0700 Subject: [PATCH] feat: health check for temporal --- apps/orchestrator/src/app.module.ts | 3 +- apps/orchestrator/src/health.controller.ts | 34 +++++++++++++++ apps/orchestrator/src/main.ts | 7 ++- .../organizations/organization.repository.ts | 43 +++++++++++-------- 4 files changed, 67 insertions(+), 20 deletions(-) create mode 100644 apps/orchestrator/src/health.controller.ts diff --git a/apps/orchestrator/src/app.module.ts b/apps/orchestrator/src/app.module.ts index a0c277db..d7b7f8f1 100644 --- a/apps/orchestrator/src/app.module.ts +++ b/apps/orchestrator/src/app.module.ts @@ -5,6 +5,7 @@ import { DatabaseModule } from '@gitroom/nestjs-libraries/database/prisma/databa import { AutopostService } from '@gitroom/nestjs-libraries/database/prisma/autopost/autopost.service'; import { EmailActivity } from '@gitroom/orchestrator/activities/email.activity'; import { IntegrationsActivity } from '@gitroom/orchestrator/activities/integrations.activity'; +import { HealthController } from '@gitroom/orchestrator/health.controller'; const activities = [ PostActivity, @@ -17,7 +18,7 @@ const activities = [ DatabaseModule, getTemporalModule(true, require.resolve('./workflows'), activities), ], - controllers: [], + controllers: [HealthController], providers: [...activities], get exports() { return [...this.providers, ...this.imports]; diff --git a/apps/orchestrator/src/health.controller.ts b/apps/orchestrator/src/health.controller.ts new file mode 100644 index 00000000..9ce0c267 --- /dev/null +++ b/apps/orchestrator/src/health.controller.ts @@ -0,0 +1,34 @@ +import { Controller, Get, Res } from '@nestjs/common'; +import { Response } from 'express'; +import { Connection } from '@temporalio/client'; + +@Controller('health') +export class HealthController { + @Get('/status') + async getHealthStatus(@Res() res: Response) { + let connection: Connection | undefined; + try { + const address = process.env.TEMPORAL_ADDRESS || 'localhost:7233'; + connection = await Connection.connect({ + address, + ...(process.env.TEMPORAL_TLS === 'true' ? { tls: true } : {}), + ...(process.env.TEMPORAL_API_KEY + ? { apiKey: process.env.TEMPORAL_API_KEY } + : {}), + }); + + const namespace = process.env.TEMPORAL_NAMESPACE || 'default'; + await Promise.race([ + connection.workflowService.describeNamespace({ namespace }), + new Promise((_, reject) => + setTimeout(() => reject(new Error('timeout')), 10000) + ), + ]); + return res.status(200).json({ status: 'ok' }); + } catch { + return res.status(500).json({ status: 'error' }); + } finally { + await connection?.close().catch(() => {}); + } + } +} diff --git a/apps/orchestrator/src/main.ts b/apps/orchestrator/src/main.ts index dacc5743..3a8b6875 100644 --- a/apps/orchestrator/src/main.ts +++ b/apps/orchestrator/src/main.ts @@ -9,9 +9,12 @@ import * as dns from 'node:dns'; dns.setDefaultResultOrder('ipv4first'); async function bootstrap() { - // some comment again - const app = await NestFactory.createApplicationContext(AppModule); + const app = await NestFactory.create(AppModule); app.enableShutdownHooks(); + const port = process.env.ORCHESTRATOR_PORT || 3002; + await app.listen(port); + console.log(`Orchestrator health check listening on port ${port}`); } + bootstrap(); diff --git a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts index 29533892..a18bda09 100644 --- a/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts +++ b/libraries/nestjs-libraries/src/database/prisma/organizations/organization.repository.ts @@ -106,25 +106,34 @@ export class OrganizationRepository { getImpersonateUser(name: string) { return this._userOrg.model.userOrganization.findMany({ where: { - user: { - OR: [ - { - name: { - contains: name, - }, + OR: [ + { + organizationId: { + contains: name, }, - { - email: { - contains: name, - }, + }, + { + user: { + OR: [ + { + name: { + contains: name, + }, + }, + { + email: { + contains: name, + }, + }, + { + id: { + contains: name, + }, + }, + ], }, - { - id: { - contains: name, - }, - }, - ], - }, + }, + ], }, select: { id: true,