Skip to content

Commit c227d76

Browse files
feat(architecture): major database adapter refactoring
- Refactor database adapter architecture for better modularity - Add dedicated adapters for PostgreSQL, SQLite, and StarRocks - Enhance session management and connection handling - Update documentation and examples
1 parent bb6ffb9 commit c227d76

43 files changed

Lines changed: 2978 additions & 1322 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
File renamed without changes.

archipy/adapters/orm/sqlalchemy/adapters.py renamed to archipy/adapters/base/sqlalchemy/adapters.py

Lines changed: 164 additions & 179 deletions
Large diffs are not rendered by default.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
AnyExecuteParams = _CoreMultiExecuteParams | _CoreSingleExecuteParams
1717

1818

19-
class SqlAlchemyPort:
19+
class SQLAlchemyPort:
2020
"""Abstract interface defining synchronous SQLAlchemy database operations.
2121
2222
This interface defines the contract that all synchronous SQLAlchemy adapters must
@@ -139,7 +139,7 @@ def scalars(self, statement: Executable, params: AnyExecuteParams | None = None)
139139
raise NotImplementedError
140140

141141

142-
class AsyncSqlAlchemyPort:
142+
class AsyncSQLAlchemyPort:
143143
"""Abstract interface defining asynchronous SQLAlchemy database operations.
144144
145145
This interface defines the contract that all asynchronous SQLAlchemy adapters must

archipy/adapters/orm/sqlalchemy/session_manager_ports.py renamed to archipy/adapters/base/sqlalchemy/session_manager_ports.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,6 @@ class SessionManagerPort:
1414
Implementing classes must provide mechanisms to:
1515
1. Retrieve a properly configured SQLAlchemy session
1616
2. Release/remove sessions when they're no longer needed
17-
18-
Examples:
19-
>>> from archipy.adapters.orm.sqlalchemy.session_manager_ports import SessionManagerPort
20-
>>>
21-
>>> class CustomSessionManager(SessionManagerPort):
22-
... def __init__(self):
23-
... # Initialize session factory
24-
... self._session_factory = create_session_factory()
25-
...
26-
... def get_session(self) -> Session:
27-
... return self._session_factory()
28-
...
29-
... def remove_session(self) -> None:
30-
... # Cleanup logic
31-
... pass
3217
"""
3318

3419
@abstractmethod
@@ -54,13 +39,6 @@ def remove_session(self) -> None:
5439
This method should be called to clean up the session when it's
5540
no longer needed, helping to prevent resource leaks and ensure
5641
proper session management.
57-
58-
Examples:
59-
>>> try:
60-
... session = session_manager.get_session()
61-
... # Perform database operations
62-
... finally:
63-
... session_manager.remove_session()
6442
"""
6543
raise NotImplementedError
6644

@@ -75,21 +53,6 @@ class AsyncSessionManagerPort:
7553
Implementing classes must provide mechanisms to:
7654
1. Retrieve a properly configured asynchronous SQLAlchemy session
7755
2. Release/remove sessions asynchronously when they're no longer needed
78-
79-
Examples:
80-
>>> from archipy.adapters.orm.sqlalchemy.session_manager_ports import AsyncSessionManagerPort
81-
>>>
82-
>>> class CustomAsyncSessionManager(AsyncSessionManagerPort):
83-
... def __init__(self):
84-
... # Initialize async session factory
85-
... self._session_factory = create_async_session_factory()
86-
...
87-
... def get_session(self) -> AsyncSession:
88-
... return self._session_factory()
89-
...
90-
... async def remove_session(self) -> None:
91-
... # Async cleanup logic
92-
... await self._session_factory.remove()
9356
"""
9457

9558
@abstractmethod
@@ -101,11 +64,6 @@ def get_session(self) -> AsyncSession:
10164
10265
Returns:
10366
AsyncSession: An asynchronous SQLAlchemy session object
104-
105-
Examples:
106-
>>> session = session_manager.get_session()
107-
>>> results = await session.execute(select(User))
108-
>>> users = results.scalars().all()
10967
"""
11068
raise NotImplementedError
11169

@@ -116,12 +74,5 @@ async def remove_session(self) -> None:
11674
This method should be called to clean up the session when it's
11775
no longer needed, helping to prevent resource leaks and ensure
11876
proper session management in async contexts.
119-
120-
Examples:
121-
>>> try:
122-
... session = session_manager.get_session()
123-
... # Perform async database operations
124-
... finally:
125-
... await session_manager.remove_session()
12677
"""
12778
raise NotImplementedError
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from typing import TYPE_CHECKING
2+
3+
from archipy.models.errors import InternalError
4+
5+
if TYPE_CHECKING:
6+
from archipy.adapters.base.sqlalchemy.session_manager_ports import AsyncSessionManagerPort, SessionManagerPort
7+
8+
9+
class SessionManagerRegistry:
10+
"""Registry for SQLAlchemy session managers.
11+
12+
This registry provides a centralized access point for both synchronous and
13+
asynchronous session managers, implementing the Service Locator pattern.
14+
15+
Subclasses should override get_sync_manager and get_async_manager to provide
16+
concrete session managers, or use set_sync_manager and set_async_manager to
17+
register managers manually.
18+
19+
Examples:
20+
>>> from archipy.adapters.postgres.sqlalchemy.session_manager_registry import PostgresSessionManagerRegistry
21+
>>> sync_manager = PostgresSessionManagerRegistry.get_sync_manager()
22+
>>> session = sync_manager.get_session()
23+
"""
24+
25+
_sync_instance = None
26+
_async_instance = None
27+
28+
@classmethod
29+
def get_sync_manager(cls) -> "SessionManagerPort":
30+
"""Get the synchronous session manager instance.
31+
32+
Returns:
33+
SessionManagerPort: The registered synchronous session manager
34+
35+
Raises:
36+
InternalError: If no synchronous session manager is set
37+
"""
38+
if cls._sync_instance is None:
39+
raise InternalError("Synchronous session manager not initialized")
40+
return cls._sync_instance
41+
42+
@classmethod
43+
def set_sync_manager(cls, manager: "SessionManagerPort") -> None:
44+
"""Set a custom synchronous session manager.
45+
46+
Args:
47+
manager: An instance implementing SessionManagerPort
48+
"""
49+
cls._sync_instance = manager
50+
51+
@classmethod
52+
def get_async_manager(cls) -> "AsyncSessionManagerPort":
53+
"""Get the asynchronous session manager instance.
54+
55+
Returns:
56+
AsyncSessionManagerPort: The registered asynchronous session manager
57+
58+
Raises:
59+
InternalError: If no asynchronous session manager is set
60+
"""
61+
if cls._async_instance is None:
62+
raise InternalError("Asynchronous session manager not initialized")
63+
return cls._async_instance
64+
65+
@classmethod
66+
def set_async_manager(cls, manager: "AsyncSessionManagerPort") -> None:
67+
"""Set a custom asynchronous session manager.
68+
69+
Args:
70+
manager: An instance implementing AsyncSessionManagerPort
71+
"""
72+
cls._async_instance = manager
73+
74+
@classmethod
75+
def reset(cls) -> None:
76+
"""Reset the registry to its initial state.
77+
78+
This method clears both registered managers, useful for testing.
79+
"""
80+
cls._sync_instance = None
81+
cls._async_instance = None

0 commit comments

Comments
 (0)