refactor: use metaclass for Singleton in FiatConverter

This commit is contained in:
Matthias
2026-01-03 14:06:17 +01:00
parent cfd048e74e
commit 0d7127bb6a
3 changed files with 24 additions and 12 deletions

View File

@@ -5,7 +5,6 @@ e.g BTC to USD
import logging
from datetime import datetime
from typing import Any
from requests.exceptions import RequestException
@@ -13,6 +12,7 @@ from freqtrade.constants import SUPPORTED_FIAT, Config
from freqtrade.mixins.logging_mixin import LoggingMixin
from freqtrade.util import FtTTLCache
from freqtrade.util.coin_gecko import FtCoinGeckoApi
from freqtrade.util.singleton import SingletonMeta
logger = logging.getLogger(__name__)
@@ -32,26 +32,16 @@ coingecko_mapping = {
}
class CryptoToFiatConverter(LoggingMixin):
class CryptoToFiatConverter(LoggingMixin, metaclass=SingletonMeta):
"""
Main class to initiate Crypto to FIAT.
This object contains a list of pair Crypto, FIAT
This object is also a Singleton
"""
__instance = None
_coinlistings: list[dict] = []
_backoff: float = 0.0
def __new__(cls, *args: Any, **kwargs: Any) -> Any:
"""
Singleton pattern to ensure only one instance is created.
"""
if not cls.__instance:
cls.__instance = super().__new__(cls)
return cls.__instance
def __init__(self, config: Config) -> None:
# Timeout: 6h
self._pair_price: FtTTLCache = FtTTLCache(maxsize=500, ttl=6 * 60 * 60)

View File

@@ -0,0 +1,16 @@
from typing import Any
class SingletonMeta(type):
"""
A thread-safe implementation of Singleton.
Use as metaclass to create singleton classes.
"""
_instances: dict = {}
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]

View File

@@ -12,6 +12,12 @@ from freqtrade.util.coin_gecko import FtCoinGeckoApi
from tests.conftest import log_has, log_has_re
@pytest.fixture(autouse=True)
def reset_singleton_instance():
# Reset the singleton instance before each test
CryptoToFiatConverter._instances = {}
def test_fiat_convert_is_singleton():
fiat_convert = CryptoToFiatConverter({"a": 22})
fiat_convert2 = CryptoToFiatConverter({})