Gestión de errores

Descubra cómo gestionar errores y excepciones.

Los errores de Java se devuelven como excepciones al crear o ejecutar la aplicación. La clase NoSQLException es la base para la mayoría de las excepciones devueltas por el controlador. Sin embargo, el controlador devuelve excepciones directamente para algunas clases, como IllegalArgumentException y NullPointerException.

En general, las instancias de excepción de NoSQL se dividen en dos categorías amplias:

  • Excepciones que se pueden reintentar con la expectativa de que se realicen correctamente con ello.

    Estas excepciones son instancias de la clase RetryableException. Estas excepciones normalmente indican infracciones de consumo de recursos, como ThrottlingException.

  • Excepciones que fallarán incluso después de volver a intentarlo.

    Algunos ejemplos de excepciones que no se deben reintentar son IllegalArgumentException, TableNotFoundException y cualquier otra excepción que indique un error sintáctico o semántico.

Consulte la guía de referencia de API de Java para obtener más información sobre estas excepciones y cómo manejarlas.

Los errores de Python se generan como excepciones definidas como parte de la API. Son todas las instancias de RuntimeError de Python. La mayoría de las excepciones son instancias de borneo.NoSQLException, que es una clase base para las excepciones generadas por el controlador de Python.

Las excepciones se dividen en 2 amplias categorías: excepciones que se pueden volver a intentar con la expectativa de que se realicen correctamente. Todas estas instancias son de borneo.RetryableException. Algunos ejemplos son las instancias de borneo.ThrottlingException que se generan cuando se exceden los límites de consumo de recursos. Excepciones que no se deben reintentar, ya que se volverán a producir fallos. Entre los ejemplos de estos se incluyen borneo.IllegalArgumentException , borneo.TableNotFoundException, etc.

Las instancias borneo.ThrottlingException nunca se devolverán en una configuración local, ya que no hay límites relevantes.

Los errores de Go SDK se notifican como valores nosqlerr.Error definidos como parte de la API. Los errores se dividen en 2 amplias categorías:
  • Errores que se pueden volver a intentar con la expectativa de que se realicen correctamente. Se trata de errores reintentables en los que la llamada al método Error.Retryable() devuelve true. Entre los ejemplos de estos se incluyen nosqlerr.OperationLimitExceeded, nosqlerr.ReadLimitExceeded, nosqlerr.WriteLimitExceeded, que se generan cuando se exceden los límites de consumo de recursos.
  • Errores que no se deben reintentar, ya que se volverán a producir. Entre los ejemplos se incluyen nosqlerr.IllegalArgumentError, nosqlerr.TableNotFoundError, etc.

Los métodos asíncronos de NoSQLClient devuelven Promise como resultado y, si se produce un error, se produce el rechazo Promise con ese error. Para métodos síncronos como NoSQLClient, los errores del constructor se devuelven como excepciones. Todos los errores utilizados por el SDK son instancias de NoSQLError o una de sus subclases. Además del mensaje de error, cada error tiene definida la propiedad errorCode en uno de los códigos de error estándar definidos por la enumeración ErrorCode. errorCode puede ser útil para ejecutar la lógica condicional en función de la naturaleza del error.

Para algunos códigos de error, se definen subclases específicas de NoSQLError, como NoSQLArgumentError, NoSQLProtocolError, NoSQLTimeoutError, etc. NoSQLAuthorizationError puede tener uno de varios códigos de error en función de la causa del fallo de autorización. Además, los errores pueden tener la propiedad cause definida en el error subyacente que causó el error actual. Tenga en cuenta que la causa es opcional y puede ser una instancia de un error que no forma parte del SDK.

Además, los códigos de error se dividen en 2 categorías generales:
  • Errores que se pueden recuperar con la expectativa de que la operación se vuelva a intentar. Algunos ejemplos son ErrorCode.READ_LIMIT_EXCEEDED y ErrorCode.WRITE_LIMIT_EXCEEDED, que son errores de limitación (relevantes para el entorno en la nube), así como ErrorCode.NETWORK_ERROR, ya que la mayoría de las condiciones de red son temporales.
  • Errores que no se deben reintentar, ya que es probable que la operación vuelva a fallar. Entre los ejemplos se incluyen ErrorCode.ILLEGAL_ARGUMENT (representado por NoSQLArgumentError), ErrorCode.TABLE_NOT_FOUND, etc.
Puede determinar si NoSQLError se puede reintentar comprobando la propiedad retryable. Su valor se define en verdadero para errores reintentables y es falso o no se define para errores no reintentables.

Reintentar manejador

El controlador reintentará automáticamente las operaciones con un error reintentable. El manejador de reintentos determina:
  • Indica si la operación se volverá a intentar y cuántas veces.
  • Tiempo que se debe esperar antes de cada reintento.
RetryHandler es una interfaz con 2 propiedades:
  • RetryHandler#doRetry que determina si se debe reintentar la operación en función de la operación, el número de reintentos que se han producido hasta el momento y el error. Esta propiedad suele ser una función, pero también se puede definir en booleano falso para desactivar los reintentos automáticos.
  • RetryHandler#delay que determina el tiempo que se debe esperar antes de cada reintento sucesivo según la misma información proporcionada a RetryHandler#doRetry. Esta propiedad suele ser una función, pero también se puede establecer en número de milisegundos para un retraso constante.
