From 5fb2572c7f89a0e37693e4830cbb2959ea717e48 Mon Sep 17 00:00:00 2001 From: SimonThordal Date: Tue, 16 Jul 2024 13:09:12 +0200 Subject: [PATCH] singleton should be scoped to event loop --- tests/test_search_provider.py | 10 +--------- yente/provider/base.py | 11 ++++++----- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/tests/test_search_provider.py b/tests/test_search_provider.py index 7b9d4fc4..e2cb6254 100644 --- a/tests/test_search_provider.py +++ b/tests/test_search_provider.py @@ -3,15 +3,7 @@ from yente import settings from yente.exc import YenteIndexError, YenteNotFoundError -from yente.provider import SearchProvider, ElasticSearchProvider, OpenSearchProvider - - -@pytest.mark.asyncio -@pytest.mark.parametrize("provider", [ElasticSearchProvider, OpenSearchProvider]) -async def test_is_singleton(provider): - s1 = await provider.create() - s2 = await provider.create() - assert id(s1) == id(s2) +from yente.provider import SearchProvider @pytest.mark.asyncio diff --git a/yente/provider/base.py b/yente/provider/base.py index 450b8c30..c4663232 100644 --- a/yente/provider/base.py +++ b/yente/provider/base.py @@ -1,20 +1,21 @@ -from abc import abstractmethod from typing import Any, Dict, List, Optional from typing import AsyncIterator from threading import Lock +from asyncio import get_running_loop class SingletonMeta(type): # This is a thread-safe implementation of the Singleton pattern. Shamelessly stolen from # https://refactoring.guru/design-patterns/singleton/python/example#example-1 - _instances: Dict[type, Any] = {} + _instances: Dict[str, Any] = {} _lock: Lock = Lock() def __call__(cls, *args: Any, **kwds: Any) -> Any: with cls._lock: - if cls not in cls._instances: - cls._instances[cls] = super().__call__(*args, **kwds) - return cls._instances[cls] + loop_class = str(hash(get_running_loop())) + str(cls) + if loop_class not in cls._instances: + cls._instances[loop_class] = super().__call__(*args, **kwds) + return cls._instances[loop_class] class SearchProvider(object, metaclass=SingletonMeta):