Skip to content

renanparaujo/datarisk-api

Repository files navigation

Datarisk - API de Pré-processamento de Dados

Descrição

API REST em .NET 8 para execução segura de scripts JavaScript de pré-processamento de dados. Sistema robusto e funcional para transformação de dados financeiros.

Arquitetura

O sistema segue uma arquitetura em camadas com separação clara de responsabilidades:

  • Datarisk.Api: Controllers REST com tratamento de erro
  • Datarisk.Dominio: Entidades e interfaces do negócio
  • Datarisk.Infra: Persistência com EF Core e PostgreSQL
  • Datarisk.Servicos: Validação e execução de scripts
  • Datarisk.Processamento.Funcional: Demonstração com F# funcional
  • Datarisk.Tests: Testes unitários

Tecnologias

  • .NET 8: Framework principal
  • ASP.NET Core: API REST
  • PostgreSQL: Banco de dados
  • Entity Framework Core: ORM
  • Jint: Engine JavaScript segura
  • F#: Programação funcional
  • Docker: Containerização
  • xUnit: Testes unitários
  • Swagger: Documentação da API

Requisitos

  • Docker e Docker Compose
  • .NET 8 SDK (para desenvolvimento local)

Como Executar

Com Docker Compose (Recomendado)

# Clonar o repositório
git clone <repository-url>
cd Datarisk

# Executar com docker-compose
docker-compose up --build

# A API estará disponível em:
# - http://localhost:8080
# - Swagger: http://localhost:8080/docs

Desenvolvimento Local

# Restaurar dependências
dotnet restore

# Executar PostgreSQL via Docker
docker run --name postgres-datarisk -e POSTGRES_DB=datarisk -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres:16-alpine

# Executar migrations
dotnet ef database update --project Datarisk.Infra --startup-project Datarisk.Api

# Executar a aplicação
dotnet run --project Datarisk.Api

# Executar testes
dotnet test

Endpoints da API

Scripts

POST /api/scripts

Cria um novo script JavaScript.

curl -X POST http://localhost:8080/api/scripts \
  -H "Content-Type: application/json" \
  -d '{
    "nome": "ProcessadorEmpresarial",
    "conteudoJs": "function process(data) { const corporativeData = data.filter(item => item.produto === \"Empresarial\"); const byQuarterAndIssuer = corporativeData.reduce((acc, item) => { const key = \`\${item.trimestre}-\${item.nomeBandeira}\`; if (!acc[key]) { acc[key] = { trimestre: item.trimestre, nomeBandeira: item.nomeBandeira, qtdCartoesEmitidos: 0, qtdCartoesAtivos: 0, qtdTransacoesNacionais: 0, valorTransacoesNacionais: 0 }; } acc[key].qtdCartoesEmitidos += item.qtdCartoesEmitidos; acc[key].qtdCartoesAtivos += item.qtdCartoesAtivos; acc[key].qtdTransacoesNacionais += item.qtdTransacoesNacionais; acc[key].valorTransacoesNacionais += item.valorTransacoesNacionais; return acc; }, {}); return Object.values(byQuarterAndIssuer); }"
  }'

GET /api/scripts

Lista todos os scripts cadastrados.

curl http://localhost:8080/api/scripts

GET /api/scripts/{id}

Obtém um script específico por ID.

curl http://localhost:8080/api/scripts/{script-id}

Execuções

POST /api/execucoes

Executa um script com dados específicos.

curl -X POST http://localhost:8080/api/execucoes \
  -H "Content-Type: application/json" \
  -d '{
    "idScript": "{script-id}",
    "dados": [
      {
        "produto": "Empresarial",
        "trimestre": "2024Q1",
        "nomeBandeira": "Visa",
        "qtdCartoesEmitidos": 1000,
        "qtdCartoesAtivos": 800,
        "qtdTransacoesNacionais": 5000,
        "valorTransacoesNacionais": 100000.50
      },
      {
        "produto": "Empresarial",
        "trimestre": "2024Q1",
        "nomeBandeira": "Mastercard",
        "qtdCartoesEmitidos": 750,
        "qtdCartoesAtivos": 600,
        "qtdTransacoesNacionais": 3500,
        "valorTransacoesNacionais": 75000.25
      }
    ]
  }'

GET /api/execucoes/{id}

Consulta status e resultado de uma execução.

curl http://localhost:8080/api/execucoes/{execucao-id}

Health Checks

GET /api/health/healthz

curl http://localhost:8080/api/health/healthz

GET /api/health/readiness

curl http://localhost:8080/api/health/readiness

