|  | 
| 69 | 69 | scheduler.start() | 
| 70 | 70 | atexit.register(lambda: scheduler.shutdown()) | 
| 71 | 71 | 
 | 
|  | 72 | +def schedule_all_repositories(): | 
|  | 73 | +    """Schedule all active repositories on startup""" | 
|  | 74 | +    try: | 
|  | 75 | +        repositories = Repository.query.filter_by(is_active=True).all() | 
|  | 76 | +        scheduled_count = 0 | 
|  | 77 | +        for repository in repositories: | 
|  | 78 | +            if repository.schedule_type != 'manual': | 
|  | 79 | +                schedule_backup_job(repository) | 
|  | 80 | +                scheduled_count += 1 | 
|  | 81 | +                logger.info(f"Scheduled backup job for repository: {repository.name} ({repository.schedule_type})") | 
|  | 82 | +        logger.info(f"Scheduled {scheduled_count} backup jobs on startup") | 
|  | 83 | +    except Exception as e: | 
|  | 84 | +        logger.error(f"Error scheduling repositories on startup: {e}") | 
|  | 85 | + | 
|  | 86 | +# Flag to ensure we only initialize once | 
|  | 87 | +_scheduler_initialized = False | 
|  | 88 | + | 
|  | 89 | +def ensure_scheduler_initialized(): | 
|  | 90 | +    """Ensure scheduler is initialized with existing repositories""" | 
|  | 91 | +    global _scheduler_initialized | 
|  | 92 | +    if not _scheduler_initialized: | 
|  | 93 | +        schedule_all_repositories() | 
|  | 94 | +        _scheduler_initialized = True | 
|  | 95 | + | 
| 72 | 96 | @login_manager.user_loader | 
| 73 | 97 | def load_user(user_id): | 
| 74 | 98 |     return User.query.get(int(user_id)) | 
| 75 | 99 | 
 | 
| 76 | 100 | @app.route('/') | 
| 77 | 101 | @login_required | 
| 78 | 102 | def dashboard(): | 
|  | 103 | +    ensure_scheduler_initialized() | 
| 79 | 104 |     repositories = Repository.query.filter_by(user_id=current_user.id).all() | 
| 80 | 105 |     recent_jobs = BackupJob.query.filter_by(user_id=current_user.id).order_by(BackupJob.created_at.desc()).limit(10).all() | 
| 81 | 106 |     return render_template('dashboard.html', repositories=repositories, recent_jobs=recent_jobs) | 
| @@ -390,6 +415,24 @@ def backup_jobs(): | 
| 390 | 415 | def health_check(): | 
| 391 | 416 |     return jsonify({'status': 'healthy', 'timestamp': datetime.utcnow().isoformat()}) | 
| 392 | 417 | 
 | 
|  | 418 | +@app.route('/api/scheduler/status') | 
|  | 419 | +@login_required | 
|  | 420 | +def scheduler_status(): | 
|  | 421 | +    """Debug endpoint to check scheduled jobs""" | 
|  | 422 | +    jobs = [] | 
|  | 423 | +    for job in scheduler.get_jobs(): | 
|  | 424 | +        jobs.append({ | 
|  | 425 | +            'id': job.id, | 
|  | 426 | +            'name': job.name, | 
|  | 427 | +            'next_run': job.next_run_time.isoformat() if job.next_run_time else None, | 
|  | 428 | +            'trigger': str(job.trigger) | 
|  | 429 | +        }) | 
|  | 430 | +    return jsonify({ | 
|  | 431 | +        'scheduler_running': scheduler.running, | 
|  | 432 | +        'scheduled_jobs': jobs, | 
|  | 433 | +        'total_jobs': len(jobs) | 
|  | 434 | +    }) | 
|  | 435 | + | 
| 393 | 436 | @app.route('/api/theme', methods=['POST']) | 
| 394 | 437 | @login_required | 
| 395 | 438 | def update_theme(): | 
|  | 
0 commit comments