Documenta: - Arquitetura implementada (4 componentes) - Estrutura de código (Clean Architecture) - Problema atual (Componente B = 0 por rede) - Soluções propostas (script standalone) - Comandos úteis e validações - Status: 95% completo, falta resolver acesso rede CAPES
12 KiB
Resumo do Projeto - Ranking de 350k Consultores CAPES
O QUE FOI FEITO
✅ Sistema de Ranking Completo Implementado
Objetivo: Classificar TODOS os 300k+ consultores CAPES (governo federal, vai para auditoria)
Arquitetura implementada:
Elasticsearch (ATUACAPES) → Busca 350k consultores com atuações
↓
Oracle REMOTO (CAPES) → Busca coordenações PPG (SUCUPIRA_PAINEL)
↓
Backend Python → Calcula pontuação A+B+C+D
↓
Oracle LOCAL (Docker) → Salva em TB_RANKING_CONSULTOR (cache)
↓
Frontend → Lê tabela paginada (50 por página)
COMPONENTES DE PONTUAÇÃO (Documento Oficial CAPES)
Componente A - Coordenação CAPES (máx 450 pts)
- CA, CAJ, CAJ-MP, CAM
- Base + tempo + áreas extras + bônus ativo + retorno
- ✅ IMPLEMENTADO E FUNCIONANDO
Componente B - Coordenação de Programa PPG (máx 180 pts)
- Base: 70 pts
- Tempo: 5 pts/ano (máx 50)
- Programas extras: 20 pts/programa (máx 40)
- Nota PPG: 7=20, 6=15, 5=10, 4=5, 3=0 (máx 20)
- ✅ CÓDIGO IMPLEMENTADO MAS NÃO FUNCIONA (problema de rede)
Componente C - Consultoria (máx 230 pts)
- Consultor ativo/histórico + tempo + eventos + áreas
- ✅ IMPLEMENTADO E FUNCIONANDO
Componente D - Premiações (máx 180 pts)
- Premiações recebidas + avaliações + inscrições
- ✅ IMPLEMENTADO E FUNCIONANDO
ARQUITETURA DO CÓDIGO
Camadas (Clean Architecture)
backend/
├── src/
│ ├── domain/ # Entidades e regras de negócio
│ │ ├── entities/
│ │ │ └── consultor.py # Consultor, Coordenação, Consultoria, etc
│ │ ├── services/
│ │ │ └── calculador_pontuacao.py # CÁLCULO DOS 4 COMPONENTES
│ │ └── value_objects/
│ │ └── pontuacao.py # ComponentePontuacao, PontuacaoCompleta
│ │
│ ├── application/ # Casos de uso e jobs
│ │ ├── use_cases/
│ │ │ └── obter_ranking.py
│ │ └── jobs/
│ │ ├── processar_ranking.py # JOB PRINCIPAL (350k)
│ │ ├── job_status.py # Status em tempo real
│ │ └── scheduler.py # Loop asyncio (sem cron)
│ │
│ ├── infrastructure/ # Acesso a dados
│ │ ├── elasticsearch/
│ │ │ └── client.py # Scroll API para 350k
│ │ ├── oracle/
│ │ │ ├── client.py # OracleClient genérico
│ │ │ └── ranking_repository.py # CRUD da TB_RANKING_CONSULTOR
│ │ └── repositories/
│ │ └── consultor_repository_impl.py # Constrói consultores
│ │
│ └── interface/ # API REST
│ └── api/
│ ├── app.py # FastAPI + lifespan (conecta Oracles)
│ ├── routes.py # Endpoints
│ ├── dependencies.py # DUAS CONEXÕES ORACLE
│ └── config.py # Settings (lê .env)
│
├── sql/
│ ├── schema_ranking.sql # TB_RANKING_CONSULTOR + SP_ATUALIZAR_POSICOES
│ └── schema_ppg.sql # TB_COORDENACAO_PROGRAMA (não usado)
│
└── scripts/
└── popular_componente_b.py # Script emergencial (roda no host)
BANCO DE DADOS
TB_RANKING_CONSULTOR (Oracle LOCAL)
CREATE TABLE TB_RANKING_CONSULTOR (
ID_PESSOA NUMBER(10) PRIMARY KEY,
NOME VARCHAR2(200),
POSICAO NUMBER(10),
PONTUACAO_TOTAL NUMBER(10,2),
COMPONENTE_A NUMBER(10,2),
COMPONENTE_B NUMBER(10,2), ← PROBLEMA: Está zerado
COMPONENTE_C NUMBER(10,2),
COMPONENTE_D NUMBER(10,2),
ATIVO CHAR(1),
ANOS_ATUACAO NUMBER(5,1),
DT_CALCULO TIMESTAMP,
JSON_DETALHES CLOB
);
Status atual: 350.215 registros com A, C, D calculados, mas B=0
CONFIGURAÇÃO (.env)
Desenvolvimento (atual)
# Elasticsearch
ES_URL=http://elastic-atuacapes.hom.capes.gov.br:9200
ES_INDEX=atuacapes
ES_USER=admin-atuacapes
ES_PASSWORD=O}!S0bj%FhJ:
# Oracle LOCAL (Docker) - Para salvar ranking
ORACLE_LOCAL_USER=local123
ORACLE_LOCAL_PASSWORD=local123
ORACLE_LOCAL_DSN=oracle18c:1521/XEPDB1
# Oracle REMOTO (CAPES) - Para ler SUCUPIRA_PAINEL
ORACLE_REMOTE_USER=FREDERICOAC
ORACLE_REMOTE_PASSWORD=FREDEricoac
ORACLE_REMOTE_DSN=oracledhtsrv02.hom.capes.gov.br:1521/hom_dr
Produção (futuro)
# Mesmo Oracle para tudo
ORACLE_LOCAL_DSN=oracle-prod.capes:1521/PROD
ORACLE_REMOTE_DSN=oracle-prod.capes:1521/PROD # Mesmo!
COMMITS IMPORTANTES
f69bcd9 - feat: Implementa job de ranking para 300k consultores
c6aaf66 - refactor: Substitui APScheduler por asyncio nativo para OCP
e11cdcd - feat: Implementa duas conexões Oracle simultâneas
57ef5a7 - fix: Corrige cálculo de pontuação da nota do PPG no Componente B
178fc2a - docs: Adiciona documentação completa do Componente B (PPG)
O PROBLEMA ATUAL
Componente B = 0 para todos os 350k consultores
Causa raiz:
Container Docker não consegue acessar oracledhtsrv02.hom.capes.gov.br porque:
- VPN CAPES está no HOST
- Container está em rede isolada
- DNS não resolve hostname interno da CAPES
Evidências:
# Dentro do container:
oracle_remote_client.is_connected = False
# Log do erro:
AVISO Oracle: ORA-12154: TNS:could not resolve the connect identifier specified
Resultado:
- Job processa 350k consultores ✅
- Componente A, C, D calculados ✅
- Componente B = 0 (não consulta Oracle REMOTO) ❌
SOLUÇÕES POSSÍVEIS
⭐ SOLUÇÃO 1: Script Standalone (RECOMENDADA - RÁPIDA)
Arquivo criado: backend/scripts/popular_componente_b.py
Como funciona:
- Roda DIRETO NO HOST (não no Docker)
- Usa VPN do host para acessar Oracle CAPES
- Lê 350k IDs da tabela
- Busca PPG do SUCUPIRA_PAINEL
- Atualiza COMPONENTE_B em batch de 1000
- Atualiza posições
Executar:
cd /home/fred/projetos/ranking/backend
pip3 install cx-Oracle # Se não tiver
python3 scripts/popular_componente_b.py
Tempo estimado: 20-40 minutos para 350k consultores
Vantagens:
- ✅ Resolve AGORA sem mexer em Docker
- ✅ Usa VPN que já está funcionando
- ✅ Roda 1x para corrigir os dados
- ✅ Depois o job normal funciona (quando tiver em produção)
SOLUÇÃO 2: Extra Hosts no Docker
# docker-compose.yml
backend:
extra_hosts:
- "oracledhtsrv02.hom.capes.gov.br:IP_DO_SERVIDOR"
Precisa: Descobrir o IP real de oracledhtsrv02.hom.capes.gov.br
nslookup oracledhtsrv02.hom.capes.gov.br
SOLUÇÃO 3: Network Mode Host
# docker-compose.yml
backend:
network_mode: "host" # Usa rede do host
Problema: Perde isolamento, pode conflitar portas
FRONTEND
Funcionalidades Implementadas
2 Modos de visualização:
-
Top N (Rápido)
- Endpoint:
/api/v1/ranking/detalhado?limite=100 - Busca do Elasticsearch + calcula na hora
- Bom para top 10/50/100/500
- Endpoint:
-
Ranking Completo (300k)
- Endpoint:
/api/v1/ranking/paginado?page=1&size=50 - Lê
TB_RANKING_CONSULTORdireto - Paginação: 350k consultores, 70k páginas
- Endpoint:
Componentes:
- ✅
RankingPaginado.jsx- Tabela com paginação - ✅
App.jsx- Seletor de modo - ✅ Barra de progresso do job em tempo real
- ✅ Estatísticas (total, ativos, média, distribuição)
- ✅ Botão reprocessar
Acesso: http://localhost:5173
JOB DE PROCESSAMENTO
Scheduler (asyncio nativo - sem cron)
Arquivo: backend/src/application/jobs/scheduler.py
Como funciona:
# Calcula tempo até 3h da manhã
proxima_execucao = datetime.now().replace(hour=3, minute=0)
await asyncio.sleep(segundos_ate_proxima)
await job.executar(limpar_antes=True)
# Loop infinito
Execução:
- Automática: Diariamente às 3h
- Manual:
POST /api/v1/ranking/processar
Compatível com OCP/Kubernetes (não usa cron do sistema)
PERFORMANCE
Máquina atual:
- CPU: 5.8GHz boost
- RAM: 64GB DDR5
- Processamento: ~350k consultores em 25-30 minutos
Batch:
- 1.000 consultores por batch
- ~350 batches total
- MERGE (upsert) em batch
O QUE PRECISA SER FEITO PARA CONCLUIR
🎯 ÚNICO PROBLEMA: Componente B zerado
Situação:
- ✅ Código do Componente B está correto e implementado
- ✅ Duas conexões Oracle configuradas
- ✅ Query SUCUPIRA_PAINEL pronta
- ❌ Container Docker não acessa rede CAPES
Solução mais rápida:
-
Rodar script standalone:
cd /home/fred/projetos/ranking/backend python3 scripts/popular_componente_b.py -
Ou configurar extra_hosts no docker-compose.yml:
# Descobrir IP: nslookup oracledhtsrv02.hom.capes.gov.br # Adicionar ao docker-compose.yml: backend: extra_hosts: - "oracledhtsrv02.hom.capes.gov.br:IP_AQUI" -
Depois rodar job completo:
curl -X POST -H "Content-Type: application/json" \ -d '{"limpar_antes": true}' \ http://localhost:8000/api/v1/ranking/processar
VALIDAÇÃO FINAL
Quando o Componente B funcionar, verificar:
-- Deve ter consultores com B > 0
SELECT
COUNT(*) AS TOTAL,
SUM(CASE WHEN COMPONENTE_B > 0 THEN 1 ELSE 0 END) AS COM_PPG,
MAX(COMPONENTE_B) AS MAX_B,
AVG(COMPONENTE_B) AS MEDIA_B
FROM TB_RANKING_CONSULTOR;
-- Ver top 5 com PPG
SELECT ID_PESSOA, NOME, COMPONENTE_A, COMPONENTE_B, COMPONENTE_C, COMPONENTE_D, PONTUACAO_TOTAL
FROM TB_RANKING_CONSULTOR
WHERE POSICAO <= 5
ORDER BY POSICAO;
Esperado: Alguns consultores com B entre 70-180 pts
DOCUMENTAÇÃO GERADA
COMPONENTE_B_STATUS.md- Implementação completa do Componente BSCHEDULER.md- Como funciona o scheduler sem cron (OCP)backend/sql/schema_ranking.sql- DDL da tabela principal.claude/rules/ranking-*.md- Regras oficiais e queries
COMANDOS ÚTEIS
Verificar tabela
echo "SELECT COUNT(*), AVG(COMPONENTE_B) FROM TB_RANKING_CONSULTOR;" | \
sqlplus -S local123/local123@127.0.0.1:1521/XEPDB1
Rodar job manualmente
curl -X POST -H "Content-Type: application/json" \
-d '{"limpar_antes": true}' \
http://localhost:8000/api/v1/ranking/processar
Ver status
curl -s http://localhost:8000/api/v1/ranking/status | python3 -m json.tool
Ver estatísticas
curl -s http://localhost:8000/api/v1/ranking/estatisticas | python3 -m json.tool
BRANCH E COMMITS
Branch: develop
Últimos commits:
178fc2a - docs: Adiciona documentação completa do Componente B (PPG)
57ef5a7 - fix: Corrige cálculo de pontuação da nota do PPG no Componente B
e11cdcd - feat: Implementa duas conexões Oracle simultâneas
f69bcd9 - feat: Implementa job de ranking para 300k consultores
c6aaf66 - refactor: Substitui APScheduler por asyncio nativo para OCP
RESUMO EXECUTIVO
Status Geral: 95% completo
Funciona:
- ✅ 350.215 consultores processados
- ✅ Componentes A, C, D calculados corretamente
- ✅ Paginação de 350k consultores
- ✅ Frontend com 2 modos (Top N + Completo)
- ✅ Scheduler asyncio para OCP
- ✅ Duas conexões Oracle configuradas
- ✅ Performance excelente (~30min para 350k)
Não funciona (1 problema):
- ❌ Componente B = 0 (Container não acessa rede CAPES)
Para resolver:
- Rodar
scripts/popular_componente_b.pyno host (20-40min) - OU configurar DNS/extra_hosts no docker-compose.yml
- OU deploy em servidor dentro da rede CAPES
Depois disso: Sistema 100% funcional e pronto para produção.
CONTEXTO IMPORTANTE
- Sistema para GOVERNO FEDERAL
- Vai passar por AUDITORIA
- Dados REAIS obrigatórios (zero mocks/fakes)
- Recursos CAPES intocáveis
- Documento técnico oficial deve ser seguido à risca
- Ambiente: OCP (sem cron disponível nos PODs)
PRÓXIMA SESSÃO - O QUE FAZER
- Verificar VPN CAPES ativa
- Rodar script:
python3 backend/scripts/popular_componente_b.py - Validar: Componente B > 0 em alguns consultores
- Testar frontend: http://localhost:5173
- Commit final e push
Tempo estimado: 30-60 minutos total