Entrega exactamente una vez

En esta página se explica cómo recibir y confirmar mensajes mediante la función de procesamiento una vez solo de Pub/Sub, que te permite hacer un seguimiento de los mensajes y evitar que se procesen dos veces. Cuando la función está habilitada, Pub/Sub proporciona la siguiente semántica:

  • Los suscriptores pueden determinar si las confirmaciones de mensajes se han realizado correctamente.

  • No se vuelve a enviar el mensaje después de que se haya confirmado correctamente.

  • No se vuelve a enviar un mensaje mientras esté pendiente. Un mensaje se considera pendiente hasta que vence el plazo de confirmación o hasta que se confirma.

  • En caso de que haya varias entregas válidas debido a que haya vencido el plazo de confirmación o a que el cliente haya enviado una confirmación negativa, solo se puede usar el ID de confirmación más reciente para confirmar el mensaje. Se producirá un error en cualquier solicitud con un ID de confirmación anterior.

Si se habilita el procesamiento exacto, los suscriptores pueden asegurarse de que los mensajes se procesen una vez siguiendo estas directrices:

  • Confirmar los mensajes antes de la fecha límite.

  • Mantener información sobre el progreso del procesamiento de un mensaje hasta que se confirme correctamente.

  • Usa la información sobre el progreso del procesamiento de un mensaje para evitar que se duplique el trabajo cuando falla una confirmación.

Solo el tipo de suscripción de extracción admite el envío exactamente una vez, incluidos los suscriptores que usan la API StreamingPull. Las suscripciones push y de exportación no admiten la entrega exactamente una vez.

Pub/Sub admite la entrega exactamente una vez en una región de la nube, basada en un ID de mensaje único definido por Pub/Sub.

Volver a proporcionar frente a duplicar

Es importante entender la diferencia entre las reintentos de envío esperados e inesperados.

  • Una nueva entrega puede producirse debido a una confirmación negativa iniciada por el cliente de un mensaje o cuando el cliente no amplía el plazo de confirmación del mensaje antes de que expire. Las reentregas se consideran válidas y el sistema funciona según lo previsto.

    Para solucionar problemas de reenvío, consulta Gestionar duplicados.

  • Se produce una duplicación cuando se vuelve a enviar un mensaje después de que se haya confirmado correctamente o antes de que caduque el plazo de confirmación.

  • Un mensaje reenviado conserva el mismo ID de mensaje entre los intentos de reenvío.

Las suscripciones con la entrega exactamente una vez habilitada no reciben entregas duplicadas.

Compatibilidad con la entrega exactamente una vez en bibliotecas de cliente

  • Las bibliotecas de cliente admitidas tienen una interfaz para la confirmación con respuesta (por ejemplo, Go). Puedes usar esta interfaz para comprobar si la solicitud de confirmación se ha realizado correctamente. Si la solicitud de confirmación se realiza correctamente, los clientes tienen la garantía de no recibir una nueva entrega. Si la solicitud de confirmación falla, los clientes pueden esperar una nueva entrega.

  • Los clientes también pueden usar las bibliotecas de cliente admitidas sin la interfaz de confirmación. Sin embargo, en estos casos, los errores de confirmación pueden provocar que los mensajes se vuelvan a enviar de forma silenciosa.

  • Las bibliotecas de cliente admitidas tienen interfaces para definir el tiempo mínimo de extensión de la concesión (por ejemplo, Go). Debe asignar un valor alto a la extensión mínima de la concesión para evitar que caduquen las confirmaciones relacionadas con la red. El valor máximo es de 600 segundos.

  • Si usas la biblioteca de cliente de Java e inicializas tu suscriptor con un canal gRPC personalizado mediante el método setChannelProvider(), te recomendamos que también definas maxInboundMetadataSize en al menos 1 MB al crear tu TransportChannelProvider. Para esta configuración, puedes usar el método InstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize() o el método ManagedChannelBuilder.maxInboundMetadataSize().

Los valores predeterminados y el intervalo de las variables relacionadas con el envío exactamente una vez y los nombres de las variables pueden variar en las bibliotecas de cliente. Por ejemplo, en la biblioteca de cliente de Java, las siguientes variables controlan el envío exactamente una vez.

Variable Descripción Valor
setEnableExactlyOnceDelivery Habilita o inhabilita el envío exactamente una vez. verdadero o falso. Valor predeterminado: falso.
minDurationPerAckExtension Tiempo mínimo en segundos que se debe usar para ampliar el plazo de confirmación de modificación. Intervalo: de 0 a 600. Valor predeterminado: ninguno.
maxDurationPerAckExtension Tiempo máximo en segundos que se puede usar para ampliar el plazo de confirmación de la modificación. Intervalo: de 0 a 600. Valor predeterminado: ninguno.

