Fixing some issues with the cron job waiting until 7 and adding a unit test for it
This commit is contained in:
parent
9e8f2598f5
commit
95019a86cf
2 changed files with 142 additions and 13 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { InjectQueue } from '@nestjs/bull'
|
||||
import { Inject, Injectable } from '@nestjs/common'
|
||||
import { Cron, CronExpression } from '@nestjs/schedule'
|
||||
import { Dayjs } from 'dayjs'
|
||||
|
||||
import dayjs from '../common/dayjs'
|
||||
import { LoggerService } from '../logger/service.logger'
|
||||
|
|
@ -30,6 +31,19 @@ export class ReservationsCronService {
|
|||
private readonly loggerService: LoggerService,
|
||||
) {}
|
||||
|
||||
private async sleepUntil(time: Dayjs) {
|
||||
let keepSleeping = true
|
||||
|
||||
while (keepSleeping) {
|
||||
const now = dayjs()
|
||||
keepSleeping = !time.isBefore(now)
|
||||
if (!keepSleeping) break
|
||||
await new Promise((res) => {
|
||||
setTimeout(() => res(null), 50)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Cron('55 06 * * *', {
|
||||
name: 'handleDailyReservations',
|
||||
timeZone: 'Europe/Amsterdam',
|
||||
|
|
@ -48,19 +62,13 @@ export class ReservationsCronService {
|
|||
|
||||
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
|
||||
}
|
||||
await this.sleepUntil(
|
||||
dayjs()
|
||||
.set('hour', 7)
|
||||
.set('minute', 0)
|
||||
.set('second', 0)
|
||||
.set('millisecond', 0),
|
||||
)
|
||||
|
||||
this.loggerService.log(`It's go-time`)
|
||||
|
||||
|
|
|
|||
121
test/unit/reservations/cron.spec.ts
Normal file
121
test/unit/reservations/cron.spec.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import { ConfigModule } from '@nestjs/config'
|
||||
import { Test, TestingModule } from '@nestjs/testing'
|
||||
import { TypeOrmModule } from '@nestjs/typeorm'
|
||||
|
||||
import { LoggerModule } from '../../../src/logger/module'
|
||||
import { LoggerService } from '../../../src/logger/service.logger'
|
||||
import { NtfyModule } from '../../../src/ntfy/module'
|
||||
import { NtfyProvider } from '../../../src/ntfy/provider'
|
||||
import { ReservationsCronService } from '../../../src/reservations/cron'
|
||||
import { Reservation } from '../../../src/reservations/entity'
|
||||
import { ReservationsModule } from '../../../src/reservations/module'
|
||||
import { ReservationsService } from '../../../src/reservations/service'
|
||||
import { BaanReserverenService } from '../../../src/runner/baanreserveren/service'
|
||||
import { RunnerModule } from '../../../src/runner/module'
|
||||
|
||||
describe('reservations.cron', () => {
|
||||
let module: TestingModule
|
||||
let cronService: ReservationsCronService
|
||||
|
||||
beforeAll(async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [
|
||||
ReservationsModule,
|
||||
RunnerModule,
|
||||
NtfyModule,
|
||||
LoggerModule,
|
||||
ConfigModule.forRoot({ isGlobal: true }),
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'sqlite',
|
||||
database: ':memory:',
|
||||
entities: [Reservation],
|
||||
}),
|
||||
],
|
||||
}).compile()
|
||||
|
||||
cronService = module.get<ReservationsCronService>(ReservationsCronService)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await module.close()
|
||||
})
|
||||
|
||||
describe('handleDailyReservations', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(
|
||||
module.get<NtfyProvider>(NtfyProvider),
|
||||
'sendCronStartNotification',
|
||||
)
|
||||
jest.spyOn(
|
||||
module.get<NtfyProvider>(NtfyProvider),
|
||||
'sendCronStopNotification',
|
||||
)
|
||||
})
|
||||
|
||||
describe('has scheduleable reservations', () => {
|
||||
const stubbedReservation = { id: 'abc-123' }
|
||||
let warmupSpy: jest.SpyInstance
|
||||
let performReservationSpy: jest.SpyInstance
|
||||
let loggerSpy: jest.SpyInstance
|
||||
const loggerInvocationDates: { msg: string; timestamp: Date }[] = []
|
||||
|
||||
beforeAll(async () => {
|
||||
jest
|
||||
.spyOn(
|
||||
module.get<ReservationsService>(ReservationsService),
|
||||
'getSchedulable',
|
||||
)
|
||||
// @ts-expect-error stubbed reservation
|
||||
.mockResolvedValue([stubbedReservation])
|
||||
|
||||
warmupSpy = jest
|
||||
.spyOn(
|
||||
module.get<BaanReserverenService>(BaanReserverenService),
|
||||
'warmup',
|
||||
)
|
||||
.mockReturnValue(new Promise((res) => setTimeout(res, 1000)))
|
||||
|
||||
performReservationSpy = jest
|
||||
.spyOn(
|
||||
module.get<BaanReserverenService>(BaanReserverenService),
|
||||
'performReservation',
|
||||
)
|
||||
.mockResolvedValue()
|
||||
|
||||
loggerSpy = jest
|
||||
.spyOn(module.get<LoggerService>(LoggerService), 'log')
|
||||
.mockImplementation((msg: string) => {
|
||||
loggerInvocationDates.push({ msg, timestamp: new Date() })
|
||||
})
|
||||
|
||||
jest
|
||||
.useFakeTimers({ advanceTimers: true })
|
||||
.setSystemTime(new Date('2024-01-01T06:59:58.050+01:00'))
|
||||
|
||||
await cronService.handleDailyReservations()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers()
|
||||
})
|
||||
|
||||
it('should perform warmup', () => {
|
||||
expect(warmupSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should wait until 7am', () => {
|
||||
expect(loggerSpy).toHaveBeenCalledTimes(5)
|
||||
const { timestamp: goTimeInvocation } =
|
||||
loggerInvocationDates.find(({ msg }) => msg === `It's go-time`) ?? {}
|
||||
expect(goTimeInvocation).toBeDefined()
|
||||
expect(goTimeInvocation?.getHours()).toEqual(7)
|
||||
expect(goTimeInvocation?.getSeconds()).toEqual(0)
|
||||
expect(goTimeInvocation?.getMilliseconds()).toBeLessThanOrEqual(100)
|
||||
})
|
||||
|
||||
it('should perform reservations', () => {
|
||||
expect(performReservationSpy).toHaveBeenCalledWith(stubbedReservation)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Reference in a new issue