fix: remove background init timeout and allow skills reload retry

- Remove 5s thread.join() timeout so git clone/pull is not truncated
- Remove _init_complete flag, reset _init_in_progress on failure instead
- Let /reload/skills API retry initialization after network failure
- Raise GIT_HTTP_LOW_SPEED_LIMIT from 1 KB/s to 10 KB/s

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
YueGuobin 2026-05-11 22:51:57 +08:00
parent 27051a89ad
commit ae1a444677
No known key found for this signature in database
3 changed files with 17 additions and 26 deletions

View File

@ -37,26 +37,13 @@ try:
from .gns3_copilot.project_agent_manager import ProjectAgentManager
AI_COPILOT_AVAILABLE = True
# Start skills repository initialization in background with 5s timeout.
# This clones/pulls GNS3-Skills during server startup.
# If GitHub is unreachable (common in some regions), the timeout
# ensures the server starts without delay, using fallback defaults.
def _init_skills_background():
"""Initialize skills repo - called from background thread."""
from gns3server.agent.gns3_copilot.skills.registry import _ensure_skills_manager
# Start skills repository initialization in background.
# Clones/pulls GNS3-Skills during server startup.
# Git network timeouts are configured in SkillsManager (_GIT_TIMEOUT_ENV).
# The daemon thread auto-terminates when the process exits.
from gns3server.agent.gns3_copilot.skills.registry import _ensure_skills_manager
t = threading.Thread(target=_ensure_skills_manager, daemon=True)
t.start()
t.join(5)
if t.is_alive():
log = logging.getLogger(__name__)
log.warning(
"Skills repository initialization timed out (5s). "
"Will use fallback defaults. "
"The background thread will complete when network is available."
)
threading.Thread(target=_init_skills_background, daemon=True).start()
threading.Thread(target=_ensure_skills_manager, daemon=True).start()
except ImportError as e:
# AI dependencies not installed, disable AI Copilot feature

View File

@ -51,7 +51,7 @@ logger = logging.getLogger(__name__)
_GIT_TIMEOUT_ENV = {
'GIT_HTTP_TIMEOUT': '10', # Connection timeout (default: 120s)
'GIT_HTTP_LOW_SPEED_TIME': '5', # Slow speed threshold window
'GIT_HTTP_LOW_SPEED_LIMIT': '1000', # < 1 KB/s = slow → abort
'GIT_HTTP_LOW_SPEED_LIMIT': '10240', # < 10 KB/s = slow → abort
}

View File

@ -57,7 +57,6 @@ INJECTION_SKILLS_REGISTRY: dict[str, dict[str, Any]] = {}
# Global skills manager instance for hot reload
_skills_manager = None
_init_in_progress = False
_init_complete = False
def set_skills_manager(manager):
@ -75,16 +74,21 @@ def set_skills_manager(manager):
def _ensure_skills_manager():
"""
Initialize the SkillsManager (runs once, idempotent).
Initialize the SkillsManager (idempotent, retryable on failure).
Reads config, creates SkillsManager, clones/pulls repo,
and loads skills/prompts into memory. Safe to call from
background threads - uses _init_in_progress to prevent
concurrent initialization.
"""
global _skills_manager, _init_in_progress, _init_complete
if _skills_manager is not None or _init_complete:
On failure, resets _init_in_progress so future calls
(e.g., /reload/skills API) can retry. On success, the
manager is stored in _skills_manager and subsequent
calls return immediately.
"""
global _skills_manager, _init_in_progress
if _skills_manager is not None:
return
if _init_in_progress:
@ -130,7 +134,7 @@ def _ensure_skills_manager():
except Exception as e:
logger.error(f"Error initializing skills manager: {e}", exc_info=True)
finally:
_init_complete = True
_init_in_progress = False
def get_skills_manager():