const crypto = require('crypto'); const db = require('../../db/knex'); function normalizeCoordinate(value) { if (value == null || value === '') { return null; } const coordinate = Number(value); if (!Number.isFinite(coordinate)) { return null; } return coordinate; } async function enqueueGeocodeJob({ entityType, entityId, lat, lon, }) { if ( entityType !== 'photo' && entityType !== 'activity' ) { throw new Error( `Tipo entità geocode non valido: ${entityType}` ); } if (!entityId) { throw new Error( 'entityId geocode mancante' ); } const normalizedLat = normalizeCoordinate(lat); const normalizedLon = normalizeCoordinate(lon); if ( normalizedLat == null || normalizedLon == null ) { return { queued: false, reason: 'coordinates_missing', }; } if ( normalizedLat < -90 || normalizedLat > 90 || normalizedLon < -180 || normalizedLon > 180 ) { return { queued: false, reason: 'coordinates_invalid', }; } const now = db.fn.now(); await db('geocode_jobs') .insert({ id: crypto.randomUUID(), entity_type: entityType, entity_id: String(entityId), lat: normalizedLat, lon: normalizedLon, status: 'pending', attempts: 0, last_error: null, started_at: null, completed_at: null, created_at: now, updated_at: now, }) .onConflict([ 'entity_type', 'entity_id', ]) .merge({ lat: normalizedLat, lon: normalizedLon, status: 'pending', attempts: 0, last_error: null, started_at: null, completed_at: null, updated_at: now, }); return { queued: true, entity_type: entityType, entity_id: String(entityId), lat: normalizedLat, lon: normalizedLon, }; } module.exports = { enqueueGeocodeJob, };