Réponses et traitement des erreurs

Le Snowflake Native SDK for Connectors utilise certaines réponses standard, en particulier pour les procédures exposées et conçues pour être utilisées à partir de l’UI. En outre, il fournit un moyen de s’assurer que les exceptions sont mappées en réponses valides et enregistrées dans la table EVENT TABLE.

Réponses

Les procédures SDK, qu’elles soient de haut niveau ou internes, utilisent la variant d’une certaine structure pour transmettre des informations. L’exigence pour une telle variant est qu’elle doit contenir un champ response_code et, dans certains cas, le code de réponse est différent de OK, dans le champ message requis. Tout champ supplémentaire peut être inclus, mais il nécessite un traitement personnalisé supplémentaire. Le format de réponse est le suivant :

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

Il est recommandé d’utiliser ce format lors du remplacement des implémentations par défaut des procédures et des objets.

Traitement des erreurs

Snowflake Native SDK for Connectors fournit un mécanisme par défaut utile pour gérer les exceptions qui peuvent survenir au cours de l’exécution. La classe responsable de cela est appelée ConnectorErrorHelper et son implémentation par défaut est DefaultConnectorErrorHelper. Cette fonction propose deux rappels personnalisables. Le premier, ExceptionMapper, est chargé d’intégrer toutes les erreurs inattendues dans le format ConnectorException. Cette fonction est utilisée principalement pour s’assurer que les réponses sont conformes au format mentionné ci-dessus.

Le deuxième rappel, appelé ExceptionLogger, garantit que l’erreur est consignée dans un journal. C’est important car toutes les entrées de journal standard sont alors enregistrées par Snowflake dans la table EVENT TABLE, ce qui facilite la résolution des problèmes avec les applications.

Comment utiliser l’assistant

L’assistant expose 2 méthodes :

  • withExceptionWrapping(Supplier<ConnectorResponse> action)

  • withExceptionLogging(Supplier<T> action)

Ces méthodes utilisent respectivement mapper et logger mentionnés ci-dessus. Il existe également une implémentation par défaut d’une méthode d’aide qui combine ces deux approches :

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

Il est recommandé d’utiliser ce wrapping au niveau le plus élevé possible lorsque vous appelez une méthode à partir d’un handler. Par exemple, dans ConnectionConfigurationHandler, il est utilisé de la manière suivante :

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

Le SDK expose également un constructeur permettant de personnaliser ce comportement, appelé ConnectorErrorHelperBuilder. Ce constructeur permet au développeur de personnaliser le comportement des rappels mapper et logger. Une fois personnalisé, le nouveau helper peut être transmis aux classes handler dans leurs builders respectifs. Par exemple :

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