Fixing monitors and migrating them to use strings instead of blobs

This commit is contained in:
Collin Duncan 2024-03-26 14:05:33 +01:00
parent bbf38c8c2a
commit 28f730cf81
No known key found for this signature in database
7 changed files with 48 additions and 25 deletions

View file

@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class BlobToVarchar1711456637438 implements MigrationInterface {
name = 'BlobToVarchar1711456637438'
public async up(queryRunner: QueryRunner): Promise<void> {
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<void> {
await queryRunner.query(`ALTER TABLE "monitors" DROP COLUMN "data";`)
await queryRunner.query(
`ALTER TABLE "monitors" ADD COLUMN "data" blob NOT NULL;`,
)
}
}

View file

@ -19,8 +19,9 @@ export class Monitor {
@Column('datetime', { @Column('datetime', {
nullable: false, nullable: false,
default: dayjs(),
transformer: { transformer: {
to: (value: Dayjs) => value.format(), to: (value?: Dayjs) => (value ?? dayjs()).format(),
from: (value: Date) => dayjs(value), from: (value: Date) => dayjs(value),
}, },
}) })
@ -37,14 +38,8 @@ export class Monitor {
}) })
createdAt: Dayjs createdAt: Dayjs
@Column('blob', { @Column('varchar', { nullable: false })
nullable: false, data: string
transformer: {
to: (value) => value,
from: (value) => value,
},
})
data: unknown
constructor(partial: Partial<Monitor>) { constructor(partial: Partial<Monitor>) {
Object.assign(this, partial) Object.assign(this, partial)

View file

@ -7,6 +7,7 @@ import { NtfyModule } from '../ntfy/module'
import { MONITORING_QUEUE_NAME } from './config' import { MONITORING_QUEUE_NAME } from './config'
import { Monitor } from './entity' import { Monitor } from './entity'
import { MonitorsService } from './service' import { MonitorsService } from './service'
import { MonitoringWorker } from './worker'
@Module({ @Module({
imports: [ imports: [
@ -15,7 +16,7 @@ import { MonitorsService } from './service'
TypeOrmModule.forFeature([Monitor]), TypeOrmModule.forFeature([Monitor]),
BullModule.registerQueueAsync({ name: MONITORING_QUEUE_NAME }), BullModule.registerQueueAsync({ name: MONITORING_QUEUE_NAME }),
], ],
providers: [MonitorsService], providers: [MonitorsService, MonitoringWorker],
exports: [MonitorsService], exports: [MonitorsService],
}) })
export class MonitoringModule {} export class MonitoringModule {}

View file

@ -11,7 +11,7 @@ export class MonitorsService {
private readonly monitorsRepository: Repository<Monitor>, private readonly monitorsRepository: Repository<Monitor>,
) {} ) {}
async performMonitor(type: MonitorType, data: unknown) { async performMonitor(type: MonitorType, data: string) {
await this.monitorsRepository.save( await this.monitorsRepository.save(
this.monitorsRepository.create({ type, data }), this.monitorsRepository.create({ type, data }),
) )

View file

@ -2,13 +2,14 @@ import { Process, Processor } from '@nestjs/bull'
import { Inject } from '@nestjs/common' import { Inject } from '@nestjs/common'
import { Job } from 'bull' import { Job } from 'bull'
import { LoggerService } from '../logger/service.logger'
import { MONITORING_QUEUE_NAME } from './config' import { MONITORING_QUEUE_NAME } from './config'
import { MonitorType } from './entity' import { MonitorType } from './entity'
import { MonitorsService } from './service' import { MonitorsService } from './service'
export interface MonitoringQueueData { export interface MonitoringQueueData {
type: MonitorType type: MonitorType
data: unknown data: any
} }
@Processor(MONITORING_QUEUE_NAME) @Processor(MONITORING_QUEUE_NAME)
@ -16,10 +17,26 @@ export class MonitoringWorker {
constructor( constructor(
@Inject(MonitorsService) @Inject(MonitorsService)
private readonly monitorsService: MonitorsService, private readonly monitorsService: MonitorsService,
@Inject(LoggerService)
private readonly loggerService: LoggerService,
) {} ) {}
@Process() @Process()
async handleMonitoringCourtsJob(job: Job<MonitoringQueueData>) { async handleMonitoringCourtsJob(job: Job<MonitoringQueueData>) {
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}`,
),
)
} }
} }

View file

@ -25,9 +25,6 @@ export class ReservationsCronService {
@InjectQueue(RESERVATIONS_QUEUE_NAME) @InjectQueue(RESERVATIONS_QUEUE_NAME)
private readonly reservationsQueue: ReservationsQueue, private readonly reservationsQueue: ReservationsQueue,
@InjectQueue(MONITORING_QUEUE_NAME)
private readonly monitoringQueue: MonitoringQueue,
@Inject(NtfyProvider) @Inject(NtfyProvider)
private readonly ntfyProvider: NtfyProvider, private readonly ntfyProvider: NtfyProvider,
@ -55,11 +52,7 @@ export class ReservationsCronService {
) )
} else { } else {
this.loggerService.log('Monitoring reservations') this.loggerService.log('Monitoring reservations')
const monitorData = await this.brService.monitorCourtReservations(dayjs()) await this.brService.monitorCourtReservations(dayjs())
await this.monitoringQueue.add({
type: MonitorType.CourtReservations,
data: monitorData,
})
} }
this.loggerService.log('handleDailyReservations ending') this.loggerService.log('handleDailyReservations ending')
await this.ntfyProvider.sendCronStopNotification( await this.ntfyProvider.sendCronStopNotification(

View file

@ -1,16 +1,14 @@
import { InjectQueue } from '@nestjs/bull' import { InjectQueue } from '@nestjs/bull'
import { Inject, Injectable } from '@nestjs/common' import { Inject, Injectable } from '@nestjs/common'
import { ConfigService } from '@nestjs/config' import { ConfigService } from '@nestjs/config'
import { Queue } from 'bull'
import { instanceToPlain } from 'class-transformer' import { instanceToPlain } from 'class-transformer'
import { Dayjs } from 'dayjs' import { Dayjs } from 'dayjs'
import { ElementHandle, Page } from 'puppeteer' import { ElementHandle, Page } from 'puppeteer'
import dayjs from '../../common/dayjs' import dayjs from '../../common/dayjs'
import { LoggerService } from '../../logger/service.logger' 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 { MonitorType } from '../../monitoring/entity'
import { MonitoringQueueData } from '../../monitoring/worker'
import { Reservation } from '../../reservations/entity' import { Reservation } from '../../reservations/entity'
import { EmptyPage } from '../pages/empty' import { EmptyPage } from '../pages/empty'
@ -95,7 +93,7 @@ export class BaanReserverenService {
constructor( constructor(
@InjectQueue(MONITORING_QUEUE_NAME) @InjectQueue(MONITORING_QUEUE_NAME)
private readonly monitoringQueue: Queue<MonitoringQueueData>, private readonly monitoringQueue: MonitoringQueue,
@Inject(LoggerService) @Inject(LoggerService)
private readonly loggerService: LoggerService, private readonly loggerService: LoggerService,