gateway/modules/services/serviceUtils/mainServiceUtils.py

187 lines
No EOL
7.1 KiB
Python

"""
Utility service for common operations across the gateway.
Provides centralized access to configuration, events, and other utilities.
"""
import logging
import os
from typing import Any, Optional, Dict, Callable
from modules.shared.configuration import APP_CONFIG
from modules.shared.eventManagement import eventManager
from modules.shared.timezoneUtils import get_utc_timestamp
from modules.security.tokenManager import TokenManager
logger = logging.getLogger(__name__)
class UtilsService:
"""Utility service providing common operations."""
def __init__(self, services):
self.services = services
def eventRegisterCron(self, job_id: str, func: Callable, cron_kwargs: Dict[str, Any],
replace_existing: bool = True, coalesce: bool = True,
max_instances: int = 1, misfire_grace_time: int = 1800):
"""
Register a cron job with the event manager.
Args:
job_id: Unique identifier for the job
func: Function to execute
cron_kwargs: Cron schedule parameters
replace_existing: Whether to replace existing job with same ID
coalesce: Whether to coalesce multiple pending executions
max_instances: Maximum number of concurrent instances
misfire_grace_time: Grace time for misfired jobs in seconds
"""
try:
eventManager.register_cron(
job_id=job_id,
func=func,
cron_kwargs=cron_kwargs,
replace_existing=replace_existing,
coalesce=coalesce,
max_instances=max_instances,
misfire_grace_time=misfire_grace_time
)
logger.info(f"Registered cron job '{job_id}' with schedule: {cron_kwargs}")
except Exception as e:
logger.error(f"Error registering cron job '{job_id}': {str(e)}")
def eventRegisterInterval(self, job_id: str, func: Callable, seconds: Optional[int] = None,
minutes: Optional[int] = None, hours: Optional[int] = None,
replace_existing: bool = True, coalesce: bool = True,
max_instances: int = 1, misfire_grace_time: int = 1800):
"""
Register an interval job with the event manager.
Args:
job_id: Unique identifier for the job
func: Function to execute
seconds: Interval in seconds
minutes: Interval in minutes
hours: Interval in hours
replace_existing: Whether to replace existing job with same ID
coalesce: Whether to coalesce multiple pending executions
max_instances: Maximum number of concurrent instances
misfire_grace_time: Grace time for misfired jobs in seconds
"""
try:
eventManager.register_interval(
job_id=job_id,
func=func,
seconds=seconds,
minutes=minutes,
hours=hours,
replace_existing=replace_existing,
coalesce=coalesce,
max_instances=max_instances,
misfire_grace_time=misfire_grace_time
)
logger.info(f"Registered interval job '{job_id}' (h={hours}, m={minutes}, s={seconds})")
except Exception as e:
logger.error(f"Error registering interval job '{job_id}': {str(e)}")
def eventRemove(self, job_id: str):
"""
Remove a scheduled job from the event manager.
Args:
job_id: ID of the job to remove
"""
try:
eventManager.remove(job_id)
logger.info(f"Removed job '{job_id}'")
except Exception as e:
logger.error(f"Error removing job '{job_id}': {str(e)}")
def configGet(self, key: str, default: Any = None, user_id: str = "system") -> Any:
"""
Get a configuration value with optional default.
Args:
key: Configuration key to retrieve
default: Default value if key not found
user_id: User ID for audit logging (default: "system")
Returns:
Configuration value or default
"""
try:
return APP_CONFIG.get(key, default, user_id)
except Exception as e:
logger.error(f"Error getting config '{key}': {str(e)}")
return default
def getUtcTimestamp(self) -> float:
"""
Get current UTC timestamp.
Returns:
float: Current UTC timestamp in seconds
"""
try:
return get_utc_timestamp()
except Exception as e:
logger.error(f"Error getting UTC timestamp: {str(e)}")
return 0.0
def getFreshConnectionToken(self, connectionId: str):
"""
Get a fresh token for a specific connection.
Args:
connectionId: ID of the connection to get token for
Returns:
Token object or None if not found/expired
"""
try:
return TokenManager().getFreshToken(connectionId)
except Exception as e:
logger.error(f"Error getting fresh token for connection {connectionId}: {str(e)}")
return None
def debugLogToFile(self, message: str, context: str = "DEBUG"):
"""
Log debug message to file if debug logging is enabled.
Args:
message: Debug message to log
context: Context identifier for the debug message
"""
try:
# Check if debug logging is enabled
debug_enabled = self.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
if not debug_enabled:
return
# Get debug directory
# Use configured log directory instead of hardcoded test-chat
logDir = self.configGet("APP_LOGGING_LOG_DIR", "./")
if not os.path.isabs(logDir):
gatewayDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
logDir = os.path.join(gatewayDir, logDir)
debug_dir = os.path.join(logDir, 'debug')
if not os.path.isabs(debug_dir):
# If relative path, make it relative to the gateway directory
gateway_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
debug_dir = os.path.join(gateway_dir, debug_dir)
# Ensure debug directory exists
os.makedirs(debug_dir, exist_ok=True)
# Create debug file path
debug_file = os.path.join(debug_dir, "debug_workflow.log")
# Format the debug entry
timestamp = self.getUtcTimestamp()
debug_entry = f"[{timestamp}] [{context}] {message}\n"
# Write to debug file
with open(debug_file, "a", encoding="utf-8") as f:
f.write(debug_entry)
except Exception as e:
# Don't log debug errors to avoid recursion
pass