import { getPrismaClient, withTenantContext, type TrunkStatus } from "@b2bcall/database"; import { createLogger } from "@b2bcall/shared"; const logger = createLogger("b2bcall-fs-events"); const GATEWAY_STATE_MAP: Record = { UP: "UP", REGED: "REGISTERED", TRYING: "TRYING", REGISTER: "TRYING", FAILED: "FAILED", FAIL_WAIT: "FAILED", DOWN: "DOWN", NOREG: "UNREGISTERED", UNREGED: "UNREGISTERED", }; /** * O gateway name no FreeSWITCH é o Trunk.id (ver buildGatewayXml em * packages/telephony) — mas RLS exige contexto de tenant, e o evento não * diz de qual tenant é. Como o número de tenants é pequeno, procura em * cada um até achar (mesmo padrão de fan-out usado em fs-config para * sincronizar trunks). */ export async function updateTrunkStatusFromGatewayEvent( gatewayName: string | undefined, rawState: string | undefined, ): Promise { if (!gatewayName || !rawState) return; const status = GATEWAY_STATE_MAP[rawState.toUpperCase()] ?? "UNKNOWN"; const prisma = getPrismaClient(); const tenants = await prisma.tenant.findMany({ where: { status: "ACTIVE" }, select: { id: true } }); for (const tenant of tenants) { const result = await withTenantContext(prisma, tenant.id, (tx) => tx.trunk.updateMany({ where: { id: gatewayName, tenantId: tenant.id }, data: { status, statusUpdatedAt: new Date() }, }), ); if (result.count > 0) { logger.info("status do trunk atualizado", { trunkId: gatewayName, status, rawState }); return; } } }