Concepto clave
Las suscripciones en GraphQL son una característica que permite a los clientes recibir actualizaciones en tiempo real cuando ocurren cambios en los datos del servidor. A diferencia de las queries tradicionales (que son solicitudes únicas) o las mutaciones (que modifican datos), las suscripciones mantienen una conexión persistente usando tecnologías como WebSockets.
Imagina que estás en una sala de control de tráfico aéreo: las queries serían como pedir un informe puntual de los aviones en un momento dado, mientras que las suscripciones son como tener una pantalla que se actualiza automáticamente cada vez que un avión cambia de posición. Esta capacidad es crucial para aplicaciones como chats en vivo, notificaciones push, o dashboards de monitoreo.
Para implementar suscripciones en Apollo Server con Next.js, necesitas configurar un servidor que soporte tanto HTTP (para queries/mutaciones) como WebSockets (para suscripciones). Apollo Server integra esto mediante PubSub, un patrón de publicación-suscripción que notifica a los clientes cuando se disparan eventos específicos.
Cómo funciona en la práctica
Vamos a desglosar el flujo paso a paso para crear una suscripción básica en GraphQL con Apollo Server y Next.js:
- Configuración del servidor: En tu archivo de configuración de Apollo Server (por ejemplo,
apollo-server.js), importaPubSubdeapollo-servery crea una instancia. Luego, en la configuración del servidor, habilita las suscripciones agregando un objetosubscriptionsque especifique la ruta para WebSockets. - Definición del esquema: En tu esquema GraphQL (usando SDL), define un tipo de suscripción. Por ejemplo, para un chat:
type Subscription { messageAdded: Message }. Esto declara que los clientes pueden suscribirse a eventos de mensajes añadidos. - Implementación del resolver: En los resolvers, crea un resolver para la suscripción que use
PubSub.asyncIterator. Por ejemplo:Subscription: { messageAdded: { subscribe: () => pubsub.asyncIterator(['MESSAGE_ADDED']) } }. Esto configura el canal de eventos. - Publicación de eventos: En los resolvers de mutaciones (por ejemplo, al añadir un mensaje), publica un evento usando
pubsub.publish. Por ejemplo:pubsub.publish('MESSAGE_ADDED', { messageAdded: newMessage }). Esto notifica a todos los suscriptores. - Conexión del cliente: En el lado del cliente (usando Apollo Client en Next.js), configura una suscripción con
useSubscriptionhook osubscriptionmétodo, especificando la query de suscripción y manejando los datos entrantes en tiempo real.
Un ejemplo mínimo de código para el servidor:
import { ApolloServer, PubSub } from 'apollo-server-micro';
const pubsub = new PubSub();
const typeDefs = `
type Message { id: ID!, text: String! }
type Query { messages: [Message] }
type Subscription { messageAdded: Message }
`;
const resolvers = {
Subscription: {
messageAdded: {
subscribe: () => pubsub.asyncIterator(['MESSAGE_ADDED'])
}
},
Mutation: {
addMessage: (_, { text }) => {
const newMessage = { id: '1', text };
pubsub.publish('MESSAGE_ADDED', { messageAdded: newMessage });
return newMessage;
}
}
};
const server = new ApolloServer({ typeDefs, resolvers });
export default server.createHandler({ path: '/api/graphql' });Caso de estudio
Considera una aplicación de monitoreo de servidores para una empresa de hosting. Los administradores necesitan ver en tiempo real el estado de los servidores (por ejemplo, uso de CPU, memoria, y alertas). Implementaremos suscripciones en GraphQL para esto.
Contexto: La aplicación usa Next.js para el frontend y Apollo Server para el backend. Los datos del servidor se actualizan cada 5 segundos desde una fuente externa (como una base de datos o API).
Implementación:
- Esquema: Definimos un tipo
ServerMetriccon campos comoid,cpuUsage,memoryUsage, ystatus. Luego, una suscripción:type Subscription { serverUpdated(serverId: ID!): ServerMetric }. - Resolvers: En el resolver de suscripción, filtramos por
serverIdusando argumentos. En el backend, un job periódico publica eventos cuando se detectan cambios, por ejemplo:pubsub.publish('SERVER_UPDATED', { serverUpdated: metric }). - Cliente: En el frontend, usamos
useSubscriptionde Apollo Client para suscribirnos a un servidor específico y actualizar la UI con los nuevos datos.
Resultado: Los administradores ven una dashboard que se actualiza automáticamente sin necesidad de refrescar la página, mejorando la eficiencia y la respuesta a incidentes.
En un despliegue real, las suscripciones pueden manejar miles de conexiones simultáneas, pero requieren optimización para evitar cuellos de botella en el servidor.
Errores comunes
Al trabajar con suscripciones en GraphQL, los desarrolladores intermedios suelen cometer estos errores:
- No configurar WebSockets correctamente: Olvidar habilitar las suscripciones en la configuración de Apollo Server o usar rutas incorrectas. Esto causa que las conexiones fallen silenciosamente. Solución: Verifica que el objeto
subscriptionsesté definido en el servidor y que el cliente use la URL correcta (por ejemplo,ws://localhost:3000/api/graphql). - Fugas de memoria en suscripciones: No limpiar las suscripciones en el cliente cuando el componente se desmonta, lo que puede llevar a múltiples suscripciones activas y degradar el rendimiento. Solución: Usa el retorno de
useSubscriptiono métodos de limpieza en Apollo Client para cancelar suscripciones al desmontar. - Publicar eventos sin datos válidos: Publicar eventos con datos que no coinciden con el esquema de la suscripción, causando errores en el cliente. Solución: Asegúrate de que el objeto publicado en
pubsub.publishtenga la estructura exacta definida en el esquema (por ejemplo,{ serverUpdated: metric }). - Ignorar la escalabilidad: Usar una instancia simple de
PubSubque no escala en producción, ya que almacena eventos en memoria. Solución: Para entornos distribuidos, integra un sistema de mensajería como Redis o Kafka con Apollo Server. - No manejar reconexiones: Asumir que las conexiones WebSocket son siempre estables, lo que lleva a desconexiones inesperadas. Solución: Implementa lógica de reconexión en el cliente (Apollo Client lo hace por defecto) y monitorea los errores de red.
Checklist de dominio
Para verificar que dominas las suscripciones y optimización en GraphQL, asegúrate de poder:
- Configurar un servidor Apollo Server con soporte para suscripciones usando WebSockets.
- Definir tipos de suscripción en el esquema GraphQL y implementar sus resolvers con
PubSub. - Publicar eventos desde mutaciones o jobs del servidor para notificar a los clientes suscritos.
- Conectar un cliente Apollo en Next.js a una suscripción y manejar los datos en tiempo real en la UI.
- Optimizar el rendimiento limitando la frecuencia de actualizaciones o filtrando suscripciones por argumentos.
- Manejar errores comunes como fugas de memoria o desconexiones en las suscripciones.
- Escalar suscripciones para producción usando sistemas de mensajería externos.
Implementa un Sistema de Notificaciones en Tiempo Real
En este ejercicio, crearás un sistema básico de notificaciones usando suscripciones en GraphQL con Apollo Server y Next.js. Sigue estos pasos:
- Configura el entorno: Crea un proyecto Next.js y configura Apollo Server en
/api/graphql. Asegúrate de instalar las dependencias necesarias:apollo-server-micro,apollo-client, ygraphql. - Define el esquema: En tu archivo de esquema GraphQL, define un tipo
Notificationcon camposid(ID!),message(String!), ytimestamp(String!). Luego, añade una suscripción:type Subscription { notificationAdded: Notification }y una mutación:type Mutation { addNotification(message: String!): Notification }. - Implementa los resolvers: En los resolvers, usa
PubSubpara la suscripción. Crea una instancia dePubSuby en el resolver denotificationAdded, usapubsub.asyncIterator(['NOTIFICATION_ADDED']). En la mutaciónaddNotification, publica un evento conpubsub.publish('NOTIFICATION_ADDED', { notificationAdded: newNotification }). - Configura el cliente: En el frontend (por ejemplo, en
pages/index.js), usa Apollo Client para suscribirte anotificationAdded. Muestra las notificaciones en una lista que se actualice automáticamente cuando se añadan nuevas. - Prueba el sistema: Ejecuta la aplicación y usa la mutación (puedes hacerlo desde Apollo Sandbox o una herramienta similar) para añadir notificaciones. Verifica que el frontend las muestre en tiempo real sin refrescar.
Entrega un repositorio GitHub con el código completo y un README que explique cómo ejecutarlo.
Pistas- Recuerda que Apollo Server en Next.js requiere configurar el handler en
/api/graphqlusandomicroo métodos similares. - En el cliente, usa el hook
useSubscriptionde Apollo Client para manejar la suscripción y actualizar el estado local. - Si las notificaciones no aparecen, revisa que la publicación del evento en la mutación coincida exactamente con el nombre del canal en la suscripción.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.