<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anderson Sinaluisa</title>
    <description>The latest articles on Forem by Anderson Sinaluisa (@andersonsinaluisa).</description>
    <link>https://forem.com/andersonsinaluisa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1041277%2Fb5671f24-fa53-466f-a589-17357c35731e.jpeg</url>
      <title>Forem: Anderson Sinaluisa</title>
      <link>https://forem.com/andersonsinaluisa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andersonsinaluisa"/>
    <language>en</language>
    <item>
      <title>Building an AI tool that generates SQL queries from natural language</title>
      <dc:creator>Anderson Sinaluisa</dc:creator>
      <pubDate>Tue, 10 Mar 2026 16:14:37 +0000</pubDate>
      <link>https://forem.com/andersonsinaluisa/building-an-ai-tool-that-generates-sql-queries-from-natural-language-54fn</link>
      <guid>https://forem.com/andersonsinaluisa/building-an-ai-tool-that-generates-sql-queries-from-natural-language-54fn</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Writing SQL queries is something most developers do frequently, but it can still be slow and repetitive.&lt;/p&gt;

&lt;p&gt;Sometimes you just want to ask something simple like:&lt;/p&gt;

&lt;p&gt;"show users created this month"&lt;/p&gt;

&lt;p&gt;Instead of switching context, checking the schema, and writing the query manually.&lt;/p&gt;

&lt;p&gt;I started experimenting with an idea:&lt;/p&gt;

&lt;p&gt;What if you could generate SQL queries using natural language?&lt;/p&gt;




&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;Describe the query in plain English and automatically generate the SQL.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Input:&lt;/p&gt;

&lt;p&gt;show users created this month&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SELECT *&lt;br&gt;
FROM users&lt;br&gt;
WHERE created_at &amp;gt;= DATE_TRUNC('month', CURRENT_DATE);&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea is not to replace developers, but to make it faster to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explore databases&lt;/li&gt;
&lt;li&gt;generate queries quickly&lt;/li&gt;
&lt;li&gt;understand complex SQL&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;While experimenting with this approach, I ran into several interesting problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema understanding
&lt;/h3&gt;

&lt;p&gt;The model needs to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tables&lt;/li&gt;
&lt;li&gt;relationships&lt;/li&gt;
&lt;li&gt;column names&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without that context, the generated SQL can be incorrect.&lt;/p&gt;




&lt;h3&gt;
  
  
  Complex joins
&lt;/h3&gt;

&lt;p&gt;Queries involving multiple tables are much harder.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;join conditions&lt;/li&gt;
&lt;li&gt;nested queries&lt;/li&gt;
&lt;li&gt;aggregations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These require much more context.&lt;/p&gt;




&lt;h3&gt;
  
  
  Ambiguous column names
&lt;/h3&gt;

&lt;p&gt;Many databases have columns like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;id&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;created_at&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without schema awareness, it becomes difficult to determine the correct table.&lt;/p&gt;




&lt;h2&gt;
  
  
  The experiment
&lt;/h2&gt;

&lt;p&gt;To explore this idea further, I built a small prototype that generates SQL queries from natural language prompts.&lt;/p&gt;

&lt;p&gt;You can try it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chatsql.andersonsinaluisa.com" rel="noopener noreferrer"&gt;https://chatsql.andersonsinaluisa.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explain complex SQL queries&lt;/li&gt;
&lt;li&gt;help explore database structures&lt;/li&gt;
&lt;li&gt;assist with query generation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  I'm curious about your thoughts
&lt;/h2&gt;

&lt;p&gt;Do you think tools like this can realistically fit into a developer workflow?&lt;/p&gt;

&lt;p&gt;Or are they mainly useful for simple queries?&lt;/p&gt;

