Tratando Erros

Saiba como tratar erros e exceções.

Os erros Java são gerados como exceções quando você cria ou executa seu aplicativo. A classe NoSQLException é a base para a maioria das exceções geradas pelo driver. No entanto, o driver gera exceções diretamente para algumas classes, como IllegalArgumentException e NullPointerException.

Em geral, as instâncias de exceção NoSQL são divididas em duas categorias amplas:

  • Exceções que podem ser repetidas com expectativa de que possam ser bem-sucedidas na nova tentativa.

    Essas exceções são instâncias da classe RetryableException. Essas exceções geralmente indicam violações de consumo de recursos, como ThrottlingException.

  • Exceções que falharão mesmo após uma nova tentativa.

    Exemplos de exceções que não devem ser repetidas são IllegalArgumentException, TableNotFoundException e qualquer outra exceção que indique um erro sintático ou semântico.

Consulte o Guia de Referência da API Java para saber mais sobre essas exceções e como tratá-las.

Os erros do Python são gerados como exceções definidas como parte da API. Elas são todas instâncias do RuntimeError do Python. A maioria das exceções são instâncias de borneo.NoSQLException, que é uma classe base para exceções geradas pelo driver Python.

As exceções são divididas em 2 categorias amplas: exceções que podem ser repetidas com expectativa de que possam ser bem-sucedidas na nova tentativa. Estas são todas as instâncias de borneo.RetryableException. Exemplos disso são as instâncias de borneo.ThrottlingException, que são geradas quando os limites de consumo de recursos são excedidos. Exceções que não devem ser repetidas, pois falharão novamente. Exemplos disso incluem borneo.IllegalArgumentException , borneo.TableNotFoundException etc.

As instâncias borneo.ThrottlingException nunca serão lançadas em uma configuração local, pois não há limites relevantes.

Os erros Go SDK são reportados como valores nosqlerr.Error definidos como parte da API. Os erros são divididos em 2 categorias amplas:
  • Erros que podem ser repetidos com expectativa de que possam ser bem-sucedidos na nova tentativa. Estes são erros repetitivos nos quais a chamada do método Error.Retryable() retorna true. Exemplos disso incluem nosqlerr.OperationLimitExceeded, nosqlerr.ReadLimitExceeded, nosqlerr.WriteLimitExceeded, que são gerados quando limites de consumo de recursos são excedidos.
  • Erros que não devem ser repetidos, pois falharão novamente. Exemplos disso incluem nosqlerr.IllegalArgumentError, nosqlerr.TableNotFoundError etc.

Os métodos assíncronos de NoSQLClient retornam a Promessa como resultado e, se um erro ocorrer, isso resultará na rejeição da Promessa com esse erro. Para métodos síncronos, como erros do construtor NoSQLClient, são gerados como exceções. Todos os erros usados pelo SDK são instâncias de NoSQLError ou uma de suas subclasses. Além da mensagem de erro, cada erro tem a propriedade errorCode definida como um dos códigos de erro padrão definidos pela enumeração ErrorCode. errorCode pode ser útil para executar lógica condicional dependendo da natureza do erro.

Para alguns códigos de erro, subclasses específicas de NoSQLError são definidas, como NoSQLArgumentError, NoSQLProtocolError, NoSQLTimeoutError etc. NoSQLAuthorizationError pode ter um dos vários códigos de erro dependendo da causa da falha de autorização. Além disso, os erros podem ter a propriedade cause definida como o erro subjacente que causou o erro atual. Observe que a causa é opcional e pode ser uma instância de um erro que não faz parte do SDK.

Além disso, os códigos de erro são divididos em 2 categorias amplas:
  • Erros que podem ser repetidos com expectativa de que a operação possa ser bem-sucedida na nova tentativa. Exemplos disso são ErrorCode.READ_LIMIT_EXCEEDED e ErrorCode.WRITE_LIMIT_EXCEEDED, que são erros de aceleração (relevantes para o ambiente de Nuvem), e também ErrorCode.NETWORK_ERROR, uma vez que a maioria das condições de rede são temporárias.
  • Erros que não devem ser repetidos, pois a operação provavelmente falhará novamente. Exemplos disso incluem ErrorCode.ILLEGAL_ARGUMENT (representado por NoSQLArgumentError), ErrorCode.TABLE_NOT_FOUND etc.
Você pode determinar se o NoSQLError pode ser repetido verificando a propriedade retryable. Seu valor é definido como verdadeiro para erros repetitivos e é falso ou indefinido para erros não repetitivos.

Processador de Repetição

O driver repetirá automaticamente as operações em um erro repetitivo. O handler de repetição determina:
  • Se e quantas vezes a operação será repetida.
  • Quanto tempo esperar antes de cada nova tentativa.
RetryHandler é uma interface com 2 propriedades:
  • RetryHandler#doRetry que determina se a operação deve ser repetida com base na operação, o número de tentativas aconteceu até o momento e o erro ocorreu. Essa propriedade geralmente é uma função, mas também pode ser definida como falsa booliana para desativar novas tentativas automáticas.
  • RetryHandler#delay que determina quanto tempo esperar antes de cada repetição sucessiva com base nas mesmas informações fornecidas para RetryHandler#doRetry. Essa propriedade geralmente é uma função, mas também pode ser definida como o número de milissegundos para um atraso constante.
