Skip to content

Commit 7cb6d54

Browse files
Scheduler and UI fixes
1 parent 80e006d commit 7cb6d54

File tree

3 files changed

+119
-5
lines changed

3 files changed

+119
-5
lines changed

app.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,38 @@
6969
scheduler.start()
7070
atexit.register(lambda: scheduler.shutdown())
7171

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+
7296
@login_manager.user_loader
7397
def load_user(user_id):
7498
return User.query.get(int(user_id))
7599

76100
@app.route('/')
77101
@login_required
78102
def dashboard():
103+
ensure_scheduler_initialized()
79104
repositories = Repository.query.filter_by(user_id=current_user.id).all()
80105
recent_jobs = BackupJob.query.filter_by(user_id=current_user.id).order_by(BackupJob.created_at.desc()).limit(10).all()
81106
return render_template('dashboard.html', repositories=repositories, recent_jobs=recent_jobs)
@@ -390,6 +415,24 @@ def backup_jobs():
390415
def health_check():
391416
return jsonify({'status': 'healthy', 'timestamp': datetime.utcnow().isoformat()})
392417

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+
393436
@app.route('/api/theme', methods=['POST'])
394437
@login_required
395438
def update_theme():

templates/edit_repository.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,12 @@ <h4 class="mb-0">
9191

9292
<div class="row">
9393
<div class="col-12 mb-3">
94-
<label for="retention_count" class="form-label">Retention Count <span class="text-danger">*</span></label>
95-
<input type="number" class="form-control" id="retention_count" name="retention_count"
96-
value="{{ repository.retention_count }}" min="1" max="50" required>
97-
<div class="form-text">
98-
Number of backup versions to keep (older backups will be automatically deleted)
94+
<label for="retention_count" class="form-label">Retention Count <span class="text-danger">*</span></label>
95+
<input type="number" class="form-control" id="retention_count" name="retention_count"
96+
value="{{ repository.retention_count }}" min="1" max="50" required>
97+
<div class="form-text">
98+
Number of backup versions to keep (older backups will be automatically deleted)
99+
</div>
99100
</div>
100101
</div>
101102

test_fixes.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Test script to verify the fixes for template and scheduler issues
4+
"""
5+
6+
import os
7+
import sys
8+
from flask import Flask
9+
from jinja2 import Environment, FileSystemLoader, TemplateError
10+
11+
def test_template_syntax():
12+
"""Test if the edit_repository.html template has valid syntax"""
13+
print("Testing template syntax...")
14+
15+
try:
16+
# Create a Jinja2 environment
17+
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
18+
env = Environment(loader=FileSystemLoader(template_dir))
19+
20+
# Try to load and parse the template
21+
template = env.get_template('edit_repository.html')
22+
print("✅ edit_repository.html syntax is valid")
23+
return True
24+
25+
except TemplateError as e:
26+
print(f"❌ Template syntax error: {e}")
27+
return False
28+
except Exception as e:
29+
print(f"❌ Error loading template: {e}")
30+
return False
31+
32+
def test_app_imports():
33+
"""Test if the app can be imported without errors"""
34+
print("Testing app imports...")
35+
36+
try:
37+
# Set environment variables to avoid missing config errors
38+
os.environ.setdefault('SECRET_KEY', 'test-key')
39+
os.environ.setdefault('DATABASE_URL', 'sqlite:///test.db')
40+
41+
# Try to import the app
42+
sys.path.insert(0, os.path.dirname(__file__))
43+
import app
44+
print("✅ App imports successfully")
45+
return True
46+
47+
except Exception as e:
48+
print(f"❌ Error importing app: {e}")
49+
return False
50+
51+
def main():
52+
print("Running fix verification tests...\n")
53+
54+
template_ok = test_template_syntax()
55+
app_ok = test_app_imports()
56+
57+
print(f"\n{'='*50}")
58+
print("Test Results:")
59+
print(f"Template syntax: {'✅ PASS' if template_ok else '❌ FAIL'}")
60+
print(f"App imports: {'✅ PASS' if app_ok else '❌ FAIL'}")
61+
62+
if template_ok and app_ok:
63+
print("\n🎉 All tests passed! The fixes should work correctly.")
64+
return 0
65+
else:
66+
print("\n⚠️ Some tests failed. Please check the errors above.")
67+
return 1
68+
69+
if __name__ == '__main__':
70+
sys.exit(main())

0 commit comments

Comments
 (0)