Procedimientos recomendados del SDK de conectores de Microsoft Graph

En este artículo se proporcionan los procedimientos recomendados que se deben seguir al usar el SDK de conectores de Microsoft Graph para implementar un conector personalizado.

Uso del marcador de progreso de rastreo

El marcador de progreso de rastreo actúa como identificador del elemento determinado enviado por el conector que la plataforma procesó por última vez. Puede implementar dos tipos de rastreos: completos e incrementales periódicos.

Los rastreos completos periódicos obtienen todos los elementos del origen de datos e ingieren solo los elementos que se modifican o no están presentes en el índice. Si no encuentra un elemento, lo elimina del índice.

Los rastreos incrementales obtienen elementos agregados o modificados desde el último rastreo incremental. El conector también puede enviar elementos que se eliminarán como parte de este rastreo. Para el primer rastreo incremental, también se envía la hora de inicio del último rastreo completo. Opcionalmente, el conector puede usar este rastreo para capturar elementos modificados solo después del último rastreo completo.

Los rastreos completos e incrementales periódicos tienen sus marcadores de progreso de rastreo.

Uso del marcador de progreso de rastreo durante rastreos completos periódicos

El SDK envía el marcador de progreso del rastreo si el rastreo anterior se bloqueó o se perdió un rastreo programado debido a que el agente del conector de Microsoft Graph está sin conexión durante los rastreos completos periódicos.

Si el rastreo anterior no se bloqueó, debe rastrear el origen de datos desde el principio.

Uso del marcador de progreso de rastreo durante los rastreos incrementales

Durante un rastreo incremental, el conector envía el marcador de progreso de rastreo a la plataforma del conector y lo seguirá haciendo para los próximos rastreos incrementales. El conector puede usar este rastreo para capturar elementos agregados o modificados después de este marcador.

Construcción de tipos genéricos

Los valores de propiedad del elemento de contenido pueden tener un intervalo de tipos de datos. Dado que gRPC no tiene una construcción para objetos genéricos, el SDK incluye una estructura GenericType que puede contener cualquiera de los tipos de datos admitidos. GenericType tiene la siguiente estructura:

// Represents a generic type that can hold any supported value
message GenericType {
 // Value of the Generic type
 oneof value {
  // String type value
  string stringValue = 1;

  // Long value
  int64 intValue = 2;


  // Double value
  double doubleValue = 3;

  // DateTime value
  google.protobuf.Timestamp dateTimeValue = 4;

  // Boolean value
  bool boolValue = 5;

  // String collection value
  StringCollectionType stringCollectionValue = 6;

  // Long collection value
  IntCollectionType intCollectionValue = 7;

  // Double collection value
  DoubleCollectionType doubleCollectionValue = 8;

  // DateTime collection value
  TimestampCollectionType dateTimeCollectionValue = 9;
 }
}

// Collection of string
message StringCollectionType {
 // Value of string collection
 repeated string values = 1;
}

// Collection of long
message IntCollectionType {
 // Value of long collection
 repeated int64 values = 1;
}

// Collection of double
message DoubleCollectionType {
 // Value of double collection
 repeated double values = 1;
}

// Collection of DateTime
message TimestampCollectionType {
 // Value of DateTime collection
 repeated google.protobuf.Timestamp values = 1;
}

GenericType puede tener uno de los siguientes tipos: string, int64, double, DateTime y Boolean o una colección de string, int64, double y DateTime. A continuación se muestran ejemplos de cómo establecer estos tipos:

// Setting string value in generic type
    GenericType stringType = new GenericType
    {
        StringValue = "Hello"
    };

    // Setting int64 value in generic type
    GenericType int64Type = new GenericType
    {
        IntValue = 1000
    };

    // Setting double value in generic type
    GenericType doubleType = new GenericType
    {
        DoubleValue = 12.54
    };

    // Setting dateTime value in generic type
    GenericType dateTimeType = new GenericType
    {
        DateTimeValue = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow)
    };

    // Setting boolean value in generic type
    GenericType boolType = new GenericType
    {
        BoolValue = true
    };

    // Setting string collection value in generic type - Initialize the string collection first, add the values to the string collection and then set it in the generic type
    StringCollectionType stringCollection = new StringCollectionType();
    stringCollection.Values.Add("Value1");
    stringCollection.Values.Add("Value2");
    GenericType stringCollectionType = new GenericType
    {
        StringCollectionValue = stringCollection
    };

    // Setting int64 collection value in generic type - Initialize the int64 collection first, add the values to the int64 collection and then set it in the generic type
    IntCollectionType intCollection = new IntCollectionType();
    intCollection.Values.Add(1234);
    intCollection.Values.Add(5436);
    GenericType intCollectionType = new GenericType
    {
        IntCollectionValue = intCollection
    };

    // Setting double collection value in generic type - Initialize the double collection first, add the values to the double collection and then set it in the generic type
    DoubleCollectionType doubleCollection = new DoubleCollectionType();
    doubleCollection.Values.Add(12.54);
    doubleCollection.Values.Add(34.213);
    GenericType doubleCollectionType = new GenericType
    {
        DoubleCollectionValue = doubleCollection
    };

    // Setting datetime collection value in generic type - Initialize the datetime collection first, add the values to the datetime collection and then set it in the generic type
    TimestampCollectionType dateTimeCollection = new TimestampCollectionType();
    dateTimeCollection.Values.Add(Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow));
    dateTimeCollection.Values.Add(Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-1)));
    GenericType dateTimeCollectionType = new GenericType
    {
        DateTimeCollectionValue = dateTimeCollection
    };

