From 28f730cf8171aed08e9bf107cbd4b02766b9a1df Mon Sep 17 00:00:00 2001 From: Collin Duncan <3679940+cgduncan7@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:05:33 +0100 Subject: [PATCH] Fixing monitors and migrating them to use strings instead of blobs --- .../migrations/1711456637438-BlobToVarchar.ts | 19 +++++++++++++++++ src/monitoring/entity.ts | 13 ++++-------- src/monitoring/module.ts | 3 ++- src/monitoring/service.ts | 2 +- src/monitoring/worker.ts | 21 +++++++++++++++++-- src/reservations/cron.ts | 9 +------- src/runner/baanreserveren/service.ts | 6 ++---- 7 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 database/migrations/1711456637438-BlobToVarchar.ts diff --git a/database/migrations/1711456637438-BlobToVarchar.ts b/database/migrations/1711456637438-BlobToVarchar.ts new file mode 100644 index 0000000..1e5ae75 --- /dev/null +++ b/database/migrations/1711456637438-BlobToVarchar.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class BlobToVarchar1711456637438 implements MigrationInterface { + name = 'BlobToVarchar1711456637438' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "monitors" DROP COLUMN "data";`) + await queryRunner.query( + `ALTER TABLE "monitors" ADD COLUMN "data" varchar NOT NULL;`, + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "monitors" DROP COLUMN "data";`) + await queryRunner.query( + `ALTER TABLE "monitors" ADD COLUMN "data" blob NOT NULL;`, + ) + } +} diff --git a/src/monitoring/entity.ts b/src/monitoring/entity.ts index 4cb7b3c..3561b35 100644 --- a/src/monitoring/entity.ts +++ b/src/monitoring/entity.ts @@ -19,8 +19,9 @@ export class Monitor { @Column('datetime', { nullable: false, + default: dayjs(), transformer: { - to: (value: Dayjs) => value.format(), + to: (value?: Dayjs) => (value ?? dayjs()).format(), from: (value: Date) => dayjs(value), }, }) @@ -37,14 +38,8 @@ export class Monitor { }) createdAt: Dayjs - @Column('blob', { - nullable: false, - transformer: { - to: (value) => value, - from: (value) => value, - }, - }) - data: unknown + @Column('varchar', { nullable: false }) + data: string constructor(partial: Partial) { Object.assign(this, partial) diff --git a/src/monitoring/module.ts b/src/monitoring/module.ts index 3d94ddd..1218c38 100644 --- a/src/monitoring/module.ts +++ b/src/monitoring/module.ts @@ -7,6 +7,7 @@ import { NtfyModule } from '../ntfy/module' import { MONITORING_QUEUE_NAME } from './config' import { Monitor } from './entity' import { MonitorsService } from './service' +import { MonitoringWorker } from './worker' @Module({ imports: [ @@ -15,7 +16,7 @@ import { MonitorsService } from './service' TypeOrmModule.forFeature([Monitor]), BullModule.registerQueueAsync({ name: MONITORING_QUEUE_NAME }), ], - providers: [MonitorsService], + providers: [MonitorsService, MonitoringWorker], exports: [MonitorsService], }) export class MonitoringModule {} diff --git a/src/monitoring/service.ts b/src/monitoring/service.ts index 9bff45e..6abe540 100644 --- a/src/monitoring/service.ts +++ b/src/monitoring/service.ts @@ -11,7 +11,7 @@ export class MonitorsService { private readonly monitorsRepository: Repository, ) {} - async performMonitor(type: MonitorType, data: unknown) { + async performMonitor(type: MonitorType, data: string) { await this.monitorsRepository.save( this.monitorsRepository.create({ type, data }), ) diff --git a/src/monitoring/worker.ts b/src/monitoring/worker.ts index e7909d1..a7e7406 100644 --- a/src/monitoring/worker.ts +++ b/src/monitoring/worker.ts @@ -2,13 +2,14 @@ import { Process, Processor } from '@nestjs/bull' import { Inject } from '@nestjs/common' import { Job } from 'bull' +import { LoggerService } from '../logger/service.logger' import { MONITORING_QUEUE_NAME } from './config' import { MonitorType } from './entity' import { MonitorsService } from './service' export interface MonitoringQueueData { type: MonitorType - data: unknown + data: any } @Processor(MONITORING_QUEUE_NAME) @@ -16,10 +17,26 @@ export class MonitoringWorker { constructor( @Inject(MonitorsService) private readonly monitorsService: MonitorsService, + + @Inject(LoggerService) + private readonly loggerService: LoggerService, ) {} @Process() async handleMonitoringCourtsJob(job: Job) { - await this.monitorsService.performMonitor(job.data.type, job.data.data) + let json + try { + json = JSON.stringify(job.data.data) + } catch (error) { + this.loggerService.error('Could not stringify data') + return + } + await this.monitorsService + .performMonitor(job.data.type, json) + .catch((error) => + this.loggerService.error( + `Failed to monitor courts: ${(error as Error).message}`, + ), + ) } } diff --git a/src/reservations/cron.ts b/src/reservations/cron.ts index e1bde10..09005bc 100644 --- a/src/reservations/cron.ts +++ b/src/reservations/cron.ts @@ -25,9 +25,6 @@ export class ReservationsCronService { @InjectQueue(RESERVATIONS_QUEUE_NAME) private readonly reservationsQueue: ReservationsQueue, - @InjectQueue(MONITORING_QUEUE_NAME) - private readonly monitoringQueue: MonitoringQueue, - @Inject(NtfyProvider) private readonly ntfyProvider: NtfyProvider, @@ -55,11 +52,7 @@ export class ReservationsCronService { ) } else { this.loggerService.log('Monitoring reservations') - const monitorData = await this.brService.monitorCourtReservations(dayjs()) - await this.monitoringQueue.add({ - type: MonitorType.CourtReservations, - data: monitorData, - }) + await this.brService.monitorCourtReservations(dayjs()) } this.loggerService.log('handleDailyReservations ending') await this.ntfyProvider.sendCronStopNotification( diff --git a/src/runner/baanreserveren/service.ts b/src/runner/baanreserveren/service.ts index 50e6260..616d78c 100644 --- a/src/runner/baanreserveren/service.ts +++ b/src/runner/baanreserveren/service.ts @@ -1,16 +1,14 @@ import { InjectQueue } from '@nestjs/bull' import { Inject, Injectable } from '@nestjs/common' import { ConfigService } from '@nestjs/config' -import { Queue } from 'bull' import { instanceToPlain } from 'class-transformer' import { Dayjs } from 'dayjs' import { ElementHandle, Page } from 'puppeteer' import dayjs from '../../common/dayjs' import { LoggerService } from '../../logger/service.logger' -import { MONITORING_QUEUE_NAME } from '../../monitoring/config' +import { MONITORING_QUEUE_NAME, MonitoringQueue } from '../../monitoring/config' import { MonitorType } from '../../monitoring/entity' -import { MonitoringQueueData } from '../../monitoring/worker' import { Reservation } from '../../reservations/entity' import { EmptyPage } from '../pages/empty' @@ -95,7 +93,7 @@ export class BaanReserverenService { constructor( @InjectQueue(MONITORING_QUEUE_NAME) - private readonly monitoringQueue: Queue, + private readonly monitoringQueue: MonitoringQueue, @Inject(LoggerService) private readonly loggerService: LoggerService,