ikk
Browse files- APSCHEDULER_ANALYSIS_SUMMARY.md +198 -0
- APSCHEDULER_TEST_PLAN.md +462 -0
- APSCHEDULER_VISIBILITY_FIX.md +170 -0
- backend/app.py +16 -0
- test_scheduler_integration.py +88 -0
- test_scheduler_visibility.py +186 -0
APSCHEDULER_ANALYSIS_SUMMARY.md
ADDED
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# APScheduler Analysis Summary
|
2 |
+
|
3 |
+
## Problem Diagnosis
|
4 |
+
|
5 |
+
### Issue Description
|
6 |
+
The user reported that when starting their Lin application, they don't see any output from the APS scheduler in the startup logs. The application starts successfully on port 7860, but there are no scheduler-related messages visible.
|
7 |
+
|
8 |
+
### Root Cause Analysis
|
9 |
+
After analyzing the code and startup logs, I identified the following issues:
|
10 |
+
|
11 |
+
1. **Missing Logging Configuration**: The APScheduler logger is not configured to show debug messages. According to APScheduler documentation, you need to explicitly configure logging for the 'apscheduler' logger to see its output.
|
12 |
+
|
13 |
+
2. **No Startup Verification**: There are no explicit verification messages to confirm that APScheduler is initialized and working.
|
14 |
+
|
15 |
+
3. **Silent Operation**: APScheduler is working in the background but operates silently without visible feedback.
|
16 |
+
|
17 |
+
## Current State Assessment
|
18 |
+
|
19 |
+
### What's Working ✅
|
20 |
+
- Flask application starts successfully on port 7860
|
21 |
+
- APScheduler is properly imported and initialized in `backend/app.py`
|
22 |
+
- Scheduler service is correctly configured with logging statements
|
23 |
+
- Database integration is properly set up
|
24 |
+
- Job creation and execution mechanisms are in place
|
25 |
+
|
26 |
+
### What's Missing ❌
|
27 |
+
- APScheduler debug messages are not visible in startup logs
|
28 |
+
- No startup verification messages
|
29 |
+
- No feedback about scheduler status or job counts
|
30 |
+
- Logging configuration not properly set up for APScheduler
|
31 |
+
|
32 |
+
## Solution Architecture
|
33 |
+
|
34 |
+
### Phase 1: Logging Configuration
|
35 |
+
**Target File**: `backend/app.py`
|
36 |
+
**Changes Required**:
|
37 |
+
```python
|
38 |
+
import logging
|
39 |
+
|
40 |
+
# Configure logging for APScheduler
|
41 |
+
logging.basicConfig(
|
42 |
+
level=logging.DEBUG,
|
43 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
44 |
+
)
|
45 |
+
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
46 |
+
```
|
47 |
+
|
48 |
+
### Phase 2: Startup Verification
|
49 |
+
**Target File**: `backend/app.py`
|
50 |
+
**Changes Required**:
|
51 |
+
Add verification messages after APScheduler initialization:
|
52 |
+
```python
|
53 |
+
# Verify APScheduler initialization
|
54 |
+
if hasattr(app, 'scheduler') and app.scheduler.scheduler is not None:
|
55 |
+
app.logger.info("✅ APScheduler initialized successfully")
|
56 |
+
app.logger.info(f"📊 Current jobs: {len(app.scheduler.scheduler.get_jobs())}")
|
57 |
+
app.logger.info("🔄 Schedule loading job added (runs every 5 minutes)")
|
58 |
+
else:
|
59 |
+
app.logger.warning("⚠️ APScheduler initialization failed")
|
60 |
+
```
|
61 |
+
|
62 |
+
### Phase 3: Testing Infrastructure
|
63 |
+
**New Files to Create**:
|
64 |
+
- `test_scheduler_visibility.py` - Standalone test script
|
65 |
+
- `test_scheduler_integration.py` - Integration test script
|
66 |
+
|
67 |
+
### Phase 4: Documentation Updates
|
68 |
+
**Files to Update**:
|
69 |
+
- `APSCHEDULER_SETUP.md` - Add troubleshooting section
|
70 |
+
- Create comprehensive test plan and implementation guide
|
71 |
+
|
72 |
+
## Expected Results
|
73 |
+
|
74 |
+
### Before Fix
|
75 |
+
```
|
76 |
+
Starting Lin application on port 7860...
|
77 |
+
============================================================
|
78 |
+
============================================================
|
79 |
+
Flask application starting...
|
80 |
+
Access the application at:
|
81 |
+
http://localhost:7860
|
82 |
+
http://127.0.0.1:7860
|
83 |
+
============================================================
|
84 |
+
* Serving Flask app 'backend.app'
|
85 |
+
* Debug mode: off
|
86 |
+
INFO:werkzeug:WARNING: This is a development server...
|
87 |
+
```
|
88 |
+
|
89 |
+
### After Fix
|
90 |
+
```
|
91 |
+
Starting Lin application on port 7860...
|
92 |
+
============================================================
|
93 |
+
============================================================
|
94 |
+
Flask application starting...
|
95 |
+
Access the application at:
|
96 |
+
http://localhost:7860
|
97 |
+
http://127.0.0.1:7860
|
98 |
+
============================================================
|
99 |
+
* Serving Flask app 'backend.app'
|
100 |
+
* Debug mode: off
|
101 |
+
INFO:werkzeug:WARNING: This is a development server...
|
102 |
+
INFO:backend.app:Initializing APScheduler...
|
103 |
+
INFO:backend.apscheduler_service:Initializing APScheduler...
|
104 |
+
INFO:backend.apscheduler_service:Initializing Supabase client...
|
105 |
+
INFO:backend.apscheduler_service:Supabase client initialized
|
106 |
+
INFO:backend.apscheduler_service:Creating BackgroundScheduler...
|
107 |
+
INFO:backend.apscheduler_service:BackgroundScheduler created
|
108 |
+
INFO:backend.apscheduler_service:Starting scheduler...
|
109 |
+
INFO:backend.apscheduler_service:Scheduler started
|
110 |
+
INFO:backend.apscheduler_service:Adding periodic job to load schedules...
|
111 |
+
INFO:backend.apscheduler_service:Periodic job added
|
112 |
+
INFO:backend.apscheduler_service:Loading schedules immediately...
|
113 |
+
INFO:backend.apscheduler_service:Found 0 schedules in database
|
114 |
+
INFO:backend.apscheduler_service:Updated APScheduler schedule
|
115 |
+
INFO:backend.app:✅ APScheduler initialized successfully
|
116 |
+
INFO:backend.app:📊 Current jobs: 1
|
117 |
+
INFO:backend.app:🔄 Schedule loading job added (runs every 5 minutes)
|
118 |
+
```
|
119 |
+
|
120 |
+
## Implementation Plan
|
121 |
+
|
122 |
+
### Step 1: Configure Logging
|
123 |
+
- Add logging configuration to `backend/app.py`
|
124 |
+
- Ensure APScheduler logger is set to DEBUG level
|
125 |
+
- Test that messages now appear in logs
|
126 |
+
|
127 |
+
### Step 2: Add Verification
|
128 |
+
- Add startup verification messages
|
129 |
+
- Include job count information
|
130 |
+
- Add clear success/failure indicators
|
131 |
+
|
132 |
+
### Step 3: Create Test Scripts
|
133 |
+
- Create standalone test script for verification
|
134 |
+
- Create integration test for Flask app
|
135 |
+
- Document usage and expected outputs
|
136 |
+
|
137 |
+
### Step 4: Update Documentation
|
138 |
+
- Update setup guide with troubleshooting section
|
139 |
+
- Add logging configuration instructions
|
140 |
+
- Document test procedures
|
141 |
+
|
142 |
+
## Risk Assessment
|
143 |
+
|
144 |
+
### Low Risk Changes
|
145 |
+
- Logging configuration (no functional changes)
|
146 |
+
- Startup verification messages (no functional changes)
|
147 |
+
- Test scripts (standalone, don't affect production)
|
148 |
+
|
149 |
+
### Medium Risk Changes
|
150 |
+
- Any modifications to `backend/app.py` require careful testing
|
151 |
+
|
152 |
+
### Mitigation Strategies
|
153 |
+
1. **Backup**: Create backup of `backend/app.py` before changes
|
154 |
+
2. **Testing**: Run test scripts after each change
|
155 |
+
3. **Rollback**: Have rollback plan ready
|
156 |
+
4. **Validation**: Verify application still starts and functions normally
|
157 |
+
|
158 |
+
## Success Criteria
|
159 |
+
|
160 |
+
The solution is successful when:
|
161 |
+
|
162 |
+
1. ✅ APScheduler messages are visible in startup logs
|
163 |
+
2. ✅ Startup verification messages appear
|
164 |
+
3. ✅ Test scripts pass successfully
|
165 |
+
4. ✅ Application continues to function normally
|
166 |
+
5. ✅ No new errors are introduced
|
167 |
+
6. ✅ Documentation is updated and accurate
|
168 |
+
|
169 |
+
## Next Steps
|
170 |
+
|
171 |
+
1. **Approve Implementation Plan** - Review and approve the proposed changes
|
172 |
+
2. **Switch to Code Mode** - Move to implementation phase
|
173 |
+
3. **Execute Changes** - Implement logging configuration and verification
|
174 |
+
4. **Test Solution** - Run test scripts to verify functionality
|
175 |
+
5. **Validate Results** - Confirm APScheduler output is now visible
|
176 |
+
6. **Update Documentation** - Finalize documentation updates
|
177 |
+
|
178 |
+
## Files Created/Modified
|
179 |
+
|
180 |
+
### Created
|
181 |
+
- `APSCHEDULER_VISIBILITY_FIX.md` - Comprehensive fix plan
|
182 |
+
- `APSCHEDULER_TEST_PLAN.md` - Detailed test plan with scripts
|
183 |
+
- `APSCHEDULER_ANALYSIS_SUMMARY.md` - This analysis summary
|
184 |
+
|
185 |
+
### To Be Modified
|
186 |
+
- `backend/app.py` - Add logging configuration and verification
|
187 |
+
- `APSCHEDULER_SETUP.md` - Update with troubleshooting section
|
188 |
+
|
189 |
+
## Conclusion
|
190 |
+
|
191 |
+
The APScheduler is functional but not visible due to missing logging configuration. The solution is straightforward and low-risk, involving primarily logging configuration and verification messages. Once implemented, users will be able to see APScheduler activity in their logs, making it easier to monitor and debug scheduling issues.
|
192 |
+
|
193 |
+
The implementation will provide:
|
194 |
+
- Clear visibility into APScheduler operations
|
195 |
+
- Better debugging capabilities
|
196 |
+
- Improved user experience
|
197 |
+
- Comprehensive testing infrastructure
|
198 |
+
- Updated documentation for future reference
|
APSCHEDULER_TEST_PLAN.md
ADDED
@@ -0,0 +1,462 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# APScheduler Test Plan
|
2 |
+
|
3 |
+
## Overview
|
4 |
+
|
5 |
+
This document outlines a comprehensive test plan to verify APScheduler functionality and visibility in the Lin application. The plan includes both automated tests and manual verification steps.
|
6 |
+
|
7 |
+
## Test Objectives
|
8 |
+
|
9 |
+
1. **Verify APScheduler is properly initialized** during application startup
|
10 |
+
2. **Confirm logging configuration** shows APScheduler messages
|
11 |
+
3. **Test schedule loading functionality** from the database
|
12 |
+
4. **Verify job creation and execution** mechanisms
|
13 |
+
5. **Ensure scheduler persistence** and error handling
|
14 |
+
|
15 |
+
## Test Environment Setup
|
16 |
+
|
17 |
+
### Prerequisites
|
18 |
+
- Python 3.8+ installed
|
19 |
+
- All dependencies from `backend/requirements.txt` installed
|
20 |
+
- Environment variables configured (Supabase credentials, etc.)
|
21 |
+
- Access to the Lin application source code
|
22 |
+
|
23 |
+
### Test Files to Create
|
24 |
+
|
25 |
+
#### 1. `test_scheduler_visibility.py`
|
26 |
+
**Purpose**: Standalone test script to verify APScheduler logging and basic functionality
|
27 |
+
|
28 |
+
```python
|
29 |
+
#!/usr/bin/env python3
|
30 |
+
"""
|
31 |
+
Test script for APScheduler visibility and functionality.
|
32 |
+
This script tests whether APScheduler is working and properly configured for logging.
|
33 |
+
"""
|
34 |
+
|
35 |
+
import sys
|
36 |
+
import os
|
37 |
+
import logging
|
38 |
+
from pathlib import Path
|
39 |
+
from datetime import datetime
|
40 |
+
|
41 |
+
# Add the backend directory to the Python path
|
42 |
+
backend_dir = Path(__file__).parent / "backend"
|
43 |
+
sys.path.insert(0, str(backend_dir))
|
44 |
+
|
45 |
+
def setup_logging():
|
46 |
+
"""Setup logging for the test script."""
|
47 |
+
logging.basicConfig(
|
48 |
+
level=logging.DEBUG,
|
49 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
50 |
+
)
|
51 |
+
# Configure APScheduler logger specifically
|
52 |
+
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
53 |
+
print("🔧 Logging configured for APScheduler")
|
54 |
+
|
55 |
+
def test_apscheduler_import():
|
56 |
+
"""Test that APScheduler can be imported."""
|
57 |
+
try:
|
58 |
+
from backend.scheduler.apscheduler_service import APSchedulerService
|
59 |
+
print("✅ APSchedulerService imported successfully")
|
60 |
+
return True
|
61 |
+
except Exception as e:
|
62 |
+
print(f"❌ Failed to import APSchedulerService: {e}")
|
63 |
+
return False
|
64 |
+
|
65 |
+
def test_scheduler_initialization():
|
66 |
+
"""Test APScheduler initialization with mock app."""
|
67 |
+
try:
|
68 |
+
from backend.scheduler.apscheduler_service import APSchedulerService
|
69 |
+
|
70 |
+
# Create a mock app object
|
71 |
+
class MockApp:
|
72 |
+
def __init__(self):
|
73 |
+
self.config = {
|
74 |
+
'SUPABASE_URL': 'https://test.supabase.co',
|
75 |
+
'SUPABASE_KEY': 'test_key',
|
76 |
+
'SCHEDULER_ENABLED': True
|
77 |
+
}
|
78 |
+
|
79 |
+
# Initialize the scheduler service
|
80 |
+
app = MockApp()
|
81 |
+
scheduler_service = APSchedulerService()
|
82 |
+
|
83 |
+
# Mock the Supabase client initialization
|
84 |
+
class MockSupabaseClient:
|
85 |
+
def table(self, table_name):
|
86 |
+
return self
|
87 |
+
|
88 |
+
def select(self, columns):
|
89 |
+
return self
|
90 |
+
|
91 |
+
def execute(self):
|
92 |
+
# Return empty schedule data for testing
|
93 |
+
return type('obj', (object,), {'data': []})()
|
94 |
+
|
95 |
+
scheduler_service.supabase_client = MockSupabaseClient()
|
96 |
+
|
97 |
+
# Test initialization
|
98 |
+
scheduler_service.init_app(app)
|
99 |
+
|
100 |
+
if scheduler_service.scheduler is not None:
|
101 |
+
print("✅ APScheduler initialized successfully")
|
102 |
+
print(f"📊 Current jobs: {len(scheduler_service.scheduler.get_jobs())}")
|
103 |
+
return True
|
104 |
+
else:
|
105 |
+
print("❌ APScheduler initialization failed")
|
106 |
+
return False
|
107 |
+
|
108 |
+
except Exception as e:
|
109 |
+
print(f"❌ Error testing APScheduler initialization: {e}")
|
110 |
+
import traceback
|
111 |
+
traceback.print_exc()
|
112 |
+
return False
|
113 |
+
|
114 |
+
def test_schedule_loading():
|
115 |
+
"""Test the schedule loading functionality."""
|
116 |
+
try:
|
117 |
+
from backend.scheduler.apscheduler_service import APSchedulerService
|
118 |
+
|
119 |
+
# Create scheduler service
|
120 |
+
scheduler_service = APSchedulerService()
|
121 |
+
|
122 |
+
# Mock the Supabase client
|
123 |
+
class MockSupabaseClient:
|
124 |
+
def table(self, table_name):
|
125 |
+
return self
|
126 |
+
|
127 |
+
def select(self, columns):
|
128 |
+
return self
|
129 |
+
|
130 |
+
def execute(self):
|
131 |
+
# Return mock schedule data
|
132 |
+
mock_data = [
|
133 |
+
{
|
134 |
+
'id': 'test_schedule_1',
|
135 |
+
'schedule_time': 'Monday 09:00',
|
136 |
+
'adjusted_time': 'Monday 08:55',
|
137 |
+
'Social_network': {
|
138 |
+
'id_utilisateur': 'test_user_1',
|
139 |
+
'token': 'test_token',
|
140 |
+
'sub': 'test_sub'
|
141 |
+
}
|
142 |
+
}
|
143 |
+
]
|
144 |
+
return type('obj', (object,), {'data': mock_data})()
|
145 |
+
|
146 |
+
scheduler_service.supabase_client = MockSupabaseClient()
|
147 |
+
|
148 |
+
# Test schedule loading
|
149 |
+
scheduler_service.load_schedules()
|
150 |
+
|
151 |
+
if scheduler_service.scheduler is not None:
|
152 |
+
jobs = scheduler_service.scheduler.get_jobs()
|
153 |
+
print(f"✅ Schedule loading test completed")
|
154 |
+
print(f"📊 Total jobs: {len(jobs)}")
|
155 |
+
|
156 |
+
# Check for specific job types
|
157 |
+
loader_jobs = [job for job in jobs if job.id == 'load_schedules']
|
158 |
+
content_jobs = [job for job in jobs if job.id.startswith('gen_')]
|
159 |
+
publish_jobs = [job for job in jobs if job.id.startswith('pub_')]
|
160 |
+
|
161 |
+
print(f"🔄 Loader jobs: {len(loader_jobs)}")
|
162 |
+
print(f"📝 Content generation jobs: {len(content_jobs)}")
|
163 |
+
print(f"📤 Publishing jobs: {len(publish_jobs)}")
|
164 |
+
|
165 |
+
return len(jobs) > 0
|
166 |
+
else:
|
167 |
+
print("❌ Scheduler not initialized for schedule loading test")
|
168 |
+
return False
|
169 |
+
|
170 |
+
except Exception as e:
|
171 |
+
print(f"❌ Error testing schedule loading: {e}")
|
172 |
+
import traceback
|
173 |
+
traceback.print_exc()
|
174 |
+
return False
|
175 |
+
|
176 |
+
def main():
|
177 |
+
"""Main test function."""
|
178 |
+
print("🚀 Testing APScheduler visibility and functionality...")
|
179 |
+
print("=" * 60)
|
180 |
+
|
181 |
+
setup_logging()
|
182 |
+
|
183 |
+
tests = [
|
184 |
+
("APScheduler Import", test_apscheduler_import),
|
185 |
+
("Scheduler Initialization", test_scheduler_initialization),
|
186 |
+
("Schedule Loading", test_schedule_loading),
|
187 |
+
]
|
188 |
+
|
189 |
+
passed = 0
|
190 |
+
total = len(tests)
|
191 |
+
|
192 |
+
for test_name, test_func in tests:
|
193 |
+
print(f"\n📋 Running test: {test_name}")
|
194 |
+
print("-" * 40)
|
195 |
+
|
196 |
+
if test_func():
|
197 |
+
passed += 1
|
198 |
+
print(f"✅ {test_name} PASSED")
|
199 |
+
else:
|
200 |
+
print(f"❌ {test_name} FAILED")
|
201 |
+
|
202 |
+
print("\n" + "=" * 60)
|
203 |
+
print(f"📊 Test Results: {passed}/{total} tests passed")
|
204 |
+
|
205 |
+
if passed == total:
|
206 |
+
print("🎉 All tests passed! APScheduler is working correctly.")
|
207 |
+
return True
|
208 |
+
else:
|
209 |
+
print("⚠️ Some tests failed. Please check the error messages above.")
|
210 |
+
return False
|
211 |
+
|
212 |
+
if __name__ == "__main__":
|
213 |
+
success = main()
|
214 |
+
sys.exit(0 if success else 1)
|
215 |
+
```
|
216 |
+
|
217 |
+
#### 2. `test_scheduler_integration.py`
|
218 |
+
**Purpose**: Test APScheduler integration with the actual Flask application
|
219 |
+
|
220 |
+
```python
|
221 |
+
#!/usr/bin/env python3
|
222 |
+
"""
|
223 |
+
Integration test for APScheduler with Flask application.
|
224 |
+
Tests the actual application startup and scheduler initialization.
|
225 |
+
"""
|
226 |
+
|
227 |
+
import sys
|
228 |
+
import os
|
229 |
+
import subprocess
|
230 |
+
import time
|
231 |
+
from pathlib import Path
|
232 |
+
|
233 |
+
def test_app_startup_with_scheduler():
|
234 |
+
"""Test that the Flask application starts with APScheduler visible."""
|
235 |
+
try:
|
236 |
+
# Change to the project directory
|
237 |
+
project_dir = Path(__file__).parent
|
238 |
+
os.chdir(project_dir)
|
239 |
+
|
240 |
+
# Start the application
|
241 |
+
print("🚀 Starting Flask application with APScheduler...")
|
242 |
+
process = subprocess.Popen(
|
243 |
+
[sys.executable, "start_app.py"],
|
244 |
+
stdout=subprocess.PIPE,
|
245 |
+
stderr=subprocess.STDOUT,
|
246 |
+
text=True,
|
247 |
+
bufsize=1,
|
248 |
+
universal_newlines=True
|
249 |
+
)
|
250 |
+
|
251 |
+
# Wait for startup and capture output
|
252 |
+
startup_timeout = 30 # 30 seconds timeout
|
253 |
+
start_time = time.time()
|
254 |
+
|
255 |
+
scheduler_found = False
|
256 |
+
while time.time() - start_time < startup_timeout:
|
257 |
+
output = process.stdout.readline()
|
258 |
+
if output:
|
259 |
+
print(output.strip())
|
260 |
+
|
261 |
+
# Check for APScheduler initialization messages
|
262 |
+
if "Initializing APScheduler" in output:
|
263 |
+
scheduler_found = True
|
264 |
+
print("✅ APScheduler initialization message found!")
|
265 |
+
|
266 |
+
# Check for successful startup
|
267 |
+
if "running on http" in output.lower():
|
268 |
+
break
|
269 |
+
|
270 |
+
# Terminate the process
|
271 |
+
process.terminate()
|
272 |
+
process.wait(timeout=10)
|
273 |
+
|
274 |
+
if scheduler_found:
|
275 |
+
print("✅ APScheduler is visible during application startup")
|
276 |
+
return True
|
277 |
+
else:
|
278 |
+
print("❌ APScheduler messages not found in startup logs")
|
279 |
+
return False
|
280 |
+
|
281 |
+
except Exception as e:
|
282 |
+
print(f"❌ Error testing app startup: {e}")
|
283 |
+
return False
|
284 |
+
|
285 |
+
def main():
|
286 |
+
"""Main integration test function."""
|
287 |
+
print("🔗 Testing APScheduler integration with Flask application...")
|
288 |
+
print("=" * 60)
|
289 |
+
|
290 |
+
success = test_app_startup_with_scheduler()
|
291 |
+
|
292 |
+
print("\n" + "=" * 60)
|
293 |
+
if success:
|
294 |
+
print("🎉 Integration test passed! APScheduler is working in the Flask app.")
|
295 |
+
else:
|
296 |
+
print("⚠️ Integration test failed. APScheduler may not be properly configured.")
|
297 |
+
|
298 |
+
return success
|
299 |
+
|
300 |
+
if __name__ == "__main__":
|
301 |
+
success = main()
|
302 |
+
sys.exit(0 if success else 1)
|
303 |
+
```
|
304 |
+
|
305 |
+
## Test Execution Steps
|
306 |
+
|
307 |
+
### Step 1: Run Standalone Test
|
308 |
+
```bash
|
309 |
+
# Navigate to project directory
|
310 |
+
cd /path/to/your/project
|
311 |
+
|
312 |
+
# Run the standalone test
|
313 |
+
python test_scheduler_visibility.py
|
314 |
+
```
|
315 |
+
|
316 |
+
**Expected Output**:
|
317 |
+
```
|
318 |
+
🚀 Testing APScheduler visibility and functionality...
|
319 |
+
============================================================
|
320 |
+
🔧 Logging configured for APScheduler
|
321 |
+
|
322 |
+
📋 Running test: APScheduler Import
|
323 |
+
----------------------------------------
|
324 |
+
✅ APSchedulerService imported successfully
|
325 |
+
✅ APScheduler Import PASSED
|
326 |
+
|
327 |
+
📋 Running test: Scheduler Initialization
|
328 |
+
----------------------------------------
|
329 |
+
✅ APScheduler initialized successfully
|
330 |
+
📊 Current jobs: 1
|
331 |
+
✅ Scheduler Initialization PASSED
|
332 |
+
|
333 |
+
📋 Running test: Schedule Loading
|
334 |
+
----------------------------------------
|
335 |
+
✅ Schedule loading test completed
|
336 |
+
📊 Total jobs: 3
|
337 |
+
🔄 Loader jobs: 1
|
338 |
+
📝 Content generation jobs: 1
|
339 |
+
📤 Publishing jobs: 1
|
340 |
+
✅ Schedule Loading PASSED
|
341 |
+
|
342 |
+
============================================================
|
343 |
+
📊 Test Results: 3/3 tests passed
|
344 |
+
🎉 All tests passed! APScheduler is working correctly.
|
345 |
+
```
|
346 |
+
|
347 |
+
### Step 2: Run Integration Test
|
348 |
+
```bash
|
349 |
+
# Run the integration test
|
350 |
+
python test_scheduler_integration.py
|
351 |
+
```
|
352 |
+
|
353 |
+
**Expected Output**:
|
354 |
+
```
|
355 |
+
🔗 Testing APScheduler integration with Flask application...
|
356 |
+
============================================================
|
357 |
+
🚀 Starting Flask application with APScheduler...
|
358 |
+
Starting Lin application on port 7860...
|
359 |
+
============================================================
|
360 |
+
============================================================
|
361 |
+
Flask application starting...
|
362 |
+
Access the application at:
|
363 |
+
http://localhost:7860
|
364 |
+
http://127.0.0.1:7860
|
365 |
+
============================================================
|
366 |
+
* Serving Flask app 'backend.app'
|
367 |
+
* Debug mode: off
|
368 |
+
INFO:backend.app:Initializing APScheduler...
|
369 |
+
INFO:backend.apscheduler_service:Initializing APScheduler...
|
370 |
+
INFO:backend.apscheduler_service:Initializing Supabase client...
|
371 |
+
INFO:backend.apscheduler_service:Supabase client initialized
|
372 |
+
INFO:backend.apscheduler_service:Creating BackgroundScheduler...
|
373 |
+
INFO:backend.apscheduler_service:BackgroundScheduler created
|
374 |
+
INFO:backend.apscheduler_service:Starting scheduler...
|
375 |
+
INFO:backend.apscheduler_service:Scheduler started
|
376 |
+
INFO:backend.apscheduler_service:Adding periodic job to load schedules...
|
377 |
+
INFO:backend.apscheduler_service:Periodic job added
|
378 |
+
INFO:backend.apscheduler_service:Loading schedules immediately...
|
379 |
+
INFO:backend.apscheduler_service:Found 0 schedules in database
|
380 |
+
INFO:backend.apscheduler_service:Updated APScheduler schedule
|
381 |
+
INFO:backend.app:✅ APScheduler initialized successfully
|
382 |
+
INFO:backend.app:📊 Current jobs: 1
|
383 |
+
INFO:backend.app:🔄 Schedule loading job added (runs every 5 minutes)
|
384 |
+
* Running on all addresses (0.0.0.0)
|
385 |
+
* Running on http://127.0.0.1:7860
|
386 |
+
* Running on http://10.108.66.211:7860
|
387 |
+
✅ APScheduler initialization message found!
|
388 |
+
✅ APScheduler is visible during application startup
|
389 |
+
|
390 |
+
============================================================
|
391 |
+
🎉 Integration test passed! APScheduler is working in the Flask app.
|
392 |
+
```
|
393 |
+
|
394 |
+
## Manual Verification Steps
|
395 |
+
|
396 |
+
### 1. Check Application Startup Logs
|
397 |
+
After implementing the logging configuration, start your application and look for:
|
398 |
+
- `Initializing APScheduler...`
|
399 |
+
- `BackgroundScheduler created`
|
400 |
+
- `Scheduler started`
|
401 |
+
- `Adding periodic job to load schedules...`
|
402 |
+
- `Schedule loading job added (runs every 5 minutes)`
|
403 |
+
|
404 |
+
### 2. Verify Scheduler Functionality
|
405 |
+
1. Create a schedule via the API
|
406 |
+
2. Check logs for schedule loading messages
|
407 |
+
3. Verify that individual jobs are created
|
408 |
+
4. Monitor for job execution at scheduled times
|
409 |
+
|
410 |
+
### 3. Test Error Handling
|
411 |
+
1. Test with invalid Supabase credentials
|
412 |
+
2. Test with missing environment variables
|
413 |
+
3. Verify appropriate error messages are logged
|
414 |
+
|
415 |
+
## Troubleshooting Guide
|
416 |
+
|
417 |
+
### Common Issues and Solutions
|
418 |
+
|
419 |
+
#### Issue 1: No APScheduler messages in logs
|
420 |
+
**Solution**: Ensure logging configuration is added to `backend/app.py`:
|
421 |
+
```python
|
422 |
+
import logging
|
423 |
+
logging.basicConfig(level=logging.DEBUG)
|
424 |
+
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
425 |
+
```
|
426 |
+
|
427 |
+
#### Issue 2: Scheduler initialization fails
|
428 |
+
**Solution**: Check environment variables and Supabase connection:
|
429 |
+
- Verify `SUPABASE_URL` and `SUPABASE_KEY` are set
|
430 |
+
- Check network connectivity to Supabase
|
431 |
+
- Verify database tables exist
|
432 |
+
|
433 |
+
#### Issue 3: Jobs not executing
|
434 |
+
**Solution**:
|
435 |
+
- Check that the application is running continuously
|
436 |
+
- Verify job triggers are correctly configured
|
437 |
+
- Check for any exceptions in job execution
|
438 |
+
|
439 |
+
#### Issue 4: Test script fails
|
440 |
+
**Solution**:
|
441 |
+
- Ensure all dependencies are installed
|
442 |
+
- Check Python path includes the backend directory
|
443 |
+
- Verify mock data structure matches actual database schema
|
444 |
+
|
445 |
+
## Success Criteria
|
446 |
+
|
447 |
+
The APScheduler implementation is considered successful when:
|
448 |
+
|
449 |
+
1. ✅ **Startup logs** show APScheduler initialization messages
|
450 |
+
2. ✅ **Test scripts** pass all tests
|
451 |
+
3. ✅ **Integration test** shows scheduler working in Flask app
|
452 |
+
4. ✅ **Manual verification** confirms job creation and execution
|
453 |
+
5. ✅ **Error handling** works appropriately
|
454 |
+
6. ✅ **Documentation** is updated with troubleshooting guide
|
455 |
+
|
456 |
+
## Next Steps
|
457 |
+
|
458 |
+
1. **Approve this test plan**
|
459 |
+
2. **Switch to Code mode** to implement the logging configuration
|
460 |
+
3. **Create the test scripts** outlined in this plan
|
461 |
+
4. **Execute the tests** to verify APScheduler visibility
|
462 |
+
5. **Update documentation** with the final solution
|
APSCHEDULER_VISIBILITY_FIX.md
ADDED
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# APScheduler Visibility Fix Plan
|
2 |
+
|
3 |
+
## Problem Analysis
|
4 |
+
|
5 |
+
Based on the provided startup logs and code analysis, the issue is that APScheduler is being initialized in your Flask application but its output is not visible. Here's what's happening:
|
6 |
+
|
7 |
+
### Current State
|
8 |
+
- ✅ Flask application starts successfully on port 7860
|
9 |
+
- ✅ APScheduler is imported and initialized in `backend/app.py`
|
10 |
+
- ✅ Scheduler service is properly configured with logging
|
11 |
+
- ❌ **No APScheduler output visible in startup logs**
|
12 |
+
- ❌ **No verification messages showing scheduler status**
|
13 |
+
|
14 |
+
### Root Cause
|
15 |
+
The APScheduler logger is not configured to show debug messages. According to APScheduler documentation, you need to explicitly configure logging for the 'apscheduler' logger to see its output.
|
16 |
+
|
17 |
+
## Solution Implementation Plan
|
18 |
+
|
19 |
+
### Phase 1: Configure APScheduler Logging
|
20 |
+
|
21 |
+
**File to modify**: `backend/app.py`
|
22 |
+
|
23 |
+
**Changes needed**:
|
24 |
+
1. Add logging configuration at the beginning of the file
|
25 |
+
2. Configure the 'apscheduler' logger to show DEBUG level messages
|
26 |
+
3. Ensure Flask app logging is also properly configured
|
27 |
+
|
28 |
+
**Code to add**:
|
29 |
+
```python
|
30 |
+
import logging
|
31 |
+
|
32 |
+
# Configure logging for APScheduler
|
33 |
+
logging.basicConfig(
|
34 |
+
level=logging.DEBUG,
|
35 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
36 |
+
)
|
37 |
+
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
38 |
+
```
|
39 |
+
|
40 |
+
### Phase 2: Add Startup Verification
|
41 |
+
|
42 |
+
**File to modify**: `backend/app.py`
|
43 |
+
|
44 |
+
**Changes needed**:
|
45 |
+
1. Add explicit verification messages after APScheduler initialization
|
46 |
+
2. Check if scheduler started successfully
|
47 |
+
3. Log the number of jobs loaded
|
48 |
+
|
49 |
+
**Code to add** (after line 131):
|
50 |
+
```python
|
51 |
+
# Verify APScheduler initialization
|
52 |
+
if hasattr(app, 'scheduler') and app.scheduler.scheduler is not None:
|
53 |
+
app.logger.info("✅ APScheduler initialized successfully")
|
54 |
+
app.logger.info(f"📊 Current jobs: {len(app.scheduler.scheduler.get_jobs())}")
|
55 |
+
app.logger.info("🔄 Schedule loading job added (runs every 5 minutes)")
|
56 |
+
else:
|
57 |
+
app.logger.warning("⚠️ APScheduler initialization failed")
|
58 |
+
```
|
59 |
+
|
60 |
+
### Phase 3: Create Test Script
|
61 |
+
|
62 |
+
**New file**: `test_scheduler_visibility.py`
|
63 |
+
|
64 |
+
**Purpose**:
|
65 |
+
- Test APScheduler functionality independently
|
66 |
+
- Verify logging configuration works
|
67 |
+
- Create a test schedule to demonstrate functionality
|
68 |
+
|
69 |
+
**Features**:
|
70 |
+
- Standalone test script
|
71 |
+
- Mock database for testing
|
72 |
+
- Clear output showing scheduler activity
|
73 |
+
- Cleanup of test jobs
|
74 |
+
|
75 |
+
### Phase 4: Update Documentation
|
76 |
+
|
77 |
+
**File to modify**: `APSCHEDULER_SETUP.md`
|
78 |
+
|
79 |
+
**Additions needed**:
|
80 |
+
1. Section on troubleshooting visibility issues
|
81 |
+
2. Logging configuration instructions
|
82 |
+
3. Test script usage guide
|
83 |
+
4. Common issues and solutions
|
84 |
+
|
85 |
+
## Implementation Steps
|
86 |
+
|
87 |
+
### Step 1: Configure Logging
|
88 |
+
1. Add logging configuration to `backend/app.py`
|
89 |
+
2. Test that APScheduler messages now appear in logs
|
90 |
+
|
91 |
+
### Step 2: Add Verification
|
92 |
+
1. Add startup verification messages
|
93 |
+
2. Ensure scheduler status is clearly reported
|
94 |
+
|
95 |
+
### Step 3: Create Test Script
|
96 |
+
1. Create `test_scheduler_visibility.py`
|
97 |
+
2. Test the script to verify functionality
|
98 |
+
3. Document usage instructions
|
99 |
+
|
100 |
+
### Step 4: Update Documentation
|
101 |
+
1. Update `APSCHEDULER_SETUP.md` with new troubleshooting section
|
102 |
+
2. Add logging configuration guide
|
103 |
+
3. Document the test script
|
104 |
+
|
105 |
+
## Expected Results
|
106 |
+
|
107 |
+
After implementing this plan, you should see:
|
108 |
+
|
109 |
+
### Startup Logs
|
110 |
+
```
|
111 |
+
Starting Lin application on port 7860...
|
112 |
+
============================================================
|
113 |
+
============================================================
|
114 |
+
Flask application starting...
|
115 |
+
Access the application at:
|
116 |
+
http://localhost:7860
|
117 |
+
http://127.0.0.1:7860
|
118 |
+
============================================================
|
119 |
+
* Serving Flask app 'backend.app'
|
120 |
+
* Debug mode: off
|
121 |
+
INFO:werkzeug:WARNING: This is a development server...
|
122 |
+
INFO:backend.app:Initializing APScheduler...
|
123 |
+
INFO:backend.apscheduler_service:Initializing APScheduler...
|
124 |
+
INFO:backend.apscheduler_service:Initializing Supabase client...
|
125 |
+
INFO:backend.apscheduler_service:Supabase client initialized
|
126 |
+
INFO:backend.apscheduler_service:Creating BackgroundScheduler...
|
127 |
+
INFO:backend.apscheduler_service:BackgroundScheduler created
|
128 |
+
INFO:backend.apscheduler_service:Starting scheduler...
|
129 |
+
INFO:backend.apscheduler_service:Scheduler started
|
130 |
+
INFO:backend.apscheduler_service:Adding periodic job to load schedules...
|
131 |
+
INFO:backend.apscheduler_service:Periodic job added
|
132 |
+
INFO:backend.apscheduler_service:Loading schedules immediately...
|
133 |
+
INFO:backend.apscheduler_service:Found 0 schedules in database
|
134 |
+
INFO:backend.apscheduler_service:Updated APScheduler schedule
|
135 |
+
INFO:backend.app:✅ APScheduler initialized successfully
|
136 |
+
INFO:backend.app:📊 Current jobs: 1
|
137 |
+
INFO:backend.app:🔄 Schedule loading job added (runs every 5 minutes)
|
138 |
+
```
|
139 |
+
|
140 |
+
### Test Script Output
|
141 |
+
```
|
142 |
+
Testing APScheduler visibility...
|
143 |
+
✅ APScheduler initialized successfully
|
144 |
+
✅ Test schedule created
|
145 |
+
✅ Test job added to scheduler
|
146 |
+
📊 Current jobs: 2
|
147 |
+
✅ Test job executed successfully
|
148 |
+
✅ Test job removed
|
149 |
+
✅ All tests passed!
|
150 |
+
```
|
151 |
+
|
152 |
+
## Troubleshooting Checklist
|
153 |
+
|
154 |
+
If you still don't see APScheduler output after implementing this plan:
|
155 |
+
|
156 |
+
1. ✅ Check that logging configuration is added to `backend/app.py`
|
157 |
+
2. ✅ Verify that `SCHEDULER_ENABLED=True` in environment variables
|
158 |
+
3. ✅ Check that APScheduler is properly imported and initialized
|
159 |
+
4. ✅ Ensure no other logging configuration is overriding the settings
|
160 |
+
5. ✅ Test with the standalone test script
|
161 |
+
6. ✅ Check for any error messages in the logs
|
162 |
+
|
163 |
+
## Next Steps
|
164 |
+
|
165 |
+
1. **Approve this plan** - Review and approve the implementation plan
|
166 |
+
2. **Switch to Code mode** - I'll implement the actual code changes
|
167 |
+
3. **Test the solution** - Verify that APScheduler output is now visible
|
168 |
+
4. **Document the fix** - Update documentation for future reference
|
169 |
+
|
170 |
+
This plan will ensure that APScheduler is not only working but also clearly visible in your application logs, making it easier to monitor and debug scheduling issues.
|
backend/app.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import os
|
2 |
import sys
|
3 |
import locale
|
|
|
4 |
from flask import Flask, send_from_directory, request
|
5 |
from flask_cors import CORS
|
6 |
from flask_jwt_extended import JWTManager
|
@@ -8,6 +9,13 @@ from flask_jwt_extended import JWTManager
|
|
8 |
import uuid
|
9 |
from concurrent.futures import ThreadPoolExecutor
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
# Use relative import for the Config class to work with Hugging Face Spaces
|
12 |
from backend.config import Config
|
13 |
from backend.utils.database import init_supabase
|
@@ -125,6 +133,14 @@ def create_app():
|
|
125 |
scheduler = APSchedulerService(app)
|
126 |
app.scheduler = scheduler
|
127 |
app.logger.info("APScheduler initialized successfully")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
except Exception as e:
|
129 |
app.logger.error(f"Failed to initialize APScheduler: {str(e)}")
|
130 |
import traceback
|
|
|
1 |
import os
|
2 |
import sys
|
3 |
import locale
|
4 |
+
import logging
|
5 |
from flask import Flask, send_from_directory, request
|
6 |
from flask_cors import CORS
|
7 |
from flask_jwt_extended import JWTManager
|
|
|
9 |
import uuid
|
10 |
from concurrent.futures import ThreadPoolExecutor
|
11 |
|
12 |
+
# Configure logging for APScheduler
|
13 |
+
logging.basicConfig(
|
14 |
+
level=logging.DEBUG,
|
15 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
16 |
+
)
|
17 |
+
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
18 |
+
|
19 |
# Use relative import for the Config class to work with Hugging Face Spaces
|
20 |
from backend.config import Config
|
21 |
from backend.utils.database import init_supabase
|
|
|
133 |
scheduler = APSchedulerService(app)
|
134 |
app.scheduler = scheduler
|
135 |
app.logger.info("APScheduler initialized successfully")
|
136 |
+
|
137 |
+
# Verify APScheduler initialization
|
138 |
+
if hasattr(app, 'scheduler') and app.scheduler.scheduler is not None:
|
139 |
+
app.logger.info("✅ APScheduler initialized successfully")
|
140 |
+
app.logger.info(f"📊 Current jobs: {len(app.scheduler.scheduler.get_jobs())}")
|
141 |
+
app.logger.info("🔄 Schedule loading job added (runs every 5 minutes)")
|
142 |
+
else:
|
143 |
+
app.logger.warning("⚠️ APScheduler initialization failed")
|
144 |
except Exception as e:
|
145 |
app.logger.error(f"Failed to initialize APScheduler: {str(e)}")
|
146 |
import traceback
|
test_scheduler_integration.py
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Integration test for APScheduler with Flask application.
|
4 |
+
Tests the actual application startup and scheduler initialization.
|
5 |
+
"""
|
6 |
+
|
7 |
+
import sys
|
8 |
+
import os
|
9 |
+
import subprocess
|
10 |
+
import time
|
11 |
+
from pathlib import Path
|
12 |
+
|
13 |
+
def test_app_startup_with_scheduler():
|
14 |
+
"""Test that the Flask application starts with APScheduler visible."""
|
15 |
+
try:
|
16 |
+
# Change to the project directory
|
17 |
+
project_dir = Path(__file__).parent
|
18 |
+
os.chdir(project_dir)
|
19 |
+
|
20 |
+
# Start the application
|
21 |
+
print("🚀 Starting Flask application with APScheduler...")
|
22 |
+
process = subprocess.Popen(
|
23 |
+
[sys.executable, "start_app.py"],
|
24 |
+
stdout=subprocess.PIPE,
|
25 |
+
stderr=subprocess.STDOUT,
|
26 |
+
text=True,
|
27 |
+
bufsize=1,
|
28 |
+
universal_newlines=True
|
29 |
+
)
|
30 |
+
|
31 |
+
# Wait for startup and capture output
|
32 |
+
startup_timeout = 30 # 30 seconds timeout
|
33 |
+
start_time = time.time()
|
34 |
+
|
35 |
+
scheduler_found = False
|
36 |
+
verification_found = False
|
37 |
+
while time.time() - start_time < startup_timeout:
|
38 |
+
output = process.stdout.readline()
|
39 |
+
if output:
|
40 |
+
print(output.strip())
|
41 |
+
|
42 |
+
# Check for APScheduler initialization messages
|
43 |
+
if "Initializing APScheduler" in output:
|
44 |
+
scheduler_found = True
|
45 |
+
print("✅ APScheduler initialization message found!")
|
46 |
+
|
47 |
+
# Check for verification messages
|
48 |
+
if "✅ APScheduler initialized successfully" in output:
|
49 |
+
verification_found = True
|
50 |
+
print("✅ APScheduler verification message found!")
|
51 |
+
|
52 |
+
# Check for successful startup
|
53 |
+
if "running on http" in output.lower():
|
54 |
+
break
|
55 |
+
|
56 |
+
# Terminate the process
|
57 |
+
process.terminate()
|
58 |
+
process.wait(timeout=10)
|
59 |
+
|
60 |
+
if scheduler_found and verification_found:
|
61 |
+
print("✅ APScheduler is visible during application startup")
|
62 |
+
return True
|
63 |
+
else:
|
64 |
+
print("❌ APScheduler messages not found in startup logs")
|
65 |
+
return False
|
66 |
+
|
67 |
+
except Exception as e:
|
68 |
+
print(f"❌ Error testing app startup: {e}")
|
69 |
+
return False
|
70 |
+
|
71 |
+
def main():
|
72 |
+
"""Main integration test function."""
|
73 |
+
print("🔗 Testing APScheduler integration with Flask application...")
|
74 |
+
print("=" * 60)
|
75 |
+
|
76 |
+
success = test_app_startup_with_scheduler()
|
77 |
+
|
78 |
+
print("\n" + "=" * 60)
|
79 |
+
if success:
|
80 |
+
print("🎉 Integration test passed! APScheduler is working in the Flask app.")
|
81 |
+
else:
|
82 |
+
print("⚠️ Integration test failed. APScheduler may not be properly configured.")
|
83 |
+
|
84 |
+
return success
|
85 |
+
|
86 |
+
if __name__ == "__main__":
|
87 |
+
success = main()
|
88 |
+
sys.exit(0 if success else 1)
|
test_scheduler_visibility.py
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Test script for APScheduler visibility and functionality.
|
4 |
+
This script tests whether APScheduler is working and properly configured for logging.
|
5 |
+
"""
|
6 |
+
|
7 |
+
import sys
|
8 |
+
import os
|
9 |
+
import logging
|
10 |
+
from pathlib import Path
|
11 |
+
from datetime import datetime
|
12 |
+
|
13 |
+
# Add the backend directory to the Python path
|
14 |
+
backend_dir = Path(__file__).parent / "backend"
|
15 |
+
sys.path.insert(0, str(backend_dir))
|
16 |
+
|
17 |
+
def setup_logging():
|
18 |
+
"""Setup logging for the test script."""
|
19 |
+
logging.basicConfig(
|
20 |
+
level=logging.DEBUG,
|
21 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
22 |
+
)
|
23 |
+
# Configure APScheduler logger specifically
|
24 |
+
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
|
25 |
+
print("Logging configured for APScheduler")
|
26 |
+
|
27 |
+
def test_apscheduler_import():
|
28 |
+
"""Test that APScheduler can be imported."""
|
29 |
+
try:
|
30 |
+
from backend.scheduler.apscheduler_service import APSchedulerService
|
31 |
+
print("SUCCESS: APSchedulerService imported successfully")
|
32 |
+
return True
|
33 |
+
except Exception as e:
|
34 |
+
print(f"ERROR: Failed to import APSchedulerService: {e}")
|
35 |
+
return False
|
36 |
+
|
37 |
+
def test_scheduler_initialization():
|
38 |
+
"""Test APScheduler initialization with mock app."""
|
39 |
+
try:
|
40 |
+
from backend.scheduler.apscheduler_service import APSchedulerService
|
41 |
+
|
42 |
+
# Create a mock app object
|
43 |
+
class MockApp:
|
44 |
+
def __init__(self):
|
45 |
+
self.config = {
|
46 |
+
'SUPABASE_URL': 'https://test.supabase.co',
|
47 |
+
'SUPABASE_KEY': 'test_key',
|
48 |
+
'SCHEDULER_ENABLED': True
|
49 |
+
}
|
50 |
+
|
51 |
+
# Initialize the scheduler service
|
52 |
+
app = MockApp()
|
53 |
+
scheduler_service = APSchedulerService()
|
54 |
+
|
55 |
+
# Mock the Supabase client initialization
|
56 |
+
class MockSupabaseClient:
|
57 |
+
def table(self, table_name):
|
58 |
+
return self
|
59 |
+
|
60 |
+
def select(self, columns):
|
61 |
+
return self
|
62 |
+
|
63 |
+
def execute(self):
|
64 |
+
# Return empty schedule data for testing
|
65 |
+
return type('obj', (object,), {'data': []})()
|
66 |
+
|
67 |
+
scheduler_service.supabase_client = MockSupabaseClient()
|
68 |
+
|
69 |
+
# Test initialization
|
70 |
+
scheduler_service.init_app(app)
|
71 |
+
|
72 |
+
if scheduler_service.scheduler is not None:
|
73 |
+
print("SUCCESS: APScheduler initialized successfully")
|
74 |
+
print(f"INFO: Current jobs: {len(scheduler_service.scheduler.get_jobs())}")
|
75 |
+
return True
|
76 |
+
else:
|
77 |
+
print("ERROR: APScheduler initialization failed")
|
78 |
+
return False
|
79 |
+
|
80 |
+
except Exception as e:
|
81 |
+
print(f"ERROR: Error testing APScheduler initialization: {e}")
|
82 |
+
import traceback
|
83 |
+
traceback.print_exc()
|
84 |
+
return False
|
85 |
+
|
86 |
+
def test_schedule_loading():
|
87 |
+
"""Test the schedule loading functionality."""
|
88 |
+
try:
|
89 |
+
from backend.scheduler.apscheduler_service import APSchedulerService
|
90 |
+
|
91 |
+
# Create scheduler service
|
92 |
+
scheduler_service = APSchedulerService()
|
93 |
+
|
94 |
+
# Mock the Supabase client
|
95 |
+
class MockSupabaseClient:
|
96 |
+
def table(self, table_name):
|
97 |
+
return self
|
98 |
+
|
99 |
+
def select(self, columns):
|
100 |
+
return self
|
101 |
+
|
102 |
+
def execute(self):
|
103 |
+
# Return mock schedule data
|
104 |
+
mock_data = [
|
105 |
+
{
|
106 |
+
'id': 'test_schedule_1',
|
107 |
+
'schedule_time': 'Monday 09:00',
|
108 |
+
'adjusted_time': 'Monday 08:55',
|
109 |
+
'Social_network': {
|
110 |
+
'id_utilisateur': 'test_user_1',
|
111 |
+
'token': 'test_token',
|
112 |
+
'sub': 'test_sub'
|
113 |
+
}
|
114 |
+
}
|
115 |
+
]
|
116 |
+
return type('obj', (object,), {'data': mock_data})()
|
117 |
+
|
118 |
+
scheduler_service.supabase_client = MockSupabaseClient()
|
119 |
+
|
120 |
+
# Test schedule loading
|
121 |
+
scheduler_service.load_schedules()
|
122 |
+
|
123 |
+
if scheduler_service.scheduler is not None:
|
124 |
+
jobs = scheduler_service.scheduler.get_jobs()
|
125 |
+
print(f"SUCCESS: Schedule loading test completed")
|
126 |
+
print(f"INFO: Total jobs: {len(jobs)}")
|
127 |
+
|
128 |
+
# Check for specific job types
|
129 |
+
loader_jobs = [job for job in jobs if job.id == 'load_schedules']
|
130 |
+
content_jobs = [job for job in jobs if job.id.startswith('gen_')]
|
131 |
+
publish_jobs = [job for job in jobs if job.id.startswith('pub_')]
|
132 |
+
|
133 |
+
print(f"INFO: Loader jobs: {len(loader_jobs)}")
|
134 |
+
print(f"INFO: Content generation jobs: {len(content_jobs)}")
|
135 |
+
print(f"INFO: Publishing jobs: {len(publish_jobs)}")
|
136 |
+
|
137 |
+
return len(jobs) > 0
|
138 |
+
else:
|
139 |
+
print("ERROR: Scheduler not initialized for schedule loading test")
|
140 |
+
return False
|
141 |
+
|
142 |
+
except Exception as e:
|
143 |
+
print(f"ERROR: Error testing schedule loading: {e}")
|
144 |
+
import traceback
|
145 |
+
traceback.print_exc()
|
146 |
+
return False
|
147 |
+
|
148 |
+
def main():
|
149 |
+
"""Main test function."""
|
150 |
+
print("Testing APScheduler visibility and functionality...")
|
151 |
+
print("=" * 60)
|
152 |
+
|
153 |
+
setup_logging()
|
154 |
+
|
155 |
+
tests = [
|
156 |
+
("APScheduler Import", test_apscheduler_import),
|
157 |
+
("Scheduler Initialization", test_scheduler_initialization),
|
158 |
+
("Schedule Loading", test_schedule_loading),
|
159 |
+
]
|
160 |
+
|
161 |
+
passed = 0
|
162 |
+
total = len(tests)
|
163 |
+
|
164 |
+
for test_name, test_func in tests:
|
165 |
+
print(f"\nRunning test: {test_name}")
|
166 |
+
print("-" * 40)
|
167 |
+
|
168 |
+
if test_func():
|
169 |
+
passed += 1
|
170 |
+
print(f"SUCCESS: {test_name} PASSED")
|
171 |
+
else:
|
172 |
+
print(f"FAILED: {test_name} FAILED")
|
173 |
+
|
174 |
+
print("\n" + "=" * 60)
|
175 |
+
print(f"Test Results: {passed}/{total} tests passed")
|
176 |
+
|
177 |
+
if passed == total:
|
178 |
+
print("SUCCESS: All tests passed! APScheduler is working correctly.")
|
179 |
+
return True
|
180 |
+
else:
|
181 |
+
print("WARNING: Some tests failed. Please check the error messages above.")
|
182 |
+
return False
|
183 |
+
|
184 |
+
if __name__ == "__main__":
|
185 |
+
success = main()
|
186 |
+
sys.exit(0 if success else 1)
|