Construyendo aplicaciones en tiempo real con AWS AppSync y Subscriptions
Aprende cómo construir aplicaciones en tiempo real con AWS AppSync y Subscriptions.
AWS AppSync
Aprende AWS AppSync para APIs GraphQL con suscripciones en tiempo real, integración de fuentes de datos y capacidades offline.
2 articles
Como expliqué en el primer artículo de AppSync, las capacidades en tiempo real se están volviendo cada vez más cruciales. Los usuarios ahora esperan actualizaciones inmediatas sin necesidad de actualización manual o sondeo constante. Aquí es donde entran en juego AWS AppSync y sus poderosas suscripciones GraphQL, permitiendo a los desarrolladores construir aplicaciones en tiempo real sin esfuerzo.
Usando suscripciones con AWS AppSync, configurarás
capacidades en tiempo realen tus aplicaciones.
1. ¿Qué son las suscripciones GraphQL?
Las suscripciones GraphQL son una característica poderosa que permite a los clientes recibir actualizaciones en tiempo real del servidor. A diferencia de las consultas y mutaciones, que son operaciones de una sola vez, las suscripciones permiten un flujo continuo de datos entre el cliente y el servidor. Esto es particularmente útil para aplicaciones que requieren notificaciones o actualizaciones en tiempo real.
2. Beneficios clave de usar suscripciones de AWS AppSync
- Actualizaciones en Tiempo Real: Las suscripciones envían datos a los clientes tan pronto como ocurren cambios, asegurando que los usuarios siempre tengan la información más reciente.
- Eficiencia: Reduce la necesidad de sondeo constante, ahorrando ancho de banda y mejorando el rendimiento.
- Integración Fluida: Se integra fácilmente con otros servicios de AWS, como DynamoDB, Lambda y más.
3. Demo: Configurando suscripciones en tiempo real con AWS AppSync
Profundicemos en los aspectos prácticos de configurar suscripciones en tiempo real en AWS AppSync.
Aquí encontrarás el código de GitHub con el ejemplo de la aplicación en tiempo real: https://github.com/alazaroc/appsync-website-subscription
Esta es la arquitectura de la solución que construiremos:
3.1. Crear la Tabla DynamoDB
Usaremos una tabla DynamoDB para almacenar datos de mensajes. Este es el schema de la tabla que crearemos:
1
2
3
4
type Messages {
id: String!
message: String
}
Para crearla, puedes usar el código Terraform proporcionado en este repositorio de GitHub para crear tu tabla DynamoDB: https://github.com/alazaroc/appsync-website-subscription/tree/main/infrastructure.
Si eres nuevo con Terraform, puedes revisar este otro artículo
Ejecutaremos estos comandos dentro de la carpeta infrastructure (donde se encuentran los archivos .tf):
1
2
3
4
5
6
# Inicializaremos la configuración de terraform
terraform init
# Verificaremos qué se creará
terraform plan
# Lo desplegaremos
terraform apply --auto-approve
Con esta ejecución, también hemos creado un primer elemento en la tabla “Messages”. Entraremos a la Consola de AWS para verificarlo:
3.2. Crear y configurar la API de AWS AppSync
3.2.1. Creando suscripciones
Crearemos una nueva API AppSync que estará conectada con la tabla DynamoDB. En este caso, no lo haremos con Terraform, porque estamos aquí para aprender cómo funciona AppSync para la configuración en tiempo real. Lo haremos manualmente.
Es muy sencillo:
- Accede al servicio AWS AppSync
- Crear API
- En
GraphQL API Data SourceseleccionaStart with a DynamoDB table - Elige un nombre de API, y en
Import from DynamoDB table, selecciona el nombre de la tabla DynamoDB creada previamente:Messages. - Finalmente, en
Configure model information, agrega un nuevo campomessagede tipoString. Opcionalmente, puedes cambiar el tipo del campoidaIDen lugar deString.- Si configuras el tipo como ID, cuando crees un valor usando el editor, el tipo
IDasegurará que el valor sea único y se trate como un identificador. Esto significa que las comparaciones se basarán en el identificador único en lugar de un simple valor de cadena, proporcionando una forma más eficiente y confiable de referenciar elementos en tu base de datos.
- Si configuras el tipo como ID, cuando crees un valor usando el editor, el tipo
- Eso es todo
Ahora, puedes explorar la API creada.
Revisemos el Schema, y específicamente la configuración de suscripción:
Esto se creó automáticamente:
1
2
3
4
5
6
7
8
type Subscription {
onCreateMessages(id: ID, message: String): Messages
@aws_subscribe(mutations: ["createMessages"])
onUpdateMessages(id: ID, message: String): Messages
@aws_subscribe(mutations: ["updateMessages"])
onDeleteMessages(id: ID, message: String): Messages
@aws_subscribe(mutations: ["deleteMessages"])
}
Aquí, se crearon 3 suscripciones, una para cada operación de mutación: crear, actualizar y eliminar. Significa que puedes suscribirte a una de estas operaciones y luego recibirás notificaciones cuando se ejecuten.
Quiero repetirlo porque así es como funciona.
Al suscribirte a una operación de mutación, recibirás una notificación cada vez que se ejecute esa operación. Esta suscripción establece una conexión WebSocket que se activa específicamente por la operación de mutación, no directamente por la base de datos en sí. Por lo tanto, si modificas la base de datos fuera del servicio AWS AppSync, no recibirás ninguna notificación.
3.2.2. Recibir notificaciones si la base de datos es modificada
Para ser notificado si el cambio se realiza directamente en la base de datos sin el uso de la operación de mutación de AWS AppSync, tendrás que usar una configuración adicional. En el caso de que estuvieras usando DynamoDB, tendrás que habilitar DynamoDB Streams y tendrás que configurar una función Lambda para notificar a tu AWS AppSync. Puedes verlo en el siguiente diagrama:
3.2.3. Suscripción alternativa: canal pub/sub
También puedes crear directamente una API en tiempo real, creando una API pub/sub simple impulsada por WebSockets serverless
Si usas la consola de AWS para crear una API WebSocket en tiempo real donde los clientes se suscriben a canales, el contenido completo del schema será el siguiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Channel {
name: String!
data: AWSJSON!
}
type Mutation {
publish(name: String!, data: AWSJSON!): Channel
}
type Query {
getChannel: Channel
}
type Subscription {
subscribe(name: String!): Channel
@aws_subscribe(mutations: ["publish"])
}
Y luego puedes usar la operación de mutación de publish para publicar los datos, y la suscripción de subscribe para recibirlos en tiempo real. Eso es todo.
3.3. Implementar aplicación en tiempo real
Continuaremos con nuestro ejemplo de aplicación en tiempo real de mensajes almacenados en la tabla DynamoDB de Messages que habíamos creado antes.
Usaremos este código HTML y JavaScript para implementar actualizaciones de datos en tiempo real en tu aplicación y al mismo tiempo, persistirlos en la base de datos. Este ejemplo usa la suscripción para escuchar nuevas entradas de mensajes.
Expliquemos cómo usar la conexión con la operación de suscripción.
- Tenemos que obtener la URL completa del WebSocket
- Tenemos que usar el nuevo endpoint en tiempo real: wss://${APPSYNC_ENDPOINT_ID}.appsync-realtime-api.${AWS_REGION}.amazonaws.com/graphql
- En la solicitud, tenemos que incluir como datos de parámetro en el encabezado la siguiente información
?header=${header}&payload=${payload}, por lo que la URL completa será algo comowss://${APPSYNC_ENDPOINT_ID}.appsync-realtime-api.${AWS_REGION}.amazonaws.com/graphql?header=${header}&payload=${payload} - El encabezado debe contener la versión codificada de los encabezados
hostyx-api-key, de la siguiente manera:
1 2 3 4 5 6 7
function encodeAppSyncCredentials() { const creds = { host: `${APPSYNC_ENDPOINT_ID}.appsync-api.${AWS_REGION}.amazonaws.com`, "x-api-key": APPSYNC_API_KEY, }; return window.btoa(JSON.stringify(creds)); }
- El payload debe estar vacío, por lo que podemos usar lo siguiente:
1
payload = window.btoa(JSON.stringify({}))
Crearemos la conexión WebSocket usando la URL del paso anterior e inicializarla:
1 2 3 4 5 6 7 8
const websocket = new WebSocket(url, ["graphql-ws"]); websocket.addEventListener("open", () => { websocket.send( JSON.stringify({ type: "connection_init", }) ); });
Después de eso, manejar los mensajes WebSocket según su tipo:
connection_ack: Indica que la conexión WebSocket se estableció exitosamente.start_ack: Reconoce que la solicitud de suscripción ha sido recibida y aceptada.error: Indica que ocurrió un error durante el proceso.data: Contiene las actualizaciones en tiempo real del servidor basadas en la suscripción.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
websocket.addEventListener("message", (event) => { const message = JSON.parse(event.data); console.log(message); switch (message.type) { case "connection_ack": startSubscription(websocket); break; case "start_ack": console.log("start_ack"); break; case "error": console.error(message); break; case "data": handleNotification(message.payload.data.onCreateMessages); break; } });
- Para crear la conexión por primera vez, enviaremos una solicitud de suscripción una vez que se reconozca la conexión:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function startSubscription(websocket) {
const subscribeMessage = {
id: window.crypto.randomUUID(),
type: "start",
payload: {
data: JSON.stringify({
query: `subscription onCreateMessages {
onCreateMessages {
id
message
}
}`,
}),
extensions: {
authorization: {
"x-api-key": APPSYNC_API_KEY,
host: `${APPSYNC_ENDPOINT_ID}.appsync-api.${AWS_REGION}.amazonaws.com`,
},
},
},
};
websocket.send(JSON.stringify(subscribeMessage));
}
Ejecutando la aplicación. Solo tienes que hacer dos cosas:
Actualiza tus credenciales en el código
1
2
3
const AWS_REGION = "your-region"
const APPSYNC_ID = "your-id-included-in-the-host";
const APPSYNC_API_KEY = "your-api-key";
- Este es un sitio web HTML estático. Solo abre el archivo html en tu navegador
3.4. Probando la aplicación
Para probar la aplicación en tiempo real tenemos que crear un mensaje usando la operación de mutación de createMessages.
La forma más fácil de hacerlo es usando la sección Queries en la consola de AWS. En los siguientes mensajes, verás cómo funciona. En el lado izquierdo de la imagen, verás la consola de AWS y la generación de mensajes, y en el lado derecho verás nuestra aplicación HTML y los mensajes apareciendo después de la creación:
Paso 1, preparando la operación 
Paso 2, ejecutando la operación y creando el mensaje actualizará inmediatamente el mensaje en nuestra aplicación en tiempo real: 
4. Conclusión
Con AWS AppSync y suscripciones, construir aplicaciones en tiempo real se convierte en un proceso sencillo. Siguiendo esta guía, has configurado un sistema de mensajería que notifica a los usuarios en tiempo real cada vez que se envían nuevos mensajes. Este enfoque puede extenderse a varios casos de uso, haciendo que tus aplicaciones sean más interactivas y responsivas.
Siéntete libre de experimentar y construir más características en tu aplicación.
Como dijo Werner Vogels:
Nunca ha habido un mejor momento para ser un constructor.
¡AHORA VE Y CONSTRUYE!




