Respostas e tratamento de erros

O Snowflake Native SDK for Connectors utiliza certas respostas padrão, especialmente para procedimentos expostos e projetados para serem usados a partir da UI. Além disso, ele fornece uma maneira de garantir que as exceções sejam mapeadas para respostas válidas e registradas no EVENT TABLE.

Respostas

Os procedimentos SDK, tanto de alto nível como internos, utilizam variant de uma certa estrutura para passar informações. A exigência de tal variant é que ele tem que conter um campo response_code e, em alguns casos, o código de resposta é diferente do OK, no campo message necessário. Qualquer campo adicional pode ser incluído, mas requer tratamento personalizado. O formato de resposta de THe é:

{
    "response_code": "<response code>",
    "message": "<message>"
}
Copy

É recomendável usar este formato ao substituir implementações padrão de procedimentos e objetos.

Tratamento de erros

O Snowflake Native SDK for Connectors fornece um mecanismo padrão útil para lidar com exceções que podem ocorrer durante o tempo de execução. A classe responsável por isso é chamada ConnectorErrorHelper e sua implementação padrão é DefaultConnectorErrorHelper. Este recurso fornece 2 retornos de chamada personalizáveis. O primeiro, ExceptionMapper, é responsável por envolver todos os erros inesperados no formato ConnectorException. Esse recurso é usado principalmente para garantir que as respostas estejam em conformidade com o formato mencionado acima.

O segundo retorno de chamada, chamado ExceptionLogger, garante que o erro seja registrado. Isso é importante porque todas as entradas de log padrão são salvas no EVENT TABLE pela Snowflake, que auxilia na resolução de problemas com os aplicativos.

Como usar o auxiliar

O auxiliar expõe 2 métodos:

  • withExceptionWrapping(Supplier<ConnectorResponse> action)

  • withExceptionLogging(Supplier<T> action)

Esses métodos usam respectivamente mapper e logger mencionados acima. Há também uma implementação padrão de um método auxiliar que mistura essas abordagens:

default ConnectorResponse withExceptionLoggingAndWrapping(Supplier<ConnectorResponse> action) {
    return withExceptionWrapping(() -> withExceptionLogging(action));
}
Copy

É recomendável usar esse encapsulamento no nível mais alto possível ao invocar um método de um handler. Por exemplo em ConnectionConfigurationHandler é usado assim:

public static Variant setConnectionConfiguration(Session session, Variant configuration) {
    var handler = ConnectionConfigurationHandler.builder(session).build();
    return handler.setConnectionConfiguration(configuration).toVariant();
}

public ConnectorResponse setConnectionConfiguration(Variant configuration) {
    return errorHelper.withExceptionLoggingAndWrapping(
        () -> setConnectionConfigurationBody(configuration)
    );
}
Copy

O SDK também expõe um construtor para personalizar esse comportamento, chamado ConnectorErrorHelperBuilder. Este construtor permite que o desenvolvedor personalize o comportamento dos retornos de chamada mapper e logger. Uma vez personalizado, o novo helper pode ser passado para as classes handler em seus respectivos builders. Por exemplo:

class CustomUnknownExceptionMapper implements ExceptionMapper<Exception> {

    @Override
    public ConnectorException map(Exception exception) {
        return new CustomConnectorException(exception);
    }
}

class CustomHandler {

    // Path to this method needs to be specified in the PUBLIC.SET_CONNECTION_CONFIGURATION procedure using SQL
    public static Variant configureConnection(Session session, Variant configuration) {
            //Using builder
        var errorHelper = new ConnectorErrorHelperBuilder()
            .withConnectorExceptionLogger(new CustomUnknownExceptionMapper())
            .build();

        var handler = ConnectionConfigurationHandler.builder(session)
            .withErrorHelper(errorHelper)
            .build();

        return handler.connectionConfiguration(configuration).toVariant();
    }
}
Copy