Cambiando idioma...

Generador de Reportes Pokémon en Azure

Solución escalable para generación de reportes CSV con datos enriquecidos de Pokémon, implementando arquitectura serverless en Azure.

Categoría

Arquitectura Cloud

Rol

Desarrollador Full Stack

Fecha

Tecnologías utilizadas

Next.js FastAPI Azure Functions Azure SQL Blob Storage Terraform Queue Storage
Vista previa del proyecto Generador de Reportes Pokémon en Azure

Generador de Reportes Pokémon en Azure

Visión General

Desarrollé un sistema completo para generar reportes CSV con estadísticas detalladas de Pokémon, implementando tres funcionalidades clave:

  1. Eliminación segura de reportes (Frontend + Backend + Blob Storage)
  2. Enriquecimiento de datos (Azure Function + PokeAPI)
  3. Muestreo aleatorio (Frontend + Backend + Proceso de cola)

Diagrama de Arquitectura Figura 1: Diagrama de la solución completa

Arquitectura Técnica

ComponenteTecnologíaResponsabilidad
FrontendNext.js (React)Interfaz de usuario y gestión de estado
Backend APIFastAPI (Python)Endpoints REST y lógica de negocio
ProcesamientoAzure FunctionsGeneración asíncrona de reportes
AlmacenamientoAzure Blob StorageArchivos CSV generados
MensajeríaQueue StorageComunicación entre servicios
Base de DatosAzure SQLRegistros de reportes y metadatos
Eventos en Tiempo RealServer-Sent EventsActualizaciones de progreso

Implementación Clave

1. Eliminación Completa de Reportes

Solución implementada en capas:

# Backend - FastAPI
@app.delete("/request/{id}")
async def delete_request(id: int):
    result = await delete_pokemon_request(id)
    await sse_manager.broadcast({
        "type": "report_deleted",
        "data": {"id": id}
    })
    return result

# Controlador
async def delete_pokemon_request(id: int) -> dict:
    blob = ABlob()
    blob_name = f"poke_report_{id}.csv"
    await blob.delete_blob(blob_name)
    await execute_query("DELETE FROM pokequeue.request WHERE id = ?", (id,))
// Frontend - React
const handleDeleteReport = async (reportId) => {
  await deleteReport(reportId);
  setReports(prev => prev.filter(r => r.ReportId !== reportId));
};

2. Enriquecimiento de Datos

Proceso en la Azure Function:

def get_pokemon_details(pokemon_url: str) -> dict:
    response = requests.get(pokemon_url)
    data = response.json()
    
    return {
        "hp": data["stats"][0]["base_stat"],
        "attack": data["stats"][1]["base_stat"],
        "defense": data["stats"][2]["base_stat"],
        "special_attack": data["stats"][3]["base_stat"],
        "special_defense": data["stats"][4]["base_stat"],
        "speed": data["stats"][5]["base_stat"],
        "abilities": ", ".join([a["ability"]["name"] for a in data["abilities"][:3]])
    }

3. Muestreo Aleatorio

Implementación del sampling:

if sample_size and 0 < sample_size < len(pokemons):
    pokemons = random.sample(pokemons, sample_size)

Server-Sent Events (SSE)

Implementé un sistema de notificaciones en tiempo real para:

  • Progreso de generación de reportes
  • Actualizaciones de estado
  • Eliminaciones confirmadas
# Backend - SSE Manager
class SSEManager:
    def __init__(self):
        self.connections: Dict[str, asyncio.Queue] = {}
    
    async def broadcast(self, message: dict):
        for queue in self.connections.values():
            await queue.put(json.dumps(message))

# Frontend - Hook personalizado
export function useSSE() {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    const eventSource = new EventSource('/events');
    eventSource.onmessage = (e) => setData(JSON.parse(e.data));
    return () => eventSource.close();
  }, []);
  
  return data;
}

Desafíos y Soluciones

DesafíoSolución Implementada
Sincronización estado frontendSSE + Context API
Eliminación atómicaTransacciones implícitas en Blob + SQL
Muestreo de grandes datasetsProcesamiento por lotes en función
Tiempos de respuesta PokeAPICache local + manejo de errores

Repositorios del Proyecto

  1. 🔗 Frontend (Next.js)
  2. 🔗 Backend API (FastAPI)
  3. 🔗 Azure Functions
  4. 🔗 Database Scripts
  5. 🔗 Infra as Code (Terraform)

Conclusión

Este proyecto demostró mi capacidad para:

  • Diseñar arquitecturas serverless complejas
  • Implementar soluciones de procesamiento asíncrono
  • Integrar múltiples servicios de Azure
  • Desarrollar interfaces reactivas con actualizaciones en tiempo real

La combinación de Next.js, FastAPI y Azure Functions resultó en una solución escalable y mantenible, con un costo operativo optimizado gracias al modelo serverless.

¿Te gustó este proyecto?