azure-cosmos-db-py
microsoft/skills
Crie serviços NoSQL do Azure Cosmos DB prontos para produção com Python/FastAPI, incluindo a configuração do cliente com autenticação dupla, operações CRUD na camada de serviço, estratégias de chave de partição, consultas parametrizadas e padrões de TDD.
...Expandir tudoImplementação do serviço Cosmos DB
Crie serviços NoSQL do Azure Cosmos DB de nível de produção seguindo as diretrizes de código limpo, as melhores práticas de segurança e os princípios de TDD.
Instalação
pip install azure-cosmos azure-identity
Variáveis de ambiente
COSMOS_ENDPOINT=https://.documents.azure.com:443/ # Required for all auth methods
COSMOS_DATABASE_NAME= # Required for all auth methods
COSMOS_CONTAINER_ID= # Required for all auth methods
# For emulator only (not production)
COSMOS_KEY= # Only required for key-based auth or emulator
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
Autenticação e ciclo de vida
🔑 Duas regras se aplicam a todos os exemplos de código abaixo:
- Dê preferência a
DefaultAzureCredential. Ele funciona localmente (Azure CLI / VS Code / Developer CLI) e no Azure (identidade gerenciada, identidade de carga de trabalho) sem alteração no código. Evite strings de conexão, chaves de conta/API — elas contornam a auditoria e a rotação do Entra.
- Desenvolvimento local:
DefaultAzureCredentialfunciona como está.- Produção: defina
AZURE_TOKEN_CREDENTIALS=prod(ouAZURE_TOKEN_CREDENTIALS=) para restringir a cadeia de credenciais a credenciais seguras para produção.- Envolva cada cliente em um gerenciador de contexto para que transportes HTTP, soquetes e caches de tokens sejam liberados de forma determinística:
- Sincronização:
with(...) as client: - Assíncrono:
async withe(...) as client: async with DefaultAzureCredential() as credential:(deazure.identity.aio)Os trechos de código podem simplificar essa configuração, mas o código de produção deve sempre seguir ambas as regras.
DefaultAzureCredential (preferencial):
import os
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=
credential = DefaultAzureCredential(require_envvar=True)
# Or use a specific credential directly in production:
# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
with CosmosClient(
url=os.environ["COSMOS_ENDPOINT"],
credential=credential
) as client:
# Use client here (see following sections for operations)
...
Emulador (desenvolvimento local):
from azure.cosmos import CosmosClient
with CosmosClient(
url="https://localhost:8081",
credential=os.environ["COSMOS_KEY"],
connection_verify=False
) as client:
# Use client here (see following sections for operations)
...
Visão geral da arquitetura
┌─────────────────────────────────────────────────────────────────┐
│ FastAPI Router │
│ - Auth dependencies (get_current_user, get_current_user_required)
│ - HTTP error responses (HTTPException) │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ Service Layer │
│ - Business logic and validation │
│ - Document ↔ Model conversion │
│ - Graceful degradation when Cosmos unavailable │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ Cosmos DB Client Module │
│ - Singleton container initialization │
│ - Dual auth: DefaultAzureCredential (Azure) / Key (emulator) │
│ - Async wrapper via run_in_threadpool │
└─────────────────────────────────────────────────────────────────┘
Introdução rápida
1. Configuração do módulo cliente
Crie um cliente Cosmos do tipo singleton com autenticação dupla:
# db/cosmos.py
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential
from starlette.concurrency import run_in_threadpool
_cosmos_container = None
def _is_emulator_endpoint(endpoint: str) -> bool:
return "localhost" in endpoint or "127.0.0.1" in endpoint
async def get_container():
global _cosmos_container
if _cosmos_container is None:
# Singleton: client lives for the FastAPI app lifetime; close in a lifespan shutdown handler.
if _is_emulator_endpoint(settings.cosmos_endpoint):
client = CosmosClient(
url=settings.cosmos_endpoint,
credential=settings.cosmos_key,
connection_verify=False
)
else:
client = CosmosClient(
url=settings.cosmos_endpoint,
credential=DefaultAzureCredential()
)
db = client.get_database_client(settings.cosmos_database_name)
_cosmos_container = db.get_container_client(settings.cosmos_container_id)
return _cosmos_container
Implementação completa: consulte references/client-setup.md
2. Hierarquia de modelos Pydantic
Use o padrão de modelo de cinco camadas para uma separação clara:
class ProjectBase(BaseModel): # Shared fields
name: str = Field(..., min_length=1, max_length=200)
class ProjectCreate(ProjectBase): # Creation request
workspace_id: str = Field(..., alias="workspaceId")
class ProjectUpdate(BaseModel): # Partial updates (all optional)
name: Optional[str] = Field(None, min_length=1)
class Project(ProjectBase): # API response
id: str
created_at: datetime = Field(..., alias="createdAt")
class ProjectInDB(Project): # Internal with docType
doc_type: str = "project"
3. Padrão da camada de serviço
class ProjectService:
def _use_cosmos(self) -> bool:
return get_container() is not None
async def get_by_id(self, project_id: str, workspace_id: str) -> Project | None:
if not self._use_cosmos():
return None
doc = await get_document(project_id, partition_key=workspace_id)
if doc is None:
return None
return self._doc_to_model(doc)
Padrões completos: consulte references/service-layer.md
Princípios fundamentais
Requisitos de segurança
- Autenticação RBAC: use
DefaultAzureCredentialno Azure — nunca armazene chaves no código - Chaves exclusivas do emulador: codifique a chave conhecida do emulador apenas para desenvolvimento local
- Consultas parametrizadas: sempre use
@parametersintaxe — nunca concatene strings - Validação da chave de partição: verifique se o acesso à chave de partição corresponde à autorização do usuário
Convenções de código limpo
- Responsabilidade única: o módulo cliente lida com a conexão; os serviços lidam com a lógica de negócios
- Degradação graciosa: os serviços retornam
None/[]quando o Cosmos estiver indisponível - Nomenclatura consistente:
_doc_to_model(),_model_to_doc(),_use_cosmos() - Sugestões de tipo: tipagem completa em todos os métodos públicos
- Aliases em CamelCase: Use
Field(alias="camelCase")para serialização JSON
Requisitos de TDD
Escreva os testes ANTES da implementação usando estes padrões:
@pytest.fixture
def mock_cosmos_container(mocker):
container = mocker.MagicMock()
mocker.patch("app.db.cosmos.get_container", return_value=container)
return container
@pytest.mark.asyncio
async def test_get_project_by_id_returns_project(mock_cosmos_container):
# Arrange
mock_cosmos_container.read_item.return_value = {"id": "123", "name": "Test"}
# Act
result = await project_service.get_by_id("123", "workspace-1")
# Assert
assert result.id == "123"
assert result.name == "Test"
Guia completo de testes: Consulte references/testing.md
Melhores práticas
- Esta habilidade utiliza async em toda a sua extensão (
azure.cosmos.aio); não misture com o clienteazure.cosmossíncrono. Mantenha todo o caminho de solicitação do FastAPI como async — não combine chamadas síncronas do Cosmos com manipuladores async. - Sempre use gerenciadores de contexto para clientes e credenciais assíncronas. Envolva o cliente em
async with CosmosClient(...) as client:(ou gerencie seu ciclo de vida por meio do lifespan do FastAPI e feche-o explicitamente). ParaDefaultAzureCredential,azure.identity.aio, use tambémasync with credential:para que os tokens e os transportes sejam liberados.
Arquivos de referência
| Arquivo | Quando ler |
|---|---|
| references/client-setup.md | Configuração do cliente Cosmos com autenticação dupla, configuração de SSL e padrão singleton |
| references/service-layer.md | Implementação da classe de serviço completa com CRUD, conversões e degradação gradual |
| references/testing.md | Escrevendo testes com pytest, simulando o Cosmos, configuração de testes de integração |
| references/partitioning.md | Escolha de chaves de partição, consultas entre partições, operações de movimentação |
| references/error-handling.md | Tratamento do CosmosResourceNotFoundError, registro em log, mapeamento de erros HTTP |
Arquivos de modelo
| Arquivo | Finalidade |
|---|---|
| assets/cosmos_client_template.py | Módulo cliente pronto para uso |
| assets/service_template.py | Esqueleto da classe de serviço |
| assets/conftest_template.py | Fixtures do pytest para simulação no Cosmos |
Atributos de qualidade (NFRs)
Confiabilidade
- Degradação gradual quando o Cosmos estiver indisponível
- Lógica de repetição de tentativas com recuo exponencial para falhas transitórias
- Pool de conexões via padrão singleton
Segurança
- Zero segredos no código (RBAC por meio de DefaultAzureCredential)
- Consultas parametrizadas impedem injeção
- O isolamento por chave de partição impõe limites aos dados
Manutenção
- O padrão do modelo de cinco camadas permite a evolução do esquema
- A camada de serviço separa a lógica de negócios do armazenamento
- Padrões consistentes em todos os serviços de entidade
Testabilidade
- Injeção de dependências por meio de
get_container() - Simulação fácil com variáveis globais no nível do módulo
- A separação clara permite testes unitários sem o Cosmos
Desempenho
- Consultas por chave de partição evitam varreduras entre partições
- O encapsulamento assíncrono evita o bloqueio do loop de eventos do FastAPI
- Sobrecarga mínima na conversão de documentos
---
name: azure-cosmos-db-py
description: Build production-grade Azure Cosmos DB NoSQL services with Python/FastAPI, including client setup with dual authentication, service layer CRUD operations, partition key strategies, parameterized queries, and TDD patterns.
license: MIT
---
# Cosmos DB Service Implementation
Build production-grade Azure Cosmos DB NoSQL services following clean code, security best practices, and TDD principles.
## Installation
```bash
pip install azure-cosmos azure-identity
```
## Environment Variables
```bash
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/ # Required for all auth methods
COSMOS_DATABASE_NAME=<database-name> # Required for all auth methods
COSMOS_CONTAINER_ID=<container-id> # Required for all auth methods
# For emulator only (not production)
COSMOS_KEY=<emulator-key> # Only required for key-based auth or emulator
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
```
## Authentication & Lifecycle
> **🔑 Two rules apply to every code sample below:**
>
> 1. **Prefer `DefaultAzureCredential`.** It works locally (Azure CLI / VS Code / Developer CLI) and in Azure (managed identity, workload identity) with no code change. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
> - Local dev: `DefaultAzureCredential` works as-is.
> - Production: set `AZURE_TOKEN_CREDENTIALS=prod` (or `AZURE_TOKEN_CREDENTIALS=<specific_credential>`) to constrain the credential chain to production-safe credentials.
> 2. **Wrap every client in a context manager** so HTTP transports, sockets, and token caches are released deterministically:
> - Sync: `with <Client>(...) as client:`
> - Async: `async with <Client>(...) as client:` **and** `async with DefaultAzureCredential() as credential:` (from `azure.identity.aio`)
>
> Snippets may abbreviate this setup, but production code should always follow both rules.
**DefaultAzureCredential (preferred)**:
```python
import os
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
credential = DefaultAzureCredential(require_envvar=True)
# Or use a specific credential directly in production:
# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
with CosmosClient(
url=os.environ["COSMOS_ENDPOINT"],
credential=credential
) as client:
# Use client here (see following sections for operations)
...
```
**Emulator (local development)**:
```python
from azure.cosmos import CosmosClient
with CosmosClient(
url="https://localhost:8081",
credential=os.environ["COSMOS_KEY"],
connection_verify=False
) as client:
# Use client here (see following sections for operations)
...
```
## Architecture Overview
```
┌─────────────────────────────────────────────────────────────────┐
│ FastAPI Router │
│ - Auth dependencies (get_current_user, get_current_user_required)
│ - HTTP error responses (HTTPException) │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ Service Layer │
│ - Business logic and validation │
│ - Document ↔ Model conversion │
│ - Graceful degradation when Cosmos unavailable │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ Cosmos DB Client Module │
│ - Singleton container initialization │
│ - Dual auth: DefaultAzureCredential (Azure) / Key (emulator) │
│ - Async wrapper via run_in_threadpool │
└─────────────────────────────────────────────────────────────────┘
```
## Quick Start
### 1. Client Module Setup
Create a singleton Cosmos client with dual authentication:
```python
# db/cosmos.py
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential
from starlette.concurrency import run_in_threadpool
_cosmos_container = None
def _is_emulator_endpoint(endpoint: str) -> bool:
return "localhost" in endpoint or "127.0.0.1" in endpoint
async def get_container():
global _cosmos_container
if _cosmos_container is None:
# Singleton: client lives for the FastAPI app lifetime; close in a lifespan shutdown handler.
if _is_emulator_endpoint(settings.cosmos_endpoint):
client = CosmosClient(
url=settings.cosmos_endpoint,
credential=settings.cosmos_key,
connection_verify=False
)
else:
client = CosmosClient(
url=settings.cosmos_endpoint,
credential=DefaultAzureCredential()
)
db = client.get_database_client(settings.cosmos_database_name)
_cosmos_container = db.get_container_client(settings.cosmos_container_id)
return _cosmos_container
```
**Full implementation**: See [references/client-setup.md](references/client-setup.md)
### 2. Pydantic Model Hierarchy
Use five-tier model pattern for clean separation:
```python
class ProjectBase(BaseModel): # Shared fields
name: str = Field(..., min_length=1, max_length=200)
class ProjectCreate(ProjectBase): # Creation request
workspace_id: str = Field(..., alias="workspaceId")
class ProjectUpdate(BaseModel): # Partial updates (all optional)
name: Optional[str] = Field(None, min_length=1)
class Project(ProjectBase): # API response
id: str
created_at: datetime = Field(..., alias="createdAt")
class ProjectInDB(Project): # Internal with docType
doc_type: str = "project"
```
### 3. Service Layer Pattern
```python
class ProjectService:
def _use_cosmos(self) -> bool:
return get_container() is not None
async def get_by_id(self, project_id: str, workspace_id: str) -> Project | None:
if not self._use_cosmos():
return None
doc = await get_document(project_id, partition_key=workspace_id)
if doc is None:
return None
return self._doc_to_model(doc)
```
**Full patterns**: See [references/service-layer.md](references/service-layer.md)
## Core Principles
### Security Requirements
1. **RBAC Authentication**: Use `DefaultAzureCredential` in Azure — never store keys in code
2. **Emulator-Only Keys**: Hardcode the well-known emulator key only for local development
3. **Parameterized Queries**: Always use `@parameter` syntax — never string concatenation
4. **Partition Key Validation**: Validate partition key access matches user authorization
### Clean Code Conventions
1. **Single Responsibility**: Client module handles connection; services handle business logic
2. **Graceful Degradation**: Services return `None`/`[]` when Cosmos unavailable
3. **Consistent Naming**: `_doc_to_model()`, `_model_to_doc()`, `_use_cosmos()`
4. **Type Hints**: Full typing on all public methods
5. **CamelCase Aliases**: Use `Field(alias="camelCase")` for JSON serialization
### TDD Requirements
Write tests BEFORE implementation using these patterns:
```python
@pytest.fixture
def mock_cosmos_container(mocker):
container = mocker.MagicMock()
mocker.patch("app.db.cosmos.get_container", return_value=container)
return container
@pytest.mark.asyncio
async def test_get_project_by_id_returns_project(mock_cosmos_container):
# Arrange
mock_cosmos_container.read_item.return_value = {"id": "123", "name": "Test"}
# Act
result = await project_service.get_by_id("123", "workspace-1")
# Assert
assert result.id == "123"
assert result.name == "Test"
```
**Full testing guide**: See [references/testing.md](references/testing.md)
## Best Practices
1. **This skill uses async throughout (`azure.cosmos.aio`); do not mix with the sync `azure.cosmos` client.** Keep the whole FastAPI request path async — don't pair sync Cosmos calls with async handlers.
2. **Always use context managers for clients and async credentials.** Wrap the client in `async with CosmosClient(...) as client:` (or manage its lifetime via FastAPI lifespan and close it explicitly). For async `DefaultAzureCredential` from `azure.identity.aio`, also use `async with credential:` so tokens and transports are cleaned up.
## Reference Files
| File | When to Read |
|------|--------------|
| [references/client-setup.md](references/client-setup.md) | Setting up Cosmos client with dual auth, SSL config, singleton pattern |
| [references/service-layer.md](references/service-layer.md) | Implementing full service class with CRUD, conversions, graceful degradation |
| [references/testing.md](references/testing.md) | Writing pytest tests, mocking Cosmos, integration test setup |
| [references/partitioning.md](references/partitioning.md) | Choosing partition keys, cross-partition queries, move operations |
| [references/error-handling.md](references/error-handling.md) | Handling CosmosResourceNotFoundError, logging, HTTP error mapping |
## Template Files
| File | Purpose |
|------|---------|
| [assets/cosmos_client_template.py](assets/cosmos_client_template.py) | Ready-to-use client module |
| [assets/service_template.py](assets/service_template.py) | Service class skeleton |
| [assets/conftest_template.py](assets/conftest_template.py) | pytest fixtures for Cosmos mocking |
## Quality Attributes (NFRs)
### Reliability
- Graceful degradation when Cosmos unavailable
- Retry logic with exponential backoff for transient failures
- Connection pooling via singleton pattern
### Security
- Zero secrets in code (RBAC via DefaultAzureCredential)
- Parameterized queries prevent injection
- Partition key isolation enforces data boundaries
### Maintainability
- Five-tier model pattern enables schema evolution
- Service layer decouples business logic from storage
- Consistent patterns across all entity services
### Testability
- Dependency injection via `get_container()`
- Easy mocking with module-level globals
- Clear separation enables unit testing without Cosmos
### Performance
- Partition key queries avoid cross-partition scans
- Async wrapping prevents blocking FastAPI event loop
- Minimal document conversion overhead
Todos os arquivos
0 arquivosInstalar azure-cosmos-db-py
Baixe e descompacte os arquivos de habilidades no diretório .claude/skills/.
Baixar ZIPClone o repositório e copie os arquivos da habilidade para o seu projeto.
git clone https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-python/skills/azure-cosmos-db-py # Copy SKILL.md to your .claude/skills/ directory
Copiar





Lar
