Skip to content
23 changes: 23 additions & 0 deletions ldclient/impl/datasystem/fdv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def __init__(self, store: FeatureStore, store_update_sink: DataStoreStatusProvid
self.__lock = ReadWriteLock()
self.__last_available = True
self.__poller: Optional[RepeatingTask] = None
self.__closed = False

def init(self, all_data: Mapping[VersionedDataKind, Mapping[str, Dict[Any, Any]]]):
return self.__wrapper(lambda: self.store.init(_FeatureStoreDataSetSorter.sort_all_collections(all_data)))
Expand Down Expand Up @@ -164,6 +165,8 @@ def __update_availability(self, available: bool):
task_to_start = None

with self.__lock.write():
if self.__closed:
return
if available == self.__last_available:
return

Expand Down Expand Up @@ -229,6 +232,26 @@ def is_monitoring_enabled(self) -> bool:

return monitoring_enabled()

def close(self):
"""
Close the wrapper and stop the repeating task poller if it's running.
Also forwards the close call to the underlying store if it has a close method.
"""
poller_to_stop = None

with self.__lock.write():
if self.__closed:
return
self.__closed = True
poller_to_stop = self.__poller
self.__poller = None

if poller_to_stop is not None:
poller_to_stop.stop()

if hasattr(self.store, "close"):
self.store.close()


class FDv2(DataSystem):
"""
Expand Down
22 changes: 22 additions & 0 deletions ldclient/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,28 @@ def initialized(self) -> bool:
# :return: true if the underlying data store is reachable
# """

# WARN: This isn't a required method on a FeatureStore. The SDK will
# check if the provided store responds to this method, and if it does,
# will call it during shutdown to release any resources (such as database
# connections or connection pools) that the store may be using.
#
# @abstractmethod
# def close(self):
# """
# Releases any resources used by the data store implementation.
#
# This method will be called by the SDK during shutdown to ensure proper
# cleanup of resources such as database connections, connection pools,
# network sockets, or other resources that should be explicitly released.
#
# Implementations should be idempotent - calling close() multiple times
# should be safe and have no additional effect after the first call.
#
# This is particularly important for persistent data stores that maintain
# connection pools or other long-lived resources that should be properly
# cleaned up when the SDK is shut down.
# """


class FeatureStoreCore:
"""
Expand Down