feat: implement auto-sync scheduler for LoTW and DCL
Add automatic synchronization scheduler that allows users to configure periodic sync intervals for LoTW and DCL via the settings page. Features: - Users can enable/disable auto-sync per service (LoTW/DCL) - Configurable sync intervals (1-720 hours) - Settings page UI for managing auto-sync preferences - Dashboard shows upcoming scheduled auto-sync jobs - Scheduler runs every minute, triggers syncs when due - Survives server restarts via database persistence - Graceful shutdown support (SIGINT/SIGTERM) Backend: - New autoSyncSettings table with user preferences - auto-sync.service.js for CRUD operations and scheduling logic - scheduler.service.js for periodic tick processing - API endpoints: GET/PUT /auto-sync/settings, GET /auto-sync/scheduler/status Frontend: - Auto-sync settings section in settings page - Upcoming auto-sync section on dashboard with scheduled job cards - Purple-themed UI for scheduled jobs with countdown animation Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -223,5 +223,39 @@ export const adminActions = sqliteTable('admin_actions', {
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
/**
|
||||
* @typedef {Object} AutoSyncSettings
|
||||
* @property {number} userId
|
||||
* @property {boolean} lotwEnabled
|
||||
* @property {number} lotwIntervalHours
|
||||
* @property {Date|null} lotwLastSyncAt
|
||||
* @property {Date|null} lotwNextSyncAt
|
||||
* @property {boolean} dclEnabled
|
||||
* @property {number} dclIntervalHours
|
||||
* @property {Date|null} dclLastSyncAt
|
||||
* @property {Date|null} dclNextSyncAt
|
||||
* @property {Date} createdAt
|
||||
* @property {Date} updatedAt
|
||||
*/
|
||||
|
||||
export const autoSyncSettings = sqliteTable('auto_sync_settings', {
|
||||
userId: integer('user_id').primaryKey().references(() => users.id),
|
||||
|
||||
// LoTW auto-sync settings
|
||||
lotwEnabled: integer('lotw_enabled', { mode: 'boolean' }).notNull().default(false),
|
||||
lotwIntervalHours: integer('lotw_interval_hours').notNull().default(24),
|
||||
lotwLastSyncAt: integer('lotw_last_sync_at', { mode: 'timestamp' }),
|
||||
lotwNextSyncAt: integer('lotw_next_sync_at', { mode: 'timestamp' }),
|
||||
|
||||
// DCL auto-sync settings
|
||||
dclEnabled: integer('dcl_enabled', { mode: 'boolean' }).notNull().default(false),
|
||||
dclIntervalHours: integer('dcl_interval_hours').notNull().default(24),
|
||||
dclLastSyncAt: integer('dcl_last_sync_at', { mode: 'timestamp' }),
|
||||
dclNextSyncAt: integer('dcl_next_sync_at', { mode: 'timestamp' }),
|
||||
|
||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
|
||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
// Export all schemas
|
||||
export const schema = { users, qsos, awards, awardProgress, syncJobs, qsoChanges, adminActions };
|
||||
export const schema = { users, qsos, awards, awardProgress, syncJobs, qsoChanges, adminActions, autoSyncSettings };
|
||||
|
||||
Reference in New Issue
Block a user