Um sistema completo de gestão de tarefas implementado com Azure Functions usando .NET 8 e Isolated Worker Model, demonstrando arquitetura limpa, padrões de design e boas práticas de desenvolvimento.
O projeto implementa uma arquitetura limpa com separação de responsabilidades:
TaskManagement.Functions/
├── Functions/ # Azure Functions (HTTP, Timer, Queue, Blob triggers)
├── Models/ # Modelos de dados e DTOs
├── Services/ # Lógica de negócio
├── Repositories/ # Padrão Repository para acesso a dados
├── Interfaces/ # Contratos e abstrações
├── Validators/ # Validações com FluentValidation
├── Mapping/ # Perfis do AutoMapper
├── Middleware/ # Middleware customizado
└── Tests/ # Testes unitários e de integração
GET /api/tasks
- Listar todas as tarefasGET /api/tasks/{id}
- Obter tarefa específicaPOST /api/tasks
- Criar nova tarefaPUT /api/tasks/{id}
- Atualizar tarefaDELETE /api/tasks/{id}
- Remover tarefaGET /api/tasks/status/{status}
- Filtrar por status
TimerCleanupFunction
- Limpeza automática de tarefas antigas (diariamente às 02:00 UTC)DailyTaskSummary
- Relatório diário de tarefas (diariamente às 08:00 UTC)
ProcessTaskFunction
- Processamento de mensagens da fila de tarefas
ProcessTaskAttachmentFunction
- Processamento de anexos de tarefas
public class TaskModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public TaskStatus Status { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? CompletedAt { get; set; }
public string AssignedTo { get; set; }
public List<string> Tags { get; set; }
}
public enum TaskStatus
{
Pending,
InProgress,
Completed,
Cancelled
}
git clone <repository-url>
cd exemplo2
dotnet restore
# Instalar Azurite globalmente
npm install -g azurite
# Iniciar Azurite
azurite --silent --location c:\\azurite --debug c:\\azurite\\debug.log
Edite o arquivo local.settings.json
e adicione sua connection string:
{
"Values": {
"APPLICATIONINSIGHTS_CONNECTION_STRING": "sua-connection-string-aqui"
}
}
func start --port 7071
A API estará disponível em: http://localhost:7071
# Todos os testes
dotnet test
# Apenas testes unitários
dotnet test --filter "Category=Unit"
# Apenas testes de integração
dotnet test --filter "Category=Integration"
# Com cobertura de código
dotnet test --collect:"XPlat Code Coverage"
GET /api/tasks
GET /api/tasks/{id}
POST /api/tasks
Content-Type: application/json
{
"title": "Nova Tarefa",
"description": "Descrição da tarefa",
"assignedTo": "usuario@exemplo.com",
"tags": ["urgente", "projeto-x"]
}
PUT /api/tasks/{id}
Content-Type: application/json
{
"title": "Título Atualizado",
"status": "InProgress"
}
DELETE /api/tasks/{id}
GET /api/tasks/status/{status}
Statuses válidos: Pending
, InProgress
, Completed
, Cancelled
Todas as respostas seguem o padrão:
{
"success": true,
"message": "Operação realizada com sucesso",
"data": { /* dados da resposta */ },
"errors": []
}
Use o arquivo requests.http
incluído no projeto para testar todos os endpoints:
# No VS Code com extensão REST Client
# Abra o arquivo requests.http e execute as requisições
Variável | Descrição | Valor Padrão |
---|---|---|
AzureWebJobsStorage |
Connection string do Azure Storage | UseDevelopmentStorage=true |
FUNCTIONS_WORKER_RUNTIME |
Runtime das functions | dotnet-isolated |
APPLICATIONINSIGHTS_CONNECTION_STRING |
Application Insights | (vazio) |
TaskQueue |
Nome da fila de processamento | task-processing-queue |
TaskAttachmentsContainer |
Container de anexos | task-attachments |
- Tratamento Global de Exceções: Captura e trata erros automaticamente
- Validação Automática: FluentValidation integrado
- Logging Estruturado: Serilog com Application Insights
- AutoMapper: Mapeamento automático entre DTOs e Models
- CORS: Configurado para desenvolvimento
- Rate Limiting: Configurado no host.json
graph TB
A[Cliente HTTP] --> B[Azure Functions HTTP Triggers]
B --> C[TaskService]
C --> D[ITaskRepository]
D --> E[InMemoryTaskRepository]
F[Timer Trigger] --> C
G[Queue Trigger] --> C
H[Blob Trigger] --> C
I[AutoMapper] --> C
J[FluentValidation] --> B
K[Exception Middleware] --> B
L[Application Insights] --> B
L --> F
L --> G
L --> H
sequenceDiagram
participant C as Cliente
participant F as Function
participant V as Validator
participant S as Service
participant R as Repository
participant M as Mapper
C->>F: HTTP Request
F->>V: Validate DTO
V-->>F: Validation Result
F->>M: Map DTO to Model
M-->>F: Mapped Model
F->>S: Call Service Method
S->>R: Repository Operation
R-->>S: Data Result
S->>M: Map Model to DTO
M-->>S: Mapped DTO
S-->>F: Service Result
F-->>C: HTTP Response
- Criar Function App no Azure:
az functionapp create \
--resource-group myResourceGroup \
--consumption-plan-location westeurope \
--runtime dotnet-isolated \
--functions-version 4 \
--name myTaskManagementApp \
--storage-account mystorageaccount
- Deploy via Azure CLI:
func azure functionapp publish myTaskManagementApp
Para o CI/CD funcionar corretamente, configure os seguintes secrets no GitHub:
Para Produção (branch main):
AZUREAPPSERVICE_CLIENTID
AZUREAPPSERVICE_TENANTID
AZUREAPPSERVICE_SUBSCRIPTIONID
Para Desenvolvimento (branch develop):
AZUREAPPSERVICE_CLIENTID_DEV
AZUREAPPSERVICE_TENANTID_DEV
AZUREAPPSERVICE_SUBSCRIPTIONID_DEV
Adicione as seguintes configurações na Function App:
{
"APPLICATIONINSIGHTS_CONNECTION_STRING": "sua-connection-string",
"AzureWebJobsStorage": "sua-storage-connection-string",
"TaskQueue": "task-processing-queue",
"TaskAttachmentsContainer": "task-attachments"
}
- Fork o projeto
- Crie uma branch para sua feature (
git checkout -b feature/AmazingFeature
) - Commit suas mudanças (
git commit -m 'Add some AmazingFeature'
) - Push para a branch (
git push origin feature/AmazingFeature
) - Abra um Pull Request
Este projeto está sob a licença MIT. Veja o arquivo LICENSE
para mais detalhes.