altcodepro-polydb-python 2.2.8__tar.gz → 2.2.9__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.
Files changed (81) hide show
  1. {altcodepro_polydb_python-2.2.8/src/altcodepro_polydb_python.egg-info → altcodepro_polydb_python-2.2.9}/PKG-INFO +1 -1
  2. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/pyproject.toml +1 -1
  3. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9/src/altcodepro_polydb_python.egg-info}/PKG-INFO +1 -1
  4. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/cloudDatabaseFactory.py +13 -2
  5. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/databaseFactory.py +4 -6
  6. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/monitoring.py +72 -87
  7. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/LICENSE +0 -0
  8. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/MANIFEST.in +0 -0
  9. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/README.md +0 -0
  10. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/example_usage.py +0 -0
  11. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/requirements-aws.txt +0 -0
  12. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/requirements-azure.txt +0 -0
  13. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/requirements-dev.txt +0 -0
  14. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/requirements-gcp.txt +0 -0
  15. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/requirements-generic.txt +0 -0
  16. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/requirements.txt +0 -0
  17. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/setup.cfg +0 -0
  18. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/setup.py +0 -0
  19. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/altcodepro_polydb_python.egg-info/SOURCES.txt +0 -0
  20. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/altcodepro_polydb_python.egg-info/dependency_links.txt +0 -0
  21. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/altcodepro_polydb_python.egg-info/requires.txt +0 -0
  22. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/altcodepro_polydb_python.egg-info/top_level.txt +0 -0
  23. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/PolyDB.py +0 -0
  24. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/__init__.py +0 -0
  25. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/AzureBlobStorageAdapter.py +0 -0
  26. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/AzureFileStorageAdapter.py +0 -0
  27. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/AzureQueueAdapter.py +0 -0
  28. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/AzureTableStorageAdapter.py +0 -0
  29. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/BlockchainBlobAdapter.py +0 -0
  30. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/BlockchainKVAdapter.py +0 -0
  31. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/BlockchainQueueAdapter.py +0 -0
  32. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/DynamoDBAdapter.py +0 -0
  33. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/EFSAdapter.py +0 -0
  34. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/FirestoreAdapter.py +0 -0
  35. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/GCPPubSubAdapter.py +0 -0
  36. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/GCPStorageAdapter.py +0 -0
  37. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/MongoDBAdapter.py +0 -0
  38. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/PostgreSQLAdapter.py +0 -0
  39. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/S3Adapter.py +0 -0
  40. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/S3CompatibleAdapter.py +0 -0
  41. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/SQSAdapter.py +0 -0
  42. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/VercelBlobAdapter.py +0 -0
  43. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/VercelKVAdapter.py +0 -0
  44. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/VercelQueueAdapter.py +0 -0
  45. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/adapters/__init__.py +0 -0
  46. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/advanced_query.py +0 -0
  47. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/audit/AuditStorage.py +0 -0
  48. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/audit/__init__.py +0 -0
  49. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/audit/context.py +0 -0
  50. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/audit/manager.py +0 -0
  51. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/audit/models.py +0 -0
  52. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/base/NoSQLKVAdapter.py +0 -0
  53. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/base/ObjectStorageAdapter.py +0 -0
  54. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/base/QueueAdapter.py +0 -0
  55. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/base/SharedFilesAdapter.py +0 -0
  56. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/base/__init__.py +0 -0
  57. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/batch.py +0 -0
  58. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/cache.py +0 -0
  59. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/decorators.py +0 -0
  60. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/errors.py +0 -0
  61. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/json_safe.py +0 -0
  62. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/models.py +0 -0
  63. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/multitenancy.py +0 -0
  64. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/py.typed +0 -0
  65. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/query.py +0 -0
  66. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/registry.py +0 -0
  67. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/retry.py +0 -0
  68. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/schema.py +0 -0
  69. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/security.py +0 -0
  70. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/types.py +0 -0
  71. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/utils.py +0 -0
  72. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/src/polydb/validation.py +0 -0
  73. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_aws.py +0 -0
  74. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_azure.py +0 -0
  75. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_blockchain.py +0 -0
  76. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_cloud_factory.py +0 -0
  77. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_gcp.py +0 -0
  78. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_mongodb.py +0 -0
  79. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_multi_engine.py +0 -0
  80. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/tests/test_postgresql.py +0 -0
  81. {altcodepro_polydb_python-2.2.8 → altcodepro_polydb_python-2.2.9}/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.8
