altcodepro-polydb-python 2.3.13__tar.gz → 2.3.15__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.
- {altcodepro_polydb_python-2.3.13/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.3.15}/PKG-INFO +3 -1
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/pyproject.toml +3 -1
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15/src/altcodepro_polydb_python.egg-info}/PKG-INFO +3 -1
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/altcodepro_polydb_python.egg-info/requires.txt +2 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/PolyDB.py +35 -35
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/PostgreSQLAdapter.py +54 -5
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/ObjectStorageAdapter.py +1 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/LICENSE +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/MANIFEST.in +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/README.md +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements-aws.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements-azure.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements-dev.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements-gcp.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements-generic.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/setup.cfg +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/setup.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/__init__.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/AzureTableStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/BlockchainFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/EFSAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/FirestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/GCPFilestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/MongoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/S3Adapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/SQSAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/VercelFileAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/VercelKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/__init__.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/advanced_query.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/AuditStorage.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/__init__.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/context.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/manager.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/models.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/NoSQLKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/QueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/SharedFilesAdapter.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/__init__.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/batch.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/cache.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/cloudDatabaseFactory.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/databaseFactory.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/decorators.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/errors.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/json_safe.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/models.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/monitoring.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/multitenancy.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/py.typed +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/query.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/registry.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/retry.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/schema.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/security.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/types.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/utils.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/validation.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_aws.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_azure.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_blockchain.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_cloud_factory.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_gcp.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_mongodb.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_multi_engine.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_postgresql.py +0 -0
- {altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_vercel.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: altcodepro-polydb-python
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.15
|
|
4
4
|
Summary: Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety
|
|
5
5
|
Author: AltCodePro
|
|
6
6
|
Project-URL: Homepage, https://github.com/altcodepro/polydb-python
|
|
@@ -38,6 +38,8 @@ Requires-Dist: web3>=7.16.0
|
|
|
38
38
|
Requires-Dist: google-cloud-firestore>=2.27.0
|
|
39
39
|
Requires-Dist: google-cloud-pubsub>=2.38.0
|
|
40
40
|
Requires-Dist: pymongo>=4.17.0
|
|
41
|
+
Requires-Dist: build>=1.5.0
|
|
42
|
+
Requires-Dist: twine>=6.2.0
|
|
41
43
|
Provides-Extra: aws
|
|
42
44
|
Requires-Dist: boto3>=1.42.47; extra == "aws"
|
|
43
45
|
Requires-Dist: botocore>=1.42.47; extra == "aws"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "altcodepro-polydb-python"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.15"
|
|
8
8
|
description = "Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety"
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -57,6 +57,8 @@ dependencies = [
|
|
|
57
57
|
"google-cloud-firestore>=2.27.0",
|
|
58
58
|
"google-cloud-pubsub>=2.38.0",
|
|
59
59
|
"pymongo>=4.17.0",
|
|
60
|
+
"build>=1.5.0",
|
|
61
|
+
"twine>=6.2.0",
|
|
60
62
|
]
|
|
61
63
|
|
|
62
64
|
# Generic/Open-source stack (cheapest option)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: altcodepro-polydb-python
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.15
|
|
4
4
|
Summary: Production-ready multi-cloud database abstraction layer with connection pooling, retry logic, and thread safety
|
|
5
5
|
Author: AltCodePro
|
|
6
6
|
Project-URL: Homepage, https://github.com/altcodepro/polydb-python
|
|
@@ -38,6 +38,8 @@ Requires-Dist: web3>=7.16.0
|
|
|
38
38
|
Requires-Dist: google-cloud-firestore>=2.27.0
|
|
39
39
|
Requires-Dist: google-cloud-pubsub>=2.38.0
|
|
40
40
|
Requires-Dist: pymongo>=4.17.0
|
|
41
|
+
Requires-Dist: build>=1.5.0
|
|
42
|
+
Requires-Dist: twine>=6.2.0
|
|
41
43
|
Provides-Extra: aws
|
|
42
44
|
Requires-Dist: boto3>=1.42.47; extra == "aws"
|
|
43
45
|
Requires-Dist: botocore>=1.42.47; extra == "aws"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
from typing import Any, Dict, List, Optional, Tuple, Type, Union
|
|
4
5
|
|
|
5
6
|
from .advanced_query import AdvancedQueryBuilder, QueryHelper
|
|
@@ -23,8 +24,6 @@ from .types import JsonDict, Lookup
|
|
|
23
24
|
from .utils import setup_logger
|
|
24
25
|
from .validation import ModelValidator, SchemaValidator
|
|
25
26
|
|
|
26
|
-
ModelRef = Union[Type, str]
|
|
27
|
-
|
|
28
27
|
|
|
29
28
|
class PolyDB:
|
|
30
29
|
"""
|
|
@@ -51,6 +50,7 @@ class PolyDB:
|
|
|
51
50
|
storage_configs: Optional[List[StorageConfig]] = None,
|
|
52
51
|
tenant_registry: Optional[TenantRegistry] = None,
|
|
53
52
|
partition_config: Optional[PartitionConfig] = None,
|
|
53
|
+
redis_cache_url: Optional[str] = None,
|
|
54
54
|
enable_retries: bool = True,
|
|
55
55
|
enable_audit: bool = True,
|
|
56
56
|
enable_audit_reads: bool = False,
|
|
@@ -59,6 +59,7 @@ class PolyDB:
|
|
|
59
59
|
enable_monitoring: bool = False,
|
|
60
60
|
enable_encryption: bool = False,
|
|
61
61
|
enable_rls: bool = False,
|
|
62
|
+
soft_delete: bool = True,
|
|
62
63
|
) -> None:
|
|
63
64
|
self.logger = setup_logger(self.__class__.__name__)
|
|
64
65
|
|
|
@@ -71,7 +72,6 @@ class PolyDB:
|
|
|
71
72
|
provider=provider,
|
|
72
73
|
cloud_factory=self.cloud,
|
|
73
74
|
engines=engines,
|
|
74
|
-
tenant_registry=tenant_registry,
|
|
75
75
|
enable_retries=enable_retries,
|
|
76
76
|
enable_audit=enable_audit,
|
|
77
77
|
enable_audit_reads=enable_audit_reads,
|
|
@@ -79,7 +79,10 @@ class PolyDB:
|
|
|
79
79
|
use_redis_cache=use_redis_cache,
|
|
80
80
|
enable_monitoring=enable_monitoring,
|
|
81
81
|
enable_encryption=enable_encryption,
|
|
82
|
-
|
|
82
|
+
soft_delete=soft_delete,
|
|
83
|
+
redis_cache_url=redis_cache_url
|
|
84
|
+
or os.getenv("REDIS_CACHE_URL")
|
|
85
|
+
or os.getenv("REDIS_URL"),
|
|
83
86
|
)
|
|
84
87
|
|
|
85
88
|
self.partition_config = partition_config
|
|
@@ -123,7 +126,7 @@ class PolyDB:
|
|
|
123
126
|
return self.cloud.get_object_storage(name)
|
|
124
127
|
|
|
125
128
|
def get_shared_files(self):
|
|
126
|
-
return self.cloud.
|
|
129
|
+
return self.cloud.get_files()
|
|
127
130
|
|
|
128
131
|
def get_queue(self):
|
|
129
132
|
return self.cloud.get_queue()
|
|
@@ -137,7 +140,7 @@ class PolyDB:
|
|
|
137
140
|
|
|
138
141
|
def create(
|
|
139
142
|
self,
|
|
140
|
-
model:
|
|
143
|
+
model: str,
|
|
141
144
|
data: JsonDict,
|
|
142
145
|
*,
|
|
143
146
|
engine_override: Optional[EngineOverride] = None,
|
|
@@ -146,7 +149,7 @@ class PolyDB:
|
|
|
146
149
|
|
|
147
150
|
def read(
|
|
148
151
|
self,
|
|
149
|
-
model:
|
|
152
|
+
model: str,
|
|
150
153
|
query: Optional[Lookup] = None,
|
|
151
154
|
*,
|
|
152
155
|
limit: Optional[int] = None,
|
|
@@ -169,7 +172,7 @@ class PolyDB:
|
|
|
169
172
|
|
|
170
173
|
def read_one(
|
|
171
174
|
self,
|
|
172
|
-
model:
|
|
175
|
+
model: str,
|
|
173
176
|
query: Lookup,
|
|
174
177
|
*,
|
|
175
178
|
no_cache: bool = False,
|
|
@@ -186,7 +189,7 @@ class PolyDB:
|
|
|
186
189
|
|
|
187
190
|
def get(
|
|
188
191
|
self,
|
|
189
|
-
model:
|
|
192
|
+
model: str,
|
|
190
193
|
entity_id: Any,
|
|
191
194
|
*,
|
|
192
195
|
include_deleted: bool = False,
|
|
@@ -203,7 +206,7 @@ class PolyDB:
|
|
|
203
206
|
|
|
204
207
|
def read_page(
|
|
205
208
|
self,
|
|
206
|
-
model:
|
|
209
|
+
model: str,
|
|
207
210
|
query: Lookup,
|
|
208
211
|
*,
|
|
209
212
|
page_size: int = 100,
|
|
@@ -222,7 +225,7 @@ class PolyDB:
|
|
|
222
225
|
|
|
223
226
|
def update(
|
|
224
227
|
self,
|
|
225
|
-
model:
|
|
228
|
+
model: str,
|
|
226
229
|
entity_id: Any,
|
|
227
230
|
data: JsonDict,
|
|
228
231
|
*,
|
|
@@ -241,7 +244,7 @@ class PolyDB:
|
|
|
241
244
|
|
|
242
245
|
def upsert(
|
|
243
246
|
self,
|
|
244
|
-
model:
|
|
247
|
+
model: str,
|
|
245
248
|
data: JsonDict,
|
|
246
249
|
*,
|
|
247
250
|
replace: bool = False,
|
|
@@ -256,7 +259,7 @@ class PolyDB:
|
|
|
256
259
|
|
|
257
260
|
def delete(
|
|
258
261
|
self,
|
|
259
|
-
model:
|
|
262
|
+
model: str,
|
|
260
263
|
entity_id: Any,
|
|
261
264
|
*,
|
|
262
265
|
etag: Optional[str] = None,
|
|
@@ -278,12 +281,12 @@ class PolyDB:
|
|
|
278
281
|
def query(self) -> QueryBuilder:
|
|
279
282
|
return QueryBuilder()
|
|
280
283
|
|
|
281
|
-
def advanced_query(self) -> AdvancedQueryBuilder:
|
|
282
|
-
return AdvancedQueryBuilder()
|
|
284
|
+
def advanced_query(self, table: str) -> AdvancedQueryBuilder:
|
|
285
|
+
return AdvancedQueryBuilder(table)
|
|
283
286
|
|
|
284
287
|
def query_linq(
|
|
285
288
|
self,
|
|
286
|
-
model:
|
|
289
|
+
model: str,
|
|
287
290
|
builder: QueryBuilder,
|
|
288
291
|
*,
|
|
289
292
|
engine_override: Optional[EngineOverride] = None,
|
|
@@ -426,7 +429,7 @@ class PolyDB:
|
|
|
426
429
|
queue_name: str = "default",
|
|
427
430
|
delay: Optional[int] = None,
|
|
428
431
|
) -> str:
|
|
429
|
-
queue = self.get_queue()
|
|
432
|
+
queue: Any = self.get_queue()
|
|
430
433
|
if hasattr(queue, "publish"):
|
|
431
434
|
return queue.publish(queue_name=queue_name, message=message, delay=delay)
|
|
432
435
|
return self.send_queue(message, queue_name=queue_name)
|
|
@@ -438,7 +441,7 @@ class PolyDB:
|
|
|
438
441
|
max_messages: int = 10,
|
|
439
442
|
wait_seconds: int = 5,
|
|
440
443
|
) -> List[Dict[str, Any]]:
|
|
441
|
-
queue = self.get_queue()
|
|
444
|
+
queue: Any = self.get_queue()
|
|
442
445
|
if hasattr(queue, "consume"):
|
|
443
446
|
return queue.consume(
|
|
444
447
|
queue_name=queue_name,
|
|
@@ -492,7 +495,7 @@ class PolyDB:
|
|
|
492
495
|
|
|
493
496
|
def set_cache(
|
|
494
497
|
self,
|
|
495
|
-
model:
|
|
498
|
+
model: str,
|
|
496
499
|
key: Any,
|
|
497
500
|
value: Any,
|
|
498
501
|
*,
|
|
@@ -504,7 +507,7 @@ class PolyDB:
|
|
|
504
507
|
|
|
505
508
|
def get_cache(
|
|
506
509
|
self,
|
|
507
|
-
model:
|
|
510
|
+
model: str,
|
|
508
511
|
key: Any,
|
|
509
512
|
) -> Optional[Any]:
|
|
510
513
|
if not self.cache:
|
|
@@ -513,7 +516,7 @@ class PolyDB:
|
|
|
513
516
|
|
|
514
517
|
def invalidate_cache(
|
|
515
518
|
self,
|
|
516
|
-
model:
|
|
519
|
+
model: str,
|
|
517
520
|
key: Optional[Any] = None,
|
|
518
521
|
) -> None:
|
|
519
522
|
if not self.cache:
|
|
@@ -530,7 +533,7 @@ class PolyDB:
|
|
|
530
533
|
|
|
531
534
|
def warm_model_cache(
|
|
532
535
|
self,
|
|
533
|
-
model:
|
|
536
|
+
model: str,
|
|
534
537
|
queries: List[Any],
|
|
535
538
|
*,
|
|
536
539
|
ttl: int = 300,
|
|
@@ -541,7 +544,7 @@ class PolyDB:
|
|
|
541
544
|
|
|
542
545
|
def warm_popular_queries(
|
|
543
546
|
self,
|
|
544
|
-
model:
|
|
547
|
+
model: str,
|
|
545
548
|
*,
|
|
546
549
|
limit: int = 20,
|
|
547
550
|
ttl: int = 300,
|
|
@@ -554,27 +557,27 @@ class PolyDB:
|
|
|
554
557
|
# BATCH
|
|
555
558
|
# ============================================================
|
|
556
559
|
|
|
557
|
-
def bulk_insert(self, model:
|
|
560
|
+
def bulk_insert(self, model: str, records: List[JsonDict]) -> BatchResult:
|
|
558
561
|
return self.batch.bulk_insert(model, records)
|
|
559
562
|
|
|
560
563
|
def bulk_update(
|
|
561
564
|
self,
|
|
562
|
-
model:
|
|
563
|
-
updates: List[
|
|
565
|
+
model: str,
|
|
566
|
+
updates: List[Dict[str, Any]], # {entity_id, data}
|
|
564
567
|
) -> BatchResult:
|
|
565
568
|
return self.batch.bulk_update(model, updates)
|
|
566
569
|
|
|
567
|
-
def bulk_delete(self, model:
|
|
570
|
+
def bulk_delete(self, model: str, entity_ids: List[Any]) -> BatchResult:
|
|
568
571
|
return self.batch.bulk_delete(model, entity_ids)
|
|
569
572
|
|
|
570
573
|
# ============================================================
|
|
571
574
|
# VALIDATION
|
|
572
575
|
# ============================================================
|
|
573
576
|
|
|
574
|
-
def validate_model(self, model:
|
|
577
|
+
def validate_model(self, model: Type):
|
|
575
578
|
return ModelValidator.validate_model(model)
|
|
576
579
|
|
|
577
|
-
def validate(self, model:
|
|
580
|
+
def validate(self, model: Type) -> None:
|
|
578
581
|
ModelValidator.validate_and_raise(model)
|
|
579
582
|
|
|
580
583
|
def validate_data(self, model: Any, data: JsonDict):
|
|
@@ -672,11 +675,7 @@ class PolyDB:
|
|
|
672
675
|
self.rls.add_policy(model, name, policy_func, apply_to)
|
|
673
676
|
|
|
674
677
|
def set_default_rls_filters(
|
|
675
|
-
self,
|
|
676
|
-
model: str,
|
|
677
|
-
*,
|
|
678
|
-
read_filters: Optional[Dict[str, Any]] = None,
|
|
679
|
-
write_filters: Optional[Dict[str, Any]] = None,
|
|
678
|
+
self, model: str, *, read_filters: Dict[str, Any], write_filters: Dict[str, Any]
|
|
680
679
|
) -> None:
|
|
681
680
|
if not self.rls:
|
|
682
681
|
raise RuntimeError("RLS is not enabled on this PolyDB instance.")
|
|
@@ -687,7 +686,8 @@ class PolyDB:
|
|
|
687
686
|
# ============================================================
|
|
688
687
|
|
|
689
688
|
def with_tenant(self, tenant_id: str) -> "PolyDB":
|
|
690
|
-
|
|
689
|
+
if self.tenant_registry:
|
|
690
|
+
TenantContext.set_tenant(tenant_id, self.tenant_registry)
|
|
691
691
|
return self
|
|
692
692
|
|
|
693
693
|
def get_tenant(self) -> Optional[TenantConfig]:
|
|
@@ -32,25 +32,64 @@ class PostgreSQLAdapter:
|
|
|
32
32
|
self._lock = threading.Lock()
|
|
33
33
|
self._initialize_pool()
|
|
34
34
|
|
|
35
|
+
def _ping_connection(self, conn) -> bool:
|
|
36
|
+
"""Test if connection is still alive"""
|
|
37
|
+
try:
|
|
38
|
+
with conn.cursor() as cur:
|
|
39
|
+
cur.execute("SELECT 1")
|
|
40
|
+
return True
|
|
41
|
+
except Exception:
|
|
42
|
+
return False
|
|
43
|
+
|
|
35
44
|
def _initialize_pool(self):
|
|
36
45
|
try:
|
|
37
46
|
import psycopg2.pool
|
|
47
|
+
from urllib.parse import urlparse, parse_qs, urlencode, urlunparse
|
|
48
|
+
|
|
49
|
+
# Enhance connection string with better Azure settings
|
|
50
|
+
dsn = self.connection_string
|
|
51
|
+
if "postgresql://" in dsn:
|
|
52
|
+
parsed = urlparse(dsn)
|
|
53
|
+
query = parse_qs(parsed.query)
|
|
54
|
+
query.setdefault("connect_timeout", ["30"])
|
|
55
|
+
query.setdefault("keepalives", ["1"])
|
|
56
|
+
query.setdefault("keepalives_idle", ["30"])
|
|
57
|
+
query.setdefault("keepalives_interval", ["10"])
|
|
58
|
+
query.setdefault("keepalives_count", ["5"])
|
|
59
|
+
|
|
60
|
+
new_query = urlencode(query, doseq=True)
|
|
61
|
+
parsed = parsed._replace(query=new_query)
|
|
62
|
+
dsn = urlunparse(parsed)
|
|
38
63
|
|
|
39
64
|
with self._lock:
|
|
40
65
|
if not self._pool:
|
|
41
66
|
self._pool = psycopg2.pool.ThreadedConnectionPool(
|
|
42
|
-
minconn=int(os.getenv("POSTGRES_MIN_CONNECTIONS", "
|
|
43
|
-
maxconn=int(os.getenv("POSTGRES_MAX_CONNECTIONS", "
|
|
44
|
-
dsn=
|
|
67
|
+
minconn=int(os.getenv("POSTGRES_MIN_CONNECTIONS", "5")),
|
|
68
|
+
maxconn=int(os.getenv("POSTGRES_MAX_CONNECTIONS", "30")),
|
|
69
|
+
dsn=dsn,
|
|
45
70
|
)
|
|
46
|
-
self.logger.info("PostgreSQL pool initialized")
|
|
71
|
+
self.logger.info("PostgreSQL pool initialized with Azure optimizations")
|
|
47
72
|
except Exception as e:
|
|
48
73
|
raise ConnectionError(f"Failed to initialize PostgreSQL pool: {str(e)}")
|
|
49
74
|
|
|
50
75
|
def _get_connection(self) -> Any:
|
|
51
76
|
if not self._pool:
|
|
52
77
|
self._initialize_pool()
|
|
53
|
-
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
conn = self._pool.getconn() # type: ignore
|
|
81
|
+
|
|
82
|
+
# Critical: Validate connection for Azure transient issues
|
|
83
|
+
if not self._ping_connection(conn):
|
|
84
|
+
self.logger.warning("Stale connection detected from pool, closing and retrying")
|
|
85
|
+
self._pool.putconn(conn, close=True) # type: ignore
|
|
86
|
+
conn = self._pool.getconn() # type: ignore # Get fresh connection
|
|
87
|
+
|
|
88
|
+
return conn
|
|
89
|
+
|
|
90
|
+
except Exception as e:
|
|
91
|
+
self.logger.error(f"Failed to acquire connection from pool: {e}")
|
|
92
|
+
raise ConnectionError(f"Could not obtain database connection: {e}") from e
|
|
54
93
|
|
|
55
94
|
def _return_connection(self, conn: Any):
|
|
56
95
|
if self._pool and conn:
|
|
@@ -59,6 +98,16 @@ class PostgreSQLAdapter:
|
|
|
59
98
|
# ---------------------------------------------------------------------
|
|
60
99
|
# TRANSACTIONS
|
|
61
100
|
# ---------------------------------------------------------------------
|
|
101
|
+
def reset_pool(self):
|
|
102
|
+
"""Reset the entire pool (call during startup or after major failures)"""
|
|
103
|
+
with self._lock:
|
|
104
|
+
if self._pool:
|
|
105
|
+
try:
|
|
106
|
+
self._pool.closeall()
|
|
107
|
+
except:
|
|
108
|
+
pass
|
|
109
|
+
self._pool = None
|
|
110
|
+
self._initialize_pool()
|
|
62
111
|
|
|
63
112
|
def begin_transaction(self) -> Any:
|
|
64
113
|
"""Begin a transaction and return the connection handle."""
|
|
@@ -18,6 +18,7 @@ class ObjectStorageAdapter(ABC):
|
|
|
18
18
|
optimize: bool = True,
|
|
19
19
|
media_type: Optional[str] = None,
|
|
20
20
|
metadata: Dict[str, Any] | None = None,
|
|
21
|
+
container_name: Optional[str] = None,
|
|
21
22
|
) -> str:
|
|
22
23
|
"""Store object with optional optimization"""
|
|
23
24
|
if optimize and media_type:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/requirements-generic.txt
RENAMED
|
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
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/S3Adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/adapters/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/advanced_query.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/AuditStorage.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/__init__.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/context.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/manager.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/audit/models.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/QueueAdapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/base/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/databaseFactory.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/decorators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/monitoring.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/multitenancy.py
RENAMED
|
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
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/src/polydb/validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_blockchain.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_cloud_factory.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_multi_engine.py
RENAMED
|
File without changes
|
{altcodepro_polydb_python-2.3.13 → altcodepro_polydb_python-2.3.15}/tests/test_postgresql.py
RENAMED
|
File without changes
|
|
File without changes
|