Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

CadastroPessoas-ViaCEP

Cadastro de Pessoas - ViaCEP

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

Desbravador – Teste Técnico: Cadastro de Pessoas

Visão geral da arquitetura

pascal
????????????????????????????????????????????????????????????????????????     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)

bash
docker run -d --name desbravador-pg \
  -e POSTGRES_DB=desbravador \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=123 \
  -p 5432:5432 \
  postgres:15

Configuração do banco

Execute o script SQL no banco criado:

bash
psql -U postgres -d desbravador -f database/01_create_tables.sql

Ou 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

ini
[Database]
Host=localhost
Port=5432
Database=desbravador
Username=postgres
Password=123

[Server]
Port=8080

bin\client.ini

ini
[Server]
Host=localhost
Port=8080

OpenSSL 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:

  1. 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)
  2. Extraia e copie para bin\:
    • libeay32.dll
    • ssleay32.dll
  3. Certifique-se de que libpq.dll (driver PostgreSQL) também está em bin\ ou no PATH do sistema. Com PostgreSQL instalado localmente, geralmente está em C:\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

  1. Abra project\DesbravadorServer.dpr no RAD Studio
  2. Compile (F9 ou Ctrl+F9)
  3. Copie o executável gerado para bin\ (ou configure o Output Directory do projeto para $(BDS)\bin\..\..\..\bin relativo ao projeto)
  4. Execute bin\DesbravadorServer.exe

O console deve exibir:

pascal
Banco de dados conectado.
Servidor iniciado na porta 8080. Pressione ENTER para encerrar.

Cliente

  1. Abra project\DesbravadorClient.dpr no RAD Studio
  2. Compile e execute
  3. O cliente lê bin\client.ini para 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:

pascal
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.Async

Endpoints 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

json
{
  "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:

json
{
  "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 CASCADE garante que endereços e dados ViaCEP são removidos junto com a pessoa
  • Service.Pessoa valida 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

pascal
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