3
+ Version: 2.2.9
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.8"
7
+ version = "2.2.9"
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.8
3
+ Version: 2.2.9
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,8 @@ import os
4
4
  import threading
5
5
  from typing import Dict, List, Optional
6
6
 
7
-
7
+ from .adapters.AzureFileStorageAdapter import AzureFileStorageAdapter
8
+ from .adapters.EFSAdapter import EFSAdapter
8
9
  from .adapters.PostgreSQLAdapter import PostgreSQLAdapter
9
10
  from .adapters.AzureBlobStorageAdapter import AzureBlobStorageAdapter
10
11
  from .adapters.BlockchainBlobAdapter import BlockchainBlobAdapter
@@ -441,7 +442,17 @@ class CloudDatabaseFactory:
441
442
  self.instances["queue"] = instance
442
443
  return instance
443
444
 
444
- def get_files(self, name: str = "files"):
445
+ def get_files(
446
+ self, name: str = "files"
447
+ ) -> (
448
+ AzureFileStorageAdapter
449
+ | EFSAdapter
450
+ | GCPStorageAdapter
451
+ | AzureBlobStorageAdapter
452
+ | S3CompatibleAdapter
453
+ | VercelBlobAdapter
454
+ | BlockchainBlobAdapter
455
+ ):
445
456
  with self._lock:
446
457
  if name in self.instances:
447
458
  return self.instances[name]
@@ -110,8 +110,6 @@ def _extract_meta(model: Union[type, str]) -> ModelMeta:
110
110
  provider=raw.get("provider"),
111
111
  cache=raw.get("cache", False),
112
112
  cache_ttl=raw.get("cache_ttl"),
113
- encrypted_fields=raw.get("encrypted_fields", []),
114
- soft_delete=raw.get("soft_delete", False),
115
113
  )
116
114
  # Default for dynamic/string models
117
115
  return ModelMeta(storage="nosql", table=None, collection=None)
@@ -480,13 +478,13 @@ class DatabaseFactory:
480
478
  )
481
479
  if self.encryption and encrypted_fields:
482
480
  raw = [self.encryption.decrypt_fields(r, encrypted_fields) for r in raw]
483
- if use_external_cache and not no_cache:
481
+ if self._cache and use_external_cache and not no_cache:
484
482
  ttl = cache_ttl or getattr(meta, "cache_ttl", 300)
485
483
  self._cache.set(name, query or {}, raw, ttl)
486
484
  return raw
487
485
 
488
486
  # Check external cache first
489
- if use_external_cache and not no_cache:
487
+ if self._cache and use_external_cache and not no_cache:
490
488
  cached = self._cache.get(name, query or {})
491
489
  if cached is not None:
492
490
  return cached
@@ -923,11 +921,11 @@ class DatabaseFactory:
923
921
  self, path: str, data: Union[bytes, str], *, adapter_name: str = "files"
924
922
  ) -> bool:
925
923
  files = self._engines[0].cloud_factory.get_files(adapter_name)
926
- return files.write(path, data.encode() if isinstance(data, str) else data)
924
+ return files.write(path, data.encode() if isinstance(data, str) else data) # type: ignore
927
925
 
928
926
  def read_file(self, path: str, *, adapter_name: str = "files") -> Optional[bytes]:
929
927
  files = self._engines[0].cloud_factory.get_files(adapter_name)
930
- return files.read(path)
928
+ return files.read(path) # type: ignore
931
929
 
932
930
  def delete_file(self, path: str, *, adapter_name: str = "files") -> bool:
933
931
  files = self._engines[0].cloud_factory.get_files(adapter_name)
