Ir al contenido

Datos en Tiempo Real y Arquitectura SSE

📡 Datos en Tiempo Real y Arquitectura SSE

Sección titulada «📡 Datos en Tiempo Real y Arquitectura SSE»

Transmitir cotizaciones en tiempo real directamente al navegador plantea retos técnicos importantes:

  1. Conectar el navegador directamente a múltiples WebSockets externos agota recursos de red, provoca problemas de CORS y expone las tenencias del usuario ante terceros.
  2. Hacer peticiones periódicas por sondeo (polling) sobre APIs REST satura los límites de tasa de los exchanges (429 Too Many Requests).

Para resolver esto de forma limpia y eficiente, Criptofolio utiliza una arquitectura centralizada basada en Server-Sent Events (SSE) orquestada por el backend en Hono.


flowchart TD
    subgraph Frontend ["Frontend en Vue 3"]
        UI["Componentes Visuales (Precio y Valoración en Vivo)"]
        BffAdapter["BffMarketDataAdapter (EventSource)"]
    end

    subgraph Backend ["Servidor Backend Hono"]
        SSEEndpoint["GET /api/market/stream (SSE)"]
        Orchestrator["MarketDataOrchestrator"]
        PriceHistory["IPriceHistoryPort (Caché y Parquet)"]

        Provider1["Adaptador Kraken WS (Activo)"]
        Provider2["Adaptador Binance WS (En espera)"]
    end

    subgraph Exchanges ["Exchanges Externos"]
        KrakenWS["Kraken WebSocket API v2"]
        BinanceWS["Binance WebSocket Stream"]
    end

    UI --> BffAdapter
    BffAdapter -->|Conexión única EventSource| SSEEndpoint
    SSEEndpoint --> Orchestrator

    Orchestrator -->|Intercambio en caliente| Provider1
    Orchestrator -.->|Desactivado| Provider2

    KrakenWS ==>|Ticks en vivo| Provider1
    Provider1 --> Orchestrator

    Orchestrator -->|1. Volcado en Caché e Histórico| PriceHistory
    Orchestrator -->|2. Difusión a Clientes| SSEEndpoint

El navegador abre exactamente una única conexión HTTP persistente mediante la API estándar de HTML5 EventSource hacia /api/market/stream. Todos los activos de la cartera (BTC/EUR, ETH/EUR, SOL/USD) viajan multiplexados por ese mismo canal.

2. Intercambio de Proveedores en Caliente (Hot-Swapping)

Sección titulada «2. Intercambio de Proveedores en Caliente (Hot-Swapping)»

El usuario puede cambiar su proveedor preferido en los ajustes de la Bóveda (por ejemplo, pasar de Kraken a Binance o CoinGecko):

  1. El MarketDataOrchestrator del backend cierra de forma ordenada la sesión activa de WebSocket con Kraken.
  2. Inicia la conexión con el nuevo proveedor seleccionado.
  3. Comienza a inyectar las nuevas cotizaciones por el mismo canal SSE que ya estaba abierto.
  4. El frontend no necesita reconectarse ni recargar la interfaz, asegurando una experiencia continua.

3. Sincronización entre REST y Series Históricas

Sección titulada «3. Sincronización entre REST y Series Históricas»

Cada tick de precio emitido por el canal SSE se guarda de forma concurrente en IPriceHistoryPort:

  • Garantiza que las llamadas REST estándar (GET /api/metrics/kpis) calculen el patrimonio usando exactamente el mismo precio que se está mostrando en los tickers en vivo.
  • Escribe las muestras de precios en archivos Apache Parquet en disco para alimentar los análisis históricos de largo plazo.

Los componentes visuales acceden al flujo de cotizaciones mediante un composable:

import { useMarketStream } from '@/composables/queries/useMarketStream';
export function useLivePortfolio() {
const { isConnected, latestTicks } = useMarketStream();
const btcPrice = computed(() => latestTicks.value['BTC/EUR']?.price);
return { isConnected, btcPrice };
}