Exemplo de Script JavaScript

O script deve expor uma função process que recebe dados JSON e retorna o resultado processado:

function process(data) {
    // Filtrar apenas dados empresariais
    const corporativeData = data.filter(item => item.produto === "Empresarial");

    // Agrupar por trimestre e bandeira
    const byQuarterAndIssuer = corporativeData.reduce((acc, item) => {
        const key = `${item.trimestre}-${item.nomeBandeira}`;
        if (!acc[key]) {
            acc[key] = {
                trimestre: item.trimestre,
                nomeBandeira: item.nomeBandeira,
                qtdCartoesEmitidos: 0,
                qtdCartoesAtivos: 0,
                qtdTransacoesNacionais: 0,
                valorTransacoesNacionais: 0
            };
        }
        acc[key].qtdCartoesEmitidos += item.qtdCartoesEmitidos;
        acc[key].qtdCartoesAtivos += item.qtdCartoesAtivos;
        acc[key].qtdTransacoesNacionais += item.qtdTransacoesNacionais;
        acc[key].valorTransacoesNacionais += item.valorTransacoesNacionais;
        return acc;
    }, {});

    return Object.values(byQuarterAndIssuer);
}

Fluxo Completo

  1. Criar Script: Use POST /api/scripts para cadastrar um script JavaScript
  2. Verificar Script: Use GET /api/scripts/{id} para confirmar que foi criado
  3. Executar Script: Use POST /api/execucoes com dados de entrada
  4. Monitorar Execução: Use GET /api/execucoes/{id} para acompanhar o progresso
  5. Obter Resultado: Quando status for "Sucesso", o campo resultadoJson terá o resultado

Segurança

  • Scripts executam em sandbox Jint sem acesso ao sistema operacional
  • Validação de padrões perigosos (require, import, eval, etc.)
  • Limite de tempo de execução (5 segundos)
  • Limite de tamanho do script (100KB)
  • Limite de payload de dados (5MB)
  • Timeout e tratamento de exceções

Estrutura do Banco

Tabela: scripts

  • id (UUID): Identificador único
  • nome (varchar): Nome do script
  • conteudo_js (text): Código JavaScript
  • criado_em (timestamp): Data de criação
  • valido (bool): Se passou na validação
  • hash_conteudo (varchar): Hash do conteúdo

Tabela: execucoes

  • id (UUID): Identificador único
  • script_id (UUID): Referência ao script
  • status (enum): PENDENTE|EM_EXECUCAO|SUCESSO|FALHA
  • resultado_json (jsonb): Resultado da execução
  • erro (text): Mensagem de erro se houver
  • criado_em (timestamp): Data de criação
  • iniciado_em (timestamp): Início da execução
  • finalizado_em (timestamp): Fim da execução
  • tempo_execucao_ms (int): Tempo em milissegundos

Logs e Monitoramento

  • Logs estruturados com correlação por request ID
  • Métricas de tempo de execução
  • Health checks em /api/health/healthz e /api/health/readiness
  • Documentação automática em /docs

Troubleshooting

Container não inicia

# Verificar logs
docker-compose logs api

# Verificar se PostgreSQL está rodando
docker-compose logs postgres

Erro de conexão com banco

# Verificar se o banco está acessível
docker-compose exec postgres pg_isready -U postgres

# Recriar containers
docker-compose down -v
docker-compose up --build

Script não executa

  • Verifique se contém função process
  • Verifique se não usa padrões proibidos
  • Consulte logs da aplicação para detalhes

Desenvolvimento

Adicionando Nova Funcionalidade

  1. Adicione entidades no projeto Dominio
  2. Implemente repositórios na Infra
  3. Crie serviços na camada Servicos
  4. Exponha via controllers na Api
  5. Adicione testes unitários

Executando Testes

dotnet test --logger trx --results-directory ./TestResults

Migrations

# Adicionar nova migration
dotnet ef migrations add NomeDaMigration --project Datarisk.Infra --startup-project Datarisk.Api

# Aplicar migrations
dotnet ef database update --project Datarisk.Infra --startup-project Datarisk.Api

Principais Arquivos

  • Program.cs: Configuração da aplicação e DI
  • DatariskDbContext.cs: Contexto do Entity Framework
  • ExecutorScript.cs: Execução segura de JavaScript
  • ProcessadorExecucao.cs: Serviço de execução
  • docker-compose.yml: Orquestração dos containers
  • Library.fs: Implementação funcional F# equivalente

Datarisk - Sistema robusto e seguro para processamento de dados financeiros com JavaScript.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors