feat: Scheduled Maintenance feature complete

This commit is contained in:
Eric Gullickson
2025-12-22 14:12:33 -06:00
parent c017b8816f
commit 91b4534e76
44 changed files with 2740 additions and 117 deletions

View File

@@ -5,18 +5,39 @@
import { FastifyPluginAsync, FastifyRequest, FastifyReply } from 'fastify';
import fp from 'fastify-plugin';
import buildGetJwks from 'get-jwks';
import fastifyJwt from '@fastify/jwt';
import { appConfig } from '../config/config-loader';
import { logger } from '../logging/logger';
import { UserProfileRepository } from '../../features/user-profile/data/user-profile.repository';
import { pool } from '../config/database';
// Define the Auth0 JWT payload type
interface Auth0JwtPayload {
sub: string;
email?: string;
name?: string;
nickname?: string;
'https://motovaultpro.com/roles'?: string[];
iss?: string;
aud?: string | string[];
iat?: number;
exp?: number;
}
// Extend @fastify/jwt module with our payload type
declare module '@fastify/jwt' {
interface FastifyJWT {
payload: Auth0JwtPayload;
user: Auth0JwtPayload;
}
}
declare module 'fastify' {
interface FastifyInstance {
authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
}
interface FastifyRequest {
jwtVerify(): Promise<void>;
user?: any;
userContext?: {
userId: string;
email?: string;
@@ -41,7 +62,7 @@ const authPlugin: FastifyPluginAsync = async (fastify) => {
});
// Register @fastify/jwt with Auth0 JWKS validation
await fastify.register(require('@fastify/jwt'), {
await fastify.register(fastifyJwt, {
decode: { complete: true },
secret: async (_request: FastifyRequest, token: any) => {
try {

View File

@@ -0,0 +1,38 @@
/**
* @ai-summary Centralized cron job scheduler
* @ai-context Uses node-cron for scheduling background tasks
*/
import cron from 'node-cron';
import { logger } from '../logging/logger';
import { processScheduledNotifications } from '../../features/notifications/jobs/notification-processor.job';
let schedulerInitialized = false;
export function initializeScheduler(): void {
if (schedulerInitialized) {
logger.warn('Scheduler already initialized, skipping');
return;
}
logger.info('Initializing cron scheduler');
// Daily notification processing at 8 AM
cron.schedule('0 8 * * *', async () => {
logger.info('Running scheduled notification job');
try {
await processScheduledNotifications();
} catch (error) {
logger.error('Scheduled notification job failed', {
error: error instanceof Error ? error.message : String(error)
});
}
});
schedulerInitialized = true;
logger.info('Cron scheduler initialized - notification job scheduled for 8 AM daily');
}
export function isSchedulerInitialized(): boolean {
return schedulerInitialized;
}