From 1e1211b3746cd6a97210654096a085a0215ca6a2 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 29 Mar 2024 11:35:25 +0100 Subject: [PATCH] feat: in memory cache for drives and transmitters --- api/src/graphql/generated/drive/nexus.ts | 3 + .../graphql/generated/drive/schema.graphql | 1 + .../modules/document-drive/drive-resolver.ts | 2 +- api/src/modules/document/model.ts | 120 +++++++++++++++--- 4 files changed, 107 insertions(+), 19 deletions(-) diff --git a/api/src/graphql/generated/drive/nexus.ts b/api/src/graphql/generated/drive/nexus.ts index 08ac7be0..16ebeccb 100644 --- a/api/src/graphql/generated/drive/nexus.ts +++ b/api/src/graphql/generated/drive/nexus.ts @@ -281,6 +281,7 @@ export interface NexusGenObjects { purchasePrice: number; // Float! purchaseProceeds: number; // Float! realizedSurplus: number; // Float! + salesProceeds?: number | null; // Float spvId: string; // ID! totalDiscount: number; // Float! } @@ -737,6 +738,7 @@ export interface NexusGenFieldTypes { purchasePrice: number; // Float! purchaseProceeds: number; // Float! realizedSurplus: number; // Float! + salesProceeds: number | null; // Float spvId: string; // ID! totalDiscount: number; // Float! } @@ -1227,6 +1229,7 @@ export interface NexusGenFieldTypeNames { purchasePrice: 'Float' purchaseProceeds: 'Float' realizedSurplus: 'Float' + salesProceeds: 'Float' spvId: 'ID' totalDiscount: 'Float' } diff --git a/api/src/graphql/generated/drive/schema.graphql b/api/src/graphql/generated/drive/schema.graphql index f0b06e4e..f3174d5a 100644 --- a/api/src/graphql/generated/drive/schema.graphql +++ b/api/src/graphql/generated/drive/schema.graphql @@ -209,6 +209,7 @@ type FixedIncome { purchasePrice: Float! purchaseProceeds: Float! realizedSurplus: Float! + salesProceeds: Float spvId: ID! totalDiscount: Float! } diff --git a/api/src/modules/document-drive/drive-resolver.ts b/api/src/modules/document-drive/drive-resolver.ts index 39bb7f5e..5875d728 100644 --- a/api/src/modules/document-drive/drive-resolver.ts +++ b/api/src/modules/document-drive/drive-resolver.ts @@ -231,7 +231,7 @@ export const getDrive = queryField('drive', { resolve: async (_parent, args, ctx) => { try { const drive = await ctx.prisma.document.getDrive(ctx.driveId ?? '1'); - return drive.global; + return drive; } catch (e) { return null; } diff --git a/api/src/modules/document/model.ts b/api/src/modules/document/model.ts index 58cd6968..b183250a 100644 --- a/api/src/modules/document/model.ts +++ b/api/src/modules/document/model.ts @@ -8,17 +8,21 @@ import { PullResponderTransmitter, IReceiver, InternalTransmitter, + + } from 'document-drive'; import { PrismaStorage } from 'document-drive/storage/prisma'; import * as DocumentModelsLibs from 'document-model-libs/document-models'; import { module as DocumentModelLib } from 'document-model/document-model'; -import { DocumentModel, Operation } from 'document-model/document'; +import { DocumentModel, Operation, State } from 'document-model/document'; import { Listener, ListenerFilter, actions, reducer, + DocumentDriveState, + DocumentDriveAction } from 'document-model-libs/document-drive'; @@ -26,12 +30,17 @@ import { init } from './listenerManager'; import { getChildLogger } from '../../logger'; const logger = getChildLogger({ msgPrefix: 'Document Model' }); + export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { const documentModels = [ DocumentModelLib, ...Object.values(DocumentModelsLibs), ] as DocumentModel[]; + let transmitters: Record> = {}; + let lastAcceessedTransmitter: Record> = {}; + let drives: Record = {}; + const driveServer = new DocumentDriveServer( documentModels, new PrismaStorage(prisma as PrismaClient), @@ -42,13 +51,49 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { await init(driveServer, prisma); } + function clearDriveCache() { + drives = {}; + } + + function clearTransmitterCache() { + transmitters = {}; + lastAcceessedTransmitter = {}; + } + + function getTransmitter(driveId: string, transmitterId: string) { + if (!transmitters[driveId]) { + return undefined; + } + const transmitter = transmitters[driveId][transmitterId]; + return transmitter + } + + function setTransmitter(driveId: string, transmitterId: string, transmitter: PullResponderTransmitter) { + if (!transmitters[driveId]) { + transmitters[driveId] = {}; + } + transmitters[driveId][transmitterId] = transmitter; + } + + function updateLastAccessedTransmitter(driveId: string, transmitterId: string) { + if (!lastAcceessedTransmitter[driveId]) { + lastAcceessedTransmitter[driveId] = {}; + } + lastAcceessedTransmitter[driveId][transmitterId] = Date.now(); + } initialize(); + setInterval(() => { + clearDriveCache(); + clearTransmitterCache(); + }, 1000 * 60 * 15); + return { addDrive: async (args: DriveInput) => { try { await driveServer.addDrive(args); await initialize(); + clearDriveCache(); } catch (e) { throw new Error("Couldn't add drive"); } @@ -59,6 +104,7 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { deleteDrive: async (id: string) => { try { await driveServer.deleteDrive(id); + clearDriveCache(); } catch (e) { throw new Error("Couldn't delete drive"); } @@ -67,16 +113,33 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { }, getDrive: async (id: string) => { try { - const { state } = await driveServer.getDrive(id); - return state; + let drive = drives[id]; + console.log(drive); + if (!drive) { + const { state } = await driveServer.getDrive(id); + drives[id] = state.global; + return state.global; + } else { + return drive; + } + + } catch (e) { throw new Error("Couldn't get drive"); } }, getDrives: async () => { try { - const drives = await driveServer.getDrives(); - return drives; + let driveIds = Object.keys(drives); + if (driveIds.length > 0) { + return driveIds; + } + driveIds = await driveServer.getDrives() + driveIds.forEach((driveId) => { + transmitters[driveId] = {}; + }) + + return driveIds; } catch (e) { throw new Error("Couldn't get drives"); } @@ -84,7 +147,7 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { pushUpdates: async ( driveId: string, - operations: Operation[], + operations: Operation[], documentId?: string, ) => { if (!documentId) { @@ -111,13 +174,22 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { listenerId: string, since?: string, ): Promise => { - const transmitter = (await driveServer.getTransmitter( - driveId, - listenerId, - )) as PullResponderTransmitter; + + console.log(transmitters) + let transmitter: PullResponderTransmitter | undefined = getTransmitter(driveId, listenerId); if (!transmitter) { - throw new Error(`Transmitter with id ${listenerId} not found`); + transmitter = await driveServer.getTransmitter( + driveId, + listenerId, + ) as PullResponderTransmitter; + + if (!transmitter) { + throw new Error(`Transmitter with id ${listenerId} not found`); + } + setTransmitter(driveId, listenerId, transmitter); + updateLastAccessedTransmitter(driveId, listenerId); } + if (transmitter.getStrands) { const result = await transmitter.getStrands(since || undefined); return result; @@ -131,12 +203,17 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { listenerId: string, revisions: ListenerRevision[], ) => { - const transmitter = (await driveServer.getTransmitter( - driveId, - listenerId, - )) as PullResponderTransmitter; + let transmitter: PullResponderTransmitter | undefined = getTransmitter(driveId, listenerId); if (!transmitter) { - throw new Error(`Transmitter with id ${listenerId} not found`); + transmitter = await driveServer.getTransmitter( + driveId, + listenerId, + ) as PullResponderTransmitter; + if (!transmitter) { + throw new Error(`Transmitter with id ${listenerId} not found`); + } + setTransmitter(driveId, listenerId, transmitter); + updateLastAccessedTransmitter(driveId, listenerId); } const result = await transmitter.processAcknowledge( driveId, @@ -172,7 +249,9 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { let drive = await driveServer.getDrive(driveId); drive = reducer(drive, actions.addListener({ listener })); const operation = drive.operations.local.slice().pop(); - + if (!operation) { + throw new Error("Operation couldnt be applied") + } await driveServer.addDriveOperations(driveId, [operation]); return listener; }, @@ -184,8 +263,13 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { let drive = await driveServer.getDrive(driveId); drive = reducer(drive, actions.removeListener({ listenerId })); const operation = drive.operations.local.slice().pop(); + if (!operation) { + throw new Error("Operation couldnt be applied") + } await driveServer.addDriveOperations(driveId, [operation]); + delete transmitters[driveId][listenerId]; + delete lastAcceessedTransmitter[driveId][listenerId]; return listenerId; }, @@ -202,5 +286,5 @@ export function getDocumentDriveCRUD(prisma: Prisma.TransactionClient) { }; return response; }, - }; + } }