🧩 Registry Pattern and Plugin System
LibreFolio uses a Registry Pattern to create a flexible and extensible plugin system. This allows new functionality—such as support for new brokers, asset pricing sources, or FX providers—to be added without modifying the core application code.
⚙️ How it Works
The system is based on three key components:
- Abstract Base Class (ABC): A template class that defines the interface a plugin must implement (e.g.,
AssetSourceProvider,BRIMProvider,FXRateProvider). - Provider Registry: A central class that discovers and stores all available plugins (e.g.,
AssetProviderRegistry). @register_providerDecorator: A simple decorator that automatically registers a plugin with its corresponding registry.
🗺️ High-Level Flow
graph TD
subgraph "1. Plugin Definition"
DEV["Developer creates<br/>MyProvider.py"] --> ABC["Inherits from<br/>ABC base class"]
DEV --> DEC["Decorates with<br/>@register_provider(Registry)"]
end
subgraph "2. Application Startup"
BOOT["App starts"] --> SCAN["Registry.auto_discover()<br/>scans plugin folder"]
SCAN --> IMPORT["Imports each .py file"]
IMPORT --> REG["@register_provider fires<br/>stores class in dict"]
end
subgraph "3. Runtime Usage"
SVC["Service needs provider"] --> GET["Registry.get_provider(code)"]
GET --> INST["Returns provider instance"]
SVC --> CALL["Calls abstract methods<br/>(fetch, parse, etc.)"]
end
DEV -.-> IMPORT
REG -.-> GET
🔍 Discovery Process
- Scan: On first access,
auto_discover()scans the designated plugin folder (e.g.,backend/app/services/fx_providers/). - Import: Each
.pyfile (except__init__.py) is loaded withimportlib. - Register: The
@register_providerdecorator fires on import, callingRegistry.register(class)which readsprovider_codeand stores the class in_providers[code] = class. - Lazy: Discovery happens once, on first
get_provider()call. Subsequent calls use the cached dictionary.
🧱 Core Components
📋 AbstractProviderRegistry
The base class for all registries. Provides:
| Method | Description |
|---|---|
register(cls, provider_class) |
Store a provider class, keyed by its provider_code |
get_provider(cls, code) |
Get provider class by code (triggers auto-discovery if needed) |
get_provider_instance(cls, code) |
Returns an instantiated provider object |
list_providers(cls) |
List all registered providers with code and name |
auto_discover(cls) |
Scan plugin folder and import all modules |
🏷️ Registry Specializations
| Registry | Plugin Folder | Base Class | Purpose |
|---|---|---|---|
BRIMProviderRegistry |
brim_providers/ |
BRIMProvider |
Parse broker CSV/Excel files |
AssetProviderRegistry |
asset_source_providers/ |
AssetSourceProvider |
Fetch asset prices |
FXProviderRegistry |
fx_providers/ |
FXRateProvider |
Fetch exchange rates |
🎯 @register_provider Decorator
The decorator is a factory that calls registry_class.register(provider_class) at import time.
📖 Plugin Development Guides
Each subsystem has its own detailed guide with ABC method tables, flow diagrams, and implementation examples:
| Subsystem | Guide | Base Class | What It Does |
|---|---|---|---|
| BRIM | BRIM Plugin Guide | BRIMProvider |
Parse broker export files (CSV, Excel) into transactions |
| Assets | Asset Plugin Guide | AssetSourceProvider |
Fetch current and historical asset prices |
| FX | FX Plugin Guide | FXRateProvider |
Fetch exchange rates from central banks |
📚 Subsystem Documentation
Each plugin subsystem also has architecture docs, provider lists, and configuration pages:
📥 BRIM (Broker Report Import Manager)
- Architecture — Pipeline design, parsing flow
- Generic CSV Provider — User-configurable CSV mapper
- Providers List — All supported brokers (Directa, Degiro, IBKR, etc.)
📈 Assets (Pricing & Metadata)
- Architecture — Provider interface, caching, refresh logic
- System Providers — Built-in providers (Scheduled Investment, Manual)
- Providers List — All available providers (Yahoo Finance, etc.)
💱 FX (Foreign Exchange)
- Architecture — Multi-provider design, sync process
- Configuration & Routing — Chain routing algorithm, priority fallback
- Providers List — ECB, FED, BOE, SNB details