altcodepro-polydb-python 2.2.6__tar.gz → 2.2.8__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.2.6/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.2.8}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/pyproject.toml +1 -1
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/cache.py +113 -70
- altcodepro_polydb_python-2.2.8/src/polydb/databaseFactory.py +957 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/registry.py +11 -0
- altcodepro_polydb_python-2.2.6/src/polydb/databaseFactory.py +0 -1299
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/LICENSE +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/MANIFEST.in +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/README.md +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/example_usage.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/requirements-aws.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/requirements-azure.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/requirements-dev.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/requirements-gcp.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/requirements-generic.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/requirements.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/setup.cfg +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/setup.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/PolyDB.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/__init__.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/AzureTableStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/EFSAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/FirestoreAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/MongoDBAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/PostgreSQLAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/S3Adapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/SQSAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/VercelKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/adapters/__init__.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/advanced_query.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/audit/AuditStorage.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/audit/__init__.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/audit/context.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/audit/manager.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/audit/models.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/base/NoSQLKVAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/base/ObjectStorageAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/base/QueueAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/base/SharedFilesAdapter.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/base/__init__.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/batch.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/cloudDatabaseFactory.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/decorators.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/errors.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/json_safe.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/models.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/monitoring.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/multitenancy.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/py.typed +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/query.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/retry.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/schema.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/security.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/types.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/utils.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/src/polydb/validation.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_aws.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_azure.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_blockchain.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_cloud_factory.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_gcp.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_mongodb.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_multi_engine.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/tests/test_postgresql.py +0 -0
- {altcodepro_polydb_python-2.2.6 → altcodepro_polydb_python-2.2.8}/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.2.
|
|
3
|
+
Version: 2.2.8
|
|
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
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "altcodepro-polydb-python"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.8"
|
|
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.8"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: altcodepro-polydb-python
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.8
|
|
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
|
|
@@ -10,8 +10,10 @@ from enum import Enum
|
|
|
10
10
|
import redis
|
|
11
11
|
from .json_safe import json_safe
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
class CacheStrategy(Enum):
|
|
14
15
|
"""Cache invalidation strategies"""
|
|
16
|
+
|
|
15
17
|
LRU = "lru" # Least Recently Used
|
|
16
18
|
LFU = "lfu" # Least Frequently Used
|
|
17
19
|
TTL = "ttl" # Time To Live
|
|
@@ -21,12 +23,9 @@ class CacheStrategy(Enum):
|
|
|
21
23
|
|
|
22
24
|
class RedisCacheEngine:
|
|
23
25
|
"""Redis-based distributed cache"""
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
redis_url: Optional[str] = None,
|
|
28
|
-
prefix: str = "polydb:",
|
|
29
|
-
default_ttl: int = 3600
|
|
28
|
+
self, redis_url: Optional[str] = None, prefix: str = "polydb:", default_ttl: int = 3600
|
|
30
29
|
):
|
|
31
30
|
self.prefix = prefix
|
|
32
31
|
self.default_ttl = default_ttl
|
|
@@ -34,7 +33,7 @@ class RedisCacheEngine:
|
|
|
34
33
|
self._lock = threading.Lock()
|
|
35
34
|
self.redis_url = redis_url
|
|
36
35
|
self._initialize()
|
|
37
|
-
|
|
36
|
+
|
|
38
37
|
def _initialize(self):
|
|
39
38
|
"""Initialize Redis connection"""
|
|
40
39
|
try:
|
|
@@ -44,32 +43,30 @@ class RedisCacheEngine:
|
|
|
44
43
|
self._client = redis.from_url(self.redis_url)
|
|
45
44
|
else:
|
|
46
45
|
import os
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
|
|
47
|
+
redis_host = os.getenv("REDIS_HOST", "localhost")
|
|
48
|
+
redis_port = int(os.getenv("REDIS_PORT", "6379"))
|
|
49
|
+
redis_db = int(os.getenv("REDIS_DB", "0"))
|
|
50
|
+
|
|
51
51
|
self._client = redis.Redis(
|
|
52
|
-
host=redis_host,
|
|
53
|
-
port=redis_port,
|
|
54
|
-
db=redis_db,
|
|
55
|
-
decode_responses=True
|
|
52
|
+
host=redis_host, port=redis_port, db=redis_db, decode_responses=True
|
|
56
53
|
)
|
|
57
54
|
except ImportError:
|
|
58
55
|
raise ImportError("Redis not installed. Install with: pip install redis")
|
|
59
|
-
|
|
56
|
+
|
|
60
57
|
def _make_key(self, model: str, query: Dict[str, Any]) -> str:
|
|
61
58
|
"""Generate cache key"""
|
|
62
|
-
query_str = json.dumps(query, sort_keys=True,default=json_safe)
|
|
59
|
+
query_str = json.dumps(query, sort_keys=True, default=json_safe)
|
|
63
60
|
query_hash = hashlib.md5(query_str.encode()).hexdigest()
|
|
64
61
|
return f"{self.prefix}{model}:{query_hash}"
|
|
65
|
-
|
|
62
|
+
|
|
66
63
|
def get(self, model: str, query: Dict[str, Any]) -> Optional[Any]:
|
|
67
64
|
"""Get from cache"""
|
|
68
65
|
if not self._client:
|
|
69
66
|
return None
|
|
70
|
-
|
|
67
|
+
|
|
71
68
|
key = self._make_key(model, query)
|
|
72
|
-
|
|
69
|
+
|
|
73
70
|
try:
|
|
74
71
|
data = self._client.get(key)
|
|
75
72
|
if data:
|
|
@@ -79,39 +76,29 @@ class RedisCacheEngine:
|
|
|
79
76
|
return None
|
|
80
77
|
except Exception:
|
|
81
78
|
return None
|
|
82
|
-
|
|
83
|
-
def set(
|
|
84
|
-
self,
|
|
85
|
-
model: str,
|
|
86
|
-
query: Dict[str, Any],
|
|
87
|
-
value: Any,
|
|
88
|
-
ttl: Optional[int] = None
|
|
89
|
-
):
|
|
79
|
+
|
|
80
|
+
def set(self, model: str, query: Dict[str, Any], value: Any, ttl: Optional[int] = None):
|
|
90
81
|
"""Set cache with TTL"""
|
|
91
82
|
if not self._client:
|
|
92
83
|
return
|
|
93
|
-
|
|
84
|
+
|
|
94
85
|
key = self._make_key(model, query)
|
|
95
86
|
ttl = ttl or self.default_ttl
|
|
96
|
-
|
|
87
|
+
|
|
97
88
|
try:
|
|
98
|
-
data = json.dumps(value,default=json_safe)
|
|
89
|
+
data = json.dumps(value, default=json_safe)
|
|
99
90
|
self._client.setex(key, ttl, data)
|
|
100
|
-
|
|
91
|
+
|
|
101
92
|
# Initialize access count
|
|
102
93
|
self._client.set(f"{key}:access_count", 0, ex=ttl)
|
|
103
94
|
except Exception:
|
|
104
95
|
pass
|
|
105
|
-
|
|
106
|
-
def invalidate(
|
|
107
|
-
self,
|
|
108
|
-
model: str,
|
|
109
|
-
query: Optional[Dict[str, Any]] = None
|
|
110
|
-
):
|
|
96
|
+
|
|
97
|
+
def invalidate(self, model: str, query: Optional[Dict[str, Any]] = None):
|
|
111
98
|
"""Invalidate cache"""
|
|
112
99
|
if not self._client:
|
|
113
100
|
return
|
|
114
|
-
|
|
101
|
+
|
|
115
102
|
if query:
|
|
116
103
|
key = self._make_key(model, query)
|
|
117
104
|
self._client.delete(key, f"{key}:access_count")
|
|
@@ -121,66 +108,122 @@ class RedisCacheEngine:
|
|
|
121
108
|
keys = self._client.keys(pattern)
|
|
122
109
|
if keys:
|
|
123
110
|
self._client.delete(*keys)
|
|
124
|
-
|
|
111
|
+
|
|
125
112
|
def clear(self):
|
|
126
113
|
"""Clear entire cache"""
|
|
127
114
|
if not self._client:
|
|
128
115
|
return
|
|
129
|
-
|
|
116
|
+
|
|
130
117
|
pattern = f"{self.prefix}*"
|
|
131
118
|
keys = self._client.keys(pattern)
|
|
132
119
|
if keys:
|
|
133
120
|
self._client.delete(*keys)
|
|
134
|
-
|
|
121
|
+
|
|
135
122
|
def get_stats(self) -> Dict[str, Any]:
|
|
136
123
|
"""Get cache statistics"""
|
|
137
124
|
if not self._client:
|
|
138
125
|
return {}
|
|
139
|
-
|
|
126
|
+
|
|
140
127
|
try:
|
|
141
|
-
info = self._client.info(
|
|
128
|
+
info = self._client.info("stats")
|
|
142
129
|
return {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
130
|
+
"hits": info.get("keyspace_hits", 0),
|
|
131
|
+
"misses": info.get("keyspace_misses", 0),
|
|
132
|
+
"hit_rate": info.get("keyspace_hits", 0)
|
|
133
|
+
/ max(info.get("keyspace_hits", 0) + info.get("keyspace_misses", 0), 1),
|
|
147
134
|
}
|
|
148
135
|
except Exception:
|
|
149
136
|
return {}
|
|
150
137
|
|
|
138
|
+
# ---------------------------------------------------------
|
|
139
|
+
# ZSET (Sorted Set) Operations — for rate limiting, ranking
|
|
140
|
+
# ---------------------------------------------------------
|
|
141
|
+
|
|
142
|
+
def _make_raw_key(self, model: str, key: str) -> str:
|
|
143
|
+
"""Direct key (no hashing) for structured use cases like rate limiting"""
|
|
144
|
+
return f"{self.prefix}{model}:{key}"
|
|
145
|
+
|
|
146
|
+
def zadd(self, model: str, key: str, mapping: Dict[str, float]) -> None:
|
|
147
|
+
if not self._client:
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
redis_key = self._make_raw_key(model, key)
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
self._client.zadd(redis_key, mapping)
|
|
154
|
+
except Exception:
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
def zcard(self, model: str, key: str) -> int:
|
|
158
|
+
if not self._client:
|
|
159
|
+
return 0
|
|
160
|
+
|
|
161
|
+
redis_key = self._make_raw_key(model, key)
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
return int(self._client.zcard(redis_key))
|
|
165
|
+
except Exception:
|
|
166
|
+
return 0
|
|
167
|
+
|
|
168
|
+
def zremrangebyscore(
|
|
169
|
+
self,
|
|
170
|
+
model: str,
|
|
171
|
+
key: str,
|
|
172
|
+
min_score: float,
|
|
173
|
+
max_score: float,
|
|
174
|
+
) -> None:
|
|
175
|
+
if not self._client:
|
|
176
|
+
return
|
|
177
|
+
|
|
178
|
+
redis_key = self._make_raw_key(model, key)
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
self._client.zremrangebyscore(redis_key, min_score, max_score)
|
|
182
|
+
except Exception:
|
|
183
|
+
pass
|
|
184
|
+
|
|
185
|
+
def expire_key(self, model: str, key: str, ttl: int) -> None:
|
|
186
|
+
if not self._client:
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
redis_key = self._make_raw_key(model, key)
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
self._client.expire(redis_key, ttl)
|
|
193
|
+
except Exception:
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
def delete_key(self, model: str, key: str) -> None:
|
|
197
|
+
if not self._client:
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
redis_key = self._make_raw_key(model, key)
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
self._client.delete(redis_key)
|
|
204
|
+
except Exception:
|
|
205
|
+
pass
|
|
206
|
+
|
|
151
207
|
|
|
152
208
|
class CacheWarmer:
|
|
153
209
|
"""Pre-populate cache with frequently accessed data"""
|
|
154
|
-
|
|
210
|
+
|
|
155
211
|
def __init__(self, factory, cache_engine):
|
|
156
212
|
self.factory = factory
|
|
157
213
|
self.cache = cache_engine
|
|
158
|
-
|
|
159
|
-
def warm_model(
|
|
160
|
-
self,
|
|
161
|
-
model,
|
|
162
|
-
queries: List[Dict[str, Any]],
|
|
163
|
-
ttl: Optional[int] = None
|
|
164
|
-
):
|
|
214
|
+
|
|
215
|
+
def warm_model(self, model, queries: List[Dict[str, Any]], ttl: Optional[int] = None):
|
|
165
216
|
"""Warm cache for specific queries"""
|
|
166
217
|
for query in queries:
|
|
167
218
|
try:
|
|
168
219
|
results = self.factory.read(model, query=query)
|
|
169
220
|
self.cache.set(
|
|
170
|
-
model.__name__ if isinstance(model, type) else model,
|
|
171
|
-
query,
|
|
172
|
-
results,
|
|
173
|
-
ttl
|
|
221
|
+
model.__name__ if isinstance(model, type) else model, query, results, ttl
|
|
174
222
|
)
|
|
175
223
|
except Exception:
|
|
176
224
|
pass
|
|
177
|
-
|
|
178
|
-
def warm_popular_queries(
|
|
179
|
-
self,
|
|
180
|
-
model,
|
|
181
|
-
limit: int = 10,
|
|
182
|
-
ttl: Optional[int] = None
|
|
183
|
-
):
|
|
225
|
+
|
|
226
|
+
def warm_popular_queries(self, model, limit: int = 10, ttl: Optional[int] = None):
|
|
184
227
|
"""Warm cache with most popular queries"""
|
|
185
228
|
# This would need query log analysis
|
|
186
229
|
# Placeholder implementation
|
|
@@ -189,17 +232,17 @@ class CacheWarmer:
|
|
|
189
232
|
|
|
190
233
|
class CacheInvalidationStrategy:
|
|
191
234
|
"""Manages cache invalidation strategies"""
|
|
192
|
-
|
|
235
|
+
|
|
193
236
|
def __init__(self, cache_engine, strategy: CacheStrategy = CacheStrategy.TTL):
|
|
194
237
|
self.cache = cache_engine
|
|
195
238
|
self.strategy = strategy
|
|
196
|
-
|
|
239
|
+
|
|
197
240
|
def invalidate_on_write(self, model: str, data: Dict[str, Any]):
|
|
198
241
|
"""Invalidate cache on write operations"""
|
|
199
242
|
if self.strategy in [CacheStrategy.WRITE_THROUGH, CacheStrategy.WRITE_BACK]:
|
|
200
243
|
self.cache.invalidate(model)
|
|
201
|
-
|
|
244
|
+
|
|
202
245
|
def invalidate_related(self, model: str, relationships: List[str]):
|
|
203
246
|
"""Invalidate related models"""
|
|
204
247
|
for related in relationships:
|
|
205
|
-
self.cache.invalidate(related)
|
|
248
|
+
self.cache.invalidate(related)
|