mdb-engine 0.1.6__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
- mdb_engine/__init__.py +104 -11
- mdb_engine/auth/ARCHITECTURE.md +112 -0
- mdb_engine/auth/README.md +648 -11
- mdb_engine/auth/__init__.py +136 -29
- mdb_engine/auth/audit.py +592 -0
- mdb_engine/auth/base.py +252 -0
- mdb_engine/auth/casbin_factory.py +264 -69
- mdb_engine/auth/config_helpers.py +7 -6
- mdb_engine/auth/cookie_utils.py +3 -7
- mdb_engine/auth/csrf.py +373 -0
- mdb_engine/auth/decorators.py +3 -10
- mdb_engine/auth/dependencies.py +47 -50
- mdb_engine/auth/helpers.py +3 -3
- mdb_engine/auth/integration.py +53 -80
- mdb_engine/auth/jwt.py +2 -6
- mdb_engine/auth/middleware.py +77 -34
- mdb_engine/auth/oso_factory.py +18 -38
- mdb_engine/auth/provider.py +270 -171
- mdb_engine/auth/rate_limiter.py +504 -0
- mdb_engine/auth/restrictions.py +8 -24
- mdb_engine/auth/session_manager.py +14 -29
- mdb_engine/auth/shared_middleware.py +600 -0
- mdb_engine/auth/shared_users.py +759 -0
- mdb_engine/auth/token_store.py +14 -28
- mdb_engine/auth/users.py +54 -113
- mdb_engine/auth/utils.py +213 -15
- mdb_engine/cli/commands/generate.py +545 -9
- mdb_engine/cli/commands/validate.py +3 -7
- mdb_engine/cli/utils.py +3 -3
- mdb_engine/config.py +7 -21
- mdb_engine/constants.py +65 -0
- mdb_engine/core/README.md +117 -6
- mdb_engine/core/__init__.py +39 -7
- mdb_engine/core/app_registration.py +22 -41
- mdb_engine/core/app_secrets.py +290 -0
- mdb_engine/core/connection.py +18 -9
- mdb_engine/core/encryption.py +223 -0
- mdb_engine/core/engine.py +1057 -93
- mdb_engine/core/index_management.py +12 -16
- mdb_engine/core/manifest.py +459 -150
- mdb_engine/core/ray_integration.py +435 -0
- mdb_engine/core/seeding.py +10 -18
- mdb_engine/core/service_initialization.py +12 -23
- mdb_engine/core/types.py +2 -5
- mdb_engine/database/README.md +140 -17
- mdb_engine/database/__init__.py +17 -6
- mdb_engine/database/abstraction.py +25 -37
- mdb_engine/database/connection.py +11 -18
- mdb_engine/database/query_validator.py +367 -0
- mdb_engine/database/resource_limiter.py +204 -0
- mdb_engine/database/scoped_wrapper.py +713 -196
- mdb_engine/dependencies.py +426 -0
- mdb_engine/di/__init__.py +34 -0
- mdb_engine/di/container.py +248 -0
- mdb_engine/di/providers.py +205 -0
- mdb_engine/di/scopes.py +139 -0
- mdb_engine/embeddings/README.md +54 -24
- mdb_engine/embeddings/__init__.py +31 -24
- mdb_engine/embeddings/dependencies.py +37 -154
- mdb_engine/embeddings/service.py +11 -25
- mdb_engine/exceptions.py +92 -0
- mdb_engine/indexes/README.md +30 -13
- mdb_engine/indexes/__init__.py +1 -0
- mdb_engine/indexes/helpers.py +1 -1
- mdb_engine/indexes/manager.py +50 -114
- mdb_engine/memory/README.md +2 -2
- mdb_engine/memory/__init__.py +1 -2
- mdb_engine/memory/service.py +30 -87
- mdb_engine/observability/README.md +4 -2
- mdb_engine/observability/__init__.py +26 -9
- mdb_engine/observability/health.py +8 -9
- mdb_engine/observability/metrics.py +32 -12
- mdb_engine/repositories/__init__.py +34 -0
- mdb_engine/repositories/base.py +325 -0
- mdb_engine/repositories/mongo.py +233 -0
- mdb_engine/repositories/unit_of_work.py +166 -0
- mdb_engine/routing/README.md +1 -1
- mdb_engine/routing/__init__.py +1 -3
- mdb_engine/routing/websockets.py +25 -60
- mdb_engine-0.2.0.dist-info/METADATA +313 -0
- mdb_engine-0.2.0.dist-info/RECORD +96 -0
- mdb_engine-0.1.6.dist-info/METADATA +0 -213
- mdb_engine-0.1.6.dist-info/RECORD +0 -75
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.2.0.dist-info}/WHEEL +0 -0
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.2.0.dist-info}/entry_points.txt +0 -0
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {mdb_engine-0.1.6.dist-info → mdb_engine-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,97 +1,60 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Embedding Service
|
|
2
|
+
Embedding Service Utilities
|
|
3
3
|
|
|
4
|
-
This module provides
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"""
|
|
4
|
+
This module provides utility functions for creating embedding services.
|
|
5
|
+
For FastAPI dependency injection, use the request-scoped dependencies
|
|
6
|
+
from `mdb_engine.dependencies` instead.
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
Usage:
|
|
9
|
+
# For FastAPI routes (RECOMMENDED):
|
|
10
|
+
from mdb_engine.dependencies import get_embedding_service
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
@app.post("/embed")
|
|
13
|
+
async def embed(embedding_service=Depends(get_embedding_service)):
|
|
14
|
+
...
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
FASTAPI_AVAILABLE = False
|
|
16
|
+
# For standalone/utility usage:
|
|
17
|
+
from mdb_engine.embeddings.dependencies import get_embedding_service_for_app
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return None
|
|
19
|
+
service = get_embedding_service_for_app("my_app", engine)
|
|
20
|
+
"""
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
pass
|
|
22
|
+
from typing import TYPE_CHECKING, Optional
|
|
25
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from ..core.engine import MongoDBEngine
|
|
26
26
|
|
|
27
27
|
from .service import EmbeddingService, get_embedding_service
|
|
28
28
|
|
|
29
|
-
# Global engine registry (for apps that don't pass engine explicitly)
|
|
30
|
-
_global_engine: Optional[Any] = None
|
|
31
|
-
_global_app_slug: Optional[str] = None
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def set_global_engine(engine: Any, app_slug: Optional[str] = None) -> None:
|
|
35
|
-
"""
|
|
36
|
-
Set global MongoDBEngine instance for embedding dependency injection.
|
|
37
|
-
|
|
38
|
-
This is useful when you have a single engine instance that you want
|
|
39
|
-
to use across all apps. Call this during application startup.
|
|
40
|
-
|
|
41
|
-
Args:
|
|
42
|
-
engine: MongoDBEngine instance
|
|
43
|
-
app_slug: Optional app slug
|
|
44
|
-
"""
|
|
45
|
-
global _global_engine, _global_app_slug
|
|
46
|
-
_global_engine = engine
|
|
47
|
-
_global_app_slug = app_slug
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def get_global_engine() -> Optional[Any]:
|
|
51
|
-
"""
|
|
52
|
-
Get global MongoDBEngine instance.
|
|
53
|
-
|
|
54
|
-
Returns:
|
|
55
|
-
MongoDBEngine instance if set, None otherwise
|
|
56
|
-
"""
|
|
57
|
-
return _global_engine
|
|
58
|
-
|
|
59
29
|
|
|
60
30
|
def get_embedding_service_for_app(
|
|
61
|
-
app_slug: str, engine:
|
|
31
|
+
app_slug: str, engine: "MongoDBEngine"
|
|
62
32
|
) -> Optional[EmbeddingService]:
|
|
63
33
|
"""
|
|
64
|
-
Get embedding service for a specific app.
|
|
34
|
+
Get embedding service for a specific app using the engine instance.
|
|
65
35
|
|
|
66
|
-
This is a
|
|
67
|
-
|
|
36
|
+
This is a utility function for cases where you need to create an
|
|
37
|
+
embedding service outside of a FastAPI request context (e.g., in
|
|
38
|
+
background tasks, CLI tools, or tests).
|
|
39
|
+
|
|
40
|
+
For FastAPI routes, use `mdb_engine.dependencies.get_embedding_service` instead.
|
|
68
41
|
|
|
69
42
|
Args:
|
|
70
|
-
app_slug: App slug
|
|
71
|
-
engine: MongoDBEngine instance
|
|
43
|
+
app_slug: App slug to get embedding config from
|
|
44
|
+
engine: MongoDBEngine instance
|
|
72
45
|
|
|
73
46
|
Returns:
|
|
74
|
-
EmbeddingService instance if embedding is enabled
|
|
47
|
+
EmbeddingService instance if embedding is enabled, None otherwise
|
|
75
48
|
|
|
76
49
|
Example:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@app.post("/embed")
|
|
82
|
-
async def embed_endpoint(
|
|
83
|
-
embedding_service = Depends(lambda: get_embedding_service_for_app("my_app"))
|
|
84
|
-
):
|
|
85
|
-
if not embedding_service:
|
|
86
|
-
raise HTTPException(503, "Embedding service not available")
|
|
87
|
-
embeddings = await embedding_service.embed_chunks(["Hello world"])
|
|
88
|
-
return {"embeddings": embeddings}
|
|
89
|
-
```
|
|
90
|
-
"""
|
|
91
|
-
# Try to get engine from context if not provided
|
|
92
|
-
if engine is None:
|
|
93
|
-
engine = _global_engine
|
|
50
|
+
# In a background task or CLI
|
|
51
|
+
engine = MongoDBEngine(...)
|
|
52
|
+
await engine.initialize()
|
|
94
53
|
|
|
54
|
+
service = get_embedding_service_for_app("my_app", engine)
|
|
55
|
+
if service:
|
|
56
|
+
embeddings = await service.embed_chunks(["Hello world"])
|
|
57
|
+
"""
|
|
95
58
|
if engine is None:
|
|
96
59
|
return None
|
|
97
60
|
|
|
@@ -108,86 +71,6 @@ def get_embedding_service_for_app(
|
|
|
108
71
|
return get_embedding_service(config=embedding_config)
|
|
109
72
|
|
|
110
73
|
|
|
111
|
-
|
|
112
|
-
""
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
This creates a dependency function that can be used with Depends()
|
|
116
|
-
to inject the embedding service into route handlers.
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
app_slug: App slug
|
|
120
|
-
engine: MongoDBEngine instance (optional)
|
|
121
|
-
|
|
122
|
-
Returns:
|
|
123
|
-
Dependency function that returns EmbeddingService or raises HTTPException
|
|
124
|
-
|
|
125
|
-
Example:
|
|
126
|
-
```python
|
|
127
|
-
from fastapi import Depends
|
|
128
|
-
from mdb_engine.embeddings.dependencies import create_embedding_dependency
|
|
129
|
-
|
|
130
|
-
embedding_dep = create_embedding_dependency("my_app", engine)
|
|
131
|
-
|
|
132
|
-
@app.post("/embed")
|
|
133
|
-
async def embed_endpoint(embedding_service = Depends(embedding_dep)):
|
|
134
|
-
embeddings = await embedding_service.embed_chunks(["Hello world"])
|
|
135
|
-
return {"embeddings": embeddings}
|
|
136
|
-
```
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
def _get_embedding_service() -> EmbeddingService:
|
|
140
|
-
embedding_service = get_embedding_service_for_app(app_slug, engine)
|
|
141
|
-
if embedding_service is None:
|
|
142
|
-
if FASTAPI_AVAILABLE:
|
|
143
|
-
raise HTTPException(
|
|
144
|
-
status_code=503,
|
|
145
|
-
detail=f"Embedding service not available for app '{app_slug}'. "
|
|
146
|
-
"Ensure 'embedding_config.enabled' is true in manifest.json and "
|
|
147
|
-
"embedding dependencies are installed.",
|
|
148
|
-
)
|
|
149
|
-
else:
|
|
150
|
-
raise RuntimeError(
|
|
151
|
-
f"Embedding service not available for app '{app_slug}'"
|
|
152
|
-
)
|
|
153
|
-
return embedding_service
|
|
154
|
-
|
|
155
|
-
return _get_embedding_service
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
def get_embedding_service_dependency(app_slug: str):
|
|
159
|
-
"""
|
|
160
|
-
Get embedding service dependency using global engine.
|
|
161
|
-
|
|
162
|
-
This is a convenience function that uses the global engine registry.
|
|
163
|
-
Set the engine with set_global_engine() during app startup.
|
|
164
|
-
|
|
165
|
-
Args:
|
|
166
|
-
app_slug: App slug
|
|
167
|
-
|
|
168
|
-
Returns:
|
|
169
|
-
Dependency function for FastAPI Depends()
|
|
170
|
-
|
|
171
|
-
Example:
|
|
172
|
-
```python
|
|
173
|
-
from fastapi import FastAPI, Depends
|
|
174
|
-
from mdb_engine.embeddings.dependencies import (
|
|
175
|
-
set_global_engine, get_embedding_service_dependency
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
app = FastAPI()
|
|
179
|
-
|
|
180
|
-
# During startup
|
|
181
|
-
set_global_engine(engine, app_slug="my_app")
|
|
182
|
-
|
|
183
|
-
# In routes
|
|
184
|
-
@app.post("/embed")
|
|
185
|
-
async def embed(embedding_service = Depends(get_embedding_service_dependency("my_app"))):
|
|
186
|
-
return await embedding_service.embed_chunks(["Hello world"])
|
|
187
|
-
```
|
|
188
|
-
"""
|
|
189
|
-
return create_embedding_dependency(app_slug, _global_engine)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
# Alias for backward compatibility
|
|
193
|
-
get_embedding_service_dep = get_embedding_service_dependency
|
|
74
|
+
__all__ = [
|
|
75
|
+
"get_embedding_service_for_app",
|
|
76
|
+
]
|
mdb_engine/embeddings/service.py
CHANGED
|
@@ -134,7 +134,7 @@ class OpenAIEmbeddingProvider(BaseEmbeddingProvider):
|
|
|
134
134
|
ConnectionError,
|
|
135
135
|
OSError,
|
|
136
136
|
) as e:
|
|
137
|
-
logger.
|
|
137
|
+
logger.exception(f"OpenAI embedding failed: {e}")
|
|
138
138
|
raise EmbeddingServiceError(f"OpenAI embedding failed: {str(e)}") from e
|
|
139
139
|
|
|
140
140
|
|
|
@@ -217,10 +217,8 @@ class AzureOpenAIEmbeddingProvider(BaseEmbeddingProvider):
|
|
|
217
217
|
ConnectionError,
|
|
218
218
|
OSError,
|
|
219
219
|
) as e:
|
|
220
|
-
logger.
|
|
221
|
-
raise EmbeddingServiceError(
|
|
222
|
-
f"Azure OpenAI embedding failed: {str(e)}"
|
|
223
|
-
) from e
|
|
220
|
+
logger.exception(f"Azure OpenAI embedding failed: {e}")
|
|
221
|
+
raise EmbeddingServiceError(f"Azure OpenAI embedding failed: {str(e)}") from e
|
|
224
222
|
|
|
225
223
|
|
|
226
224
|
def _detect_provider_from_env() -> str:
|
|
@@ -281,24 +279,16 @@ class EmbeddingProvider:
|
|
|
281
279
|
else:
|
|
282
280
|
# Auto-detect provider from environment variables
|
|
283
281
|
provider_type = _detect_provider_from_env()
|
|
284
|
-
default_model = (config or {}).get(
|
|
285
|
-
"default_embedding_model", "text-embedding-3-small"
|
|
286
|
-
)
|
|
282
|
+
default_model = (config or {}).get("default_embedding_model", "text-embedding-3-small")
|
|
287
283
|
|
|
288
284
|
if provider_type == "azure":
|
|
289
|
-
self.embedding_provider = AzureOpenAIEmbeddingProvider(
|
|
290
|
-
default_model=default_model
|
|
291
|
-
)
|
|
285
|
+
self.embedding_provider = AzureOpenAIEmbeddingProvider(default_model=default_model)
|
|
292
286
|
logger.info(
|
|
293
287
|
f"Auto-detected Azure OpenAI embedding provider (model: {default_model})"
|
|
294
288
|
)
|
|
295
289
|
else:
|
|
296
|
-
self.embedding_provider = OpenAIEmbeddingProvider(
|
|
297
|
-
|
|
298
|
-
)
|
|
299
|
-
logger.info(
|
|
300
|
-
f"Auto-detected OpenAI embedding provider (model: {default_model})"
|
|
301
|
-
)
|
|
290
|
+
self.embedding_provider = OpenAIEmbeddingProvider(default_model=default_model)
|
|
291
|
+
logger.info(f"Auto-detected OpenAI embedding provider (model: {default_model})")
|
|
302
292
|
|
|
303
293
|
# Store config for potential future use
|
|
304
294
|
self.config = config or {}
|
|
@@ -341,7 +331,7 @@ class EmbeddingProvider:
|
|
|
341
331
|
return vectors
|
|
342
332
|
|
|
343
333
|
except (AttributeError, TypeError, ValueError, RuntimeError, KeyError) as e:
|
|
344
|
-
logger.
|
|
334
|
+
logger.exception(f"EMBED_FAILED: {str(e)}")
|
|
345
335
|
raise EmbeddingServiceError(f"Embedding failed: {str(e)}") from e
|
|
346
336
|
|
|
347
337
|
|
|
@@ -573,7 +563,7 @@ class EmbeddingService:
|
|
|
573
563
|
ConnectionError,
|
|
574
564
|
OSError,
|
|
575
565
|
) as e:
|
|
576
|
-
logger.
|
|
566
|
+
logger.exception(f"Failed to generate embeddings for {source_id}: {e}")
|
|
577
567
|
raise EmbeddingServiceError(f"Embedding generation failed: {str(e)}") from e
|
|
578
568
|
|
|
579
569
|
if len(vectors) != len(chunks):
|
|
@@ -614,9 +604,7 @@ class EmbeddingService:
|
|
|
614
604
|
result = await collection.insert_many(documents_to_insert)
|
|
615
605
|
inserted_count = len(result.inserted_ids)
|
|
616
606
|
|
|
617
|
-
logger.info(
|
|
618
|
-
f"Successfully inserted {inserted_count} documents for source: {source_id}"
|
|
619
|
-
)
|
|
607
|
+
logger.info(f"Successfully inserted {inserted_count} documents for source: {source_id}")
|
|
620
608
|
|
|
621
609
|
return {
|
|
622
610
|
"chunks_created": len(chunks),
|
|
@@ -632,9 +620,7 @@ class EmbeddingService:
|
|
|
632
620
|
KeyError,
|
|
633
621
|
ConnectionError,
|
|
634
622
|
) as e:
|
|
635
|
-
logger.error(
|
|
636
|
-
f"Failed to store documents for {source_id}: {e}", exc_info=True
|
|
637
|
-
)
|
|
623
|
+
logger.error(f"Failed to store documents for {source_id}: {e}", exc_info=True)
|
|
638
624
|
raise EmbeddingServiceError(f"Storage failed: {str(e)}") from e
|
|
639
625
|
|
|
640
626
|
async def process_text(
|
mdb_engine/exceptions.py
CHANGED
|
@@ -165,3 +165,95 @@ class ConfigurationError(MongoDBEngineError):
|
|
|
165
165
|
super().__init__(message, context=context)
|
|
166
166
|
self.config_key = config_key
|
|
167
167
|
self.config_value = config_value
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class QueryValidationError(MongoDBEngineError):
|
|
171
|
+
"""
|
|
172
|
+
Raised when a query fails validation checks.
|
|
173
|
+
|
|
174
|
+
This exception is raised when a query contains dangerous operators,
|
|
175
|
+
exceeds complexity limits, or violates security policies.
|
|
176
|
+
|
|
177
|
+
Attributes:
|
|
178
|
+
message: Error message
|
|
179
|
+
query_type: Type of query that failed (filter, pipeline, etc.)
|
|
180
|
+
operator: Dangerous operator that was found (if applicable)
|
|
181
|
+
path: JSON path where the issue was found (if applicable)
|
|
182
|
+
context: Additional context information
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
def __init__(
|
|
186
|
+
self,
|
|
187
|
+
message: str,
|
|
188
|
+
query_type: Optional[str] = None,
|
|
189
|
+
operator: Optional[str] = None,
|
|
190
|
+
path: Optional[str] = None,
|
|
191
|
+
context: Optional[Dict[str, Any]] = None,
|
|
192
|
+
) -> None:
|
|
193
|
+
"""
|
|
194
|
+
Initialize the query validation error.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
message: Error message
|
|
198
|
+
query_type: Type of query that failed (filter, pipeline, etc.)
|
|
199
|
+
operator: Dangerous operator that was found (if applicable)
|
|
200
|
+
path: JSON path where the issue was found (if applicable)
|
|
201
|
+
context: Additional context information
|
|
202
|
+
"""
|
|
203
|
+
context = context or {}
|
|
204
|
+
if query_type:
|
|
205
|
+
context["query_type"] = query_type
|
|
206
|
+
if operator:
|
|
207
|
+
context["operator"] = operator
|
|
208
|
+
if path:
|
|
209
|
+
context["path"] = path
|
|
210
|
+
super().__init__(message, context=context)
|
|
211
|
+
self.query_type = query_type
|
|
212
|
+
self.operator = operator
|
|
213
|
+
self.path = path
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class ResourceLimitExceeded(MongoDBEngineError):
|
|
217
|
+
"""
|
|
218
|
+
Raised when a resource limit is exceeded.
|
|
219
|
+
|
|
220
|
+
This exception is raised when queries exceed timeouts, result sizes,
|
|
221
|
+
or other resource limits.
|
|
222
|
+
|
|
223
|
+
Attributes:
|
|
224
|
+
message: Error message
|
|
225
|
+
limit_type: Type of limit that was exceeded (timeout, size, etc.)
|
|
226
|
+
limit_value: The limit value that was exceeded
|
|
227
|
+
actual_value: The actual value that exceeded the limit
|
|
228
|
+
context: Additional context information
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
def __init__(
|
|
232
|
+
self,
|
|
233
|
+
message: str,
|
|
234
|
+
limit_type: Optional[str] = None,
|
|
235
|
+
limit_value: Optional[Any] = None,
|
|
236
|
+
actual_value: Optional[Any] = None,
|
|
237
|
+
context: Optional[Dict[str, Any]] = None,
|
|
238
|
+
) -> None:
|
|
239
|
+
"""
|
|
240
|
+
Initialize the resource limit exceeded error.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
message: Error message
|
|
244
|
+
limit_type: Type of limit that was exceeded (timeout, size, etc.)
|
|
245
|
+
limit_value: The limit value that was exceeded
|
|
246
|
+
actual_value: The actual value that exceeded the limit
|
|
247
|
+
context: Additional context information
|
|
248
|
+
"""
|
|
249
|
+
context = context or {}
|
|
250
|
+
if limit_type:
|
|
251
|
+
context["limit_type"] = limit_type
|
|
252
|
+
if limit_value is not None:
|
|
253
|
+
context["limit_value"] = limit_value
|
|
254
|
+
if actual_value is not None:
|
|
255
|
+
context["actual_value"] = actual_value
|
|
256
|
+
super().__init__(message, context=context)
|
|
257
|
+
self.limit_type = limit_type
|
|
258
|
+
self.limit_value = limit_value
|
|
259
|
+
self.actual_value = actual_value
|
mdb_engine/indexes/README.md
CHANGED
|
@@ -573,7 +573,7 @@ try:
|
|
|
573
573
|
collection_name="users",
|
|
574
574
|
index_definitions=index_definitions
|
|
575
575
|
)
|
|
576
|
-
except
|
|
576
|
+
except (PyMongoError, ValueError, TypeError) as e:
|
|
577
577
|
logger.error(f"Failed to create indexes: {e}", exc_info=True)
|
|
578
578
|
raise
|
|
579
579
|
```
|
|
@@ -613,12 +613,20 @@ index_definitions = [
|
|
|
613
613
|
}
|
|
614
614
|
]
|
|
615
615
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
616
|
+
# Get scoped database and collection
|
|
617
|
+
db = engine.get_scoped_db("my_app")
|
|
618
|
+
collection = db.users
|
|
619
|
+
|
|
620
|
+
# Use collection.index_manager for index operations
|
|
621
|
+
index_manager = collection.index_manager
|
|
622
|
+
for index_def in index_definitions:
|
|
623
|
+
if index_def["type"] == "regular":
|
|
624
|
+
await index_manager.create_index(
|
|
625
|
+
keys=list(index_def["keys"].items()),
|
|
626
|
+
name=index_def.get("name"),
|
|
627
|
+
**index_def.get("options", {})
|
|
628
|
+
)
|
|
629
|
+
# Handle other index types similarly...
|
|
622
630
|
```
|
|
623
631
|
|
|
624
632
|
### Multiple Collections
|
|
@@ -635,13 +643,22 @@ collections_with_indexes = {
|
|
|
635
643
|
]
|
|
636
644
|
}
|
|
637
645
|
|
|
646
|
+
# Get scoped database
|
|
647
|
+
db = engine.get_scoped_db("my_app")
|
|
648
|
+
|
|
649
|
+
# Use collection.index_manager for each collection
|
|
638
650
|
for collection_name, index_definitions in collections_with_indexes.items():
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
651
|
+
collection = getattr(db, collection_name)
|
|
652
|
+
index_manager = collection.index_manager
|
|
653
|
+
|
|
654
|
+
for index_def in index_definitions:
|
|
655
|
+
if index_def["type"] == "regular":
|
|
656
|
+
await index_manager.create_index(
|
|
657
|
+
keys=list(index_def["keys"].items()),
|
|
658
|
+
name=index_def.get("name"),
|
|
659
|
+
**index_def.get("options", {})
|
|
660
|
+
)
|
|
661
|
+
# Handle other index types similarly...
|
|
645
662
|
```
|
|
646
663
|
|
|
647
664
|
## Related Modules
|
mdb_engine/indexes/__init__.py
CHANGED
|
@@ -8,6 +8,7 @@ This module is part of MDB_ENGINE - MongoDB Engine.
|
|
|
8
8
|
|
|
9
9
|
# Re-export index managers from database module for convenience
|
|
10
10
|
from ..database.scoped_wrapper import AsyncAtlasIndexManager, AutoIndexManager
|
|
11
|
+
|
|
11
12
|
# Export high-level management functions
|
|
12
13
|
from .manager import normalize_json_def, run_index_creation_for_collection
|
|
13
14
|
|
mdb_engine/indexes/helpers.py
CHANGED
|
@@ -12,7 +12,7 @@ logger = logging.getLogger(__name__)
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def normalize_keys(
|
|
15
|
-
keys: Union[Dict[str, Any], List[Tuple[str, Any]]]
|
|
15
|
+
keys: Union[Dict[str, Any], List[Tuple[str, Any]]],
|
|
16
16
|
) -> List[Tuple[str, Any]]:
|
|
17
17
|
"""
|
|
18
18
|
Normalize index keys to a consistent format.
|