-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding report locking cron job (#363)
- Loading branch information
Showing
19 changed files
with
341 additions
and
390 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import './delete-draft-service-scheduler'; | ||
import './lock-reports-scheduler'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import waitFor from 'wait-for-expect'; | ||
import { LocalDateTime, ZoneId, convert } from '@js-joda/core'; | ||
import createPrismaMock from 'prisma-mock'; | ||
import { Prisma, PrismaClient } from '@prisma/client'; | ||
|
||
let prismaClient: PrismaClient< | ||
Prisma.PrismaClientOptions, | ||
'query' | 'info' | 'warn' | 'error' | ||
>; | ||
|
||
const mock_prismaClient = () => prismaClient; | ||
|
||
jest.mock('../v1/prisma/prisma-client', () => ({ | ||
__esModule: true, | ||
...jest.requireActual('../v1/prisma/prisma-client'), | ||
default: mock_prismaClient(), | ||
})); | ||
|
||
jest.mock('cron', () => ({ | ||
CronJob: class MockCron { | ||
constructor( | ||
public expression: string, | ||
public cb: Function, | ||
) {} | ||
async start() { | ||
return this.cb(); | ||
} | ||
}, | ||
})); | ||
|
||
jest.mock('../config', () => ({ | ||
config: { | ||
get: (key: string) => { | ||
const settings = { | ||
'server:reportEditDurationInDays': 30, | ||
'server:reportUnlockDurationInDays': 2 | ||
} | ||
|
||
return settings[key]; | ||
} | ||
} | ||
})) | ||
|
||
const mock_tryLock = jest.fn(); | ||
const mock_unlock = jest.fn(); | ||
jest.mock('advisory-lock', () => ({ | ||
...jest.requireActual('advisory-lock'), | ||
default: () => { | ||
return () => ({ | ||
tryLock: () => mock_tryLock(), | ||
}); | ||
}, | ||
})); | ||
|
||
describe('lock-report-scheduler', () => { | ||
beforeEach(async () => { | ||
prismaClient = createPrismaMock( | ||
{ | ||
pay_transparency_report: [ | ||
// Cannot be locked | ||
{ | ||
report_id: '1', | ||
is_unlocked: true, | ||
report_status: 'Published', | ||
create_date: convert(LocalDateTime.now(ZoneId.UTC)).toDate(), | ||
report_unlock_date: null, | ||
}, | ||
// Can be locked, older than default editable period (30 days) | ||
{ | ||
report_id: '2', | ||
is_unlocked: true, | ||
report_status: 'Published', | ||
create_date: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays(40), | ||
).toDate(), | ||
report_unlock_date: null, | ||
}, | ||
// Cannot be locked, before report_unlock_date | ||
{ | ||
report_id: '3', | ||
is_unlocked: true, | ||
report_status: 'Published', | ||
create_date: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays(40), | ||
).toDate(), | ||
report_unlock_date: convert( | ||
LocalDateTime.now(ZoneId.UTC)).toDate(), | ||
}, | ||
// Can be locked, past report_unlock_date | ||
{ | ||
report_id: '4', | ||
is_unlocked: true, | ||
report_status: 'Published', | ||
create_date: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays(40), | ||
).toDate(), | ||
report_unlock_date: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays(3), | ||
).toDate(), | ||
}, | ||
// Cannot be locked, not published | ||
{ | ||
report_id: '5', | ||
is_unlocked: true, | ||
report_status: 'Draft', | ||
create_date: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays(40), | ||
).toDate(), | ||
report_unlock_date: convert( | ||
LocalDateTime.now(ZoneId.UTC).plusDays(3), | ||
).toDate(), | ||
}, | ||
], | ||
}, | ||
Prisma.dmmf.datamodel, | ||
); | ||
}); | ||
|
||
it('should lock all lockable reports', async () => { | ||
mock_tryLock.mockReturnValue(mock_unlock); | ||
await require('./lock-reports-scheduler'); | ||
await waitFor(async () => { | ||
expect(mock_tryLock).toHaveBeenCalledTimes(1); | ||
expect(mock_unlock).toHaveBeenCalledTimes(1); | ||
const reports = await prismaClient.pay_transparency_report.findMany({ | ||
select: { report_id: true, is_unlocked: true }, | ||
}); | ||
expect(reports.find(r => r.report_id === '1').is_unlocked).toBeTruthy(); | ||
expect(reports.find(r => r.report_id === '2').is_unlocked).toBeFalsy(); | ||
expect(reports.find(r => r.report_id === '3').is_unlocked).toBeTruthy(); | ||
expect(reports.find(r => r.report_id === '4').is_unlocked).toBeFalsy(); | ||
expect(reports.find(r => r.report_id === '5').is_unlocked).toBeTruthy(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { CronJob } from 'cron'; | ||
import { config } from '../config'; | ||
import { logger as log } from '../logger'; | ||
import advisoryLock from 'advisory-lock'; | ||
import prisma from '../v1/prisma/prisma-client'; | ||
import { LocalDateTime, ZoneId, convert } from '@js-joda/core'; | ||
|
||
try { | ||
const mutex = advisoryLock(config.get('server:databaseUrl'))('lock_reports'); | ||
const crontime = config.get('server:schedulerLockReportCronTime'); | ||
const timezone = config.get('server:schedulerTimeZone'); | ||
const reportEditDurationInDays = config.get( | ||
'server:reportEditDurationInDays', | ||
); | ||
const reportUnlockDurationInDays = config.get( | ||
'server:reportUnlockDurationInDays', | ||
); | ||
|
||
const job = new CronJob( | ||
crontime, // cronTime | ||
async function () { | ||
try { | ||
const unlock = await mutex.tryLock(); | ||
if (unlock) { | ||
log.info('Starting report locking Schedule Job.'); | ||
await prisma.$transaction(async (tx) => { | ||
await tx.pay_transparency_report.updateMany({ | ||
data: { is_unlocked: false }, | ||
where: { | ||
AND: [ | ||
{ is_unlocked: true }, | ||
{ report_status: 'Published' }, | ||
{ | ||
OR: [ | ||
{ | ||
report_unlock_date: null, | ||
create_date: { | ||
lt: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays( | ||
reportEditDurationInDays, | ||
), | ||
).toDate(), | ||
}, | ||
}, | ||
{ | ||
report_unlock_date: { | ||
not: null, | ||
lt: convert( | ||
LocalDateTime.now(ZoneId.UTC).minusDays( | ||
reportUnlockDurationInDays, | ||
), | ||
).toDate(), | ||
}, | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
}); | ||
}); | ||
|
||
log.info('Report locking Schedule Job completed.'); | ||
await unlock(); | ||
} | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
log.error('Error in lockReports.'); | ||
/* istanbul ignore next */ | ||
log.error(e); | ||
} | ||
}, // onTick | ||
null, // onComplete | ||
true, // start | ||
timezone, // timeZone | ||
); | ||
job.start(); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
log.error(e); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.