File size: 15,409 Bytes
98b8066
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# APScheduler Test Plan

## Overview

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.

## Test Objectives

1. **Verify APScheduler is properly initialized** during application startup
2. **Confirm logging configuration** shows APScheduler messages
3. **Test schedule loading functionality** from the database
4. **Verify job creation and execution** mechanisms
5. **Ensure scheduler persistence** and error handling

## Test Environment Setup

### Prerequisites
- Python 3.8+ installed
- All dependencies from `backend/requirements.txt` installed
- Environment variables configured (Supabase credentials, etc.)
- Access to the Lin application source code

### Test Files to Create

#### 1. `test_scheduler_visibility.py`
**Purpose**: Standalone test script to verify APScheduler logging and basic functionality

```python
#!/usr/bin/env python3
"""
Test script for APScheduler visibility and functionality.
This script tests whether APScheduler is working and properly configured for logging.
"""

import sys
import os
import logging
from pathlib import Path
from datetime import datetime

# Add the backend directory to the Python path
backend_dir = Path(__file__).parent / "backend"
sys.path.insert(0, str(backend_dir))

def setup_logging():
    """Setup logging for the test script."""
    logging.basicConfig(
        level=logging.DEBUG,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    # Configure APScheduler logger specifically
    logging.getLogger('apscheduler').setLevel(logging.DEBUG)
    print("πŸ”§ Logging configured for APScheduler")

def test_apscheduler_import():
    """Test that APScheduler can be imported."""
    try:
        from backend.scheduler.apscheduler_service import APSchedulerService
        print("βœ… APSchedulerService imported successfully")
        return True
    except Exception as e:
        print(f"❌ Failed to import APSchedulerService: {e}")
        return False

def test_scheduler_initialization():
    """Test APScheduler initialization with mock app."""
    try:
        from backend.scheduler.apscheduler_service import APSchedulerService
        
        # Create a mock app object
        class MockApp:
            def __init__(self):
                self.config = {
                    'SUPABASE_URL': 'https://test.supabase.co',
                    'SUPABASE_KEY': 'test_key',
                    'SCHEDULER_ENABLED': True
                }
        
        # Initialize the scheduler service
        app = MockApp()
        scheduler_service = APSchedulerService()
        
        # Mock the Supabase client initialization
        class MockSupabaseClient:
            def table(self, table_name):
                return self
                
            def select(self, columns):
                return self
                
            def execute(self):
                # Return empty schedule data for testing
                return type('obj', (object,), {'data': []})()
        
        scheduler_service.supabase_client = MockSupabaseClient()
        
        # Test initialization
        scheduler_service.init_app(app)
        
        if scheduler_service.scheduler is not None:
            print("βœ… APScheduler initialized successfully")
            print(f"πŸ“Š Current jobs: {len(scheduler_service.scheduler.get_jobs())}")
            return True
        else:
            print("❌ APScheduler initialization failed")
            return False
            
    except Exception as e:
        print(f"❌ Error testing APScheduler initialization: {e}")
        import traceback
        traceback.print_exc()
        return False

def test_schedule_loading():
    """Test the schedule loading functionality."""
    try:
        from backend.scheduler.apscheduler_service import APSchedulerService
        
        # Create scheduler service
        scheduler_service = APSchedulerService()
        
        # Mock the Supabase client
        class MockSupabaseClient:
            def table(self, table_name):
                return self
                
            def select(self, columns):
                return self
                
            def execute(self):
                # Return mock schedule data
                mock_data = [
                    {
                        'id': 'test_schedule_1',
                        'schedule_time': 'Monday 09:00',
                        'adjusted_time': 'Monday 08:55',
                        'Social_network': {
                            'id_utilisateur': 'test_user_1',
                            'token': 'test_token',
                            'sub': 'test_sub'
                        }
                    }
                ]
                return type('obj', (object,), {'data': mock_data})()
        
        scheduler_service.supabase_client = MockSupabaseClient()
        
        # Test schedule loading
        scheduler_service.load_schedules()
        
        if scheduler_service.scheduler is not None:
            jobs = scheduler_service.scheduler.get_jobs()
            print(f"βœ… Schedule loading test completed")
            print(f"πŸ“Š Total jobs: {len(jobs)}")
            
            # Check for specific job types
            loader_jobs = [job for job in jobs if job.id == 'load_schedules']
            content_jobs = [job for job in jobs if job.id.startswith('gen_')]
            publish_jobs = [job for job in jobs if job.id.startswith('pub_')]
            
            print(f"πŸ”„ Loader jobs: {len(loader_jobs)}")
            print(f"πŸ“ Content generation jobs: {len(content_jobs)}")
            print(f"πŸ“€ Publishing jobs: {len(publish_jobs)}")
            
            return len(jobs) > 0
        else:
            print("❌ Scheduler not initialized for schedule loading test")
            return False
            
    except Exception as e:
        print(f"❌ Error testing schedule loading: {e}")
        import traceback
        traceback.print_exc()
        return False

def main():
    """Main test function."""
    print("πŸš€ Testing APScheduler visibility and functionality...")
    print("=" * 60)
    
    setup_logging()
    
    tests = [
        ("APScheduler Import", test_apscheduler_import),
        ("Scheduler Initialization", test_scheduler_initialization),
        ("Schedule Loading", test_schedule_loading),
    ]
    
    passed = 0
    total = len(tests)
    
    for test_name, test_func in tests:
        print(f"\nπŸ“‹ Running test: {test_name}")
        print("-" * 40)
        
        if test_func():
            passed += 1
            print(f"βœ… {test_name} PASSED")
        else:
            print(f"❌ {test_name} FAILED")
    
    print("\n" + "=" * 60)
    print(f"πŸ“Š Test Results: {passed}/{total} tests passed")
    
    if passed == total:
        print("πŸŽ‰ All tests passed! APScheduler is working correctly.")
        return True
    else:
        print("⚠️ Some tests failed. Please check the error messages above.")
        return False

if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)
```