@@ -14,6 +14,7 @@ import logging
14
14
  @dataclass
15
15
  class QueryMetrics:
16
16
  """Metrics for a single query"""
17
+
17
18
  operation: str
18
19
  model: str
19
20
  duration_ms: float
@@ -29,12 +30,13 @@ class QueryMetrics:
29
30
  @dataclass
30
31
  class AggregatedMetrics:
31
32
  """Aggregated metrics over time window"""
33
+
32
34
  total_queries: int = 0
33
35
  successful_queries: int = 0
34
36
  failed_queries: int = 0
35
37
  total_duration_ms: float = 0.0
36
38
  avg_duration_ms: float = 0.0
37
- min_duration_ms: float = float('inf')
39
+ min_duration_ms: float = float("inf")
38
40
  max_duration_ms: float = 0.0
39
41
  cache_hit_rate: float = 0.0
40
42
  queries_by_operation: Dict[str, int] = field(default_factory=dict)
@@ -44,117 +46,113 @@ class AggregatedMetrics:
44
46
 
45
47
  class MetricsCollector:
46
48
  """Collects and aggregates metrics"""
47
-
49
+
48
50
  def __init__(self, slow_query_threshold_ms: float = 1000.0):
49
51
  self.slow_query_threshold = slow_query_threshold_ms
50
52
  self._metrics: List[QueryMetrics] = []
51
53
  self._lock = threading.Lock()
52
54
  self._hooks: List[Callable] = []
53
55
  self.logger = logging.getLogger(__name__)
54
-
56
+
55
57
  def record(self, metric: QueryMetrics):
56
58
  """Record a query metric"""
57
59
  with self._lock:
58
60
  self._metrics.append(metric)
59
-
61
+
60
62
  # Log slow queries
61
63
  if metric.duration_ms > self.slow_query_threshold:
62
64
  self.logger.warning(
63
65
  f"Slow query detected: {metric.operation} on {metric.model} "
64
66
  f"took {metric.duration_ms:.2f}ms"
65
67
  )
66
-
68
+
67
69
  # Trigger hooks
68
70
  for hook in self._hooks:
69
71
  try:
70
72
  hook(metric)
71
73
  except Exception as e:
72
74
  self.logger.error(f"Metrics hook failed: {e}")
73
-
75
+
74
76
  def register_hook(self, hook: Callable[[QueryMetrics], None]):
75
77
  """Register a metrics hook"""
76
78
  self._hooks.append(hook)
77
-
79
+
78
80
  def get_metrics(
79
81
  self,
80
82
  since: Optional[datetime] = None,
81
83
  model: Optional[str] = None,
82
- operation: Optional[str] = None
84
+ operation: Optional[str] = None,
83
85
  ) -> List[QueryMetrics]:
84
86
  """Get filtered metrics"""
85
87
  with self._lock:
86
88
  metrics = self._metrics.copy()
87
-
89
+
88
90
  if since:
89
91
  metrics = [m for m in metrics if m.timestamp >= since]
90
-
92
+
91
93
  if model:
92
94
  metrics = [m for m in metrics if m.model == model]
93
-
95
+
94
96
  if operation:
95
97
  metrics = [m for m in metrics if m.operation == operation]
96
-
98
+
97
99
  return metrics
98
-
100
+
99
101
  def aggregate(
100
- self,
101
- since: Optional[datetime] = None,
102
- model: Optional[str] = None
102
+ self, since: Optional[datetime] = None, model: Optional[str] = None
103
103
  ) -> AggregatedMetrics:
104
104
  """Generate aggregated metrics"""
105
105
  metrics = self.get_metrics(since=since, model=model)
106
-
106
+
107
107
  if not metrics:
108
108
  return AggregatedMetrics()
109
-
109
+
110
110
  agg = AggregatedMetrics()
111
111
  agg.total_queries = len(metrics)
112
-
112
+
113
113
  durations = []
114
114
  cache_hits = 0
115
-
115
+
116
116
  for m in metrics:
117
117
  if m.success:
118
118
  agg.successful_queries += 1
