feat: adds redis locking mechanism to KuzuAdapter
This commit is contained in:
parent
ce4a55a474
commit
e7e8ec3bfd
3 changed files with 54 additions and 3 deletions
46
cognee/infrastructure/databases/cache/RedisAdapter.py
vendored
Normal file
46
cognee/infrastructure/databases/cache/RedisAdapter.py
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import redis
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
class RedisAdapter:
|
||||||
|
def __init__(self, host, port, lock_name):
|
||||||
|
self.redis = redis.Redis(host=host, port=port)
|
||||||
|
self.lock_name = lock_name
|
||||||
|
self.lock = None
|
||||||
|
|
||||||
|
def acquire(self, timeout=240, blocking_timeout=300):
|
||||||
|
"""
|
||||||
|
Acquire the Redis lock manually. Raises if acquisition fails.
|
||||||
|
"""
|
||||||
|
self.lock = self.redis.lock(
|
||||||
|
name=self.lock_name,
|
||||||
|
timeout=timeout,
|
||||||
|
blocking_timeout=blocking_timeout,
|
||||||
|
)
|
||||||
|
|
||||||
|
acquired = self.lock.acquire()
|
||||||
|
if not acquired:
|
||||||
|
raise RuntimeError(f"Could not acquire Redis lock: {self.lock_name}")
|
||||||
|
|
||||||
|
return self.lock
|
||||||
|
|
||||||
|
def release(self):
|
||||||
|
"""
|
||||||
|
Release the Redis lock manually, if held.
|
||||||
|
"""
|
||||||
|
if self.lock:
|
||||||
|
try:
|
||||||
|
self.lock.release()
|
||||||
|
self.lock = None
|
||||||
|
except redis.exceptions.LockError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def hold(self, timeout=60, blocking_timeout=300):
|
||||||
|
"""
|
||||||
|
Context manager for acquiring and releasing the Redis lock automatically.
|
||||||
|
"""
|
||||||
|
self.acquire(timeout=timeout, blocking_timeout=blocking_timeout)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
self.release()
|
||||||
1
cognee/infrastructure/databases/cache/__init__.py
vendored
Normal file
1
cognee/infrastructure/databases/cache/__init__.py
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
from .RedisAdapter import RedisAdapter
|
||||||
|
|
@ -4,7 +4,7 @@ import os
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import tempfile
|
import tempfile
|
||||||
from uuid import UUID
|
from uuid import UUID, uuid5, NAMESPACE_OID
|
||||||
from kuzu import Connection
|
from kuzu import Connection
|
||||||
from kuzu.database import Database
|
from kuzu.database import Database
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
@ -23,6 +23,7 @@ from cognee.infrastructure.engine import DataPoint
|
||||||
from cognee.modules.storage.utils import JSONEncoder
|
from cognee.modules.storage.utils import JSONEncoder
|
||||||
from cognee.modules.engine.utils.generate_timestamp_datapoint import date_to_int
|
from cognee.modules.engine.utils.generate_timestamp_datapoint import date_to_int
|
||||||
from cognee.tasks.temporal_graph.models import Timestamp
|
from cognee.tasks.temporal_graph.models import Timestamp
|
||||||
|
from cognee.infrastructure.databases.cache.RedisAdapter import RedisAdapter
|
||||||
|
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
|
|
@ -41,10 +42,11 @@ class KuzuAdapter(GraphDBInterface):
|
||||||
"""Initialize Kuzu database connection and schema."""
|
"""Initialize Kuzu database connection and schema."""
|
||||||
self.db_path = db_path # Path for the database directory
|
self.db_path = db_path # Path for the database directory
|
||||||
self.db: Optional[Database] = None
|
self.db: Optional[Database] = None
|
||||||
self._is_closed = False
|
self._is_closed = True
|
||||||
|
redis_lock_name = "kuzu-lock" + (str)(uuid5(NAMESPACE_OID, db_path))
|
||||||
|
self.redis_lock = RedisAdapter(host="localhost", port=6379, lock_name=redis_lock_name)
|
||||||
self.connection: Optional[Connection] = None
|
self.connection: Optional[Connection] = None
|
||||||
self.executor = ThreadPoolExecutor()
|
self.executor = ThreadPoolExecutor()
|
||||||
self._initialize_connection()
|
|
||||||
self.KUZU_ASYNC_LOCK = asyncio.Lock()
|
self.KUZU_ASYNC_LOCK = asyncio.Lock()
|
||||||
|
|
||||||
def _initialize_connection(self) -> None:
|
def _initialize_connection(self) -> None:
|
||||||
|
|
@ -155,10 +157,12 @@ class KuzuAdapter(GraphDBInterface):
|
||||||
del self.db
|
del self.db
|
||||||
self.db = None
|
self.db = None
|
||||||
self._is_closed = True
|
self._is_closed = True
|
||||||
|
self.redis_lock.release()
|
||||||
logger.info(f"Kuzu database closed successfully")
|
logger.info(f"Kuzu database closed successfully")
|
||||||
|
|
||||||
def reopen(self):
|
def reopen(self):
|
||||||
if self._is_closed:
|
if self._is_closed:
|
||||||
|
self.redis_lock.acquire()
|
||||||
self._is_closed = False
|
self._is_closed = False
|
||||||
self._initialize_connection()
|
self._initialize_connection()
|
||||||
logger.info(f"Kuzu database re-opened successfully")
|
logger.info(f"Kuzu database re-opened successfully")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue