Uso de suscripciones para aplicaciones de datos en tiempo real en AWS AppSync - AWS AppSync

Uso de suscripciones para aplicaciones de datos en tiempo real en AWS AppSync

AWS AppSync le permite utilizar las suscripciones para implementar actualizaciones de aplicaciones en tiempo real, notificaciones push, etc. Cuando los clientes invocan las operaciones de suscripción de GraphQL, AWS AppSync establece y mantiene automáticamente una conexión WebSocket segura. De este modo, las aplicaciones pueden distribuir los datos en tiempo real desde un origen de datos a los suscriptores, mientras que AWS AppSync gestiona continuamente los requisitos de conexión y escalado de la aplicación. En las siguientes secciones se explica el funcionamiento de las suscripciones en AWS AppSync.

Directivas de suscripción del esquema de GraphQL

Las suscripciones en AWS AppSync se invocan como respuesta a una mutación. Esto significa que puede hacer que cualquier origen de datos de AWS AppSync envíe datos en tiempo real especificando una directiva de esquema de GraphQL para una mutación.

Las bibliotecas de cliente de AWS Amplify gestionan automáticamente la administración de las conexiones de suscripción. Las bibliotecas utilizan WebSockets puros como protocolo de red entre el cliente y el servicio.

nota

Para controlar la autorización en el momento de conectarse a una suscripción, puede usar AWS Identity and Access Management (IAM), AWS Lambda, los grupos de identidades de Amazon Cognito o los grupos de usuarios de Amazon Cognito para la autorización de nivel de campo. Para controles de acceso a las suscripciones más precisos, puede asociar solucionadores a los campos de la suscripción y aplicar una lógica basada en la identidad del intermediario y los orígenes de datos de AWS AppSync. Para obtener más información, consulte Configuración de la autorización y la autenticación para proteger las API de GraphQL.

Las suscripciones se activan a partir de mutaciones y el conjunto de mutaciones seleccionado se envía a los suscriptores.

En el siguiente ejemplo se muestra cómo usar las suscripciones de GraphQL. No especifica un origen de datos porque este puede ser Lambda, Amazon DynamoDB o Amazon OpenSearch Service.

Para comenzar a utilizar las suscripciones, debe agregar un punto de entrada de la suscripción a su esquema de este modo:

schema { query: Query mutation: Mutation subscription: Subscription }

Imagine que dispone de un sitio donde se publican blogs y que desea suscribirse a nuevos blogs y a los cambios en los blogs existentes. Para ello, puede añadir la siguiente definición Subscription a su esquema:

type Subscription { addedPost: Post updatedPost: Post deletedPost: Post }

Imagine también que tiene las siguientes mutaciones:

type Mutation { addPost(id: ID! author: String! title: String content: String url: String): Post! updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post! deletePost(id: ID!): Post! }

Puede convertir estos campos a tiempo real añadiendo una directiva @aws_subscribe(mutations: ["mutation_field_1", "mutation_field_2"]) para cada una de las suscripciones de las que desea recibir notificaciones, tal y como se indica a continuación:

type Subscription { addedPost: Post @aws_subscribe(mutations: ["addPost"]) updatedPost: Post @aws_subscribe(mutations: ["updatePost"]) deletedPost: Post @aws_subscribe(mutations: ["deletePost"]) }

Dado que la mutación @aws_subscribe(mutations: ["",..,""]) tiene una matriz de entradas de mutaciones, puede especificar varias mutaciones que inician una suscripción. Si se suscribe desde un cliente, su consulta de GraphQL podría tener el siguiente aspecto:

subscription NewPostSub { addedPost { __typename version title content author url } }

Esta consulta de suscripción es necesaria para las conexiones de cliente y para las herramientas.

Si utiliza el cliente WebSockets puro, el filtrado del conjunto de selecciones se realiza por cliente, ya que cada cliente puede definir su propio conjunto de este tipo. En este caso, el conjunto de selecciones de la suscripción debe ser un subconjunto del conjunto de selecciones de la mutación. Por ejemplo, una suscripción addedPost{author title} vinculada a la mutación addPost(...){id author title url version} solo recibe el autor y el título de la publicación. No recibe el resto de campos. Sin embargo, si la mutación no incluye el autor en su conjunto de selecciones, el suscriptor obtiene un valor null para el campo de autor (o bien un error, en caso de que el campo de autor se defina como obligatorio o no nulo en el esquema).

El conjunto de selección de suscripciones es esencial cuando se utiliza WebSockets puro. Si un campo no está definido explícitamente en la suscripción, AWS AppSync no lo devuelve.

En el ejemplo anterior, las suscripciones no tenía argumentos. Imaginemos que su esquema es similar al siguiente:

