mirror of
https://github.com/movie-web/backend.git
synced 2025-09-13 16:33:26 +00:00
scheduled cleanup jobs
This commit is contained in:
@@ -29,7 +29,7 @@ Backend for movie-web
|
||||
- [X] catpcha support
|
||||
- [X] global namespacing (accounts are stored on a namespace)
|
||||
- [ ] cleanup jobs
|
||||
- [ ] cleanup expired sessions
|
||||
- [X] cleanup expired sessions
|
||||
- [ ] cleanup old provider metrics
|
||||
|
||||
## Second todo list
|
||||
|
@@ -36,6 +36,7 @@
|
||||
"@fastify/cors": "^8.3.0",
|
||||
"@mikro-orm/core": "^5.9.0",
|
||||
"@mikro-orm/postgresql": "^5.9.0",
|
||||
"cron": "^3.1.5",
|
||||
"fastify": "^4.21.0",
|
||||
"fastify-metrics": "^10.3.2",
|
||||
"fastify-type-provider-zod": "^1.1.9",
|
||||
|
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ dependencies:
|
||||
'@mikro-orm/postgresql':
|
||||
specifier: ^5.9.0
|
||||
version: 5.9.0(@mikro-orm/core@5.9.0)
|
||||
cron:
|
||||
specifier: ^3.1.5
|
||||
version: 3.1.5
|
||||
fastify:
|
||||
specifier: ^4.21.0
|
||||
version: 4.24.3
|
||||
@@ -432,6 +435,10 @@ packages:
|
||||
'@types/node': 20.8.9
|
||||
dev: true
|
||||
|
||||
/@types/luxon@3.3.3:
|
||||
resolution: {integrity: sha512-/BJF3NT0pRMuxrenr42emRUF67sXwcZCd+S1ksG/Fcf9O7C3kKCY4uJSbKBE4KDUIYr3WMsvfmWD8hRjXExBJQ==}
|
||||
dev: false
|
||||
|
||||
/@types/node@20.8.9:
|
||||
resolution: {integrity: sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==}
|
||||
dependencies:
|
||||
@@ -892,6 +899,13 @@ packages:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
dev: true
|
||||
|
||||
/cron@3.1.5:
|
||||
resolution: {integrity: sha512-e/ivHUhSZVvF5PUqgj7dzQ96KqAhK1/peMDr5Mmfm/vEho01/O+ySJnhTBJ2JPvFEWXpjLESIJBke0ZpZ7r7FA==}
|
||||
dependencies:
|
||||
'@types/luxon': 3.3.3
|
||||
luxon: 3.4.3
|
||||
dev: false
|
||||
|
||||
/cross-spawn@7.0.3:
|
||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -1830,6 +1844,11 @@ packages:
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
|
||||
/luxon@3.4.3:
|
||||
resolution: {integrity: sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/make-error@1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: true
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { setupFastify, startFastify } from '@/modules/fastify';
|
||||
import { setupJobs } from '@/modules/jobs';
|
||||
import { setupMetrics } from '@/modules/metrics';
|
||||
import { setupMikroORM } from '@/modules/mikro';
|
||||
import { scopedLogger } from '@/services/logger';
|
||||
@@ -13,6 +14,7 @@ async function bootstrap(): Promise<void> {
|
||||
const app = await setupFastify();
|
||||
await setupMikroORM();
|
||||
await setupMetrics(app);
|
||||
await setupJobs();
|
||||
|
||||
await startFastify(app);
|
||||
|
||||
|
5
src/modules/jobs/index.ts
Normal file
5
src/modules/jobs/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { sessionExpiryJob } from '@/modules/jobs/list/sessionExpiry';
|
||||
|
||||
export async function setupJobs() {
|
||||
sessionExpiryJob.start();
|
||||
}
|
43
src/modules/jobs/job.ts
Normal file
43
src/modules/jobs/job.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { getORM } from '@/modules/mikro';
|
||||
import { scopedLogger } from '@/services/logger';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { CronJob } from 'cron';
|
||||
|
||||
const minOffset = 0;
|
||||
const maxOffset = 60 * 4;
|
||||
const secondsOffset =
|
||||
Math.floor(Math.random() * (maxOffset - minOffset)) + minOffset;
|
||||
|
||||
const log = scopedLogger('jobs');
|
||||
|
||||
const wait = (sec: number) =>
|
||||
new Promise<void>((resolve) => {
|
||||
setTimeout(() => resolve(), sec * 1000);
|
||||
});
|
||||
|
||||
/**
|
||||
* @param cron crontime in this order: (min of hour) (hour of day) (day of month) (day of week) (sec of month)
|
||||
*/
|
||||
export function job(
|
||||
cron: string,
|
||||
cb: (ctx: { em: EntityManager }) => Promise<void>,
|
||||
): CronJob {
|
||||
return CronJob.from({
|
||||
cronTime: cron,
|
||||
onTick: async () => {
|
||||
// offset by random amount of seconds, just to prevent jobs running at
|
||||
// the same time when running multiple instances
|
||||
await wait(secondsOffset);
|
||||
|
||||
// actually run the job
|
||||
try {
|
||||
const em = getORM().em.fork();
|
||||
await cb({ em });
|
||||
} catch (err) {
|
||||
log.error('Failed to run job!');
|
||||
log.error(err);
|
||||
}
|
||||
},
|
||||
start: false,
|
||||
});
|
||||
}
|
15
src/modules/jobs/list/sessionExpiry.ts
Normal file
15
src/modules/jobs/list/sessionExpiry.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Session } from '@/db/models/Session';
|
||||
import { job } from '@/modules/jobs/job';
|
||||
|
||||
// every day at 12:00:00
|
||||
export const sessionExpiryJob = job('0 12 * * *', async ({ em }) => {
|
||||
await em
|
||||
.createQueryBuilder(Session)
|
||||
.delete()
|
||||
.where({
|
||||
expiresAt: {
|
||||
$lt: new Date(),
|
||||
},
|
||||
})
|
||||
.execute();
|
||||
});
|
Reference in New Issue
Block a user