maleo-database 0.0.1__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {maleo_database-0.0.1 → maleo_database-0.0.3}/PKG-INFO +19 -2
- {maleo_database-0.0.1 → maleo_database-0.0.3}/maleo_database.egg-info/PKG-INFO +19 -2
- {maleo_database-0.0.1 → maleo_database-0.0.3}/maleo_database.egg-info/requires.txt +18 -1
- {maleo_database-0.0.1 → maleo_database-0.0.3}/pyproject.toml +19 -2
- maleo_database-0.0.3/src/managers/session.py +256 -0
- maleo_database-0.0.1/src/managers/session.py +0 -123
- {maleo_database-0.0.1 → maleo_database-0.0.3}/LICENSE +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/README.md +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/maleo_database.egg-info/SOURCES.txt +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/maleo_database.egg-info/dependency_links.txt +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/maleo_database.egg-info/top_level.txt +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/setup.cfg +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/config/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/config/additional.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/config/connection.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/config/identifier.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/config/pooling.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/enums.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/clients/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/clients/elasticsearch.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/clients/mongodb.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/clients/redis.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/engines/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/engines/mysql.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/engines/postgresql.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/engines/sqlite.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/managers/engines/sqlserver.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/base.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/models/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/models/mixins/__init__.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/models/mixins/identifier.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/models/mixins/status.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/models/mixins/timestamp.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/models/table.py +0 -0
- {maleo_database-0.0.1 → maleo_database-0.0.3}/src/orm/queries.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: maleo-database
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.3
|
4
4
|
Summary: Database package for MaleoSuite
|
5
5
|
Author-email: Agra Bima Yuda <agra@nexmedis.com>
|
6
6
|
License: Proprietary
|
@@ -16,6 +16,7 @@ Requires-Dist: cachetools>=5.5.2
|
|
16
16
|
Requires-Dist: certifi>=2025.8.3
|
17
17
|
Requires-Dist: cffi>=1.17.1
|
18
18
|
Requires-Dist: cfgv>=3.4.0
|
19
|
+
Requires-Dist: charset-normalizer>=3.4.3
|
19
20
|
Requires-Dist: click>=8.2.1
|
20
21
|
Requires-Dist: cryptography>=45.0.6
|
21
22
|
Requires-Dist: distlib>=0.4.0
|
@@ -24,23 +25,37 @@ Requires-Dist: elastic-transport>=9.1.0
|
|
24
25
|
Requires-Dist: elasticsearch>=9.1.0
|
25
26
|
Requires-Dist: fastapi>=0.116.1
|
26
27
|
Requires-Dist: filelock>=3.19.1
|
28
|
+
Requires-Dist: google-api-core>=2.25.1
|
27
29
|
Requires-Dist: google-auth>=2.40.3
|
30
|
+
Requires-Dist: google-cloud-appengine-logging>=1.6.2
|
31
|
+
Requires-Dist: google-cloud-audit-log>=0.3.2
|
32
|
+
Requires-Dist: google-cloud-core>=2.4.3
|
33
|
+
Requires-Dist: google-cloud-logging>=3.12.1
|
34
|
+
Requires-Dist: googleapis-common-protos>=1.70.0
|
28
35
|
Requires-Dist: greenlet>=3.2.4
|
36
|
+
Requires-Dist: grpc-google-iam-v1>=0.14.2
|
37
|
+
Requires-Dist: grpcio>=1.74.0
|
38
|
+
Requires-Dist: grpcio-status>=1.74.0
|
29
39
|
Requires-Dist: identify>=2.6.13
|
30
40
|
Requires-Dist: idna>=3.10
|
41
|
+
Requires-Dist: importlib_metadata>=8.7.0
|
31
42
|
Requires-Dist: maleo-constants>=0.0.2
|
32
43
|
Requires-Dist: maleo-enums>=0.0.2
|
33
|
-
Requires-Dist: maleo-
|
44
|
+
Requires-Dist: maleo-logging>=0.0.1
|
45
|
+
Requires-Dist: maleo-mixins>=0.0.5
|
34
46
|
Requires-Dist: maleo-types-base>=0.0.2
|
35
47
|
Requires-Dist: maleo-types-enums>=0.0.2
|
36
48
|
Requires-Dist: maleo-utils>=0.0.3
|
37
49
|
Requires-Dist: motor>=3.7.1
|
38
50
|
Requires-Dist: mypy_extensions>=1.1.0
|
39
51
|
Requires-Dist: nodeenv>=1.9.1
|
52
|
+
Requires-Dist: opentelemetry-api>=1.36.0
|
40
53
|
Requires-Dist: packaging>=25.0
|
41
54
|
Requires-Dist: pathspec>=0.12.1
|
42
55
|
Requires-Dist: platformdirs>=4.4.0
|
43
56
|
Requires-Dist: pre_commit>=4.3.0
|
57
|
+
Requires-Dist: proto-plus>=1.26.1
|
58
|
+
Requires-Dist: protobuf>=6.32.0
|
44
59
|
Requires-Dist: pyasn1>=0.6.1
|
45
60
|
Requires-Dist: pyasn1_modules>=0.4.2
|
46
61
|
Requires-Dist: pycparser>=2.22
|
@@ -51,6 +66,7 @@ Requires-Dist: pymongo>=4.14.1
|
|
51
66
|
Requires-Dist: python-dateutil>=2.9.0.post0
|
52
67
|
Requires-Dist: PyYAML>=6.0.2
|
53
68
|
Requires-Dist: redis>=6.4.0
|
69
|
+
Requires-Dist: requests>=2.32.5
|
54
70
|
Requires-Dist: rsa>=4.9.1
|
55
71
|
Requires-Dist: six>=1.17.0
|
56
72
|
Requires-Dist: sniffio>=1.3.1
|
@@ -60,6 +76,7 @@ Requires-Dist: typing-inspection>=0.4.1
|
|
60
76
|
Requires-Dist: typing_extensions>=4.15.0
|
61
77
|
Requires-Dist: urllib3>=2.5.0
|
62
78
|
Requires-Dist: virtualenv>=20.34.0
|
79
|
+
Requires-Dist: zipp>=3.23.0
|
63
80
|
Dynamic: license-file
|
64
81
|
|
65
82
|
# README #
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: maleo-database
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.3
|
4
4
|
Summary: Database package for MaleoSuite
|
5
5
|
Author-email: Agra Bima Yuda <agra@nexmedis.com>
|
6
6
|
License: Proprietary
|
@@ -16,6 +16,7 @@ Requires-Dist: cachetools>=5.5.2
|
|
16
16
|
Requires-Dist: certifi>=2025.8.3
|
17
17
|
Requires-Dist: cffi>=1.17.1
|
18
18
|
Requires-Dist: cfgv>=3.4.0
|
19
|
+
Requires-Dist: charset-normalizer>=3.4.3
|
19
20
|
Requires-Dist: click>=8.2.1
|
20
21
|
Requires-Dist: cryptography>=45.0.6
|
21
22
|
Requires-Dist: distlib>=0.4.0
|
@@ -24,23 +25,37 @@ Requires-Dist: elastic-transport>=9.1.0
|
|
24
25
|
Requires-Dist: elasticsearch>=9.1.0
|
25
26
|
Requires-Dist: fastapi>=0.116.1
|
26
27
|
Requires-Dist: filelock>=3.19.1
|
28
|
+
Requires-Dist: google-api-core>=2.25.1
|
27
29
|
Requires-Dist: google-auth>=2.40.3
|
30
|
+
Requires-Dist: google-cloud-appengine-logging>=1.6.2
|
31
|
+
Requires-Dist: google-cloud-audit-log>=0.3.2
|
32
|
+
Requires-Dist: google-cloud-core>=2.4.3
|
33
|
+
Requires-Dist: google-cloud-logging>=3.12.1
|
34
|
+
Requires-Dist: googleapis-common-protos>=1.70.0
|
28
35
|
Requires-Dist: greenlet>=3.2.4
|
36
|
+
Requires-Dist: grpc-google-iam-v1>=0.14.2
|
37
|
+
Requires-Dist: grpcio>=1.74.0
|
38
|
+
Requires-Dist: grpcio-status>=1.74.0
|
29
39
|
Requires-Dist: identify>=2.6.13
|
30
40
|
Requires-Dist: idna>=3.10
|
41
|
+
Requires-Dist: importlib_metadata>=8.7.0
|
31
42
|
Requires-Dist: maleo-constants>=0.0.2
|
32
43
|
Requires-Dist: maleo-enums>=0.0.2
|
33
|
-
Requires-Dist: maleo-
|
44
|
+
Requires-Dist: maleo-logging>=0.0.1
|
45
|
+
Requires-Dist: maleo-mixins>=0.0.5
|
34
46
|
Requires-Dist: maleo-types-base>=0.0.2
|
35
47
|
Requires-Dist: maleo-types-enums>=0.0.2
|
36
48
|
Requires-Dist: maleo-utils>=0.0.3
|
37
49
|
Requires-Dist: motor>=3.7.1
|
38
50
|
Requires-Dist: mypy_extensions>=1.1.0
|
39
51
|
Requires-Dist: nodeenv>=1.9.1
|
52
|
+
Requires-Dist: opentelemetry-api>=1.36.0
|
40
53
|
Requires-Dist: packaging>=25.0
|
41
54
|
Requires-Dist: pathspec>=0.12.1
|
42
55
|
Requires-Dist: platformdirs>=4.4.0
|
43
56
|
Requires-Dist: pre_commit>=4.3.0
|
57
|
+
Requires-Dist: proto-plus>=1.26.1
|
58
|
+
Requires-Dist: protobuf>=6.32.0
|
44
59
|
Requires-Dist: pyasn1>=0.6.1
|
45
60
|
Requires-Dist: pyasn1_modules>=0.4.2
|
46
61
|
Requires-Dist: pycparser>=2.22
|
@@ -51,6 +66,7 @@ Requires-Dist: pymongo>=4.14.1
|
|
51
66
|
Requires-Dist: python-dateutil>=2.9.0.post0
|
52
67
|
Requires-Dist: PyYAML>=6.0.2
|
53
68
|
Requires-Dist: redis>=6.4.0
|
69
|
+
Requires-Dist: requests>=2.32.5
|
54
70
|
Requires-Dist: rsa>=4.9.1
|
55
71
|
Requires-Dist: six>=1.17.0
|
56
72
|
Requires-Dist: sniffio>=1.3.1
|
@@ -60,6 +76,7 @@ Requires-Dist: typing-inspection>=0.4.1
|
|
60
76
|
Requires-Dist: typing_extensions>=4.15.0
|
61
77
|
Requires-Dist: urllib3>=2.5.0
|
62
78
|
Requires-Dist: virtualenv>=20.34.0
|
79
|
+
Requires-Dist: zipp>=3.23.0
|
63
80
|
Dynamic: license-file
|
64
81
|
|
65
82
|
# README #
|
@@ -7,6 +7,7 @@ cachetools>=5.5.2
|
|
7
7
|
certifi>=2025.8.3
|
8
8
|
cffi>=1.17.1
|
9
9
|
cfgv>=3.4.0
|
10
|
+
charset-normalizer>=3.4.3
|
10
11
|
click>=8.2.1
|
11
12
|
cryptography>=45.0.6
|
12
13
|
distlib>=0.4.0
|
@@ -15,23 +16,37 @@ elastic-transport>=9.1.0
|
|
15
16
|
elasticsearch>=9.1.0
|
16
17
|
fastapi>=0.116.1
|
17
18
|
filelock>=3.19.1
|
19
|
+
google-api-core>=2.25.1
|
18
20
|
google-auth>=2.40.3
|
21
|
+
google-cloud-appengine-logging>=1.6.2
|
22
|
+
google-cloud-audit-log>=0.3.2
|
23
|
+
google-cloud-core>=2.4.3
|
24
|
+
google-cloud-logging>=3.12.1
|
25
|
+
googleapis-common-protos>=1.70.0
|
19
26
|
greenlet>=3.2.4
|
27
|
+
grpc-google-iam-v1>=0.14.2
|
28
|
+
grpcio>=1.74.0
|
29
|
+
grpcio-status>=1.74.0
|
20
30
|
identify>=2.6.13
|
21
31
|
idna>=3.10
|
32
|
+
importlib_metadata>=8.7.0
|
22
33
|
maleo-constants>=0.0.2
|
23
34
|
maleo-enums>=0.0.2
|
24
|
-
maleo-
|
35
|
+
maleo-logging>=0.0.1
|
36
|
+
maleo-mixins>=0.0.5
|
25
37
|
maleo-types-base>=0.0.2
|
26
38
|
maleo-types-enums>=0.0.2
|
27
39
|
maleo-utils>=0.0.3
|
28
40
|
motor>=3.7.1
|
29
41
|
mypy_extensions>=1.1.0
|
30
42
|
nodeenv>=1.9.1
|
43
|
+
opentelemetry-api>=1.36.0
|
31
44
|
packaging>=25.0
|
32
45
|
pathspec>=0.12.1
|
33
46
|
platformdirs>=4.4.0
|
34
47
|
pre_commit>=4.3.0
|
48
|
+
proto-plus>=1.26.1
|
49
|
+
protobuf>=6.32.0
|
35
50
|
pyasn1>=0.6.1
|
36
51
|
pyasn1_modules>=0.4.2
|
37
52
|
pycparser>=2.22
|
@@ -42,6 +57,7 @@ pymongo>=4.14.1
|
|
42
57
|
python-dateutil>=2.9.0.post0
|
43
58
|
PyYAML>=6.0.2
|
44
59
|
redis>=6.4.0
|
60
|
+
requests>=2.32.5
|
45
61
|
rsa>=4.9.1
|
46
62
|
six>=1.17.0
|
47
63
|
sniffio>=1.3.1
|
@@ -51,3 +67,4 @@ typing-inspection>=0.4.1
|
|
51
67
|
typing_extensions>=4.15.0
|
52
68
|
urllib3>=2.5.0
|
53
69
|
virtualenv>=20.34.0
|
70
|
+
zipp>=3.23.0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "maleo-database"
|
7
|
-
version = "0.0.
|
7
|
+
version = "0.0.3"
|
8
8
|
description = "Database package for MaleoSuite"
|
9
9
|
authors = [
|
10
10
|
{ name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
|
@@ -22,6 +22,7 @@ dependencies = [
|
|
22
22
|
"certifi>=2025.8.3",
|
23
23
|
"cffi>=1.17.1",
|
24
24
|
"cfgv>=3.4.0",
|
25
|
+
"charset-normalizer>=3.4.3",
|
25
26
|
"click>=8.2.1",
|
26
27
|
"cryptography>=45.0.6",
|
27
28
|
"distlib>=0.4.0",
|
@@ -30,23 +31,37 @@ dependencies = [
|
|
30
31
|
"elasticsearch>=9.1.0",
|
31
32
|
"fastapi>=0.116.1",
|
32
33
|
"filelock>=3.19.1",
|
34
|
+
"google-api-core>=2.25.1",
|
33
35
|
"google-auth>=2.40.3",
|
36
|
+
"google-cloud-appengine-logging>=1.6.2",
|
37
|
+
"google-cloud-audit-log>=0.3.2",
|
38
|
+
"google-cloud-core>=2.4.3",
|
39
|
+
"google-cloud-logging>=3.12.1",
|
40
|
+
"googleapis-common-protos>=1.70.0",
|
34
41
|
"greenlet>=3.2.4",
|
42
|
+
"grpc-google-iam-v1>=0.14.2",
|
43
|
+
"grpcio>=1.74.0",
|
44
|
+
"grpcio-status>=1.74.0",
|
35
45
|
"identify>=2.6.13",
|
36
46
|
"idna>=3.10",
|
47
|
+
"importlib_metadata>=8.7.0",
|
37
48
|
"maleo-constants>=0.0.2",
|
38
49
|
"maleo-enums>=0.0.2",
|
39
|
-
"maleo-
|
50
|
+
"maleo-logging>=0.0.1",
|
51
|
+
"maleo-mixins>=0.0.5",
|
40
52
|
"maleo-types-base>=0.0.2",
|
41
53
|
"maleo-types-enums>=0.0.2",
|
42
54
|
"maleo-utils>=0.0.3",
|
43
55
|
"motor>=3.7.1",
|
44
56
|
"mypy_extensions>=1.1.0",
|
45
57
|
"nodeenv>=1.9.1",
|
58
|
+
"opentelemetry-api>=1.36.0",
|
46
59
|
"packaging>=25.0",
|
47
60
|
"pathspec>=0.12.1",
|
48
61
|
"platformdirs>=4.4.0",
|
49
62
|
"pre_commit>=4.3.0",
|
63
|
+
"proto-plus>=1.26.1",
|
64
|
+
"protobuf>=6.32.0",
|
50
65
|
"pyasn1>=0.6.1",
|
51
66
|
"pyasn1_modules>=0.4.2",
|
52
67
|
"pycparser>=2.22",
|
@@ -57,6 +72,7 @@ dependencies = [
|
|
57
72
|
"python-dateutil>=2.9.0.post0",
|
58
73
|
"PyYAML>=6.0.2",
|
59
74
|
"redis>=6.4.0",
|
75
|
+
"requests>=2.32.5",
|
60
76
|
"rsa>=4.9.1",
|
61
77
|
"six>=1.17.0",
|
62
78
|
"sniffio>=1.3.1",
|
@@ -66,6 +82,7 @@ dependencies = [
|
|
66
82
|
"typing_extensions>=4.15.0",
|
67
83
|
"urllib3>=2.5.0",
|
68
84
|
"virtualenv>=20.34.0",
|
85
|
+
"zipp>=3.23.0",
|
69
86
|
]
|
70
87
|
|
71
88
|
[tool.setuptools]
|
@@ -0,0 +1,256 @@
|
|
1
|
+
from contextlib import (
|
2
|
+
AbstractAsyncContextManager,
|
3
|
+
AbstractContextManager,
|
4
|
+
asynccontextmanager,
|
5
|
+
contextmanager,
|
6
|
+
)
|
7
|
+
from datetime import datetime, timezone
|
8
|
+
from pydantic import ValidationError
|
9
|
+
from sqlalchemy.engine import Engine
|
10
|
+
from sqlalchemy.exc import SQLAlchemyError
|
11
|
+
from sqlalchemy.ext.asyncio import AsyncEngine, async_sessionmaker, AsyncSession
|
12
|
+
from sqlalchemy.orm import sessionmaker, Session
|
13
|
+
from typing import AsyncGenerator, Generator, Literal, Tuple, Union, overload
|
14
|
+
from uuid import UUID, uuid4
|
15
|
+
from maleo.mixins.timestamp import OperationTimestamp
|
16
|
+
from maleo.types.base.uuid import OptionalUUID
|
17
|
+
from maleo.logging.logger import Database
|
18
|
+
from ..enums import Connection
|
19
|
+
from ..config import (
|
20
|
+
PostgreSQLDatabaseConfig,
|
21
|
+
MySQLDatabaseConfig,
|
22
|
+
SQLiteDatabaseConfig,
|
23
|
+
SQLServerDatabaseConfig,
|
24
|
+
)
|
25
|
+
|
26
|
+
|
27
|
+
class SessionManager:
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
config: Union[
|
31
|
+
PostgreSQLDatabaseConfig,
|
32
|
+
MySQLDatabaseConfig,
|
33
|
+
SQLiteDatabaseConfig,
|
34
|
+
SQLServerDatabaseConfig,
|
35
|
+
],
|
36
|
+
engines: Tuple[AsyncEngine, Engine],
|
37
|
+
logger: Database,
|
38
|
+
) -> None:
|
39
|
+
self._config = config
|
40
|
+
self._async_engine, self._sync_engine = engines
|
41
|
+
self._logger = logger
|
42
|
+
self._async_sessionmaker: async_sessionmaker[AsyncSession] = async_sessionmaker[
|
43
|
+
AsyncSession
|
44
|
+
](bind=self._async_engine, expire_on_commit=True)
|
45
|
+
self._sync_sessionmaker: sessionmaker[Session] = sessionmaker[Session](
|
46
|
+
bind=self._sync_engine, expire_on_commit=True
|
47
|
+
)
|
48
|
+
|
49
|
+
async def _async_session_handler(
|
50
|
+
self, operation_id: UUID
|
51
|
+
) -> AsyncGenerator[AsyncSession, None]:
|
52
|
+
"""Async session handler with proper error handling."""
|
53
|
+
executed_at = datetime.now(tz=timezone.utc)
|
54
|
+
session = self._async_sessionmaker()
|
55
|
+
try:
|
56
|
+
yield session
|
57
|
+
await session.commit()
|
58
|
+
completed_at = datetime.now(tz=timezone.utc)
|
59
|
+
self._logger.info(
|
60
|
+
f"Operation {operation_id} - success - Committed async database transaction",
|
61
|
+
extra={
|
62
|
+
"json_fields": {
|
63
|
+
"config": self._config.model_dump(mode="json"),
|
64
|
+
"operation_id": operation_id,
|
65
|
+
"success": True,
|
66
|
+
"timestamp": OperationTimestamp(
|
67
|
+
executed_at=executed_at,
|
68
|
+
completed_at=completed_at,
|
69
|
+
duration=(completed_at - executed_at).total_seconds(),
|
70
|
+
).model_dump(mode="json"),
|
71
|
+
},
|
72
|
+
},
|
73
|
+
)
|
74
|
+
except (SQLAlchemyError, ValidationError, Exception):
|
75
|
+
await session.rollback()
|
76
|
+
completed_at = datetime.now(tz=timezone.utc)
|
77
|
+
self._logger.error(
|
78
|
+
f"Operation {operation_id} - failed - Error handling async database session",
|
79
|
+
exc_info=True,
|
80
|
+
extra={
|
81
|
+
"json_fields": {
|
82
|
+
"config": self._config.model_dump(mode="json"),
|
83
|
+
"operation_id": operation_id,
|
84
|
+
"success": False,
|
85
|
+
"timestamp": OperationTimestamp(
|
86
|
+
executed_at=executed_at,
|
87
|
+
completed_at=completed_at,
|
88
|
+
duration=(completed_at - executed_at).total_seconds(),
|
89
|
+
).model_dump(mode="json"),
|
90
|
+
},
|
91
|
+
},
|
92
|
+
)
|
93
|
+
raise
|
94
|
+
finally:
|
95
|
+
await session.close()
|
96
|
+
completed_at = datetime.now(tz=timezone.utc)
|
97
|
+
self._logger.info(
|
98
|
+
f"Operation {operation_id} - success - Closed async database session",
|
99
|
+
extra={
|
100
|
+
"json_fields": {
|
101
|
+
"config": self._config.model_dump(mode="json"),
|
102
|
+
"operation_id": operation_id,
|
103
|
+
"success": True,
|
104
|
+
"timestamp": OperationTimestamp(
|
105
|
+
executed_at=executed_at,
|
106
|
+
completed_at=completed_at,
|
107
|
+
duration=(completed_at - executed_at).total_seconds(),
|
108
|
+
).model_dump(mode="json"),
|
109
|
+
},
|
110
|
+
},
|
111
|
+
)
|
112
|
+
|
113
|
+
def _sync_session_handler(
|
114
|
+
self, operation_id: UUID
|
115
|
+
) -> Generator[Session, None, None]:
|
116
|
+
"""Sync session handler with proper error handling."""
|
117
|
+
executed_at = datetime.now(tz=timezone.utc)
|
118
|
+
session = self._sync_sessionmaker()
|
119
|
+
try:
|
120
|
+
yield session
|
121
|
+
session.commit()
|
122
|
+
completed_at = datetime.now(tz=timezone.utc)
|
123
|
+
self._logger.info(
|
124
|
+
f"Operation {operation_id} - success - Committed sync database transaction",
|
125
|
+
extra={
|
126
|
+
"json_fields": {
|
127
|
+
"config": self._config.model_dump(mode="json"),
|
128
|
+
"operation_id": operation_id,
|
129
|
+
"success": True,
|
130
|
+
"timestamp": OperationTimestamp(
|
131
|
+
executed_at=executed_at,
|
132
|
+
completed_at=completed_at,
|
133
|
+
duration=(completed_at - executed_at).total_seconds(),
|
134
|
+
).model_dump(mode="json"),
|
135
|
+
},
|
136
|
+
},
|
137
|
+
)
|
138
|
+
except (SQLAlchemyError, ValidationError, Exception):
|
139
|
+
session.rollback()
|
140
|
+
completed_at = datetime.now(tz=timezone.utc)
|
141
|
+
self._logger.error(
|
142
|
+
f"Operation {operation_id} - failed - Error handling sync database session",
|
143
|
+
exc_info=True,
|
144
|
+
extra={
|
145
|
+
"json_fields": {
|
146
|
+
"config": self._config.model_dump(mode="json"),
|
147
|
+
"operation_id": operation_id,
|
148
|
+
"success": False,
|
149
|
+
"timestamp": OperationTimestamp(
|
150
|
+
executed_at=executed_at,
|
151
|
+
completed_at=completed_at,
|
152
|
+
duration=(completed_at - executed_at).total_seconds(),
|
153
|
+
).model_dump(mode="json"),
|
154
|
+
},
|
155
|
+
},
|
156
|
+
)
|
157
|
+
raise
|
158
|
+
finally:
|
159
|
+
session.close()
|
160
|
+
completed_at = datetime.now(tz=timezone.utc)
|
161
|
+
self._logger.info(
|
162
|
+
f"Operation {operation_id} - success - Closed sync database session",
|
163
|
+
extra={
|
164
|
+
"json_fields": {
|
165
|
+
"config": self._config.model_dump(mode="json"),
|
166
|
+
"operation_id": operation_id,
|
167
|
+
"success": True,
|
168
|
+
"timestamp": OperationTimestamp(
|
169
|
+
executed_at=executed_at,
|
170
|
+
completed_at=completed_at,
|
171
|
+
duration=(completed_at - executed_at).total_seconds(),
|
172
|
+
).model_dump(mode="json"),
|
173
|
+
},
|
174
|
+
},
|
175
|
+
)
|
176
|
+
|
177
|
+
@asynccontextmanager
|
178
|
+
async def _async_context_manager(
|
179
|
+
self, operation_id: UUID
|
180
|
+
) -> AsyncGenerator[AsyncSession, None]:
|
181
|
+
"""Async context manager implementation."""
|
182
|
+
async for session in self._async_session_handler(operation_id):
|
183
|
+
yield session
|
184
|
+
|
185
|
+
@contextmanager
|
186
|
+
def _sync_context_manager(
|
187
|
+
self, operation_id: UUID
|
188
|
+
) -> Generator[Session, None, None]:
|
189
|
+
"""Sync context manager implementation."""
|
190
|
+
yield from self._sync_session_handler(operation_id)
|
191
|
+
|
192
|
+
# Overloaded context manager methods
|
193
|
+
@overload
|
194
|
+
def get(
|
195
|
+
self, connection: Literal[Connection.ASYNC], operation_id: OptionalUUID = None
|
196
|
+
) -> AbstractAsyncContextManager[AsyncSession]: ...
|
197
|
+
|
198
|
+
@overload
|
199
|
+
def get(
|
200
|
+
self, connection: Literal[Connection.SYNC], operation_id: OptionalUUID = None
|
201
|
+
) -> AbstractContextManager[Session]: ...
|
202
|
+
|
203
|
+
def get(
|
204
|
+
self,
|
205
|
+
connection: Connection = Connection.ASYNC,
|
206
|
+
operation_id: OptionalUUID = None,
|
207
|
+
) -> Union[
|
208
|
+
AbstractAsyncContextManager[AsyncSession], AbstractContextManager[Session]
|
209
|
+
]:
|
210
|
+
"""Context manager for manual session handling."""
|
211
|
+
if operation_id is None:
|
212
|
+
operation_id = uuid4()
|
213
|
+
if connection is Connection.ASYNC:
|
214
|
+
return self._async_context_manager(operation_id)
|
215
|
+
else:
|
216
|
+
return self._sync_context_manager(operation_id)
|
217
|
+
|
218
|
+
# Alternative: More explicit methods
|
219
|
+
@asynccontextmanager
|
220
|
+
async def get_async(
|
221
|
+
self, operation_id: OptionalUUID = None
|
222
|
+
) -> AsyncGenerator[AsyncSession, None]:
|
223
|
+
"""Explicit async context manager."""
|
224
|
+
if operation_id is None:
|
225
|
+
operation_id = uuid4()
|
226
|
+
async for session in self._async_session_handler(operation_id):
|
227
|
+
yield session
|
228
|
+
|
229
|
+
@contextmanager
|
230
|
+
def get_sync(
|
231
|
+
self, operation_id: OptionalUUID = None
|
232
|
+
) -> Generator[Session, None, None]:
|
233
|
+
"""Explicit sync context manager."""
|
234
|
+
if operation_id is None:
|
235
|
+
operation_id = uuid4()
|
236
|
+
yield from self._sync_session_handler(operation_id)
|
237
|
+
|
238
|
+
def as_async_dependency(self, operation_id: OptionalUUID = None):
|
239
|
+
"""Explicit async dependency injection."""
|
240
|
+
if operation_id is None:
|
241
|
+
operation_id = uuid4()
|
242
|
+
|
243
|
+
def dependency() -> AsyncGenerator[AsyncSession, None]:
|
244
|
+
return self._async_session_handler(operation_id)
|
245
|
+
|
246
|
+
return dependency
|
247
|
+
|
248
|
+
def as_sync_dependency(self, operation_id: OptionalUUID = None):
|
249
|
+
"""Explicit sync dependency injection."""
|
250
|
+
if operation_id is None:
|
251
|
+
operation_id = uuid4()
|
252
|
+
|
253
|
+
def dependency() -> AsyncGenerator[AsyncSession, None]:
|
254
|
+
return self._async_session_handler(operation_id)
|
255
|
+
|
256
|
+
return dependency
|
@@ -1,123 +0,0 @@
|
|
1
|
-
from contextlib import (
|
2
|
-
AbstractAsyncContextManager,
|
3
|
-
AbstractContextManager,
|
4
|
-
asynccontextmanager,
|
5
|
-
contextmanager,
|
6
|
-
)
|
7
|
-
from pydantic import ValidationError
|
8
|
-
from sqlalchemy.engine import Engine
|
9
|
-
from sqlalchemy.exc import SQLAlchemyError
|
10
|
-
from sqlalchemy.ext.asyncio import AsyncEngine, async_sessionmaker, AsyncSession
|
11
|
-
from sqlalchemy.orm import sessionmaker, Session
|
12
|
-
from typing import AsyncGenerator, Generator, Literal, Tuple, Union, overload
|
13
|
-
from ..enums import Connection
|
14
|
-
|
15
|
-
|
16
|
-
class SessionManager:
|
17
|
-
def __init__(self, engines: Tuple[AsyncEngine, Engine]) -> None:
|
18
|
-
self._async_engine, self._sync_engine = engines
|
19
|
-
self._async_sessionmaker: async_sessionmaker[AsyncSession] = async_sessionmaker[
|
20
|
-
AsyncSession
|
21
|
-
](bind=self._async_engine, expire_on_commit=True)
|
22
|
-
self._sync_sessionmaker: sessionmaker[Session] = sessionmaker[Session](
|
23
|
-
bind=self._sync_engine, expire_on_commit=True
|
24
|
-
)
|
25
|
-
|
26
|
-
async def _async_session_handler(self) -> AsyncGenerator[AsyncSession, None]:
|
27
|
-
"""Async session handler with proper error handling."""
|
28
|
-
session = self._async_sessionmaker()
|
29
|
-
try:
|
30
|
-
yield session
|
31
|
-
await session.commit()
|
32
|
-
except (SQLAlchemyError, ValidationError, Exception):
|
33
|
-
await session.rollback()
|
34
|
-
raise
|
35
|
-
finally:
|
36
|
-
await session.close()
|
37
|
-
|
38
|
-
def _sync_session_handler(self) -> Generator[Session, None, None]:
|
39
|
-
"""Sync session handler with proper error handling."""
|
40
|
-
session = self._sync_sessionmaker()
|
41
|
-
try:
|
42
|
-
yield session
|
43
|
-
session.commit()
|
44
|
-
except (SQLAlchemyError, ValidationError, Exception):
|
45
|
-
session.rollback()
|
46
|
-
raise
|
47
|
-
finally:
|
48
|
-
session.close()
|
49
|
-
|
50
|
-
# Overloaded inject methods
|
51
|
-
@overload
|
52
|
-
def inject(
|
53
|
-
self, connection: Literal[Connection.ASYNC]
|
54
|
-
) -> AsyncGenerator[AsyncSession, None]: ...
|
55
|
-
|
56
|
-
@overload
|
57
|
-
def inject(
|
58
|
-
self, connection: Literal[Connection.SYNC]
|
59
|
-
) -> Generator[Session, None, None]: ...
|
60
|
-
|
61
|
-
def inject(
|
62
|
-
self, connection: Connection = Connection.ASYNC
|
63
|
-
) -> Union[AsyncGenerator[AsyncSession, None], Generator[Session, None, None]]:
|
64
|
-
"""Returns a generator for dependency injection."""
|
65
|
-
if connection is Connection.ASYNC:
|
66
|
-
return self._async_session_handler()
|
67
|
-
else:
|
68
|
-
return self._sync_session_handler()
|
69
|
-
|
70
|
-
# Overloaded context manager methods
|
71
|
-
@overload
|
72
|
-
def get(
|
73
|
-
self, connection: Literal[Connection.ASYNC]
|
74
|
-
) -> AbstractAsyncContextManager[AsyncSession]: ...
|
75
|
-
|
76
|
-
@overload
|
77
|
-
def get(
|
78
|
-
self, connection: Literal[Connection.SYNC]
|
79
|
-
) -> AbstractContextManager[Session]: ...
|
80
|
-
|
81
|
-
def get(
|
82
|
-
self, connection: Connection = Connection.ASYNC
|
83
|
-
) -> Union[
|
84
|
-
AbstractAsyncContextManager[AsyncSession], AbstractContextManager[Session]
|
85
|
-
]:
|
86
|
-
"""Context manager for manual session handling."""
|
87
|
-
if connection is Connection.ASYNC:
|
88
|
-
return self._async_context_manager()
|
89
|
-
else:
|
90
|
-
return self._sync_context_manager()
|
91
|
-
|
92
|
-
@asynccontextmanager
|
93
|
-
async def _async_context_manager(self) -> AsyncGenerator[AsyncSession, None]:
|
94
|
-
"""Async context manager implementation."""
|
95
|
-
async for session in self._async_session_handler():
|
96
|
-
yield session
|
97
|
-
|
98
|
-
@contextmanager
|
99
|
-
def _sync_context_manager(self) -> Generator[Session, None, None]:
|
100
|
-
"""Sync context manager implementation."""
|
101
|
-
yield from self._sync_session_handler()
|
102
|
-
|
103
|
-
# Alternative: More explicit methods
|
104
|
-
@asynccontextmanager
|
105
|
-
async def get_async(self) -> AsyncGenerator[AsyncSession, None]:
|
106
|
-
"""Explicit async context manager."""
|
107
|
-
async for session in self._async_session_handler():
|
108
|
-
yield session
|
109
|
-
|
110
|
-
@contextmanager
|
111
|
-
def get_sync(self) -> Generator[Session, None, None]:
|
112
|
-
"""Explicit sync context manager."""
|
113
|
-
yield from self._sync_session_handler()
|
114
|
-
# with self._sync_session_handler() as session:
|
115
|
-
# yield session
|
116
|
-
|
117
|
-
def inject_async(self) -> AsyncGenerator[AsyncSession, None]:
|
118
|
-
"""Explicit async dependency injection."""
|
119
|
-
return self._async_session_handler()
|
120
|
-
|
121
|
-
def inject_sync(self) -> Generator[Session, None, None]:
|
122
|
-
"""Explicit sync dependency injection."""
|
123
|
-
return self._sync_session_handler()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|