type Subscription { updatedPost(id:ID! author:String): Post @aws_subscribe(mutations: ["updatePost"]) }

En este caso, el cliente define una suscripción de este modo:

subscription UpdatedPostSub { updatedPost(id:"XYZ", author:"ABC") { title content } }

El tipo que devuelve el campo subscription del esquema debe coincidir con el tipo devuelto para el campo de mutación correspondiente. En el ejemplo anterior, tanto addPost como addedPost se devolvían con el tipo Post.

Para configurar las suscripciones en el cliente, consulte Creación de una aplicación cliente mediante el cliente de Amplify.

Uso de argumentos de suscripción

Un aspecto importante del uso de las suscripciones de GraphQL es comprender cuándo y cómo se deben usar los argumentos. Puede hacer cambios sutiles para modificar la forma y el momento de informar a los clientes acerca de las mutaciones que se han producido. Para ello, consulte el esquema de ejemplo del capítulo de inicio rápido, en el que se crean “Todos”. Para este esquema de ejemplo se definen las mutaciones siguientes:

type Mutation { createTodo(input: CreateTodoInput!): Todo updateTodo(input: UpdateTodoInput!): Todo deleteTodo(input: DeleteTodoInput!): Todo }

En el ejemplo de muestra, los clientes pueden suscribirse a las actualizaciones de cualquier Todo utilizando la opción onUpdateTodo subscription sin argumentos:

subscription OnUpdateTodo { onUpdateTodo { description id name when } }

Puede filtrar su subscription utilizando sus argumentos. Por ejemplo, para activar solo una subscription cuando se actualiza un todo con un ID específico, especifique el valor ID:

subscription OnUpdateTodo { onUpdateTodo(id: "a-todo-id") { description id name when } }

También se pueden transferir varios argumentos. Por ejemplo, la siguiente subscription muestra cómo recibir notificaciones de cualquier actualización de Todo en un lugar y hora específicos:

subscription todosAtHome { onUpdateTodo(when: "tomorrow", where: "at home") { description id name when where } }

Tenga en cuenta que todos los argumentos son opcionales. Si no especifica ningún argumento en su subscription, se suscribirá a todas las actualizaciones de Todo que se produzcan en su aplicación. Sin embargo, puede actualizar la definición de campo de su subscription para requerir el argumento ID. De este modo, forzaría la respuesta de un todo específico en lugar de la de todos los todo:

onUpdateTodo( id: ID!, name: String, when: String, where: String, description: String ): Todo

El valor nulo del argumento tiene un significado

Al hacer una consulta de suscripción en AWS AppSync, un valor de argumento null filtrará los resultados de una forma diferente sin omitir el argumento por completo.

Volvamos al ejemplo de la API de todos, donde podríamos crear todos. Consulte el ejemplo de esquema del capítulo de inicio rápido.

Vamos a modificar nuestro esquema para incluir un nuevo campo owner, del tipo Todo, que describa quién es el propietario. El campo owner no es obligatorio y solo se puede configurar en UpdateTodoInput. Consulte la siguiente versión simplificada del esquema:

type Todo { id: ID! name: String! when: String! where: String! description: String! owner: String } input CreateTodoInput { name: String! when: String! where: String! description: String! } input UpdateTodoInput { id: ID! name: String when: String where: String description: String owner: String } type Subscription { onUpdateTodo( id: ID, name: String, when: String, where: String, description: String ): Todo @aws_subscribe(mutations: ["updateTodo"]) }

La siguiente suscripción devuelve todas las actualizaciones de Todo:

subscription MySubscription { onUpdateTodo { description id name when where } }

Si modifica la suscripción anterior para agregar el argumento del campo owner: null, ahora está planteando una pregunta diferente. Ahora, esta suscripción registra al cliente para recibir notificaciones de todas las actualizaciones de Todo que no hayan indicado un propietario.

subscription MySubscription { onUpdateTodo(owner: null) { description id name when where } }
nota

A partir del 1 de enero de 2022, MQTT en WebSockets ya no estará disponible como protocolo para las suscripciones de GraphQL en las API de AWS AppSync. WebSockets puro es el único protocolo compatible con AWS AppSync.

Los clientes basados que usan el SDK de AWS AppSync o las bibliotecas de Amplify, publicadas después de noviembre de 2019, utilizan automáticamente WebSockets puro de forma predeterminada. Al actualizar los clientes a la última versión, les permite utilizar el motor de WebSockets puro de AWS AppSync.

WebSockets puro incorpora un tamaño de carga mayor (240 KB), una variedad más amplia de opciones de cliente y métricas de CloudWatch mejoradas. Para obtener más información sobre el uso de clientes WebSocket puros, consulte Creación de un cliente WebSocket en tiempo real en AWS AppSync.