2023-05-26 15:43:14 -05:00
|
|
|
import { InjectQueue } from '@nestjs/bull'
|
|
|
|
|
import { Inject, Injectable } from '@nestjs/common'
|
|
|
|
|
import { Cron, CronExpression } from '@nestjs/schedule'
|
2023-06-29 10:32:09 +02:00
|
|
|
|
2024-03-14 12:27:47 +01:00
|
|
|
import dayjs from '../common/dayjs'
|
2023-08-29 10:44:12 +02:00
|
|
|
import { LoggerService } from '../logger/service.logger'
|
2023-09-06 11:23:21 +02:00
|
|
|
import { NtfyProvider } from '../ntfy/provider'
|
2024-03-14 12:27:47 +01:00
|
|
|
import { BaanReserverenService } from '../runner/baanreserveren/service'
|
|
|
|
|
import { RESERVATIONS_QUEUE_NAME, ReservationsQueue } from './config'
|
2023-05-26 15:43:14 -05:00
|
|
|
import { ReservationsService } from './service'
|
|
|
|
|
|
2024-02-23 07:35:35 -06:00
|
|
|
export const DAILY_RESERVATIONS_ATTEMPTS = 2
|
|
|
|
|
|
2023-05-26 15:43:14 -05:00
|
|
|
@Injectable()
|
|
|
|
|
export class ReservationsCronService {
|
|
|
|
|
constructor(
|
|
|
|
|
@Inject(ReservationsService)
|
|
|
|
|
private readonly reservationService: ReservationsService,
|
2023-06-27 16:06:19 +02:00
|
|
|
|
2024-03-14 12:27:47 +01:00
|
|
|
@Inject(BaanReserverenService)
|
|
|
|
|
private readonly brService: BaanReserverenService,
|
|
|
|
|
|
2023-05-26 15:43:14 -05:00
|
|
|
@InjectQueue(RESERVATIONS_QUEUE_NAME)
|
2024-03-14 12:27:47 +01:00
|
|
|
private readonly reservationsQueue: ReservationsQueue,
|
|
|
|
|
|
2023-09-06 11:23:21 +02:00
|
|
|
@Inject(NtfyProvider)
|
|
|
|
|
private readonly ntfyProvider: NtfyProvider,
|
|
|
|
|
|
2023-05-26 15:43:14 -05:00
|
|
|
@Inject(LoggerService)
|
2023-07-29 14:58:48 +02:00
|
|
|
private readonly loggerService: LoggerService,
|
2023-05-26 15:43:14 -05:00
|
|
|
) {}
|
|
|
|
|
|
2024-04-09 23:19:57 +02:00
|
|
|
@Cron('55 06 * * *', {
|
2023-05-26 15:43:14 -05:00
|
|
|
name: 'handleDailyReservations',
|
|
|
|
|
timeZone: 'Europe/Amsterdam',
|
|
|
|
|
})
|
|
|
|
|
async handleDailyReservations() {
|
2023-08-29 10:44:12 +02:00
|
|
|
this.loggerService.log('handleDailyReservations beginning')
|
2023-09-06 11:23:21 +02:00
|
|
|
await this.ntfyProvider.sendCronStartNotification('handleDailyReservations')
|
2023-09-13 12:01:06 +02:00
|
|
|
const reservationsToPerform = await this.reservationService.getSchedulable()
|
2024-03-14 12:27:47 +01:00
|
|
|
if (reservationsToPerform.length > 0) {
|
|
|
|
|
this.loggerService.log(
|
|
|
|
|
`Found ${reservationsToPerform.length} reservations to perform`,
|
|
|
|
|
)
|
2024-04-09 23:19:57 +02:00
|
|
|
|
|
|
|
|
// In order to make sure session is fresh and speed up some shit let's warm him up
|
|
|
|
|
await this.brService.warmup()
|
|
|
|
|
|
|
|
|
|
this.loggerService.log(`Warmed up! Waiting for go-time`)
|
|
|
|
|
|
|
|
|
|
let not7AM = true
|
|
|
|
|
const waitTime = 10
|
|
|
|
|
const time7AM = dayjs()
|
|
|
|
|
.set('hour', 7)
|
|
|
|
|
.set('minute', 0)
|
|
|
|
|
.set('second', 0)
|
|
|
|
|
.set('millisecond', 0)
|
|
|
|
|
|
|
|
|
|
while (not7AM) {
|
|
|
|
|
not7AM = time7AM.isBefore(dayjs()) && time7AM.diff(dayjs()) >= waitTime // current time is more than 100ms from 7am
|
|
|
|
|
if (!not7AM) break
|
|
|
|
|
await new Promise((res) => setTimeout(res, waitTime)) // wait for waitTime and then try again
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.loggerService.log(`It's go-time`)
|
|
|
|
|
|
|
|
|
|
for (const res of reservationsToPerform) {
|
|
|
|
|
await this.brService.performReservation(res).catch(
|
|
|
|
|
async () =>
|
|
|
|
|
await this.reservationsQueue.add(res, {
|
|
|
|
|
attempts: Math.max(DAILY_RESERVATIONS_ATTEMPTS - 1, 1),
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
}
|
2024-03-14 12:27:47 +01:00
|
|
|
} else {
|
|
|
|
|
this.loggerService.log('Monitoring reservations')
|
2024-03-27 09:30:51 +01:00
|
|
|
await this.brService.monitorCourtReservations(dayjs().add(7, 'day'))
|
2024-03-14 12:27:47 +01:00
|
|
|
}
|
2023-08-29 10:44:12 +02:00
|
|
|
this.loggerService.log('handleDailyReservations ending')
|
2023-09-06 11:23:21 +02:00
|
|
|
await this.ntfyProvider.sendCronStopNotification(
|
|
|
|
|
'handleDailyReservations',
|
|
|
|
|
`Count: ${reservationsToPerform.length}`,
|
|
|
|
|
)
|
2023-06-27 16:06:19 +02:00
|
|
|
}
|
2023-07-29 15:23:13 +02:00
|
|
|
|
|
|
|
|
@Cron(CronExpression.EVERY_DAY_AT_11PM, {
|
|
|
|
|
name: 'cleanUpExpiredReservations',
|
|
|
|
|
timeZone: 'Europe/Amsterdam',
|
|
|
|
|
})
|
|
|
|
|
async cleanUpExpiredReservations() {
|
2023-08-29 10:44:12 +02:00
|
|
|
this.loggerService.log('cleanUpExpiredReservations beginning')
|
2023-09-06 11:23:21 +02:00
|
|
|
await this.ntfyProvider.sendCronStartNotification(
|
|
|
|
|
'cleanUpExpiredReservations',
|
|
|
|
|
)
|
2023-07-29 15:23:13 +02:00
|
|
|
const reservations = await this.reservationService.getByDate()
|
|
|
|
|
this.loggerService.log(
|
|
|
|
|
`Found ${reservations.length} reservations to delete`,
|
|
|
|
|
)
|
|
|
|
|
for (const reservation of reservations) {
|
|
|
|
|
await this.reservationService.deleteById(reservation.id)
|
|
|
|
|
}
|
2023-08-29 10:44:12 +02:00
|
|
|
this.loggerService.log('cleanUpExpiredReservations ending')
|
2023-09-06 11:23:21 +02:00
|
|
|
await this.ntfyProvider.sendCronStopNotification(
|
|
|
|
|
'cleanUpExpiredReservations',
|
|
|
|
|
`Count: ${reservations.length}`,
|
|
|
|
|
)
|
2023-07-29 15:23:13 +02:00
|
|
|
}
|
2023-05-26 15:43:14 -05:00
|
|
|
}
|