&lt;p&gt;I'd love to hear your feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg2jpobhq6wdtxsw8j3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg2jpobhq6wdtxsw8j3n.png" alt=" " width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsxap2dbjvjb9tk44m56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpsxap2dbjvjb9tk44m56.png" alt=" " width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>database</category>
      <category>productivity</category>
      <category>sql</category>
    </item>
    <item>
      <title>Cómo Ejecutar Tareas Asíncronas en React Usando Web Workers</title>
      <dc:creator>Anderson Sinaluisa</dc:creator>
      <pubDate>Mon, 30 Dec 2024 04:26:12 +0000</pubDate>
      <link>https://forem.com/andersonsinaluisa/como-ejecutar-tareas-asincronas-en-react-usando-web-workers-5e7j</link>
      <guid>https://forem.com/andersonsinaluisa/como-ejecutar-tareas-asincronas-en-react-usando-web-workers-5e7j</guid>
      <description>&lt;p&gt;Cuando trabajas con React, tarde o temprano te vas a topar con situaciones donde necesitas ejecutar tareas que toman tiempo, como consultar una API cada cierto tiempo para ver si un proceso terminó. Si no lo manejas bien, puedes trabar la app o saturar el navegador. Para evitar eso, podemos usar Web Workers.&lt;/p&gt;

&lt;p&gt;Voy a explicarte un ejemplo que hice para monitorear el estado de un reporte que se genera en el backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué Necesitamos Hacer?
&lt;/h2&gt;

&lt;p&gt;Llamar a la API para iniciar el proceso de generación del reporte.&lt;br&gt;
Obtener un task_id que identifica esa tarea.&lt;br&gt;
Consultar cada 30 segundos si la tarea ya terminó.&lt;br&gt;
Manejar todo esto sin afectar la interfaz del usuario.&lt;br&gt;
El truco aquí está en usar un Web Worker, que es como un ayudante en segundo plano que se encarga de hacer todo el trabajo pesado sin bloquear la app.&lt;/p&gt;
&lt;h2&gt;
  
  
  El Código
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Paso 1: Configura Axios para la API
&lt;/h3&gt;

&lt;p&gt;Lo primero es preparar Axios para que pueda conectarse a la API. Aquí configuro un cliente que tiene la URL base y los headers que necesito:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from "axios";

