Skip to content

Commit

Permalink
SIMSBIOHUB:587 prisma client bug fix (#66)
Browse files Browse the repository at this point in the history
* fix: removed default prisma client from base repository class

* feat: better structured prisma client singleton
  • Loading branch information
MacQSL authored Sep 10, 2024
1 parent ddd8265 commit 39acac5
Show file tree
Hide file tree
Showing 11 changed files with 39 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/api/bulk/bulk.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ const bulkDeleteData = async (bulkParams: IBulkDelete, db: ICbDatabase) => {
deleted: {}
};

const repository = new Repository();
const repository = new Repository(prisma);

//TODO: Update this service to use Promise.all once all services are refactored

Expand Down
22 changes: 15 additions & 7 deletions src/client/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { PrismaClient } from '@prisma/client';
import { captureExtension } from './extensions';
/**
* Prevents multiple unwated instances of PrismaClient when hot reloading (development).
* Note: Global variables are not affected on hot-reloads.
*
* @link https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#prevent-hot-reloading-from-creating-new-instances-of-prismaclient
*/
const globalPrismaClient = global as unknown as { prisma: PrismaClientExtended };

/**
* Extended Prisma client.
Expand All @@ -13,13 +20,14 @@ const extendedPrismaClient = new PrismaClient().$extends(captureExtension);
export type PrismaClientExtended = typeof extendedPrismaClient;

/**
* Prevents multiple unwated instances of PrismaClient when hot reloading (development).
* Note: Global variables are not affected on hot-reloads.
* Get the Prisma client singleton.
*
* @link https://www.prisma.io/docs/guides/performance-and-optimization/connection-management#prevent-hot-reloading-from-creating-new-instances-of-prismaclient
* @returns {PrismaClientExtended} The extended Prisma client.
*/
const globalPrisma = global as unknown as { prisma: PrismaClientExtended };

export const prismaClient = globalPrisma.prisma || extendedPrismaClient;
export const getPrismaClient = (): PrismaClientExtended => {
if (!globalPrismaClient.prisma) {
globalPrismaClient.prisma = extendedPrismaClient;
}

if (process.env.NODE_ENV !== 'production') globalPrisma.prisma = prismaClient;
return globalPrismaClient.prisma;
};
11 changes: 5 additions & 6 deletions src/repositories/base-repository.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Prisma, PrismaClient } from '@prisma/client';
import { Prisma } from '@prisma/client';
import { z } from 'zod';
import { PrismaClientExtended } from '../client/client';
import { apiError } from '../utils/types';
import { Repository } from './base-repository';