119
119
  else:
120
120
  agg.failed_queries += 1
121
-
121
+
122
122
  durations.append(m.duration_ms)
123
123
  agg.total_duration_ms += m.duration_ms
124
-
124
+
125
125
  if m.cache_hit:
126
126
  cache_hits += 1
127
-
127
+
128
128
  # Count by operation
129
- agg.queries_by_operation[m.operation] = \
130
- agg.queries_by_operation.get(m.operation, 0) + 1
131
-
129
+ agg.queries_by_operation[m.operation] = agg.queries_by_operation.get(m.operation, 0) + 1
130
+
132
131
  # Count by model
133
- agg.queries_by_model[m.model] = \
134
- agg.queries_by_model.get(m.model, 0) + 1
135
-
132
+ agg.queries_by_model[m.model] = agg.queries_by_model.get(m.model, 0) + 1
133
+
136
134
  # Track slow queries
137
135
  if m.duration_ms > self.slow_query_threshold:
138
136
  agg.slow_queries.append(m)
139
-
137
+
140
138
  agg.avg_duration_ms = agg.total_duration_ms / agg.total_queries
141
139
  agg.min_duration_ms = min(durations)
142
140
  agg.max_duration_ms = max(durations)
143
141
  agg.cache_hit_rate = cache_hits / agg.total_queries
144
-
142
+
145
143
  return agg
146
-
144
+
147
145
  def clear_old_metrics(self, older_than: timedelta):
148
146
  """Clear metrics older than specified duration"""
149
147
  cutoff = datetime.utcnow() - older_than
150
-
148
+
151
149
  with self._lock:
152
150
  self._metrics = [m for m in self._metrics if m.timestamp >= cutoff]
153
-
151
+
154
152
  def export_prometheus(self) -> str:
155
153
  """Export metrics in Prometheus format"""
156
154
  agg = self.aggregate()
157
-
155
+
158
156
  lines = [
159
157
  f"# HELP polydb_queries_total Total number of queries",
160
158
  f"# TYPE polydb_queries_total counter",
@@ -177,20 +175,20 @@ class MetricsCollector:
177
175
  f"# TYPE polydb_cache_hit_rate gauge",
178
176
  f"polydb_cache_hit_rate {agg.cache_hit_rate}",
179
177
  ]
180
-
178
+
181
179
  return "\n".join(lines)
182
180
 
183
181
 
184
182
  class PerformanceMonitor:
185
183
  """Context manager for automatic query timing"""
186
-
184
+
187
185
  def __init__(
188
186
  self,
189
187
  collector: MetricsCollector,
190
188
  operation: str,
191
189
  model: str,
192
190
  tenant_id: Optional[str] = None,
193
- actor_id: Optional[str] = None
191
+ actor_id: Optional[str] = None,
194
192
  ):
195
193
  self.collector = collector
196
194
  self.operation = operation
@@ -200,21 +198,22 @@ class PerformanceMonitor:
200
198
  self.start_time = None
201
199
  self.success = False
202
200
  self.error = None
203
- self.rows_affected = None
201
+ self.rows_affected = 0
202
+ self.rows_returned = 0
204
203
  self.cache_hit = False
205
-
204
+
206
205
  def __enter__(self):
207
206
  self.start_time = time.perf_counter()
208
207
  return self
209
-
208
+
210
209
  def __exit__(self, exc_type, exc_val, exc_tb):
211
- duration_ms = (time.perf_counter() - self.start_time) * 1000 # type: ignore
212
-
210
+ duration_ms = (time.perf_counter() - self.start_time) * 1000 # type: ignore
211
+
213
212
  if exc_type is None:
214
213
  self.success = True
215
214
  else:
216
215
  self.error = str(exc_val)
217
-
216
+
218
217
  metric = QueryMetrics(
219
218
  operation=self.operation,
220
219
  model=self.model,
@@ -224,40 +223,36 @@ class PerformanceMonitor:
224
223
  tenant_id=self.tenant_id,
225
224
  actor_id=self.actor_id,
226
225
  rows_affected=self.rows_affected,
227
- cache_hit=self.cache_hit
226
+ cache_hit=self.cache_hit,
228
227
  )