NoSQLException serve como uma classe base para muitas exceções geradas pelo driver. No entanto, em determinados casos, o driver usa tipos de exceção padrão, como:
  • ArgumentException e suas subclasses, como ArgumentNullException. Eles são lançados quando um argumento inválido é passado para um método ou quando uma configuração inválida (em código ou em JSON) é especificada para criar uma instância NoSQLClient.
  • TimeoutException é lançado quando há timeout de uma operação emitida por NoSQLClient. Se você estiver obtendo muitas exceções de timeout, poderá tentar aumentar os valores de timeout em NoSQLConfig ou no argumento de opções passado para o método NoSQLClient.
  • InvalidOperationException é lançado quando o serviço é um estado inválido para executar uma operação. Ela também poderá ser lançada se a consulta tiver falhado, pois seu processamento excedeu o limite de memória especificado em QueryOptions.MaxMemoryMB ou NoSQLConfig.MaxMemoryMB. Nesse caso, você pode aumentar o limite de memória correspondente. Caso contrário, você poderá repetir a operação.
  • InvalidCastException e OverflowException podem ocorrer ao trabalhar com subáreas de FieldValue e tentar converter um valor em um tipo que não suporta ou converter um valor numérico em um tipo menor causando overflow aritmético.
  • OperationCanceledException e TaskCanceledException se você tiver emitido um cancelamento da operação iniciada por um método NoSQLClient usando o CancellationToken fornecido.
Além disso, as exceções podem ser divididas em duas categorias amplas:
  • Exceções que podem ser repetidas com expectativa de que a operação possa ser bem-sucedida na nova tentativa. Em geral, são subclasses de RetryableException. Isso inclui a limitação de exceções, bem como outras exceções em que um recurso está temporariamente indisponível. Algumas outras subclasses de NoSQLException também podem ser repetidas dependendo das condições nas quais a exceção ocorreu. Além disso, erros relacionados à rede são repetidos porque a maioria das condições de rede é temporária.
  • Exceções que não devem ser repetidas porque ainda falharão após a nova tentativa. Eles incluem exceções como TableNotFoundException, TableExistsException e outras, além de exceções padrão, como ArgumentException.
Você pode determinar se determinada instância de NoSQLException pode ser repetida verificando sua propriedade IsRetryable.

Processador de Repetição

Por padrão, o driver repetirá automaticamente as operações que geraram uma exceção repetitiva (veja acima). O driver usa o handler de repetição para controlar novas tentativas de operação. O handler de repetição determina:
  • Se e quantas vezes a operação será repetida.
  • Quanto tempo esperar antes de cada nova tentativa.
Todos os handlers de repetição implementam a interface IRetryHandler. Essa interface fornece dois métodos: um para determinar se a operação em seu estado atual deve ser repetida e outro para determinar um atraso de repetição antes da próxima repetição. Você tem a opção de usar o handler de repetição padrão ou definir seu próprio handler de repetição como propriedade RetryHandler de NoSQLConfig ao criar a instância NoSQLClient.
Observação

As tentativas só são executadas dentro do período de timeout alocado para a operação e configuradas como uma das propriedades de timeout em NoSQLConfig ou em opções passadas para o método NoSQLClient. Se a operação ou suas novas tentativas não tiverem sido bem-sucedidas antes de o timeout ser atingido, TimeoutException será lançado.
Por padrão, o driver usa a classe NoSQLRetryHandler que controla a retirada com base no tipo de operação, no tipo de exceção e se o número de novas tentativas executadas atingiu um máximo pré-configurado. Ele também usa atraso de backoff exponencial para aguardar entre novas tentativas, começando com um atraso base pré-configurado. Você pode personalizar as propriedades, como o número máximo de novas tentativas, atraso base e outras, criando sua própria instância de NoSQLRetryHandler e definindo-a como uma propriedade RetryHandler em NoSQLConfig. Por exemplo:
var client = new NoSQLClient(
    new NoSQLConfig
    {
        Region = .....,
        ...............
        RetryHandler = new NoSQLRetryHandler
        {
            MaxRetryAttempts = 20,
            BaseDelay = TimeSpan.FromSeconds(2)
        }
    });
Se você não especificar o handler de repetição, o driver usará uma instância de NoSQLRetryHandler com valores padrão para todos os parâmetros. Como alternativa, você pode optar por criar sua própria classe de handler de repetição implementando a interface IRetryHandler . A última opção é desativar todas as tentativas juntas. Você poderá fazer isso se planejar repetir as operações no seu aplicativo. Para desativar novas tentativas, defina a propriedade RetryHandler como NoSQLConfig como NoRetries:
var client = new NoSQLClient(
    new NoSQLConfig
    {
        Region = .....,
        ...............
        RetryHandler = NoSQLConfig.NoRetries
    });

Tratar Limites de Recursos: A programação em um ambiente com recursos limitados pode ser um desafio. As tabelas têm limites de throughput especificados pelo usuário e, se um aplicativo exceder esses limites, ele poderá ser acelerado, o que significa que uma operação poderá falhar com uma das exceções de limitação, como ReadThrottlingException ou WriteThrottlingException. Isso é mais comum ao usar consultas, o que pode ler muitos dados, usando a capacidade muito rapidamente. Isso também pode acontecer em operações get e put que funcionam em um loop rígido.

Embora os erros de controle de fluxo sejam repetidos e o uso de RetryHandler personalizado possa permitir um controle mais direto sobre as repetições, um aplicativo não deve confiar em novas tentativas para tratar o controle de fluxo, pois isso resultará em desempenho ruim e incapacidade de usar todo o throughput disponível para a tabela. A melhor abordagem seria evitar totalmente a limitação de taxa de seu aplicativo. Nesse contexto, a limitação de taxas significa manter as taxas de operação abaixo dos limites para a tabela.