How to create a custom health check for Prisma with @nestjs/terminus?
Asked Answered
I

3

9

Since @nestjs/terminus doesn't provide a health check for Prisma, I'm trying to create it based on their Mongoose health check.

When I try:

import * as Prisma from 'prisma';
...
...
  private getContextConnection(): any | null {
    const {
      getConnectionToken,
      // eslint-disable-next-line @typescript-eslint/no-var-requires
    } = require('prisma') as typeof Prisma;

    try {
      return this.moduleRef.get(getConnectionToken('DatabaseConnection') as string, {
        strict: false,
      });
    } catch (err) {
      return null;
    }
  }
...
...
    const connection = options.connection || this.getContextConnection();

    if (!connection) {
      throw new ConnectionNotFoundError(
        this.getStatus(key, isHealthy, {
          message: 'Connection provider not found in application context',
        }),
      );
    }

I always seem to get: "message": "Connection provider not found in application context". There is a problem with the connection or I don't really understand how the health check actually works

Ibex answered 14/10, 2021 at 10:4 Comment(1)
Since there's no NestJS Prisma package and therefore nobody registers the DatabaseConnection token, it probably makes more sense to do PrismaClient.$connect() in the health check.Smegma
C
5

A naive copy of the mongoose implementation isn't going to work because there are differences between the NestJSMongoose type/module and Prisma. In particular, getConnectionToken does not exist inside the Prisma package.

I can't comment on what the best way would be to extend terminus to support prisma. You might have to dig a bit into the terminus interface for that. However, a simple way to get a health check/ping in Prisma is to use the following query:

    prisma.$queryRaw`SELECT 1`
Culinary answered 14/10, 2021 at 14:41 Comment(0)
P
11

This question helped me build a Prisma health check for NestJS.

Here's what I made:

import { Injectable } from "@nestjs/common";
import { HealthCheckError, HealthIndicator, HealthIndicatorResult } from "@nestjs/terminus";
import { PrismaService } from "./prisma.service";

@Injectable()
export class PrismaHealthIndicator extends HealthIndicator {
  constructor(private readonly prismaService: PrismaService) {
    super();
  }

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    try {
      await this.prismaService.$queryRaw`SELECT 1`;
      return this.getStatus(key, true);
    } catch (e) {
      throw new HealthCheckError("Prisma check failed", e);
    }
  }
}

This injects a PrismaService exactly as it is shown in the NestJS docs. https://docs.nestjs.com/recipes/prisma#use-prisma-client-in-your-nestjs-services

You could alternatively replace prismaService with new PrismaClient().

Primer answered 11/3, 2022 at 22:26 Comment(1)
Could you please add an example of how you'd use PrismaHealthIndicator in a health check controllerSortilege
C
5

A naive copy of the mongoose implementation isn't going to work because there are differences between the NestJSMongoose type/module and Prisma. In particular, getConnectionToken does not exist inside the Prisma package.

I can't comment on what the best way would be to extend terminus to support prisma. You might have to dig a bit into the terminus interface for that. However, a simple way to get a health check/ping in Prisma is to use the following query:

    prisma.$queryRaw`SELECT 1`
Culinary answered 14/10, 2021 at 14:41 Comment(0)
T
0

@Jeff's answer is very good, but if you want the error state to be properly formatted you should throw the error like this:

// keep in mind that it is not recommended to send server errors directly to the client,
// you may not want to expose your DB location or other sensitive data
Logger.error(error, `${PrismaHealthIndicator.name}::isHealthy`)

throw new HealthCheckError(
  'cannot perform DB checks',
  this.getStatus(key, false, {
    message: 'cannot perform DB checks'
  })
)

docs: https://docs.nestjs.com/recipes/terminus#custom-health-indicator

Trevelyan answered 26/3, 2023 at 12:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.