Agregar Suscripciones para Notificaciones y Actualizaciones

Lectura
30 min~5 min lectura

Concepto clave

Las suscripciones GraphQL son un mecanismo que permite a los clientes recibir actualizaciones en tiempo real cuando ocurren eventos especificos en el servidor. A diferencia de las queries (consultas) y mutations (mutaciones), que siguen el modelo request-response tradicional, las suscripciones mantienen una conexion persistente mediante WebSockets.

Imagina una red social como Twitter: cuando alguien que sigues publica un nuevo tweet, no tienes que recargar la pagina constantemente para verlo. En su lugar, la aplicacion se suscribe a las actualizaciones de tu feed, y el servidor empuja la nueva informacion tan pronto como esta disponible. Esto es exactamente lo que hacen las suscripciones GraphQL: transforman tu API de un sistema de "preguntar y esperar" a uno de "escuchar y recibir".

Como funciona en la practica

Para implementar suscripciones en una API GraphQL con Apollo Server y Next.js, necesitas configurar tanto el servidor como el cliente. En el servidor, defines un resolver de suscripcion que utiliza PubSub (publicador-suscriptor) para manejar eventos. En el cliente, configuras Apollo Client para usar WebSockets.

Paso a paso:

  1. Instala las dependencias necesarias: graphql-subscriptions y subscriptions-transport-ws en el servidor.
  2. Configura Apollo Server para aceptar conexiones WebSockets, ademas de HTTP.
  3. Define el tipo de suscripcion en tu schema GraphQL, por ejemplo: type Subscription { newNotification: Notification }.
  4. Crea un resolver de suscripcion que utilice PubSub.asyncIterator para escuchar eventos.
  5. En las mutations relevantes (como crear una notificacion), publica el evento usando PubSub.publish.
  6. En el cliente Next.js, configura Apollo Client con un link de WebSockets para suscribirse a los datos.

Caso de estudio

Vamos a aplicar esto a nuestro proyecto de red social. Supongamos que queremos notificar a los usuarios cuando reciben un nuevo mensaje privado. Primero, definimos el schema:

type Message {
  id: ID!
  content: String!
  sender: User!
  receiver: User!
  createdAt: String!
}

type Subscription {
  newMessage(receiverId: ID!): Message
}

Luego, en el servidor, implementamos el resolver de suscripcion:

import { PubSub } from 'graphql-subscriptions';
const pubsub = new PubSub();

const resolvers = {
  Subscription: {
    newMessage: {
      subscribe: (_, { receiverId }) => {
        return pubsub.asyncIterator([`NEW_MESSAGE_${receiverId}`]);
      }
    }
  },
  Mutation: {
    sendMessage: async (_, { content, receiverId }) => {
      const message = await createMessage(content, receiverId);
      pubsub.publish(`NEW_MESSAGE_${receiverId}`, { newMessage: message });
      return message;
    }
  }
};

En el cliente, nos suscribimos en un componente React:

import { useSubscription } from '@apollo/client';
import { NEW_MESSAGE_SUBSCRIPTION } from '../graphql/subscriptions';

function MessageNotification({ userId }) {
  const { data } = useSubscription(NEW_MESSAGE_SUBSCRIPTION, {
    variables: { receiverId: userId }
  });
  
  if (data) {
    return 
Nuevo mensaje de {data.newMessage.sender.name}
; } return null; }

Errores comunes

  • Olvidar configurar WebSockets en Apollo Server: Sin esto, las suscripciones no funcionaran. Asegurate de usar ApolloServer con subscriptions: { path: '/graphql' } en Next.js API routes.
  • No limpiar suscripciones en el cliente: En React, si no limpias las suscripciones al desmontar el componente, pueden causar fugas de memoria. Usa useEffect con una funcion de limpieza.
  • Publicar eventos sin datos validos: Asegurate de que los datos publicados coincidan con el tipo esperado en la suscripcion, o GraphQL lanzara errores.
  • Ignorar la escalabilidad: PubSub en memoria no escala en produccion. Para aplicaciones reales, usa adaptadores como Redis.
  • Confundir suscripciones con polling: Las suscripciones son para tiempo real; no las uses para datos que cambian raramente, donde una query periodica es mas simple.

Checklist de dominio

  1. He configurado Apollo Server en Next.js para soportar suscripciones via WebSockets.
  2. He definido al menos un tipo de suscripcion en mi schema GraphQL con parametros si es necesario.
  3. He implementado un resolver de suscripcion que usa PubSub.asyncIterator para escuchar eventos especificos.
  4. He modificado una mutation para publicar eventos usando PubSub.publish cuando ocurre un cambio relevante.
  5. He configurado Apollo Client en el frontend con un link de WebSockets para manejar suscripciones.
  6. He usado useSubscription en un componente React para suscribirme y mostrar datos en tiempo real.
  7. He probado que las suscripciones funcionan enviando datos y viendo las actualizaciones automaticas en el cliente.

Implementar Suscripciones para Notificaciones de Likes en una Red Social

En este ejercicio, vas a agregar suscripciones GraphQL a tu API para notificar a los usuarios cuando alguien da like a uno de sus posts. Sigue estos pasos:

  1. En tu proyecto Next.js con Apollo Server, asegurate de tener configurado WebSockets. Si no, actualiza tu configuracion en /pages/api/graphql.js para incluir subscriptions: { path: '/graphql' } en el constructor de ApolloServer.
  2. Agrega un tipo de suscripcion a tu schema GraphQL: type Subscription { newLike(postId: ID!): Like }, donde Like es un tipo existente con campos como id, user, y post.
  3. Crea un resolver de suscripcion en tu archivo de resolvers. Usa PubSub de graphql-subscriptions para suscribirte a eventos con el patron NEW_LIKE_${postId}.
  4. Modifica la mutation addLike para publicar un evento cuando se agrega un like. Asegurate de incluir el postId en la publicacion.
  5. En el frontend, configura Apollo Client para usar suscripciones. Instala subscriptions-transport-ws y crea un WebSocket link que apunte a tu servidor (ej., ws://localhost:3000/api/graphql).
  6. En un componente React, usa useSubscription para suscribirte a newLike con un postId especifico. Muestra una notificacion cuando llegue un nuevo like.
  7. Prueba la funcionalidad: ejecuta tu aplicacion, da like a un post desde otra sesion, y verifica que la notificacion aparezca en tiempo real.
Pistas
  • Recuerda inicializar PubSub como una instancia compartida en tus resolvers para evitar problemas de scope.
  • En el cliente, asegurate de que el WebSocket link este correctamente integrado en la configuracion de Apollo Client usando split para manejar tanto queries como suscripciones.
  • Si no ves las actualizaciones, revisa la consola del navegador y del servidor para errores de conexion WebSocket o de schema.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.