export const apiClient = axios.create({
  baseURL: "https://example.com/api", // Cambia esta URL por la base de tu API
  headers: {
    "Content-Type": "application/json",
    Accept: "application/json",
  },
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 2: Crea el Web Worker
&lt;/h3&gt;

&lt;p&gt;El Web Worker es donde pasa la magia. Básicamente, este chico está revisando la API cada 30 segundos para ver si la tarea ya terminó:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self.onmessage = async (event) =&amp;gt; {
  const { task_id, apiEndpoint } = event.data;

  const checkTaskStatus = async () =&amp;gt; {
    try {
      const response = await fetch(`${apiEndpoint}/${task_id}`);
      const task = await response.json();

      self.postMessage(task);

      if (task.status !== "SUCCESS" &amp;amp;&amp;amp; task.status !== "FAILURE") {
        setTimeout(checkTaskStatus, 30000);
      }
    } catch (error) {
      console.error("Error en el Worker:", error);
    }
  };

  checkTaskStatus();
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 3: Maneja el Worker en React
&lt;/h3&gt;

&lt;p&gt;En tu app React, necesitas controlar este Web Worker: iniciarlo, pasarle datos, y manejar las respuestas que te manda.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class AsyncTaskManager {
  private worker: Worker | null = null;

  public async startTask(taskId: string, apiEndpoint: string, onResult: (data: any) =&amp;gt; void) {
    if (this.worker) {
      this.worker.terminate();
    }

    this.worker = new Worker(new URL("./GenericWorker.js", import.meta.url), { type: "module" });

    this.worker.postMessage({ task_id: taskId, apiEndpoint });

    this.worker.onmessage = (event) =&amp;gt; {
      const data = event.data;
      onResult(data);

      if (data.status === "SUCCESS" || data.status === "FAILURE") {
        this.stopWorker();
      }
    };
  }

  public stopWorker() {
    if (this.worker) {
      this.worker.terminate();
      this.worker = null;
    }
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 4: Uso en el componente
&lt;/h3&gt;

&lt;p&gt;Ahora, en el componente de React, utilizamos el AsyncTaskManager para gestionar la tarea. El proceso incluye iniciar la tarea, mostrar un cargando, y actualizar el estado cuando se recibe el resultado de la tarea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";
import { AsyncTaskManager } from "./AsyncTaskManager";

const taskManager = new AsyncTaskManager();

export const ExampleComponent = () =&amp;gt; {
  const [isLoading, setIsLoading] = useState(false);
  const [result, setResult] = useState(null);

  const handleStartTask = async () =&amp;gt; {
    setIsLoading(true);

    // Simula el inicio de una tarea en el backend
    const response = await fetch("https://example.com/api/start-task", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
    });
    const { task_id } = await response.json();

    taskManager.startTask(task_id, "https://example.com/api/task-status", (data) =&amp;gt; {
      if (data.status === "SUCCESS" || data.status === "FAILURE") {
        setIsLoading(false);
        setResult(data.result); // Maneja el resultado de la tarea
      }
    });
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;button onClick={handleStartTask} disabled={isLoading}&amp;gt;
        {isLoading ? "Procesando..." : "Iniciar Tarea"}
      &amp;lt;/button&amp;gt;
      {result &amp;amp;&amp;amp; &amp;lt;div&amp;gt;Resultado: {JSON.stringify(result)}&amp;lt;/div&amp;gt;}
    &amp;lt;/div&amp;gt;
  );
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explicación del Flujo
&lt;/h2&gt;

&lt;p&gt;Generar el Reporte: Al hacer clic en "Iniciar Tarea", se llama a una API que inicia el proceso de generación del reporte y devuelve un &lt;code&gt;task_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Monitoreo en Segundo Plano: Usamos un Web Worker que recibe este &lt;code&gt;task_id&lt;/code&gt; y consulta la API de estado cada 30 segundos, enviando el estado de la tarea de vuelta a React.&lt;/p&gt;

&lt;p&gt;Actualizar UI: Mientras la tarea se ejecuta, la UI permanece fluida, con un botón que muestra "Procesando..." y, una vez completada la tarea, muestra el resultado.&lt;/p&gt;

&lt;p&gt;Liberar Recursos: Cuando la tarea termina (ya sea con éxito o fracaso), el Worker se detiene para liberar recursos y evitar procesos innecesarios en segundo plano.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por Qué Hacerlo Así?
&lt;/h2&gt;

&lt;p&gt;Este enfoque es súper útil porque:&lt;/p&gt;

&lt;p&gt;No bloqueas la interfaz del usuario mientras consultas la API.&lt;br&gt;
Puedes manejar procesos largos sin que la app se congele.&lt;br&gt;
El usuario siempre sabe qué está pasando gracias a los loaders y notificaciones.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Como Crear anotaciones en Java</title>
      <dc:creator>Anderson Sinaluisa</dc:creator>
      <pubDate>Sat, 22 Jul 2023 21:02:55 +0000</pubDate>
      <link>https://forem.com/andersonsinaluisa/como-crear-anotaciones-en-java-2071</link>
      <guid>https://forem.com/andersonsinaluisa/como-crear-anotaciones-en-java-2071</guid>
      <description>&lt;p&gt;Las anotaciones en Java son una poderosa herramienta que permite agregar metadatos personalizados a clases, métodos, variables y otros elementos del código. Estas anotaciones pueden ser utilizadas para proporcionar información adicional, configurar comportamientos especiales o simplificar la lógica de programación. En este artículo, exploraremos cómo crear anotaciones en Java y cómo aprovechar su potencial para mejorar la legibilidad y funcionalidad de tu código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué son las anotaciones en Java?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En esencia, una anotación en Java es una forma de metadatos que se puede agregar al código fuente. Las anotaciones comienzan con el símbolo @, seguido del nombre de la anotación. Estas pueden incluir parámetros que se utilizan para personalizar su comportamiento.&lt;/p&gt;

&lt;p&gt;Java incluye muchas anotaciones integradas, como &lt;code&gt;@Override&lt;/code&gt;, &lt;code&gt;@Deprecated&lt;/code&gt; y &lt;code&gt;@SuppressWarnings&lt;/code&gt;, que proporcionan información adicional sobre el código. Sin embargo, también puedes crear tus propias anotaciones personalizadas para adaptarlas a tus necesidades específicas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creando una Anotación Personalizada&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para crear una anotación personalizada en Java, debes definir una nueva interfaz y marcarla con la anotación &lt;code&gt;@interface&lt;/code&gt;. Veamos un ejemplo sencillo de una anotación para marcar métodos que requieren ser probados exhaustivamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.asinaluisa.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ApiClass {
    String value() default "";

    String keyProjectId() default "{projectId}";

    String[] methods() default {};

    String[] methodclass() default {};

    String[] keyPath() default {};    

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este ejemplo, hemos creado la anotación &lt;code&gt;@ApiClass&lt;/code&gt;. También hemos especificado que la anotación debe conservarse en tiempo de ejecución &lt;code&gt;(RetentionPolicy.RUNTIME)&lt;/code&gt;, lo que permitirá que se acceda a ella mediante reflexión.&lt;/p&gt;

&lt;p&gt;La anotación tiene varios parámetros, responsable y casos, que son de tipo String y String[], respectivamente. Estos parámetros permitirán proporcionar información adicional al marcar una clase con esta anotación. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aplicando la Anotación en Código&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Una vez creada la anotación, podemos aplicarla a un método en nuestro código. Supongamos que tenemos una clase &lt;code&gt;Folder&lt;/code&gt;y queremos relacionarla con una url para enviar los datos a un API Rest,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@ApiClass(value="/projects/{projectId}/testcase-folders",
            keyProjectId = "{projectId}", methods = {"POST","GET","PUT","DELETE","GET"},
            methodclass = {"save","get","update","delete","getAll"}, keyPath = {"{projectId}"}
)
public class Folder extends QMetryAPI&amp;lt;Folder&amp;gt;  {

    private String folderName;
    private int parentId;

    public Folder() {
        super("10000");
    }


    public Folder(String folderName, int parentId) {
        this.folderName = folderName;
        this.parentId = parentId;
    }


    public String getFolderName() {
        return folderName;
    }

    public int getParentId() {
        return parentId;
    }

    public void setFolderName(String folderName) {
        this.folderName = folderName;
    }

    public void setParentId(int parentId) {
        this.parentId = parentId;
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso, hemos aplicado la anotación &lt;code&gt;@ApiClass&lt;/code&gt; a la clase &lt;code&gt;Folder&lt;/code&gt;, proporcionando valores para los parámetros.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recuperando Anotaciones mediante Reflexión&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Un aspecto interesante de las anotaciones en Java es que puedes recuperar la información que contienen mediante reflexión. Esto es útil cuando deseas analizar o procesar la anotación en tiempo de ejecución. A continuación, se muestra un ejemplo sencillo de cómo recuperar la información de la anotación&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ApiClass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;aplicada en la clase Padre &lt;code&gt;QMetryAPI&amp;lt;T&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class QMetryAPI&amp;lt;T&amp;gt;{

    private final String URL = "https://private-anon-643f6a92e0-qmetryforjiracloud40.apiary-mock.com/rest/api/latest";

    private final String APIKEY = "";



    public T save() {
        ApiClass api = null ;
        Class&amp;lt;?&amp;gt; subclase =  this.getClass();

        api = getApiClass(subclase);


        String[] methods = api.methods();
        String[] methodsClass = api.methodclass();
        String Path =api.value();

    }

    protected ApiClass getApiClass(Class&amp;lt;?&amp;gt; c){
        ApiClass apiClass = null;

        boolean isApiClass = c.isAnnotationPresent(ApiClass.class);



        if (isApiClass) {
            apiClass = c.getAnnotation(ApiClass.class);
        }
        return apiClass;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las anotaciones en Java son una característica valiosa que te permite agregar metadatos personalizados a tu código. Al crear tus propias anotaciones, puedes mejorar la legibilidad, el mantenimiento y la funcionalidad de tus programas, proporcionando información adicional o configurando comportamientos específicos. Además, la capacidad de recuperar anotaciones mediante reflexión abre un mundo de posibilidades para la creación de bibliotecas y marcos avanzados. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>¿Qué son los Server-Sent Events (SSE) y cómo funcionan?</title>
      <dc:creator>Anderson Sinaluisa</dc:creator>
      <pubDate>Wed, 08 Mar 2023 16:33:51 +0000</pubDate>
      <link>https://forem.com/andersonsinaluisa/que-son-los-server-sent-events-sse-y-como-funcionan-fk4</link>
      <guid>https://forem.com/andersonsinaluisa/que-son-los-server-sent-events-sse-y-como-funcionan-fk4</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4kzNbVnk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94mq080p1f9sgresdpko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4kzNbVnk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/94mq080p1f9sgresdpko.png" alt="Image description" width="428" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En una aplicación web tradicional, la actualización de información en tiempo real puede ser un problema, ya que requiere una comunicación constante entre el cliente y el servidor. En estos casos, se suelen utilizar técnicas como polling o long-polling, en las que el cliente realiza peticiones al servidor en intervalos regulares para obtener actualizaciones de información.&lt;/p&gt;

&lt;p&gt;Sin embargo, estas técnicas pueden resultar ineficientes en situaciones en las que se necesita una actualización constante de información, ya que pueden generar un tráfico excesivo en la red y un aumento en el consumo de recursos del servidor.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo solucionar estos problemas?
&lt;/h2&gt;

&lt;p&gt;Para solucionar estos problemas, se han desarrollado alternativas más eficientes como WebSockets y Server-Sent Events (SSE), que permiten una comunicación bidireccional entre el cliente y el servidor y una actualización constante de información en tiempo real sin tener que realizar peticiones innecesarias al servidor.&lt;/p&gt;

&lt;p&gt;Los Server-Sent Events (SSE) son una tecnología web que permite a los servidores enviar datos a los clientes de forma asincrónica, en tiempo real y sin necesidad de realizar peticiones adicionales al servidor. Esto se logra a través de una conexión HTTP de larga duración entre el cliente y el servidor, en la que el servidor envía eventos al cliente cuando se producen actualizaciones en los datos.&lt;br&gt;
El protocolo HTTP es el que se utiliza para establecer la conexión SSE, utilizando una petición GET con una cabecera específica que indica que se desea una respuesta en formato de eventos. El servidor envía los eventos al cliente en un stream continuo, separados por líneas en blanco y precedidos por un identificador único y opcionalmente, otros campos de metadatos.&lt;br&gt;
El cliente recibe los eventos en tiempo real y puede procesarlos para actualizar la información en la página web sin necesidad de refrescarla. Además, los SSE permiten la gestión de errores y la posibilidad de reintentar la conexión en caso de fallos.&lt;br&gt;
Un ejemplo sencillo de cómo se ve un stream de eventos en el navegador sería el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var source = new EventSource('/stream');
source.onmessage = function(event) {
  console.log(event.data);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este ejemplo, se crea una instancia de EventSource para conectarse al servidor y recibir los eventos. El servidor envía los eventos a través de la ruta «/stream» y el cliente los recibe mediante la función «onmessage», que muestra los datos del evento en la consola del navegador.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ventajas y desventajas de los Server-Sent Events
&lt;/h2&gt;

&lt;p&gt;Los Server-Sent Events (SSE), WebSockets y polling son tecnologías que permiten la actualización de información en tiempo real en aplicaciones web, pero presentan diferencias en cuanto a sus ventajas y desventajas.&lt;/p&gt;

&lt;p&gt;Las principales ventajas de los SSE son:&lt;/p&gt;

&lt;p&gt;Compatibilidad con el protocolo HTTP: Los SSE utilizan el protocolo HTTP, lo que significa que no es necesario abrir un nuevo canal de comunicación, como en el caso de WebSockets, y pueden utilizarse con servidores web estándar.&lt;br&gt;
Fácil implementación: La implementación de SSE es relativamente sencilla y no requiere conocimientos avanzados de programación.&lt;br&gt;
Consumo de recursos limitado: Los SSE son menos demandantes en cuanto a recursos del servidor y del cliente que otras tecnologías, como WebSockets o polling, lo que puede resultar beneficioso en aplicaciones con grandes volúmenes de tráfico.&lt;br&gt;
Capacidad de reintentar la conexión: En caso de fallos en la conexión, los SSE permiten la reanudación automática de la conexión, lo que mejora la fiabilidad de la tecnología.&lt;br&gt;
Sin embargo, los SSE también presentan algunas desventajas, entre ellas:&lt;/p&gt;

&lt;p&gt;Limitaciones en la comunicación bidireccional: Los SSE solo permiten la comunicación unidireccional, es decir, del servidor al cliente, lo que puede ser un problema en aplicaciones que requieren una comunicación bidireccional, como en juegos en línea.&lt;br&gt;
Limitaciones en la cantidad y tamaño de los datos: Los SSE pueden ser limitados en cuanto a la cantidad y tamaño de los datos que se pueden enviar en cada evento, lo que puede limitar su utilidad en aplicaciones con grandes volúmenes de información.&lt;br&gt;
En cuanto a cuándo es recomendable utilizar SSE, esta tecnología puede ser una buena opción en aplicaciones que requieren actualizaciones en tiempo real de información, pero no necesitan una comunicación bidireccional constante y no tienen grandes volúmenes de información para enviar. Por ejemplo, en aplicaciones de noticias, actualizaciones de redes sociales o seguimiento de eventos en tiempo real.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementación de Server-Sent Events en una aplicación web
&lt;/h2&gt;

&lt;p&gt;Aquí describiré un ejemplo de implementación de Server-Sent Events (SSE) utilizando PHP y JavaScript:&lt;/p&gt;

&lt;p&gt;En el lado del servidor (PHP):&lt;/p&gt;

&lt;p&gt;En primer lugar, se debe habilitar la respuesta HTTP de SSE en el servidor mediante la configuración de cabeceras. Para ello, se debe enviar una respuesta con las siguientes cabeceras:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;

class StreamController extends Controller
{
    public function stream()
    {
        $response = new StreamedResponse();
        $response-&amp;gt;headers-&amp;gt;set('Content-Type', 'text/event-stream');
        $response-&amp;gt;headers-&amp;gt;set('Cache-Control', 'no-cache');
        $response-&amp;gt;headers-&amp;gt;set('Connection', 'keep-alive');

        $response-&amp;gt;setCallback(function () {
            while (true) {
                // Agrega aquí la lógica para obtener los datos que deseas enviar
                $data = [
                    'mensaje' =&amp;gt; 'Este es un mensaje de ejemplo',
                    'fecha' =&amp;gt; date('Y-m-d H:i:s')
                ];

                // Crea el evento Server-Sent Event y envía los datos
                echo 
"event: nombre_del_evento\n";
                echo "data: " . json_encode($data) . "\n\n";
                ob_flush();
                flush();

                // Espera 10 segundos antes de enviar el siguiente evento
                sleep(10);
            }
        });

        return $response;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A continuación, se deben enviar los eventos desde el servidor. Esto se hace mediante la escritura de los eventos en el cuerpo de la respuesta HTTP.&lt;br&gt;
echo "event: nombre_del_evento\n";&lt;br&gt;
echo "data: " . $datos_del_evento . "\n\n";&lt;br&gt;
Aquí, el «nombre_del_evento» es un nombre arbitrario que se le da al evento, y los «datos_del_evento» son los datos que se envían con el evento.&lt;/p&gt;

&lt;p&gt;Es necesario enviar un carácter de nueva línea en blanco («\n\n») después de cada evento para que el navegador pueda procesarlo adecuadamente.&lt;/p&gt;

&lt;p&gt;En el lado del cliente (JavaScript):&lt;/p&gt;

&lt;p&gt;Se debe crear un objeto EventSource en JavaScript para conectarse al servidor y recibir los eventos.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const source = new EventSource('url_del_servidor');&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
A continuación, se deben definir los manejadores de eventos para procesar los eventos recibidos del servidor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source.addEventListener('nombre_del_evento', function(evento) {
  console.log(evento.data); // procesa los datos del evento recibido
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es posible definir manejadores de eventos para diferentes eventos en el servidor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source.addEventListener('otro_nombre_de_evento', function(evento) {
  console.log(evento.data); // procesa los datos del evento recibido
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En resumen, el proceso de envío de eventos desde el servidor a través de SSE se realiza mediante la configuración de cabeceras para habilitar la respuesta HTTP SSE, la escritura de eventos en el cuerpo de la respuesta y el envío de un carácter de nueva línea en blanco después de cada evento. Por otro lado, en el lado del cliente, se debe crear un objeto EventSource para conectarse al servidor y definir manejadores de eventos para procesar los eventos recibidos del servidor.&lt;/p&gt;

&lt;p&gt;Las principales ventajas de los SSE son:&lt;/p&gt;

&lt;p&gt;Compatibilidad con el protocolo HTTP: Los SSE utilizan el protocolo HTTP, lo que significa que no es necesario abrir un nuevo canal de comunicación, como en el caso de WebSockets, y pueden utilizarse con servidores web estándar.&lt;br&gt;
Fácil implementación: La implementación de SSE es relativamente sencilla y no requiere conocimientos avanzados de programación.&lt;br&gt;
Consumo de recursos limitado: Los SSE son menos demandantes en cuanto a recursos del servidor y del cliente que otras tecnologías, como WebSockets o polling, lo que puede resultar beneficioso en aplicaciones con grandes volúmenes de tráfico.&lt;br&gt;
Capacidad de reintentar la conexión: En caso de fallos en la conexión, los SSE permiten la reanudación automática de la conexión, lo que mejora la fiabilidad de la tecnología.&lt;br&gt;
Sin embargo, los SSE también presentan algunas desventajas, entre ellas:&lt;/p&gt;

&lt;p&gt;Limitaciones en la comunicación bidireccional: Los SSE solo permiten la comunicación unidireccional, es decir, del servidor al cliente, lo que puede ser un problema en aplicaciones que requieren una comunicación bidireccional, como en juegos en línea.&lt;br&gt;
Limitaciones en la cantidad y tamaño de los datos: Los SSE pueden ser limitados en cuanto a la cantidad y tamaño de los datos que se pueden enviar en cada evento, lo que puede limitar su utilidad en aplicaciones con grandes volúmenes de información.&lt;br&gt;
En cuanto a cuándo es recomendable utilizar SSE, esta tecnología puede ser una buena opción en aplicaciones que requieren actualizaciones en tiempo real de información, pero no necesitan una comunicación bidireccional constante y no tienen grandes volúmenes de información para enviar. Por ejemplo, en aplicaciones de noticias, actualizaciones de redes sociales o seguimiento de eventos en tiempo real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso de Server-Sent Events
&lt;/h2&gt;

&lt;p&gt;Server-Sent Events (SSE) es una tecnología que permite enviar eventos desde el servidor al cliente de forma asíncrona y en tiempo real. A continuación, se presentan algunos casos de uso comunes de SSE:&lt;/p&gt;

&lt;p&gt;Notificaciones en tiempo real: Las notificaciones en tiempo real son un caso de uso común para SSE. Por ejemplo, una aplicación de mensajería puede utilizar SSE para enviar notificaciones a los usuarios en tiempo real cuando reciben un nuevo mensaje.&lt;br&gt;
Actualización de feeds de redes sociales: Las redes sociales pueden utilizar SSE para actualizar los feeds de los usuarios en tiempo real. Por ejemplo, cuando un usuario sigue a otra persona, SSE puede utilizarse para actualizar automáticamente el feed de ese usuario con las publicaciones más recientes de la persona que sigue.&lt;br&gt;
Monitoreo de eventos en tiempo real: Las empresas pueden utilizar SSE para monitorear eventos en tiempo real, como el rendimiento del servidor o el comportamiento de los usuarios en una aplicación. SSE permite que las empresas reciban alertas en tiempo real cuando ocurre un evento importante.&lt;br&gt;
Actualización de información en tiempo real: Las aplicaciones pueden utilizar SSE para actualizar la información en tiempo real en el navegador sin necesidad de recargar la página. Por ejemplo, una aplicación de seguimiento de precios puede utilizar SSE para actualizar los precios de los productos en tiempo real.&lt;br&gt;
SSE es una solución más adecuada en estos casos que otras alternativas como el polling o WebSockets por las siguientes razones:&lt;/p&gt;

&lt;p&gt;SSE utiliza una conexión HTTP de larga duración, lo que reduce la sobrecarga de red en comparación con el polling, donde el cliente debe realizar solicitudes frecuentes al servidor.&lt;br&gt;
SSE es una solución más simple que WebSockets y no requiere la implementación de un protocolo personalizado.&lt;br&gt;
SSE es compatible con la mayoría de los navegadores modernos, lo que lo hace una opción más accesible que WebSockets.&lt;br&gt;
En general, SSE es una solución adecuada para casos de uso que requieren actualizaciones en tiempo real, pero que no requieren una comunicación bidireccional compleja entre el servidor y el cliente.&lt;/p&gt;

&lt;p&gt;Es importante destacar que SSE es una opción más simple y accesible que WebSockets, por lo que es ideal para aplicaciones que no requieren una comunicación bidireccional compleja. Además, SSE ofrece una solución más eficiente que el polling, ya que reduce la sobrecarga de red al mantener una conexión HTTP de larga duración. En general, SSE es una herramienta valiosa para mantener a los usuarios informados en tiempo real sobre los eventos importantes en una aplicación.&lt;/p&gt;

&lt;p&gt;Referencias&lt;br&gt;
«Server-Sent Events» en MDN Web Docs: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events&lt;/a&gt;&lt;br&gt;
«HTML5 Server-Sent Events» en W3Schools: &lt;a href="https://www.w3schools.com/html/html5_serversentevents.asp"&gt;https://www.w3schools.com/html/html5_serversentevents.asp&lt;/a&gt;&lt;br&gt;
«How to Use Server-Sent Events (SSE) in Your Node.js App» en SitePoint: &lt;a href="https://www.sitepoint.com/server-sent-events-nodejs/"&gt;https://www.sitepoint.com/server-sent-events-nodejs/&lt;/a&gt;&lt;br&gt;
«Server-Sent Events (SSE) with PHP» en Tania Rascia’s blog: &lt;a href="https://www.taniarascia.com/server-sent-events-php/"&gt;https://www.taniarascia.com/server-sent-events-php/&lt;/a&gt;&lt;br&gt;
«Server-Sent Events (SSE) with Express» en Tania Rascia’s blog: &lt;a href="https://www.taniarascia.com/server-sent-events-with-node-js/"&gt;https://www.taniarascia.com/server-sent-events-with-node-js/&lt;/a&gt;&lt;br&gt;
«Real-time Notifications with Server-Sent Events» en Scotch.io: &lt;a href="https://scotch.io/tutorials/real-time-notifications-with-server-sent-events#toc-part-1-what-are-server-sent-events-sse-"&gt;https://scotch.io/tutorials/real-time-notifications-with-server-sent-events#toc-part-1-what-are-server-sent-events-sse-&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