Expand All @@ -8,13 +9,13 @@ describe('base-repository', () => {

describe('constructor', () => {
it('should set variables to defaults', () => {
const repo = new Repository();
const repo = new Repository({} as unknown as PrismaClientExtended);
expect(repo.transactionTimeoutMilliseconds).toBeDefined();
expect(repo.prisma).toBeDefined();
});

it('should be able to inject new dependencies', () => {
const repo = new Repository('test' as unknown as PrismaClient, 1);
const repo = new Repository('test' as unknown as PrismaClientExtended, 1);
expect(repo.transactionTimeoutMilliseconds).toBe(1);
expect(repo.prisma).toBe('test');
});
Expand Down Expand Up @@ -68,8 +69,6 @@ describe('base-repository', () => {
});

describe('transactionHandler', () => {
//const repo = new Repository();

beforeEach(() => {
jest.useFakeTimers();
mockPrismaClient = {
Expand Down Expand Up @@ -129,7 +128,7 @@ describe('base-repository', () => {
});

describe('validateSameResponse', () => {
const repo = new Repository();
const repo = new Repository(mockPrismaClient);
it('should return new response when both objects are equal', () => {
expect(repo.validateSameResponse({ a: 1 }, { a: 1 })).toBeTruthy();
expect(repo.validateSameResponse([{ a: 1 }], [{ a: 1 }])).toBeTruthy();
Expand Down
4 changes: 2 additions & 2 deletions src/repositories/base-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Prisma } from '@prisma/client';
import { isDeepStrictEqual } from 'util';
import { z } from 'zod';
import { PrismaClientExtended } from '../client/client';
import { IS_DEV, prisma } from '../utils/constants';
import { IS_DEV } from '../utils/constants';
import { apiError } from '../utils/types';

/**
Expand All @@ -18,7 +18,7 @@ export class Repository {
prisma: PrismaClientExtended;
transactionTimeoutMilliseconds: number;

constructor(prismaClient: PrismaClientExtended = prisma, transactionTimeout = 5000) {
constructor(prismaClient: PrismaClientExtended, transactionTimeout = 5000) {
this.prisma = prismaClient;
this.transactionTimeoutMilliseconds = transactionTimeout;
}
Expand Down
3 changes: 2 additions & 1 deletion src/services/bulk-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BulkRepository } from '../repositories/bulk-repository';
import { prisma } from '../utils/constants';
import { Service } from './base-service';

/**
Expand Down Expand Up @@ -28,6 +29,6 @@ export class BulkService implements Service {
* @returns {BulkService}
*/
static init(): BulkService {
return new BulkService(new BulkRepository());
return new BulkService(new BulkRepository(prisma));
}
}
3 changes: 2 additions & 1 deletion src/services/capture-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Prisma } from '@prisma/client';
import { CaptureRepository } from '../repositories/capture-repository';
import { Capture, CaptureCreate, CaptureUpdate, DetailedCapture } from '../schemas/capture-schema';
import { prisma } from '../utils/constants';
import { Service } from './base-service';

/**
Expand Down Expand Up @@ -29,7 +30,7 @@ export class CaptureService implements Service {
* @returns {MarkingService}
*/
static init(): CaptureService {
return new CaptureService(new CaptureRepository());
return new CaptureService(new CaptureRepository(prisma));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/services/critter-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
SimilarCritterQuery
} from '../schemas/critter-schema';
import { CaptureMortalityGeometry } from '../schemas/spatial-schema';
import { defaultFormat } from '../utils/constants';
import { defaultFormat, prisma } from '../utils/constants';
import { QueryFormats } from '../utils/types';
import { Service } from './base-service';
import { CaptureService } from './capture-service';
Expand Down Expand Up @@ -61,7 +61,7 @@ export class CritterService implements Service {
* @returns {CritterService}
*/
static init(): CritterService {
return new CritterService(new CritterRepository(), {
return new CritterService(new CritterRepository(prisma), {
itisService: new ItisService(),
mortalityService: MortalityService.init(),
markingService: MarkingService.init(),
Expand Down
3 changes: 2 additions & 1 deletion src/services/marking-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { MarkingVerificationType } from '../api/marking/marking.utils';
import { MarkingRepository } from '../repositories/marking-repository';
import { IDetailedCritterMarking } from '../schemas/critter-schema';
import { prisma } from '../utils/constants';
import { Service } from './base-service';
import { ItisService } from './itis-service';

Expand Down Expand Up @@ -33,7 +34,7 @@ export class MarkingService implements Service {
* @returns {MarkingService}
*/
static init(): MarkingService {
return new MarkingService(new MarkingRepository(), new ItisService());
return new MarkingService(new MarkingRepository(prisma), new ItisService());
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/services/mortality-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { mortality } from '@prisma/client';
import { MortalityRepository } from '../repositories/mortality-repository';
import { IDetailedCritterMortality } from '../schemas/critter-schema';
import { MortalityCreate, MortalityDetailed, MortalityUpdate } from '../schemas/mortality-schema';
import { prisma } from '../utils/constants';
import { Service } from './base-service';
import { ItisService } from './itis-service';

Expand Down Expand Up @@ -34,7 +35,7 @@ export class MortalityService implements Service {
* @returns {MortalityService}
*/
static init(): MortalityService {
return new MortalityService(new MortalityRepository(), new ItisService());
return new MortalityService(new MortalityRepository(prisma), new ItisService());
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/services/xref-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ITsnQualitativeMeasurementOption,
ITsnQuantitativeMeasurement
} from '../schemas/xref-schema';
import { prisma } from '../utils/constants';
import { toSelectFormat } from '../utils/helper_functions';
import { ISelect, ISelectChildren } from '../utils/types';
import { Service } from './base-service';
Expand Down Expand Up @@ -43,7 +44,7 @@ export class XrefService implements Service {
* @returns {XrefService}
*/
static init(): XrefService {
return new XrefService(new XrefRepository(), new ItisService());
return new XrefService(new XrefRepository(prisma), new ItisService());
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { prismaClient } from '../client/client';
import { getPrismaClient } from '../client/client';
import { QueryFormats } from './types';

declare global {
Expand All @@ -16,6 +16,9 @@ declare global {
}
}

// Get the Prisma client singleton.
const prisma = getPrismaClient();

const api = '/api';
const routes = {
home: api,
Expand Down Expand Up @@ -50,7 +53,4 @@ const NO_AUTH = process.env.AUTHENTICATE === 'false';

const defaultFormat = QueryFormats.default;

// TODO: Update all prisma imports to client.ts
const prisma = prismaClient;

export { IS_DEV, IS_PROD, IS_TEST, NO_AUTH, PORT, defaultFormat, prisma, routes };

0 comments on commit 39acac5

Please sign in to comment.