229
-
228
+
230
229
  self.collector.record(metric)
231
-
230
+
232
231
  return False
233
232
 
234
233
 
235
234
  class HealthCheck:
236
235
  """System health monitoring"""
237
-
236
+
238
237
  def __init__(self, factory):
239
238
  self.factory = factory
240
239
  self.logger = logging.getLogger(__name__)
241
-
240
+
242
241
  def check_sql_health(self) -> Dict[str, Any]:
243
242
  """Check SQL database health"""
244
243
  try:
245
244
  start = time.perf_counter()
246
245
  self.factory._sql.execute("SELECT 1", fetch_one=True)
247
246
  duration_ms = (time.perf_counter() - start) * 1000
248
-
247
+
249
248
  return {
250
- 'status': 'healthy',
251
- 'latency_ms': duration_ms,
252
- 'provider': self.factory._provider_name
249
+ "status": "healthy",
250
+ "latency_ms": duration_ms,
251
+ "provider": self.factory._provider_name,
253
252
  }
254
253
  except Exception as e:
255
- return {
256
- 'status': 'unhealthy',
257
- 'error': str(e),
258
- 'provider': self.factory._provider_name
259
- }
260
-
254
+ return {"status": "unhealthy", "error": str(e), "provider": self.factory._provider_name}
255
+
261
256
  def check_nosql_health(self) -> Dict[str, Any]:
262
257
  """Check NoSQL database health"""
263
258
  try:
@@ -265,49 +260,39 @@ class HealthCheck:
265
260
  start = time.perf_counter()
266
261
  # This would need a test model
267
262
  duration_ms = (time.perf_counter() - start) * 1000
268
-
263
+
269
264
  return {
270
- 'status': 'healthy',
271
- 'latency_ms': duration_ms,
272
- 'provider': self.factory._provider_name
265
+ "status": "healthy",
266
+ "latency_ms": duration_ms,
267
+ "provider": self.factory._provider_name,
273
268
  }
274
269
  except Exception as e:
275
- return {
276
- 'status': 'unhealthy',
277
- 'error': str(e),
278
- 'provider': self.factory._provider_name
279
- }
280
-
270
+ return {"status": "unhealthy", "error": str(e), "provider": self.factory._provider_name}
271
+
281
272
  def check_cache_health(self) -> Dict[str, Any]:
282
273
  """Check cache health"""
283
274
  if not self.factory._cache:
284
- return {'status': 'disabled'}
285
-
275
+ return {"status": "disabled"}
276
+
286
277
  try:
287
278
  # Test cache operations
288
279
  test_key = "_health_check"
289
280
  test_value = {"test": True}
290
-
281
+
291
282
  start = time.perf_counter()
292
283
  self.factory._cache.set(test_key, {}, test_value, 10)
293
284
  retrieved = self.factory._cache.get(test_key, {})
294
285
  duration_ms = (time.perf_counter() - start) * 1000
295
-
296
- return {
297
- 'status': 'healthy',
298
- 'latency_ms': duration_ms
299
- }
286
+
287
+ return {"status": "healthy", "latency_ms": duration_ms}
300
288
  except Exception as e:
301
- return {
302
- 'status': 'unhealthy',
303
- 'error': str(e)
304
- }
305
-
289
+ return {"status": "unhealthy", "error": str(e)}
290
+
306
291
  def full_health_check(self) -> Dict[str, Any]:
307
292
  """Complete system health check"""
308
293
  return {
309
- 'timestamp': datetime.utcnow().isoformat(),
310
- 'sql': self.check_sql_health(),
311
- 'nosql': self.check_nosql_health(),
312
- 'cache': self.check_cache_health()
313
- }
294
+ "timestamp": datetime.utcnow().isoformat(),
295
+ "sql": self.check_sql_health(),
296
+ "nosql": self.check_nosql_health(),
297
+ "cache": self.check_cache_health(),
298
+ }