CadastroPessoas-ViaCEP
Cadastro de Pessoas - ViaCEP
- Active · last change 6-26-2026
- ★ 1 on GitHub
README
Desbravador – Teste Técnico: Cadastro de Pessoas
Visão geral da arquitetura
???????????????????????????????????????????????????????????????????????? HTTP/JSON ????????????????????????????????????????????????????????????????????????????????????
??? Cliente (VCL App) ??? ?????????????????????????????????????????????????????? ??? Servidor REST (Indy) ???
??? DesbravadorClient ??? ??? DesbravadorServer ???
???????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????????
??? FireDAC
????????????????????????????????????????????????????????????????????????????????????
??? PostgreSQL ???
????????????????????????????????????????????????????????????????????????????????????Camadas
| Camada | Responsabilidade | Units principais |
|---|---|---|
| Shared | Modelos de domínio, interfaces e serialização | Model.Pessoa, Model.Endereco, Model.EnderecoIntegracao, Interfaces, REST.Serializer |
| DAL (Servidor) | Persistência com FireDAC + PostgreSQL | DAL.Connection, DAL.Pessoa.Repository, DAL.Endereco.Repository |
| Service (Servidor) | Regras de negócio e integração ViaCEP | Service.Pessoa, Service.ViaCEP |
| REST (Servidor) | HTTP Server Indy + roteamento | REST.Server, REST.Router |
| Client | Comunicação REST + View VCL | Client.REST, Client.Config, View.Principal |
Pré-requisitos
- RAD Studio CE 12 (Delphi 12 Alexandria)
- PostgreSQL 12+ instalado localmente (ou via Docker)
- OpenSSL com suporte a TLS 1.2 — ver seção específica abaixo
PostgreSQL via Docker (opção rápida)
docker run -d --name desbravador-pg \
-e POSTGRES_DB=desbravador \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=123 \
-p 5432:5432 \
postgres:15Configuração do banco
Execute o script SQL no banco criado:
psql -U postgres -d desbravador -f database/01_create_tables.sqlOu abra database/01_create_tables.sql no pgAdmin e execute.
Configuração via arquivos INI
As credenciais e portas são lidas de arquivos INI na pasta bin\. Não há nada hardcoded nos fontes.
bin\server.ini
[Database]
Host=localhost
Port=5432
Database=desbravador
Username=postgres
Password=123
[Server]
Port=8080bin\client.ini
[Server]
Host=localhost
Port=8080OpenSSL para ViaCEP (HTTPS / TLS 1.2)
O serviço ViaCEP exige TLS 1.2. As DLLs antigas que acompanham o Indy suportam apenas TLS 1.0 e causam erro tlsv1 alert protocol version.
Procedimento:
- Baixe os binários Win32 do OpenSSL compatíveis com Indy:
**https://github.com/IndySockets/OpenSSL-Binaries** → arquivo
openssl-1.0.2u-i386-win32.zip(ou similar) - Extraia e copie para
bin\:libeay32.dllssleay32.dll
- Certifique-se de que
libpq.dll(driver PostgreSQL) também está embin\ou no PATH do sistema. Com PostgreSQL instalado localmente, geralmente está emC:\Program Files\PostgreSQL\<versão>\bin\.
Compilação e execução
Os projetos já possuem todos os in clauses configurados nos .dpr — não é necessário configurar Search Path.
Servidor
- Abra
project\DesbravadorServer.dprno RAD Studio - Compile (F9 ou Ctrl+F9)
- Copie o executável gerado para
bin\(ou configure o Output Directory do projeto para$(BDS)\bin\..\..\..\binrelativo ao projeto) - Execute
bin\DesbravadorServer.exe
O console deve exibir:
Banco de dados conectado.
Servidor iniciado na porta 8080. Pressione ENTER para encerrar.Cliente
- Abra
project\DesbravadorClient.dprno RAD Studio - Compile e execute
- O cliente lê
bin\client.inipara localizar o servidor
Nota: execute o servidor antes de abrir o cliente. O cliente tenta carregar a lista de pessoas ao iniciar.
Dependências FireDAC (servidor)
As units abaixo já estão incluídas nos arquivos .pas e no .dpr. Listadas aqui para referência:
FireDAC.DApt // Registra factory de TFDQuery — obrigatório, sem isso ocorre erro de GUID
FireDAC.Phys.PG // Driver PostgreSQL
FireDAC.Phys.PGDef
FireDAC.VCLUI.Wait
FireDAC.Stan.AsyncEndpoints REST
| Método | Endpoint | Descrição | Status de retorno |
|---|---|---|---|
GET |
/pessoas |
Lista todas as pessoas | 200 |
GET |
/pessoas/{id} |
Busca pessoa por ID | 200 / 404 |
POST |
/pessoas |
Insere uma pessoa | 201 |
PUT |
/pessoas/{id} |
Atualiza uma pessoa | 200 |
DELETE |
/pessoas/{id} |
Remove uma pessoa | 200 |
POST |
/pessoas/lote |
Insere lista em lote (até 50 mil+) | 201 |
POST |
/enderecos/atualizar |
Dispara atualização ViaCEP (assíncrono) | 202 / 409 |
GET |
/enderecos/progresso |
Consulta progresso da atualização ViaCEP | 200 |
Exemplo de payload — POST /pessoas
{
"flnatureza": 1,
"dsdocumento": "123.456.789-09",
"nmprimeiro": "João",
"nmsegundo": "Silva",
"dtregistro": "2026-06-24",
"enderecos": [
{ "dscep": "01310-100" }
]
}POST /pessoas/lote — body é um array com o mesmo formato acima.
POST /enderecos/atualizar — retorna 202 imediatamente e inicia a atualização em background. Retorna 409 se uma atualização já estiver em andamento. O cliente faz polling em GET /enderecos/progresso a cada 1,5 s para exibir o progresso na barra de status e na progress bar.
GET /enderecos/progresso — retorna um snapshot thread-safe do estado atual:
{
"total": 120,
"concluidos": 45,
"erros": 2,
"em_processamento": true
}Decisões de design
Batch Insert (50.000 registros)
Utiliza query preparada com RETURNING idpessoa: a mesma query é preparada uma vez e executada registro a registro com Open/Close por linha, capturando o ID gerado para inserir os endereços vinculados em seguida. As inserções são agrupadas em chunks de 2.000 registros por transação, limitando o impacto de erros pontuais e evitando transações longas.
Nota: FireDAC ArrayDML não retorna IDs gerados pelo PostgreSQL (
RETURNING), por isso a abordagem de query preparada é necessária para vincular endereços ao ID recém-criado.
Thread Pool ViaCEP com deduplicação de CEPs
Antes de disparar as threads, o serviço agrupa todos os endereços por CEP único. Um banco com 9.907 endereços mas apenas ~120 CEPs distintos resulta em apenas ~120 chamadas HTTP ao ViaCEP. O resultado de cada CEP é aplicado a todos os registros do grupo em uma única transação.
O pool usa no máximo 3 threads simultâneas com delay de 500 ms entre lançamentos (~6 req/s máximo), respeitando os limites da API pública. Cada thread faz até 1 retry com backoff de 2 s em caso de falha. Threads gerenciadas com FreeOnTerminate = False + WaitFor para garante segura do pool.
Polling de progresso (cliente → servidor)
O cliente não bloqueia enquanto a atualização ViaCEP ocorre. Após receber o 202, um TTimer (1,5 s) consulta GET /enderecos/progresso e atualiza a progress bar e o status bar na thread principal via TThread.Synchronize. A interface fica travada (botões desabilitados individualmente para que a progress bar permaneça visível) até em_processamento retornar false.
Grid do cliente
Utiliza TDBGrid vinculado a um TFDMemTable criado em memória — sem conexão direta com banco no cliente. A lista é preenchida via chamada REST ao servidor.
Integridade de dados
ON DELETE CASCADEgarante que endereços e dados ViaCEP são removidos junto com a pessoaService.Pessoavalida campos obrigatórios e que toda pessoa tem ao menos um endereço antes de persistir- O cliente também valida: não é possível salvar sem ao menos um CEP na lista
Configuração externalizada
Credenciais e portas ficam em server.ini e client.ini na pasta bin\ — sem dados sensíveis nos fontes.
Estrutura de arquivos
Teste Desbravador/
????????? bin/
??? ????????? server.ini ??? configura????o do servidor (DB + porta)
??? ????????? client.ini ??? configura????o do cliente (host + porta do servidor)
??? ????????? libeay32.dll ??? OpenSSL TLS 1.2 (baixar manualmente)
??? ????????? ssleay32.dll ??? OpenSSL TLS 1.2 (baixar manualmente)
????????? database/
??? ????????? 01_create_tables.sql
????????? project/
??? ????????? DesbravadorServer.dpr / .dproj
??? ????????? DesbravadorClient.dpr / .dproj
????????? src/
??? ????????? Shared/
??? ??? ????????? Desbravador.Interfaces.pas
??? ??? ????????? Desbravador.Model.Pessoa.pas
??? ??? ????????? Desbravador.Model.Endereco.pas
??? ??? ????????? Desbravador.Model.EnderecoIntegracao.pas
??? ??? ????????? Desbravador.REST.Serializer.pas
??? ????????? Server/
??? ??? ????????? Desbravador.Config.pas
??? ??? ????????? DAL/
??? ??? ??? ????????? Desbravador.DAL.Connection.pas
??? ??? ??? ????????? Desbravador.DAL.Pessoa.Repository.pas
??? ??? ??? ????????? Desbravador.DAL.Endereco.Repository.pas
??? ??? ????????? Service/
??? ??? ??? ????????? Desbravador.Service.Pessoa.pas
??? ??? ??? ????????? Desbravador.Service.ViaCEP.pas
??? ??? ????????? REST/
??? ??? ????????? Desbravador.REST.Server.pas
??? ??? ????????? Desbravador.REST.Router.pas
??? ????????? Client/
??? ????????? Desbravador.Client.Config.pas
??? ????????? Desbravador.Client.REST.pas
??? ????????? View.Principal.pas
??? ????????? View.Principal.dfm
README.md
