dsp-job-data-migration — Validação pós-migração¶
Checklist e consultas para confirmar que a migração via dsp-job-data-migration concluiu com sucesso e que o destino está consistente.
Quando validar¶
| Momento | Objetivo |
|---|---|
| Após cada job (L1, L2, L3, área de interesse, camadas, kpi-job) | Isolar problemas por nível |
Após a sequência completa (incluindo kpiCalculationJob) |
Confirmar base pronta para o DSP e KPIs na Home |
| Antes de liberar GeoServer/API | Evitar publicação de dados incompletos |
Checklist rápido¶
- Última execução do job com
status = COMPLETED - Sem steps
FAILEDemBATCH_STEP_EXECUTION - Watermark gravado em
BATCH_JOB_EXECUTION_SYNC_STATEpara osync-keydo job - Contagem do destino coerente com a origem (respeitando
where-clausee o recorte do watermark) - PK/unique presentes nas colunas de conflito
- Amostra de geometrias com
ST_IsValide SRID conformesriddo YAML — em ambos os destinos (dsp-db: bbox/centroid;geoserver-db:geom) - FKs de hierarquia resolvidas (se aplicável)
- Layer GeoServer aponta para a tabela/view correta
-
kpiCalculationJobcomstatus = COMPLETED(quandokpi-jobhabilitado) -
dsp.area_of_interest.areapreenchida onde há geometria no geo-target -
dsp.kpi_measurecoerente comtheme-counte camadas configuradas
1. Status do Spring Batch¶
Conecte no banco de destino (spring.datasource.target / dsp-db), schema data_migration:
Últimas execuções¶
SELECT i.job_name,
e.status,
e.exit_code,
e.start_time,
e.end_time
FROM batch_job_execution e
JOIN batch_job_instance i
ON e.job_instance_id = i.job_instance_id
ORDER BY e.job_execution_id DESC
LIMIT 20;
A linha mais recente deve estar COMPLETED. Se aparecer FAILED, use a consulta de steps abaixo e os logs da aplicação para achar a causa.
Steps da última execução de um job¶
SELECT se.step_name,
se.status,
se.read_count,
se.write_count,
se.skip_count,
se.exit_message
FROM batch_step_execution se
JOIN batch_job_execution je
ON se.job_execution_id = je.job_execution_id
JOIN batch_job_instance ji
ON je.job_instance_id = ji.job_instance_id
WHERE ji.job_name = 'adminUnitLevel1GeoserverJob'
ORDER BY se.step_execution_id DESC
LIMIT 20;
Nomes dos jobs
Use o nome do bean (adminUnitLevel1GeoserverJob, etc.), não a flag execution-jobs em kebab-case.
Watermark incremental¶
SELECT sync_key,
source_table,
watermark_last_event_at,
last_success_at,
last_orphan_check_at,
last_job_execution_id
FROM data_migration.BATCH_JOB_EXECUTION_SYNC_STATE
ORDER BY sync_key;
| Leitura | Significado |
|---|---|
watermark_last_event_at nulo |
Ainda não houve carga COMPLETED com delta |
last_orphan_check_at antigo (> 24 h) |
A próxima execução deve varrer órfãos |
Job COMPLETED mas watermark igual |
Sem delta temporal (SKIP ou só órfãos) |
Para reprocessar do zero um job, apague a linha do sync-key correspondente (e, se precisar, os dados do destino).
2. Contagens origem × destino¶
Valide os dois destinos após cada job. Adapte schema/tabela ao seu YAML. No contrato oficial do DSP:
dsp-db (operacional — sem geom completa)¶
geoserver-db (geometria completa)¶
A primeira carga deve refletir a origem filtrada por where-clause e creation-date-column IS NOT NULL. Cargas seguintes só entram registros novos ou atualizados depois do watermark; órfãos saem no scan periódico.
3. Integridade de chave e órfãos¶
PK no destino¶
SELECT tc.constraint_type, kcu.column_name
FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu
ON tc.constraint_name = kcu.constraint_name
AND tc.table_schema = kcu.table_schema
WHERE tc.table_schema = 'dsp'
AND tc.table_name = 'territory_level_1'
AND tc.constraint_type IN ('PRIMARY KEY', 'UNIQUE');
IDs e FKs no destino oficial são VARCHAR (territory_level_*: varchar(64); AOI/camadas: varchar(255) no id).
4. Geometrias¶
geoserver-db — geom completa¶
SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE NOT ST_IsValid(geom)) AS invalidas,
COUNT(*) FILTER (WHERE ST_SRID(geom) <> 4326) AS srid_diferente,
COUNT(*) FILTER (WHERE geom IS NULL) AS nulas
FROM dsp.territory_level_1;
Substitua 4326 pelo valor de srid do bloco YAML correspondente. AOI e camadas também usam geom.
dsp-db — bbox e centroid¶
SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE NOT ST_IsValid(boundary_box)) AS bbox_invalidas,
COUNT(*) FILTER (WHERE ST_SRID(boundary_box) <> 4326) AS bbox_srid_diferente,
COUNT(*) FILTER (WHERE NOT ST_IsValid(centroid_coordinates)) AS centroid_invalidos,
COUNT(*) FILTER (WHERE ST_SRID(centroid_coordinates) <> 4326) AS centroid_srid_diferente
FROM dsp.territory_level_1;
| Verificação | Critério de aceite |
|---|---|
invalidas |
0 (ou lista conhecida tratada à parte) |
srid_diferente |
0 em relação ao srid do YAML |
nulas |
Compatível com regras de negócio |
5. Hierarquia entre levels¶
SELECT c.id, c.parent_id
FROM dsp.territory_level_2 c
LEFT JOIN dsp.territory_level_1 p
ON p.id = c.parent_id
WHERE p.id IS NULL
LIMIT 50;
Repita o padrão para level-3 → level-2. AOI: territory_level_3_id deve existir em dsp.territory_level_3.
6. Paralelização e performance¶
| Sinal | Interpretação |
|---|---|
write_count muito menor que esperado |
Filtros de geometria / skips no writer / só delta do watermark |
| Muitos erros de conexão | thread-pool-size maior que o pool Hikari |
Job lento com thread-pool-size: 1 |
Esperado em tabelas grandes |
SKIP imediato |
Sem delta temporal — confirme se a origem realmente mudou depois do watermark |
7. KPI job (kpiCalculationJob)¶
Confirme a última execução do bean kpiCalculationJob (não confundir com a flag kebab-case kpi-job):
SELECT i.job_name, e.status, e.exit_code, e.start_time, e.end_time
FROM data_migration.batch_job_execution e
JOIN data_migration.batch_job_instance i ON e.job_instance_id = i.job_instance_id
WHERE i.job_name = 'kpiCalculationJob'
ORDER BY e.job_execution_id DESC
LIMIT 5;
Área da AOI (dsp-db)¶
SELECT COUNT(*) AS total,
COUNT(area) AS com_area,
COUNT(*) FILTER (WHERE area IS NOT NULL AND area > 0) AS area_positiva
FROM dsp.area_of_interest;
Compare com geometrias válidas no geo-target:
Medidas de tema (kpi_measure)¶
SELECT kpi_name, COUNT(*) AS registros, SUM(value) AS soma
FROM dsp.kpi_measure
GROUP BY kpi_name
ORDER BY kpi_name;
Com theme-count: 0, espere zero linhas após o truncate. Com temas habilitados, cada kpi_name deve corresponder ao layer-name do YAML e ao card.layer no installation-config.json.
8. GeoServer¶
| Checagem | Como |
|---|---|
| Layer existe | UI/REST do GeoServer com o mesmo layer-name do YAML |
| Store aponta para geoserver-db | Conferir datastore JDBC/PostGIS → dsp-geoserver-db (não dsp-db) |
| Preview WMS | Bounding box coerente com a amostra SQL do geoserver-db |
Sinais de falha frequentes¶
| Sintoma | Causa provável | Correção |
|---|---|---|
batch_job_instance does not exist |
Schema BATCH ausente | Rodar 01_spring_batch_schema.sql |
Erro ON CONFLICT |
Sem PK/unique no destino | Criar constraint |
| Contagem destino = 0 | Job em SKIP, flags false, JDBC errado ou watermark já avançado | Revisar execution-jobs, URLs e SYNC_STATE |
| Geometrias nulas | Mapping da coluna geom incorreto | Revisar geometry-column / column-mapping (destino: geom) |
| FK quebrada entre levels | Ordem invertida ou L1 incompleto | Reexecutar L1 → L2 → L3 |
| App sobe e encerra "ok" sem dados | Nenhuma flag true |
Habilitar ao menos um job |
| Incremental “atrasado” | updated-at-column nula ou ausente |
Preencher a coluna ou resetar o sync-key |
| Cards de tema vazios ou ausentes na Home | kpi-job não rodou, theme-count diferente das camadas, ou backend com cache antigo |
Conferir kpiCalculationJob COMPLETED; alinhar kpis.themes[].layer-name com as camadas migradas; reiniciar dsp-backend após ./config.sh |
| Área da AOI zerada ou nula | Geometria ausente/inválida no geo-target ou KPI job não executado | Conferir geom em dsp.area_of_interest no geoserver-db; rodar kpi-job |
Visão do job: Visão geral.