Skip to main content

Plugins

Whoosh-NG uses a plugin architecture to keep the core lightweight while enabling advanced features. Plugins are loaded via entry points and managed by the PluginManager.

Plugin Architecture​

PluginManager
├── load_plugins() # Auto-discover from entry points
├── register(name, plugin) # Manual registration
├── enable(name) # Enable a plugin
├── disable(name) # Disable a plugin
├── get(name) # Retrieve a plugin
└── list_plugins() # List all plugins

Built-in Plugins​

PluginPackageDescription
whoosh-ng-vectorwhoosh_modern.vectorVector search providers (NumPy, HNSW, Faiss)
whoosh-ng-autocompletewhoosh_modern.autocompleteEdge ngram autocomplete
whoosh-ng-fastapiwhoosh_fastapiFastAPI app factory
whoosh-ng-observabilitywhoosh_observabilityPrometheus metrics
whoosh-ng-adminwhoosh_adminAdmin UI

Creating a Plugin​

Every plugin is a subclass of BasePlugin:

from whoosh.plugins.base import BasePlugin

class MyPlugin(BasePlugin):
name = "my_plugin"
version = "1.0.0"
dependencies = []

def setup(self, registry):
"""Called when the plugin is enabled."""
registry.register("my_provider", MyProvider())

def teardown(self, registry):
"""Called when the plugin is disabled."""
registry.unregister("my_provider")

def middleware(self):
"""Return middleware to inject into the pipeline."""
return [MyMiddleware()]

def on_startup(self):
"""Called once at application startup."""
pass

def on_shutdown(self):
"""Called once at application shutdown."""
pass

Plugin Registration​

Via entry_points (pyproject.toml)​

[project.entry-points."whoosh_ng.plugins"]
my_plugin = "my_package.plugin:MyPlugin"

Programmatic​

from whoosh.plugins.manager import PluginManager

plugin = MyPlugin()
PluginManager.register("my_plugin", plugin)
PluginManager.enable("my_plugin")

Plugin Lifecycle​

register() -> setup() -> enable() -> middleware hooks -> teardown() -> disable()

Plugin Dependencies​

Plugins can declare dependencies on other plugins:

class VectorPlugin(BasePlugin):
name = "vector"
version = "1.0.0"
dependencies = ["metrics"] # Requires metrics plugin

The PluginManager resolves dependency order and detects conflicts.

Example: Vector Plugin​

from whoosh.plugins.base import BasePlugin
from whoosh.vector.base import VectorProvider, VectorField
from whoosh.vector.numpy_provider import NumpyProvider

class VectorPlugin(BasePlugin):
name = "vector"
version = "1.0.0"
dependencies = []

def setup(self, registry):
provider = NumpyProvider()
registry.register("numpy", provider, owner="vector")

def middleware(self):
from whoosh.middleware import MetricsMiddleware
return [MetricsMiddleware()]

def on_startup(self):
print("Vector plugin loaded")

Example: FastAPI Plugin​

from whoosh.plugins.base import BasePlugin

class FastAPIPlugin(BasePlugin):
name = "fastapi"
version = "1.0.0"

def setup(self, registry):
self.app = None

def create_app(self, index, **kwargs):
from whoosh_fastapi import create_app
self.app = create_app(index=index, **kwargs)
return self.app

def middleware(self):
from whoosh.middleware import CacheMiddleware
return [CacheMiddleware()]

Best Practices​

  1. Keep plugins small: One plugin, one responsibility
  2. Declare dependencies: Help PluginManager resolve load order
  3. Handle conflicts: Check for existing registrations before adding
  4. Clean up: Implement teardown() to remove registries and middleware
  5. Version your plugin: Semver for compatibility checking

Modern Plugin System (Whoosh-NG 2.0)​

Whoosh-NG 2.0 introduces an enhanced PluginManager with registry support for datasources, vector providers, embeddings, and middleware. For full details on the modern plugin architecture, entry point groups, and deployment, see the Plugin System Guide.