En el caso de la entrega exactamente una vez, la solicitud modifyAckDeadline o acknowledgment a Pub/Sub falla cuando el ID de confirmación ya ha caducado. En estos casos, el servicio considera que el ID de confirmación caducado no es válido, ya que es posible que ya se haya enviado una entrega más reciente. Este es el comportamiento programado para la entrega exactamente una vez. A continuación, verás que las solicitudes acknowledgment y ModifyAckDeadline devuelven una respuesta INVALID_ARGUMENT. Cuando la entrega exactamente una vez está inhabilitada, estas solicitudes devuelven OK en los casos de IDs de confirmación caducados.

Para asegurarse de que las solicitudes acknowledgment y ModifyAckDeadline tengan IDs de confirmación válidos, puede asignar un valor alto a minDurationPerAckExtension.

Consideraciones regionales

La garantía de entrega exactamente una vez solo se aplica cuando los suscriptores se conectan al servicio en la misma región. Si tu aplicación de suscriptor se distribuye en varias regiones, puede provocar que los mensajes se entreguen por duplicado, incluso cuando la entrega exactamente una vez esté habilitada. Los editores pueden enviar mensajes a cualquier región y se sigue manteniendo la garantía de entrega exactamente una vez.

Cuando ejecutas tu aplicación en Google Cloud, se conecta de forma predeterminada al endpoint de Pub/Sub de la misma región. Por lo tanto, si ejecutas tu aplicación en una sola región de Google Cloud generalmente te aseguras de interactuar con una sola región.

Si ejecutas tu aplicación de suscriptor fuera de Google Cloud o en varias regiones, puedes asegurarte de que te conectas a una sola región usando un endpoint de ubicación al configurar tu cliente de Pub/Sub. Todos los endpoints de ubicación de Pub/Sub apuntan a regiones únicas. Para obtener más información sobre los endpoints de ubicación, consulta Endpoints de Pub/Sub. Para ver una lista de todos los endpoints de ubicación de Pub/Sub, consulta la lista de endpoints de ubicación.

Crear suscripciones con entrega exactamente una vez

Puedes crear una suscripción con entrega exactamente una vez mediante la consola de Google Cloud, la CLI de Google Cloud, la biblioteca de cliente o la API de Pub/Sub. Google Cloud

Suscripción de extracción

Consola

Para crear una suscripción de extracción con entrega exactamente una vez, sigue estos pasos:

  1. En la Google Cloud consola, ve a la página Suscripciones.

    Ir a Suscripciones

  2. Haz clic en Crear suscripción.

  3. Introduce el ID de suscripción.

  4. Elige o crea un tema en el menú desplegable.

    La suscripción recibe mensajes del tema.

  5. En la sección Entrega exactamente una vez, seleccione Habilitar entrega exactamente una vez.

  6. Haz clic en Crear.

gcloud

Para crear una suscripción pull con entrega exactamente una vez, usa el comando gcloud pubsub subscriptions create con la marca --enable-exactly-once-delivery:

gcloud pubsub subscriptions create SUBSCRIPTION_ID \
  --topic=TOPIC_ID \
  --enable-exactly-once-delivery

Haz los cambios siguientes:

  • SUBSCRIPTION_ID: ID de la suscripción que se va a crear.
  • TOPIC_ID: el ID del tema al que se adjuntará la suscripción

REST

Para crear una suscripción con entrega exactamente una vez, usa el método projects.subscriptions.create.

PUT https://pubsub.googleapis.com/v1/projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID
Authorization: Bearer $(gcloud auth print-access-token)

Haz los cambios siguientes:

  • PROJECT_ID: el ID del proyecto en el que se va a crear la suscripción
  • SUBSCRIPTION_ID: ID de la suscripción que se va a crear.

Para crear una suscripción de extracción con entrega exactamente una vez, especifica lo siguiente en el cuerpo de la solicitud:

{
  "topic": "projects/PROJECT_ID/topics/TOPIC_ID",
  "enableExactlyOnceDelivery": true,
}

Haz los cambios siguientes:

  • PROJECT_ID: el ID del proyecto que contiene el tema
  • TOPIC_ID: el ID del tema al que se adjuntará la suscripción

C++

