WasabiDrop Claude commited on
Commit
287a98e
·
1 Parent(s): 6e75c75

🔧 Fix Add Models worker timeout and missing logging method

Browse files

- Add missing log_user_action method to FirebaseStructuredLogger
- Add timeout protection to Firebase sync operations (5s timeout)
- Prevent worker crashes during model addition
- Ensure proper fallback to local storage on timeout

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

src/services/firebase_logger.py CHANGED
@@ -279,6 +279,34 @@ class FirebaseStructuredLogger:
279
  print(f"Failed to log structured event to Firebase: {e}")
280
  return False
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  def get_analytics(self, days: int = 30) -> Dict[str, Any]:
283
  """Get comprehensive analytics from Firebase"""
284
  if not self.firebase_available:
 
279
  print(f"Failed to log structured event to Firebase: {e}")
280
  return False
281
 
282
+ def log_user_action(self, user_token: str, action: str, details: Dict[str, Any] = None,
283
+ admin_user: str = None) -> bool:
284
+ """Log a user action event (admin actions, etc.)"""
285
+ if not self.firebase_available:
286
+ return False
287
+
288
+ try:
289
+ with self.lock:
290
+ event_data = {
291
+ "event_type": "user_action",
292
+ "timestamp": datetime.now().isoformat(),
293
+ "user_token": user_token,
294
+ "action": action,
295
+ "details": details or {},
296
+ "admin_user": admin_user
297
+ }
298
+
299
+ # Use timestamp-based key for ordering
300
+ timestamp_key = int(time.time() * 1000) # milliseconds
301
+ event_key = f"{timestamp_key}_{uuid.uuid4().hex[:8]}"
302
+
303
+ self.db_ref.child(event_key).set(event_data)
304
+ return True
305
+
306
+ except Exception as e:
307
+ print(f"Failed to log user action to Firebase: {e}")
308
+ return False
309
+
310
  def get_analytics(self, days: int = 30) -> Dict[str, Any]:
311
  """Get comprehensive analytics from Firebase"""
312
  if not self.firebase_available:
src/services/model_families.py CHANGED
@@ -382,17 +382,36 @@ class ModelFamilyManager:
382
 
383
  if self.firebase_db:
384
  try:
385
- config_ref = self.firebase_db.child('model_families_config')
386
- config_ref.set(config)
387
- print("Saved model families config to Firebase (sync)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  except Exception as e:
389
  print(f"Failed to save model families to Firebase (sync): {e}")
390
- else:
391
- try:
392
- with open("model_families_config.json", 'w') as f:
393
- json.dump(config, f, indent=2)
394
- except Exception as e:
395
- print(f"Failed to save model families to file: {e}")
 
396
 
397
  def is_model_whitelisted(self, provider: AIProvider, model_id: str) -> bool:
398
  """Check if a model is whitelisted for use"""
@@ -716,17 +735,36 @@ class ModelFamilyManager:
716
 
717
  if self.firebase_db:
718
  try:
719
- custom_models_ref = self.firebase_db.child('custom_models')
720
- custom_models_ref.set(config)
721
- print("Saved custom models to Firebase (sync)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
722
  except Exception as e:
723
  print(f"Failed to save custom models to Firebase (sync): {e}")
724
- else:
725
- try:
726
- with open("custom_models.json", 'w') as f:
727
- json.dump(config, f, indent=2)
728
- except Exception as e:
729
- print(f"Failed to save custom models to file: {e}")
 
730
 
731
  def _load_custom_models(self):
732
  """Load custom models from persistent storage"""
 
382
 
383
  if self.firebase_db:
384
  try:
385
+ import threading
386
+ success = [False]
387
+
388
+ def save_config():
389
+ try:
390
+ config_ref = self.firebase_db.child('model_families_config')
391
+ config_ref.set(config)
392
+ success[0] = True
393
+ print("Saved model families config to Firebase (sync)")
394
+ except Exception as e:
395
+ print(f"Failed to save model families to Firebase (sync): {e}")
396
+
397
+ # Run with timeout protection
398
+ save_thread = threading.Thread(target=save_config)
399
+ save_thread.daemon = True
400
+ save_thread.start()
401
+ save_thread.join(timeout=5.0) # 5 second timeout
402
+
403
+ if save_thread.is_alive():
404
+ print("Firebase config save timed out, falling back to local file")
405
+
406
  except Exception as e:
407
  print(f"Failed to save model families to Firebase (sync): {e}")
408
+
409
+ # Always save to local file as backup
410
+ try:
411
+ with open("model_families_config.json", 'w') as f:
412
+ json.dump(config, f, indent=2)
413
+ except Exception as e:
414
+ print(f"Failed to save model families to file: {e}")
415
 
416
  def is_model_whitelisted(self, provider: AIProvider, model_id: str) -> bool:
417
  """Check if a model is whitelisted for use"""
 
735
 
736
  if self.firebase_db:
737
  try:
738
+ import threading
739
+ success = [False]
740
+
741
+ def save_custom_models():
742
+ try:
743
+ custom_models_ref = self.firebase_db.child('custom_models')
744
+ custom_models_ref.set(config)
745
+ success[0] = True
746
+ print("Saved custom models to Firebase (sync)")
747
+ except Exception as e:
748
+ print(f"Failed to save custom models to Firebase (sync): {e}")
749
+
750
+ # Run with timeout protection
751
+ save_thread = threading.Thread(target=save_custom_models)
752
+ save_thread.daemon = True
753
+ save_thread.start()
754
+ save_thread.join(timeout=5.0) # 5 second timeout
755
+
756
+ if save_thread.is_alive():
757
+ print("Firebase custom models save timed out, falling back to local file")
758
+
759
  except Exception as e:
760
  print(f"Failed to save custom models to Firebase (sync): {e}")
761
+
762
+ # Always save to local file as backup
763
+ try:
764
+ with open("custom_models.json", 'w') as f:
765
+ json.dump(config, f, indent=2)
766
+ except Exception as e:
767
+ print(f"Failed to save custom models to file: {e}")
768
 
769
  def _load_custom_models(self):
770
  """Load custom models from persistent storage"""