NoSQLException sirve como clase base para muchas excepciones devueltas por el controlador. Sin embargo, en algunos casos el controlador utiliza tipos de excepción estándar, como:
  • ArgumentException y sus subclases como ArgumentNullException. Se devuelven cuando se transfiere un argumento no válido a un método o cuando se transfiere una configuración no válida (en código o en JSON) para crear una instancia NoSQLClient.
  • TimeoutException se devuelve cuando finaliza el tiempo de espera de una operación emitida por NoSQLClient. Si obtiene muchas excepciones de timeout, puede intentar aumentar los valores de timeout en NoSQLConfig o en el argumento de opciones transferido al método NoSQLClient.
  • InvalidOperationException se devuelve cuando el servicio tiene un estado no válido para realizar una operación. También se puede devolver si la consulta ha fallado porque su procesamiento ha excedido el límite de memoria especificado en QueryOptions.MaxMemoryMB o NoSQLConfig.MaxMemoryMB. En este caso, puede aumentar el límite de memoria correspondiente. De lo contrario, puede volver a intentar la operación.
  • InvalidCastException y OverflowException se pueden producir cuando se trabaja con subclases de FieldValue e intenta convertir un valor en un tipo que no admite o convierte un valor numérico en un tipo más pequeño que causa el desbordamiento aritmético.
  • OperationCanceledException y TaskCanceledException si ha emitido una cancelación de la operación iniciada por un método de NoSQLClient utilizando el CancellationToken proporcionado.
Además, las excepciones pueden dividirse en dos grandes categorías:
  • Excepciones que se pueden recuperar con la expectativa de que la operación se vuelva a intentar. En general, son subclases de RetryableException. Estas incluyen excepciones de limitación y otras excepciones en las que un recurso no está disponible temporalmente. Algunas otras subclases de NoSQLException también se pueden volver a intentar en función de las condiciones en las que se produjo la excepción. Además, los errores relacionados con la red se pueden reintentar porque la mayoría de las condiciones de red son temporales.
  • Excepciones que no se deben reintentar porque seguirán fallando después de volver a intentarlo. Incluyen excepciones como TableNotFoundException, TableExistsException y otras, así como excepciones estándar como ArgumentException.
Puede determinar si una determinada instancia de NoSQLException se puede reintentar comprobando su propiedad IsRetryable.

Reintentar manejador

De manera predeterminada, el controlador reintentará automáticamente las operaciones que generaron una excepción reintentable (consulte la información anterior). El controlador utiliza el manejador de reintentos para controlar los reintentos de operación. El manejador de reintentos determina:
  • Indica si la operación se volverá a intentar y cuántas veces.
  • Tiempo que se debe esperar antes de cada reintento.
Todos los controladores de reintentos implementan la interfaz IRetryHandler. Esta interfaz proporciona dos métodos, uno para determinar si se debe reintentar la operación en su estado actual y otro para determinar un retraso de reintento antes del siguiente reintento. Puede utilizar el manejador de reintentos por defecto o definir su propio manejador de reintentos como propiedad RetryHandler de NoSQLConfig al crear la instancia NoSQLClient.
Nota

Los reintentos solo se realizan dentro del período de timeout asignado a la operación y se configuran como una de las propiedades de timeout en NoSQLConfig o en las opciones transferidas al método NoSQLClient. Si la operación o sus reintentos no se han realizado correctamente antes de que se alcance el timeout, se devuelve TimeoutException.
Por defecto, el controlador utiliza la clase NoSQLRetryHandler que controla las bajas según el tipo de operación, el tipo de excepción y si el número de reintentos realizados ha alcanzado un máximo preconfigurado. También utiliza un retraso de retroceso exponencial para esperar entre reintentos que comienzan con un retraso base preconfigurado. Puede personalizar las propiedades como el número máximo de reintentos, el retraso base y otros mediante la creación de su propia instancia de NoSQLRetryHandler y su definición como una propiedad RetryHandler en NoSQLConfig. Por ejemplo:
var client = new NoSQLClient(
    new NoSQLConfig
    {
        Region = .....,
        ...............
        RetryHandler = new NoSQLRetryHandler
        {
            MaxRetryAttempts = 20,
            BaseDelay = TimeSpan.FromSeconds(2)
        }
    });
Si no especifica el manejador de reintentos, el controlador utilizará una instancia de NoSQLRetryHandler con valores por defecto para todos los parámetros. También puede elegir crear su propia clase de manejador de reintentos implementando la interfaz IRetryHandler . La última opción es desactivar todos los reintentos juntos. Puede hacerlo si planea reintentar las operaciones dentro de la aplicación en su lugar. Para desactivar los reintentos, defina la propiedad RetryHandler de NoSQLConfig en NoRetries:
var client = new NoSQLClient(
    new NoSQLConfig
    {
        Region = .....,
        ...............
        RetryHandler = NoSQLConfig.NoRetries
    });

Manejar límites de recursos: la programación en un entorno limitado por recursos puede resultar difícil. Las tablas tienen límites de rendimiento especificados por el usuario y, si una aplicación excede esos límites, se puede limitar, lo que significa que una operación puede fallar con una de las excepciones de limitación, como ReadThrottlingException o WriteThrottlingException. Esto es más común cuando se utilizan consultas, que pueden leer muchos datos, con una capacidad muy rápida. También puede suceder para operaciones get y put que se ejecutan en un bucle ajustado.

Aunque se reintentarán los errores de limitación y el uso de RetryHandler personalizado puede permitir un control más directo de los reintentos, una aplicación no debe basarse en reintentos para gestionar la limitación, ya que esto dará como resultado un rendimiento deficiente y la incapacidad para utilizar todo el rendimiento disponible para la tabla. El mejor enfoque sería evitar la limitación por completo mediante la limitación de velocidad de su aplicación. En este contexto, la limitación de la tasa significa mantener las tasas de operación por debajo de los límites de la tabla.