Antes de probar este ejemplo, sigue las instrucciones de configuración de C++ que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de C++ de Pub/Sub.

namespace pubsub = ::google::cloud::pubsub;
namespace pubsub_admin = ::google::cloud::pubsub_admin;
[](pubsub_admin::SubscriptionAdminClient client,
   std::string const& project_id, std::string const& topic_id,
   std::string const& subscription_id) {
  google::pubsub::v1::Subscription request;
  request.set_name(
      pubsub::Subscription(project_id, subscription_id).FullName());
  request.set_topic(pubsub::Topic(project_id, topic_id).FullName());
  request.set_enable_exactly_once_delivery(true);
  auto sub = client.CreateSubscription(request);
  if (sub.status().code() == google::cloud::StatusCode::kAlreadyExists) {
    std::cout << "The subscription already exists\n";
    return;
  }
  if (!sub) throw std::move(sub).status();

  std::cout << "The subscription was successfully created: "
            << sub->DebugString() << "\n";
}

C#

Antes de probar este ejemplo, sigue las instrucciones de configuración de C# que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de C# de Pub/Sub.


using Google.Cloud.PubSub.V1;
using Grpc.Core;

public class CreateSubscriptionWithExactlyOnceDeliverySample
{
    public Subscription CreateSubscriptionWithExactlyOnceDelivery(string projectId, string topicId, string subscriptionId)
    {
        SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();
        TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);
        SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);

        var subscriptionRequest = new Subscription
        {
            SubscriptionName = subscriptionName,
            TopicAsTopicName = topicName,
            EnableExactlyOnceDelivery = true
        };

        Subscription subscription = null;

        try
        {
            subscription = subscriber.CreateSubscription(subscriptionRequest);
        }
        catch (RpcException e) when (e.Status.StatusCode == StatusCode.AlreadyExists)
        {
            // Already exists.  That's fine.
        }
        return subscription;
    }
}

Go

En el siguiente ejemplo se usa la versión principal de la biblioteca de cliente de Pub/Sub de Go (v2). Si sigues usando la biblioteca v1, consulta la guía de migración a la versión 2. Para ver una lista de ejemplos de código de la versión 1, consulta los ejemplos de código obsoletos.

Antes de probar este ejemplo, sigue las instrucciones de configuración de Go que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API Go de Pub/Sub.

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub/v2"
	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
)

func createSubscriptionWithExactlyOnceDelivery(w io.Writer, projectID, topic, subscription string) error {
	// projectID := "my-project-id"
	// topic := "projects/my-project-id/topics/my-topic"
	// subscription := "projects/my-project/subscriptions/my-sub"
	ctx := context.Background()
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("pubsub.NewClient: %w", err)
	}
	defer client.Close()

	pbSub := &pubsubpb.Subscription{
		Name:                      subscription,
		Topic:                     topic,
		EnableExactlyOnceDelivery: true,
	}
	sub, err := client.SubscriptionAdminClient.CreateSubscription(ctx, pbSub)
	if err != nil {
		return fmt.Errorf("failed to create exactly once sub: %w", err)
	}
	fmt.Fprintf(w, "Created a subscription with exactly once delivery enabled: %v\n", sub)
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración de Java que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Java de Pub/Sub.

import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.ProjectTopicName;
import com.google.pubsub.v1.Subscription;
import java.io.IOException;

public class CreateSubscriptionWithExactlyOnceDelivery {
  public static void main(String... args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String topicId = "your-topic-id";
    String subscriptionId = "your-subscription-id";

    createSubscriptionWithExactlyOnceDeliveryExample(projectId, topicId, subscriptionId);
  }

  public static void createSubscriptionWithExactlyOnceDeliveryExample(
      String projectId, String topicId, String subscriptionId) throws IOException {
    try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {

      ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
      ProjectSubscriptionName subscriptionName =
          ProjectSubscriptionName.of(projectId, subscriptionId);

      Subscription subscription =
          subscriptionAdminClient.createSubscription(
              Subscription.newBuilder()
                  .setName(subscriptionName.toString())
                  .setTopic(topicName.toString())
                  // Enable exactly once delivery in the subscription.
                  .setEnableExactlyOnceDelivery(true)
                  .build());

      System.out.println(
          "Created a subscription with exactly once delivery enabled: "
              + subscription.getAllFields());
    }
  }
}

Python

Antes de probar este ejemplo, sigue las instrucciones de configuración de Python que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Python de Pub/Sub.

from google.cloud import pubsub_v1

