"""Background task execution for long-running operations.""" import threading import logging from typing import Callable, Any, Dict logger = logging.getLogger(__name__) def run_background_task(task_func: Callable, *args, **kwargs) -> threading.Thread: """ Run a function in a background thread. Args: task_func: Function to execute *args: Positional arguments for the function **kwargs: Keyword arguments for the function Returns: Thread object """ def wrapper(): try: logger.info(f"Starting background task: {task_func.__name__}") task_func(*args, **kwargs) logger.info(f"Completed background task: {task_func.__name__}") except Exception as e: logger.error(f"Background task failed ({task_func.__name__}): {str(e)}", exc_info=True) thread = threading.Thread(target=wrapper, daemon=True) thread.start() return thread def background_player_deployment( hostname: str, username: str, password: str, player_name: str, player_id: int, port: int = 22, server_url: str = None, server_api_key: str = None ) -> None: """ Deploy player code to host in background. Args: hostname: SSH hostname/IP username: SSH username password: SSH password player_name: Player name player_id: Player database ID port: SSH port server_url: DigiServer URL for player server_api_key: API key for player """ from app.utils.ssh_deploy import deploy_player_to_host from app.models import Player from app.extensions import db from app.utils.logger import log_action try: # Execute deployment result = deploy_player_to_host( hostname=hostname, username=username, password=password, player_name=player_name, port=port, server_url=server_url, server_api_key=server_api_key ) # Update player with deployment status from datetime import datetime player = Player.query.get(player_id) if player: player.last_deployment_at = datetime.utcnow() if result.get('success'): player.deployment_status = 'deployed' player.last_deployment_status = 'success' player.last_deployment_message = result.get('message', 'Deployment successful') log_action('info', f'Background deployment completed for player "{player_name}": {result["message"]}') else: player.deployment_status = 'failed' player.last_deployment_status = 'failed' player.last_deployment_message = result.get('error', result.get('message', 'Deployment failed')) log_action('error', f'Background deployment failed for player "{player_name}": {result.get("error", result.get("message"))}') db.session.commit() except Exception as e: logger.error(f"Background deployment error for player '{player_name}': {str(e)}", exc_info=True) log_action('error', f'Background deployment error for player "{player_name}": {str(e)}')