JatsTheAIGen commited on
Commit
e2eb926
·
1 Parent(s): 1b4b874

Add initialization diagnostics and background initialization

Browse files

- Add initialization tracking (attempted, error state)
- Improve /api/health endpoint with detailed diagnostics
- Add background initialization thread for Gunicorn compatibility
- Initialize orchestrator on module import (works with Gunicorn)
- Add initialization error tracking and reporting
- Better error messages in health check endpoint

Files changed (1) hide show
  1. flask_api_standalone.py +77 -10
flask_api_standalone.py CHANGED
@@ -141,10 +141,15 @@ def set_security_headers(response):
141
  # Global orchestrator
142
  orchestrator = None
143
  orchestrator_available = False
 
 
144
 
145
  def initialize_orchestrator():
146
  """Initialize the AI orchestrator with local GPU models"""
147
- global orchestrator, orchestrator_available
 
 
 
148
 
149
  try:
150
  logger.info("=" * 60)
@@ -271,6 +276,7 @@ def initialize_orchestrator():
271
  except Exception as fallback_error:
272
  logger.error(f"❌ Failed to initialize in API-only mode: {fallback_error}", exc_info=True)
273
  orchestrator_available = False
 
274
  return False
275
  except Exception as e:
276
  logger.error("=" * 60)
@@ -281,6 +287,7 @@ def initialize_orchestrator():
281
  logger.error("=" * 60)
282
  logger.error("Full traceback:", exc_info=True)
283
  orchestrator_available = False
 
284
  return False
285
 
286
  # Root endpoint
@@ -309,11 +316,24 @@ def root():
309
  # Health check
310
  @app.route('/api/health', methods=['GET'])
311
  def health_check():
312
- """Health check endpoint"""
313
- return jsonify({
314
- 'status': 'healthy' if orchestrator_available else 'initializing',
315
- 'orchestrator_ready': orchestrator_available
316
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
  # Chat endpoint
319
  @app.route('/api/chat', methods=['POST'])
@@ -642,14 +662,61 @@ def set_context_mode():
642
  'error': str(e)
643
  }), 500
644
 
645
- # Initialize on startup
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  if __name__ == '__main__':
647
  logger.info("=" * 60)
648
- logger.info("STARTING PURE FLASK API")
649
  logger.info("=" * 60)
650
 
651
- # Initialize orchestrator
652
- initialize_orchestrator()
 
 
 
 
 
 
 
 
 
 
 
 
653
 
654
  port = int(os.getenv('PORT', 7860))
655
 
 
141
  # Global orchestrator
142
  orchestrator = None
143
  orchestrator_available = False
144
+ initialization_attempted = False
145
+ initialization_error = None
146
 
147
  def initialize_orchestrator():
148
  """Initialize the AI orchestrator with local GPU models"""
149
+ global orchestrator, orchestrator_available, initialization_attempted, initialization_error
150
+
151
+ initialization_attempted = True
152
+ initialization_error = None
153
 
154
  try:
155
  logger.info("=" * 60)
 
276
  except Exception as fallback_error:
277
  logger.error(f"❌ Failed to initialize in API-only mode: {fallback_error}", exc_info=True)
278
  orchestrator_available = False
279
+ initialization_error = str(fallback_error)
280
  return False
281
  except Exception as e:
282
  logger.error("=" * 60)
 
287
  logger.error("=" * 60)
288
  logger.error("Full traceback:", exc_info=True)
289
  orchestrator_available = False
290
+ initialization_error = f"{type(e).__name__}: {str(e)}"
291
  return False
292
 
293
  # Root endpoint
 
316
  # Health check
317
  @app.route('/api/health', methods=['GET'])
318
  def health_check():
319
+ """Health check endpoint with detailed diagnostics"""
320
+ status = {
321
+ 'status': 'healthy' if orchestrator_available else 'unhealthy',
322
+ 'orchestrator_ready': orchestrator_available,
323
+ 'initialization_attempted': initialization_attempted,
324
+ }
325
+
326
+ if not orchestrator_available:
327
+ if initialization_error:
328
+ status['error'] = initialization_error
329
+ status['message'] = 'Initialization failed. Check logs for details.'
330
+ elif initialization_attempted:
331
+ status['message'] = 'Initialization completed but orchestrator not available'
332
+ else:
333
+ status['message'] = 'Initialization not yet attempted'
334
+ status['help'] = 'Try POST /api/initialize to trigger initialization'
335
+
336
+ return jsonify(status)
337
 
338
  # Chat endpoint
339
  @app.route('/api/chat', methods=['POST'])
 
662
  'error': str(e)
663
  }), 500
664
 
665
+ # Initialize orchestrator on module import (for Gunicorn compatibility)
666
+ # This ensures initialization happens even when running via Gunicorn
667
+ logger.info("=" * 60)
668
+ logger.info("FLASK API MODULE LOADED")
669
+ logger.info("=" * 60)
670
+ logger.info("Initializing orchestrator on module import...")
671
+
672
+ # Use a flag to prevent multiple simultaneous initializations
673
+ import threading
674
+ _init_lock = threading.Lock()
675
+ _init_started = False
676
+
677
+ def _start_initialization():
678
+ """Start initialization in background thread to avoid blocking"""
679
+ global _init_started
680
+ with _init_lock:
681
+ if _init_started:
682
+ return
683
+ _init_started = True
684
+
685
+ def init_worker():
686
+ try:
687
+ logger.info("Background initialization thread started")
688
+ initialize_orchestrator()
689
+ except Exception as e:
690
+ logger.error(f"Background initialization failed: {e}", exc_info=True)
691
+
692
+ # Start initialization in background thread
693
+ init_thread = threading.Thread(target=init_worker, daemon=True, name="OrchInit")
694
+ init_thread.start()
695
+ logger.info("Initialization thread started (non-blocking)")
696
+
697
+ # Start initialization when module is imported
698
+ _start_initialization()
699
+
700
+ # Initialize on startup (for direct execution)
701
  if __name__ == '__main__':
702
  logger.info("=" * 60)
703
+ logger.info("STARTING PURE FLASK API (Direct Execution)")
704
  logger.info("=" * 60)
705
 
706
+ # Wait a moment for background initialization if it hasn't completed
707
+ import time
708
+ if not orchestrator_available:
709
+ logger.info("Waiting for background initialization to complete...")
710
+ for i in range(30): # Wait up to 30 seconds
711
+ if orchestrator_available:
712
+ break
713
+ time.sleep(1)
714
+ if i % 5 == 0:
715
+ logger.info(f"Still waiting... ({i}s)")
716
+
717
+ if not orchestrator_available:
718
+ logger.warning("Orchestrator not ready after wait, attempting direct initialization...")
719
+ initialize_orchestrator()
720
 
721
  port = int(os.getenv('PORT', 7860))
722