# TODO(developer): Choose an existing topic.
# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"

publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
topic_path = publisher.topic_path(project_id, topic_id)
subscription_path = subscriber.subscription_path(project_id, subscription_id)

with subscriber:
    subscription = subscriber.create_subscription(
        request={
            "name": subscription_path,
            "topic": topic_path,
            "enable_exactly_once_delivery": True,
        }
    )
    print(
        f"Created subscription with exactly once delivery enabled: {subscription}"
    )

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración de Node.js que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Node.js de Pub/Sub.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';

// Imports the Google Cloud client library
const {PubSub} = require('@google-cloud/pubsub');

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createSubscriptionWithExactlyOnceDelivery(
  topicNameOrId,
  subscriptionNameOrId,
) {
  // Creates a new subscription
  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, {
      enableExactlyOnceDelivery: true,
    });
  console.log(
    `Created subscription ${subscriptionNameOrId} with exactly-once delivery.`,
  );
  console.log(
    'To process messages, remember to check the return value of ackWithResponse().',
  );
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración de Node.js que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Node.js de Pub/Sub.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';

// Imports the Google Cloud client library
import {PubSub} from '@google-cloud/pubsub';

// Creates a client; cache this for further use
const pubSubClient = new PubSub();

async function createSubscriptionWithExactlyOnceDelivery(
  topicNameOrId: string,
  subscriptionNameOrId: string,
) {
  // Creates a new subscription
  await pubSubClient
    .topic(topicNameOrId)
    .createSubscription(subscriptionNameOrId, {
      enableExactlyOnceDelivery: true,
    });
  console.log(
    `Created subscription ${subscriptionNameOrId} with exactly-once delivery.`,
  );
  console.log(
    'To process messages, remember to check the return value of ackWithResponse().',
  );
}

Ruby

En el siguiente ejemplo se usa la biblioteca de cliente de Ruby Pub/Sub v3. Si sigues usando la biblioteca v2, consulta la guía de migración a la versión 3. Para ver una lista de ejemplos de código de Ruby v2, consulta los ejemplos de código obsoletos.

Antes de probar este ejemplo, sigue las instrucciones de configuración de Ruby que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Ruby de Pub/Sub.

# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"

pubsub = Google::Cloud::PubSub.new project_id: project_id
subscription_admin = pubsub.subscription_admin

subscription = subscription_admin.create_subscription \
  name: pubsub.subscription_path(subscription_id),
  topic: pubsub.topic_path(topic_id),
  enable_exactly_once_delivery: true

puts "Created subscription with exactly once delivery enabled: " \
     "#{subscription_id}"

PHP

Antes de probar este ejemplo, sigue las instrucciones de configuración de PHP que se indican en la guía de inicio rápido sobre cómo usar bibliotecas de cliente. Para obtener más información, consulta la documentación de referencia de la API de Pub/Sub para PHP.

use Google\Cloud\PubSub\PubSubClient;

/**
 * Creates a Pub/Sub subscription with `Exactly Once Delivery` enabled.
 *
 * @param string $projectId  The Google project ID.
 * @param string $topicName  The Pub/Sub topic name.
 * @param string $subscriptionName  The Pub/Sub subscription name.
 */
function create_subscription_with_exactly_once_delivery(
    string $projectId,
    string $topicName,
    string $subscriptionName
): void {
    $pubsub = new PubSubClient([
        'projectId' => $projectId,
    ]);
    $topic = $pubsub->topic($topicName);
    $subscription = $topic->subscription($subscriptionName);
    $subscription->create([
        'enableExactlyOnceDelivery' => true
    ]);

    // Exactly Once Delivery status for the subscription
    $status = $subscription->info()['enableExactlyOnceDelivery'];

    printf('Subscription created with exactly once delivery status: %s' . PHP_EOL, $status ? 'true' : 'false');
}

Monitorizar suscripciones de entrega de mensajes exactamente una vez

La métrica subscription/exactly_once_warning_count registra el número de eventos que pueden provocar reenvíos (válidos o duplicados). Esta métrica cuenta las veces que Pub/Sub no puede procesar las solicitudes asociadas a IDs de confirmación (solicitud ModifyAckDeadline o acknowledgment). Los motivos del fallo pueden deberse al servidor o al cliente. Por ejemplo, si la capa de persistencia utilizada para mantener la información de entrega exactamente una vez no está disponible, se trataría de un evento basado en el servidor. Si el cliente intenta confirmar un mensaje con un ID de confirmación no válido, se trataría de un evento basado en el cliente.