#### 2. `test_scheduler_integration.py`
**Purpose**: Test APScheduler integration with the actual Flask application

```python
#!/usr/bin/env python3
"""
Integration test for APScheduler with Flask application.
Tests the actual application startup and scheduler initialization.
"""

import sys
import os
import subprocess
import time
from pathlib import Path

def test_app_startup_with_scheduler():
    """Test that the Flask application starts with APScheduler visible."""
    try:
        # Change to the project directory
        project_dir = Path(__file__).parent
        os.chdir(project_dir)
        
        # Start the application
        print("πŸš€ Starting Flask application with APScheduler...")
        process = subprocess.Popen(
            [sys.executable, "start_app.py"],
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True,
            bufsize=1,
            universal_newlines=True
        )
        
        # Wait for startup and capture output
        startup_timeout = 30  # 30 seconds timeout
        start_time = time.time()
        
        scheduler_found = False
        while time.time() - start_time < startup_timeout:
            output = process.stdout.readline()
            if output:
                print(output.strip())
                
                # Check for APScheduler initialization messages
                if "Initializing APScheduler" in output:
                    scheduler_found = True
                    print("βœ… APScheduler initialization message found!")
                
                # Check for successful startup
                if "running on http" in output.lower():
                    break
        
        # Terminate the process
        process.terminate()
        process.wait(timeout=10)
        
        if scheduler_found:
            print("βœ… APScheduler is visible during application startup")
            return True
        else:
            print("❌ APScheduler messages not found in startup logs")
            return False
            
    except Exception as e:
        print(f"❌ Error testing app startup: {e}")
        return False

def main():
    """Main integration test function."""
    print("πŸ”— Testing APScheduler integration with Flask application...")
    print("=" * 60)
    
    success = test_app_startup_with_scheduler()
    
    print("\n" + "=" * 60)
    if success:
        print("πŸŽ‰ Integration test passed! APScheduler is working in the Flask app.")
    else:
        print("⚠️ Integration test failed. APScheduler may not be properly configured.")
    
    return success

if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)
```

## Test Execution Steps

### Step 1: Run Standalone Test
```bash
# Navigate to project directory
cd /path/to/your/project

# Run the standalone test
python test_scheduler_visibility.py
```