Creación de un esquema de búsqueda

El esquema de conectores tiene las siguientes restricciones:

  • Nombre de propiedad: el nombre de la propiedad puede tener un máximo de 32 caracteres y solo se permiten caracteres alfanuméricos.
  • Búsqueda anotaciones:
    • Solo se pueden buscar las propiedades de tipo String o StringCollection .
    • Solo las propiedades de tipo String pueden ser una propiedad de contenido.
    • Las propiedades de contenido deben poder buscarse.
    • Las propiedades de contenido no se pueden consultar ni recuperar.
    • La propiedad refinable no debe ser de búsqueda.
    • La propiedad refinable debe ser consultable y recuperable.
    • Las propiedades booleanas no pueden ser refinables.
  • Alias: un conjunto de alias o un nombre descriptivo para la propiedad puede tener un máximo de 32 caracteres y solo se permiten caracteres alfanuméricos.

Captura de elementos durante un rastreo

El método GetCrawlStream es un método de streaming de servidor. Convierte cada elemento del origen de datos en un CrawlStreamBit durante el rastreo y lo envía a través del flujo de respuesta.

Para obtener un buen rendimiento, el conector debe recuperar un lote de elementos del origen de datos, convertir cada elemento en CrawlStreamBit y enviarlos a través del flujo de respuesta. El tamaño del lote depende del origen de datos. Se recomienda 25 como tamaño óptimo para mantener el flujo continuo de elementos a través de la secuencia.

Control de excepciones en el código del conector

Todas las respuestas de las llamadas gRPC tienen un operationstatus que indica si la operación se realizó correctamente o no, el motivo del error y los detalles de reintento si hay errores. Se recomienda ajustar todo el código en un bloque try-catch. El conector debe registrar todas las excepciones y enviar un estado de operación adecuado a la plataforma.

Los flujos de administración de conexiones envían una respuesta con StatusMessage que aparece en el Centro de administración de Microsoft 365. El envío de mensajes significativos facilita la depuración de los errores en la interfaz de usuario y evita dejar excepciones no controladas.

Timeouts

Todos los métodos de ConnectionManagementService deben completarse y devolverse en 30 segundos; De lo contrario, la plataforma devolverá un mensaje de error de tiempo de espera para la solicitud.

Envío de errores desde el conector a la plataforma

Todas las respuestas usan OperationStatus en la estructura de respuesta. Si se producen errores, los conectores deben usar OperationStatus para enviar el motivo del error y volver a intentar la información a la plataforma. Use OperationStatus para establecer los errores durante los rastreos si se producen errores de nivel de conexión, como credenciales expiradas para acceder al origen de datos.

La estructura OperationStatus tiene tres campos que se pueden usar para representar los errores.

OperationResult

OperationResult es una enumeración que puede contener el motivo del error.

StatusMessage

StatusMessage es una propiedad de OperationStatus que puede almacenar el mensaje personalizado para mostrar el motivo del error que aparecerá al administrador durante la configuración de la conexión. Por ejemplo, si las credenciales son incorrectas durante la validación con el método ValidateAuthentication , la propiedad result se puede establecer en AuthenticationIssue y la propiedad statusMessage se puede establecer en Credenciales incorrectas proporcionadas. Cuando se llama al método ValidateAuthentication , este statusMessage se mostrará al administrador de búsqueda. Durante los rastreos, este escenario moverá la conexión al estado de error, mostrará el error de autenticación al administrador y pedirá al administrador que actualice las credenciales para acceder al origen de datos.

RetryDetails

RetryDetails permite que el conector vuelva a enviar información a la plataforma sobre errores transitorios durante los rastreos y usarlo para repetir la operación.

El reintento puede ser un retroceso estándar o exponencial. El conector puede establecer el tiempo de pausa, la tasa de retroceso y el coeficiente de retroceso y enviarlos de vuelta. Por ejemplo, si el origen de datos está limitado durante el rastreo, el conector puede establecer OperationResult en DatasourceError y enviar los detalles del reintento según el encabezado retry-header en los encabezados de respuesta desde el origen de datos.

Asignación de errores para OperationResult

Los errores siguientes mueven la conexión al estado de error:

  • OperationResult.AuthenticationIssue

  • OperationResult.ValidationFailure

Los demás códigos de operación se tratarán como errores transitorios y se reintentarán en rastreos posteriores.