FEAT: Adiciona validação caso endereço esteja acima do raio de 5000 no geogrid.

This commit is contained in:
tulioperdigao 2025-10-23 09:31:37 -03:00
parent 81ab094433
commit bb1b9912d9
3 changed files with 132 additions and 110 deletions

2
.env
View File

@ -1,5 +1,5 @@
GOOGLE_API_KEY="AIzaSyCTrRFGKCZSspHRmTWQiclmIEOg-LROgyo" GOOGLE_API_KEY="AIzaSyCTrRFGKCZSspHRmTWQiclmIEOg-LROgyo"
API_URL="https://plutao.geogridmaps.com.br/vale/api/v3/viabilidade/raio" API_URL="https://plutao.geogridmaps.com.br/vale/api/v3/viabilidade/raio"
API_KEY="6d717e972ba17c7cf0ab731801b8bbeac2f281e5" API_KEY="6d717e972ba17c7cf0ab731801b8bbeac2f281e5"
COKIE="PHPSESSID=6d717e972ba17c7cf0ab731801b8bbeac2f281e5" COOKIE="PHPSESSID=6d717e972ba17c7cf0ab731801b8bbeac2f281e5"
PORT="3000" PORT="3000"

10
app.js
View File

@ -80,6 +80,16 @@ function createApp() {
}); });
} }
} }
// quando a consulta não retorna um resultado válido, responder como 'Não viável'
// isso evita que a UI fique presa em "Consultando..." esperando uma resposta
return res.json({
endereco,
latitude: lat,
longitude: lon,
distancia: null,
dedicado: "Não viável",
naoDedicado: "Não viável",
});
} catch (err) { } catch (err) {
console.error(err); console.error(err);
return res.status(500).json({ error: "erro na consulta" }); return res.status(500).json({ error: "erro na consulta" });

View File

@ -23,25 +23,31 @@ const { normalizePartnerSigla } = require("./partnerSiglaService");
const MAX_RETRIES = 5; const MAX_RETRIES = 5;
async function getMinDistance(lat, lon) { async function getMinDistance(lat, lon) {
// tenta várias vezes com backoff exponencial; trata 429 usando Retry-After se disponível const radii = [5000, 10000, 20000];
for (const raio of radii) {
let attempt = 0; let attempt = 0;
while (attempt < MAX_RETRIES) { while (attempt < MAX_RETRIES) {
try { try {
// envia também o raio (em metros) - API espera esse parâmetro em várias rotas // observe que aqui enviamos itens[] como string simples (algumas APIs esperam isto)
const resp = await axios.get(API_URL, { const resp = await axios.get(API_URL, {
headers: HEADERS, headers: HEADERS,
params: { params: {
raio: 5000, raio,
latitude: lat, latitude: lat,
longitude: lon, longitude: lon,
"itens[]": ["caixa"], "itens[]": "caixa",
consultarPasta: "S", consultarPasta: "S",
}, },
timeout: 10000, timeout: 10000,
}); });
const data = resp.data;
const registros = data && data.registros ? data.registros : []; const data = resp.data || {};
// find registros that have a numeric distancia and keep original object for robust extraction const registros = data.registros || [];
console.info(
`[INFO] API resp. raio=${raio} lat=${lat} lon=${lon} registros=${registros.length}`
);
if (registros.length > 0) {
// same extraction logic as before
const candidates = registros const candidates = registros
.map((r) => ({ raw: r, distanciaRaw: r && r.distancia })) .map((r) => ({ raw: r, distanciaRaw: r && r.distancia }))
.map((o) => ({ .map((o) => ({
@ -58,7 +64,6 @@ async function getMinDistance(lat, lon) {
candidates.sort((a, b) => a.num - b.num); candidates.sort((a, b) => a.num - b.num);
const best = candidates[0]; const best = candidates[0];
const r = best.raw || {}; const r = best.raw || {};
// robust extraction of pasta sigla with fallbacks
let pastaSigla = null; let pastaSigla = null;
try { try {
if (r.pasta) { if (r.pasta) {
@ -76,7 +81,6 @@ async function getMinDistance(lat, lon) {
} catch (e) { } catch (e) {
pastaSigla = null; pastaSigla = null;
} }
// if closest has no pastaSigla, try find any candidate with non-empty sigla
if (!pastaSigla) { if (!pastaSigla) {
for (let j = 0; j < candidates.length; j++) { for (let j = 0; j < candidates.length; j++) {
const rr = candidates[j].raw || {}; const rr = candidates[j].raw || {};
@ -111,11 +115,18 @@ async function getMinDistance(lat, lon) {
pastaSigla = normalizePartnerSigla(pastaSigla); pastaSigla = normalizePartnerSigla(pastaSigla);
return { dist: best.num, pastaSigla }; return { dist: best.num, pastaSigla };
} }
// sem distancias válidas } else {
return null; // log mais detalhado para diagnóstico quando vazio
console.debug(
`[DEBUG] resposta vazia para raio=${raio} lat=${lat} lon=${lon} -> primeiroFragmento: ${JSON.stringify(
Array.isArray(data.registros) ? data.registros.slice(0, 3) : data
)}`
);
}
// sem distancias válidas para este raio -> tenta próximo raio
break;
} catch (err) { } catch (err) {
attempt += 1; attempt += 1;
// se for 429, tente respeitar Retry-After quando disponível
if (err.response && err.response.status === 429) { if (err.response && err.response.status === 429) {
const ra = const ra =
err.response.headers && err.response.headers &&
@ -132,8 +143,6 @@ async function getMinDistance(lat, lon) {
await sleep(waitMs); await sleep(waitMs);
continue; continue;
} }
// para outros erros de rede/timeout, aguarda backoff exponencial e tenta de novo
const waitMs = BASE_BACKOFF_MS * Math.pow(2, attempt - 1); const waitMs = BASE_BACKOFF_MS * Math.pow(2, attempt - 1);
console.warn( console.warn(
`[WARN] Erro ao consultar API para ${lat},${lon}: ${err.message} - backoff ${waitMs}ms (attempt ${attempt}/${MAX_RETRIES})` `[WARN] Erro ao consultar API para ${lat},${lon}: ${err.message} - backoff ${waitMs}ms (attempt ${attempt}/${MAX_RETRIES})`
@ -141,8 +150,11 @@ async function getMinDistance(lat, lon) {
await sleep(waitMs); await sleep(waitMs);
} }
} }
// exauriu tentativas // pequena espera entre mudanças de raio
console.error(`[ERROR] Exauriu retries para ${lat},${lon}`); await sleep(50);
}
console.error(`[ERROR] Sem registros válidos para ${lat},${lon} após todos os raios`);
return null; return null;
} }