Files
Sergei Miloserdov 6b3c8b65ef Improve error handling and reliability across backend and frontend
Enhanced backend (nodes.py, __init__.py):

Added robust error handling for loading resolutions.json and aspect_ratios.json with safe defaults.
Implemented per-file error handling when loading individual model configurations to prevent one failure from blocking others.
Added data structure validation for model files.
Introduced a comprehensive fallback data structure in __init__.py to ensure the node initializes and functions even if all data loading fails.

Strengthened frontend (js/optimal_resolution.js):

Added HTTP status check and data structure validation for the /optimal_resolution/models API response.
Implemented null/undefined checks (?.) and explicit validation for all widget lookups and critical data properties.
Made widget callbacks safer by verifying the original callback is a function before calling it.
Added a minimal fallback data structure in the fetch error handler to prevent UI crashes.
2026-05-16 00:55:16 +03:00

84 lines
2.7 KiB
Python

from .nodes import OptimalResolutionNode, load_models_data, NODE_DIR
from .nodes import ComfyExtension, io
from server import PromptServer
import json
import os
import aiohttp
WEB_DIRECTORY = "./js"
# Load data immediately at module import time with error handling
try:
OptimalResolutionNode.models_data = load_models_data()
if not OptimalResolutionNode.models_data:
raise ValueError("Loaded data is empty")
except Exception as e:
print(f"[OptimalResolution] Critical error during initialization: {e}. Using fallback data.")
# Fallback to minimal viable data structure
OptimalResolutionNode.models_data = {
"model_types": {"Image": ["Fallback Model"], "Video": []},
"models_data": {
"Fallback Model": {
"base_resolution": 1024,
"multiple_of": 16,
"resolution_options": {
"values": ["Standard"],
"default": "Standard"
}
},
"default": {
"base_resolution": 1024,
"multiple_of": 16
}
},
"resolutions": {},
"aspect_ratios": {}
}
class OptimalResolutionExtension(ComfyExtension):
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [OptimalResolutionNode]
async def comfy_entrypoint() -> ComfyExtension:
return OptimalResolutionExtension()
# Setup API Routes
prompt_server = PromptServer.instance
@prompt_server.routes.get("/optimal_resolution/models")
async def get_models_data(request):
"""Returns the configuration JSON to the frontend."""
data = OptimalResolutionNode.models_data
if not data:
data = load_models_data()
return aiohttp.web.json_response(data, status=200)
@prompt_server.routes.post("/optimal_resolution/calculate")
async def calculate_resolution_api(request):
"""Calculates resolution without executing the workflow."""
try:
body = await request.json()
model_type = body.get("model_type", "Image")
model = body.get("model", "Flux 1")
aspect_ratio = body.get("aspect_ratio", "1:1")
resolution = body.get("resolution", "Standard")
data = OptimalResolutionNode.models_data
if not data:
data = load_models_data()
w, h, text = OptimalResolutionNode.calculate_resolution_logic(
model_type, model, aspect_ratio, resolution, data
)
return aiohttp.web.json_response({
"width": w,
"height": h,
"resolution_text": text
}, status=200)
except Exception as e:
print(f"[OptimalResolution] API Error: {e}")
return aiohttp.web.json_response({"error": str(e)}, status=500)
__all__ = ['WEB_DIRECTORY']