feat: refactor pipeline registry and support external plugin registra…#254
Conversation
…tion - Replace utils.py with dedicated registry module for pipeline management - Add plugins.py for external pipeline registration via exposed function - Lazy import pipeline to improve startup performance - Update engine and worker to use new registry interface
There was a problem hiding this comment.
Code Review
This pull request refactors the pipeline loading mechanism by replacing directory scanning with a registry-based lazy-loading system and introduces a plugin discovery mechanism using entry points. Feedback highlights a bug in get_pipeline_class where registering a custom pipeline beforehand prevents built-in pipelines and general plugins from being loaded, as well as a potential race condition in load_general_plugins under multi-threaded environments.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def load_general_plugins() -> None: | ||
| global _plugins_loaded | ||
| if _plugins_loaded: | ||
| return | ||
| _plugins_loaded = True | ||
|
|
||
| plugins = load_plugins_by_group(DIFFSYNTH_DEFAULT_PLUGINS_GROUP) | ||
| # execute the loaded functions of general plugins | ||
| for name, func in plugins.items(): | ||
| try: | ||
| func() | ||
| logger.info("Executed general plugin %r", name) | ||
| except Exception: | ||
| logger.warning("Failed to execute general plugin %r", name, exc_info=True) |
There was a problem hiding this comment.
There is a potential race condition here in multi-threaded environments (e.g., when running under a multi-threaded web server).
Setting _plugins_loaded = True at the very beginning of the function means that any concurrent thread calling load_general_plugins() will return immediately, even though the first thread is still in the middle of loading and executing the plugins. This can cause the second thread to attempt to use pipelines or plugins before they are fully registered.
We should use a threading.Lock to ensure thread-safe initialization, and only set _plugins_loaded = True after the plugins have been successfully loaded and executed.
def load_general_plugins() -> None:
global _plugins_loaded
if _plugins_loaded:
return
import threading
lock = getattr(load_general_plugins, "_lock", None)
if lock is None:
lock = threading.Lock()
setattr(load_general_plugins, "_lock", lock)
with lock:
if _plugins_loaded:
return
plugins = load_plugins_by_group(DIFFSYNTH_DEFAULT_PLUGINS_GROUP)
# execute the loaded functions of general plugins
for name, func in plugins.items():
try:
func()
logger.info("Executed general plugin %r", name)
except Exception:
logger.warning("Failed to execute general plugin %r", name, exc_info=True)
_plugins_loaded = True
This pull request refactors how pipelines and plugins are registered and loaded in the
diffsynth_enginecodebase. The main improvements include introducing a new plugin system for extensibility, centralizing pipeline registration and lazy loading, and simplifying pipeline class resolution logic. The changes also clean up and streamline the code by removing the old pipeline utility module.Pipeline and Plugin System Refactor:
diffsynth_engine/pipelines/registry.pymodule that centralizes pipeline registration, supports lazy loading of pipeline classes, and provides a consistent API for retrieving pipeline classes and class names. This replaces the previous dynamic import logic.engine.pyandworker.pyto use the newpipelines.registrymodule for pipeline class resolution. [1] [2]diffsynth_engine/pipelines/utils.pymodule, eliminating the previous dynamic import and class map logic.Plugin System Enhancements:
diffsynth_engine/plugins.py, using Python entry points for extensibility. This allows external plugins to register themselves and be loaded/executed automatically.Code Quality and Maintenance:
load()indiffsynth_engine/utils/import_utils.pyfor clarity and consistency.