feat(hotreload): implement hot-reload functionality for addons#832
Draft
rdo-gishantsingh wants to merge 4 commits intoynput:developfrom
Draft
feat(hotreload): implement hot-reload functionality for addons#832rdo-gishantsingh wants to merge 4 commits intoynput:developfrom
rdo-gishantsingh wants to merge 4 commits intoynput:developfrom
Conversation
- Add utilities to trigger hot-reload without server restart - Notify clients of addon changes after successful reload - Fallback to server restart if hot-reload fails
- Introduced a new ReloadStatusModel to provide hot-reload status information. - Added a /health/reload endpoint to retrieve the last reload timestamp and count. - Improved handle_need_restart logic to pass event_id explicitly, avoiding race conditions. - Updated trigger_hotreload to support verification of reload success.
- Implemented functions to persist and retrieve reload statistics from Redis. - Updated hot-reload manager to use persisted stats for last reload time and count. - Ensures reload stats survive worker restarts.
- Import trigger_hotreload and notify_clients_addon_reload functions - Replace require_server_restart with hot-reload on addon/version deletion - Fall back to require_server_restart if hot-reload fails - Add logging for both success and fallback scenarios
Member
|
I appreciate the concept - Hot reloading is definitely something the server needs, but i have two main concerns:
def restart_server():
"""Force the server to restart.
This is usually called from ayon_server.api.messaging,
when `server.restart_requested` event is triggered.
"""
logger.warning("Server is restarting")
# Send a SIGHUP to the parent process (gunicorn) to request a reload
# Gunicorn will restart the server when it receives this signal,
# but it won't quit itself, so the container will keep running.
os.kill(os.getppid(), signal.SIGHUP)
As i said, this is something we really need - My idea to reduce the startup latency was we import new addons during runtime and replace addon instances in the AddonLibrary and this should be triggered using EventStream global handler to ensure it happens on all replicas) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements hot-reload functionality for AYON Server addons, allowing addons to be installed and deleted without requiring a full server restart. This significantly improves the developer experience and reduces downtime in production environments.
Related Issue: Improves addon management workflow by eliminating unnecessary server restarts
Problem Statement
ps aux) for process detectionSolution
Implement a robust hot-reload system that:
psutilfor reliable cross-platform process detectionChanges Made
Added
AYON_RELOAD_SCRIPTandAYON_SERVER_TYPEenvironment variablesGET /api/health/reloadreturns reload statisticsserver.addons_changedevent dispatched after successful reloadChanged
ayon_server/installer/hotreload.py: Complete rewrite with:_get_server_pid(): Uses psutil.process_iter() instead of parsingps aux_signal_server_reload(): Proper error handling with custom exceptions_get_reload_script_path(): Configurable via environment with security validation_persist_reload_stats()/_get_persisted_reload_stats(): Redis persistence helperstrigger_hotreload(): Main function with addon library cache clearingnotify_clients_addon_reload(): Client notification via EventStreamHotReloadManager: Dataclass with asyncget_status()methodayon_server/installer/__init__.py: Fixed race condition by passingevent_idexplicitly tohandle_need_restart()api/addons/delete_addon.py: Integrated hot-reload for addon deletion with fallback torequire_server_restart()api/system/__init__.py: AddedReloadStatusModeland/health/reloadendpointFixed
current_event_idinstance variableImplementation Details
Hot-Reload Flow (Installation)
Hot-Reload Flow (Deletion)
Redis Keys Used
hotreload-reload_count: Integer counter of successful reloadshotreload-last_reload: ISO timestamp of last reloadEnvironment Variables
AYON_SERVER_TYPEgunicorngunicornorgranian)AYON_RELOAD_SCRIPTTesting
Test Strategy
Test Commands
Manual Testing Steps
/api/health/reload- should showreloadCount: 1/api/health/reload- should showreloadCount: 2Before/After Comparison
Before (Server Restart Required)
Downtime: 10-30 seconds, all WebSocket connections lost
After (Hot-Reload)
Downtime: 0 seconds, WebSocket connections preserved
Code Quality
Breaking Changes
Are there any breaking changes? No
The hot-reload is transparent to clients. The existing
require_server_restart()mechanism remains as a fallback if hot-reload fails.Dependencies
No new dependencies added.
psutilwas already inpyproject.toml.