Familiarizarse con la métrica

subscription/exactly_once_warning_count registra eventos que pueden o no provocar reenvíos reales y puede ser ruidoso en función del comportamiento del cliente. Por ejemplo, las solicitudes repetidas de acknowledgment o ModifyAckDeadline con IDs de confirmación no válidos incrementan la métrica repetidamente.

Las siguientes métricas también son útiles para comprender el comportamiento de los clientes:

  • subscription/expired_ack_deadlines_count muestra el número de expiraciones de IDs de confirmación. Si caducan los IDs de confirmación, se pueden producir errores en las solicitudes ModifyAckDeadline y acknowledgment.

  • La métrica service.serviceruntime.googleapis.com/api/request_count se puede usar para registrar los errores de las solicitudes ModifyAckDeadline o acknowledgment en los casos en los que las solicitudes llegan a Google Cloud , pero no a Pub/Sub. Hay fallos que esta métrica no registrará, como cuando los clientes se desconectan de Google Cloud.

En la mayoría de los casos de eventos de error que se pueden reintentar, las bibliotecas de cliente admitidas reintentan la solicitud automáticamente.

Cuotas

Las suscripciones de entrega exactamente una vez están sujetas a requisitos de cuota adicionales. Estas cuotas se aplican en los siguientes casos:

  • Número de mensajes consumidos de suscripciones con la opción de entrega exactamente una vez habilitada por región.
  • Número de mensajes confirmados o cuyo plazo se ha ampliado al usar suscripciones con la opción de envío exactamente una vez habilitada por región.

Para obtener más información sobre estas cuotas, consulta la tabla del tema Cuotas.

Entrega única y suscripciones ordenadas

Pub/Sub admite la entrega exacta una sola vez con la entrega ordenada.

Cuando se usa la ordenación con la entrega exactamente una vez, Pub/Sub espera que las confirmaciones estén ordenadas. Si los acuses de recibo no están en orden, el servicio rechaza las solicitudes con errores temporales. Si el plazo de confirmación vence antes de que se confirme la entrega, el cliente recibirá una nueva entrega del mensaje. Por este motivo, cuando usas la ordenación con la entrega exactamente una vez, el rendimiento del cliente se limita a un orden de mil mensajes por segundo.

Entrega exacta y suscripciones push

Pub/Sub solo admite la entrega de mensajes una sola vez con suscripciones de extracción.

Los clientes que consumen mensajes de las suscripciones push confirman la recepción de los mensajes respondiendo a las solicitudes push con una respuesta correcta. Sin embargo, los clientes no saben si la suscripción de Pub/Sub ha recibido la respuesta y la ha procesado. Esto es diferente de las suscripciones de extracción, en las que los clientes inician las solicitudes de confirmación y la suscripción de Pub/Sub responde si la solicitud se ha procesado correctamente. Por este motivo, la semántica de envío exactamente una vez no se ajusta bien a las suscripciones push.

Puntos a tener en cuenta

  • Si no se especifica ningún plazo de confirmación al crear la suscripción, las suscripciones con la opción de envío exactamente una vez habilitada tendrán un plazo de confirmación predeterminado de 60 segundos.

  • Los plazos de confirmación predeterminados más largos son útiles para evitar que se vuelva a enviar el contenido debido a eventos de red. Las bibliotecas de cliente admitidas no usan el plazo de confirmación de suscripción predeterminado.

  • Las suscripciones con entrega exactamente una vez tienen una latencia de publicación a suscripción significativamente mayor que las suscripciones normales.

  • Si necesitas un alto rendimiento, tus clientes de entrega exactamente una vez también deben usar streaming pull.

  • Una suscripción puede recibir varias copias del mismo mensaje debido a duplicados del lado de la publicación, incluso si se ha habilitado la entrega exactamente una vez. Las duplicaciones del lado de la publicación pueden deberse a varios reintentos de publicación únicos por parte del cliente de publicación o del servicio Pub/Sub. Si el cliente de publicación publica varios elementos únicos en diferentes reintentos, se producirán reenvíos con diferentes IDs de mensaje. Si el servicio Pub/Sub publica varios mensajes únicos para responder a una solicitud de publicación de un cliente, se volverán a enviar con los mismos IDs de mensaje.

  • Puedes volver a intentar las operaciones fallidas en subscription/exactly_once_warning_count y las bibliotecas de cliente admitidas lo harán automáticamente. Sin embargo, los errores relacionados con IDs de confirmación no válidos no se pueden reintentar.