**Expected Output**:
```
πŸš€ Testing APScheduler visibility and functionality...
============================================================
πŸ”§ Logging configured for APScheduler

πŸ“‹ Running test: APScheduler Import
----------------------------------------
βœ… APSchedulerService imported successfully
βœ… APScheduler Import PASSED

πŸ“‹ Running test: Scheduler Initialization
----------------------------------------
βœ… APScheduler initialized successfully
πŸ“Š Current jobs: 1
βœ… Scheduler Initialization PASSED

πŸ“‹ Running test: Schedule Loading
----------------------------------------
βœ… Schedule loading test completed
πŸ“Š Total jobs: 3
πŸ”„ Loader jobs: 1
πŸ“ Content generation jobs: 1
πŸ“€ Publishing jobs: 1
βœ… Schedule Loading PASSED

============================================================
πŸ“Š Test Results: 3/3 tests passed
πŸŽ‰ All tests passed! APScheduler is working correctly.
```

### Step 2: Run Integration Test
```bash
# Run the integration test
python test_scheduler_integration.py
```

**Expected Output**:
```
πŸ”— Testing APScheduler integration with Flask application...
============================================================
πŸš€ Starting Flask application with APScheduler...
Starting Lin application on port 7860...
============================================================
============================================================
Flask application starting...
Access the application at:
  http://localhost:7860
  http://127.0.0.1:7860
============================================================
 * Serving Flask app 'backend.app'
 * Debug mode: off
INFO:backend.app:Initializing APScheduler...
INFO:backend.apscheduler_service:Initializing APScheduler...
INFO:backend.apscheduler_service:Initializing Supabase client...
INFO:backend.apscheduler_service:Supabase client initialized
INFO:backend.apscheduler_service:Creating BackgroundScheduler...
INFO:backend.apscheduler_service:BackgroundScheduler created
INFO:backend.apscheduler_service:Starting scheduler...
INFO:backend.apscheduler_service:Scheduler started
INFO:backend.apscheduler_service:Adding periodic job to load schedules...
INFO:backend.apscheduler_service:Periodic job added
INFO:backend.apscheduler_service:Loading schedules immediately...
INFO:backend.apscheduler_service:Found 0 schedules in database
INFO:backend.apscheduler_service:Updated APScheduler schedule
INFO:backend.app:βœ… APScheduler initialized successfully
INFO:backend.app:πŸ“Š Current jobs: 1
INFO:backend.app:πŸ”„ Schedule loading job added (runs every 5 minutes)
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:7860
 * Running on http://10.108.66.211:7860
βœ… APScheduler initialization message found!
βœ… APScheduler is visible during application startup

============================================================
πŸŽ‰ Integration test passed! APScheduler is working in the Flask app.
```

## Manual Verification Steps

### 1. Check Application Startup Logs
After implementing the logging configuration, start your application and look for:
- `Initializing APScheduler...`
- `BackgroundScheduler created`
- `Scheduler started`
- `Adding periodic job to load schedules...`
- `Schedule loading job added (runs every 5 minutes)`

### 2. Verify Scheduler Functionality
1. Create a schedule via the API
2. Check logs for schedule loading messages
3. Verify that individual jobs are created
4. Monitor for job execution at scheduled times

### 3. Test Error Handling
1. Test with invalid Supabase credentials
2. Test with missing environment variables
3. Verify appropriate error messages are logged

## Troubleshooting Guide

### Common Issues and Solutions

#### Issue 1: No APScheduler messages in logs
**Solution**: Ensure logging configuration is added to `backend/app.py`:
```python
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
```

#### Issue 2: Scheduler initialization fails
**Solution**: Check environment variables and Supabase connection:
- Verify `SUPABASE_URL` and `SUPABASE_KEY` are set
- Check network connectivity to Supabase
- Verify database tables exist

#### Issue 3: Jobs not executing
**Solution**: 
- Check that the application is running continuously
- Verify job triggers are correctly configured
- Check for any exceptions in job execution

#### Issue 4: Test script fails
**Solution**:
- Ensure all dependencies are installed
- Check Python path includes the backend directory
- Verify mock data structure matches actual database schema

## Success Criteria

The APScheduler implementation is considered successful when:

1. βœ… **Startup logs** show APScheduler initialization messages
2. βœ… **Test scripts** pass all tests
3. βœ… **Integration test** shows scheduler working in Flask app
4. βœ… **Manual verification** confirms job creation and execution
5. βœ… **Error handling** works appropriately
6. βœ… **Documentation** is updated with troubleshooting guide

## Next Steps

1. **Approve this test plan**
2. **Switch to Code mode** to implement the logging configuration
3. **Create the test scripts** outlined in this plan
4. **Execute the tests** to verify APScheduler visibility
5. **Update documentation** with the final solution