Manejar la paginación al leer desde una API en Jitterbit Studio
Introducción
La mayoría de las API REST limitan la cantidad de registros devueltos en una sola respuesta. Cuando un conjunto de datos es más grande que ese límite, la API divide los resultados en varias páginas y espera que quien realiza la llamada solicite cada página en secuencia. Sin soporte de paginación, una operación de Studio recupera solo la primera página y descarta silenciosamente el resto.
Esta guía cubre el enfoque de paginación por número de página, donde cada solicitud incluye un parámetro page que se incrementa con cada llamada. Una nota al final de la Parte 2 describe cómo adaptar el patrón para API basadas en cursores.
Esta guía asume familiaridad con la configuración de conexiones y actividades HTTP v2. Para una introducción general, consulta Llamar a una API REST usando el conector HTTP v2.
Patrón de diseño
El patrón utiliza dos operaciones:
-
Operación de obtención de página: Lee una página de la API y escribe los registros en el destino, utilizando el patrón de transformación:
flowchart LR A[Actividad HTTP v2 GET] --> B[Transformación] --> C[Actividad de destino] -
Operación controladora: Un paso de script único que realiza un bucle hasta que se recuperan todas las páginas.
El script controlador utiliza un bucle While que llama a RunOperation en la operación de obtención de página para cada página. RunOperation se ejecuta de forma síncrona de manera predeterminada, por lo que los cambios en las variables globales realizados dentro de la operación de obtención de página (incluida la señal de que no quedan más páginas) son visibles nuevamente en el controlador después de cada llamada.
Dos variables globales coordinan el bucle:
page: el número de página actual, inicializado a1en el controlador e incrementado después de cada obtención.has_more: una bandera inicializada atruey establecida afalsepor la transformación cuando se detecta la última página.
Parte 1: Configurar la operación de obtención de página
Paso 1: Configurar la actividad HTTP v2 GET
-
En el lienzo de diseño, arrastra una actividad HTTP v2 GET desde un extremo existente al lienzo para iniciar la operación de obtención de página.
-
Haz doble clic en la actividad para abrir su configuración.
-
Nombre: Ingresa un nombre como
Get Contacts Page. -
Ruta: Ingresa la ruta del extremo de la API, por ejemplo
/contacts. -
Parámetros de solicitud: Haz clic en el icono de agregar para agregar una fila e ingresa lo siguiente:
- Nombre:
page - Valor:
$page
Esto pasa la variable global
pagecomo parámetro de consulta en cada solicitud. Agrega una segunda fila con Nombreper_pagey un valor fijo como100para controlar la cantidad de registros devueltos por página. - Nombre:
-
Haz clic en Siguiente.
Paso 2: Definir el esquema de respuesta
-
Selecciona Sí, proporcionar esquema nuevo.
-
Ingresa un esquema JSON que incluya el array de registros y el campo de metadatos de paginación devuelto por la API. El siguiente esquema de ejemplo representa una respuesta que incluye un array
contactsy un campototal_pages:{ "type": "object", "properties": { "contacts": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "email": { "type": "string" } } } }, "total_pages": { "type": "integer" } } }Ajusta el esquema para que coincida con la estructura de respuesta real de tu API.
-
Haz clic en Siguiente y luego en Finalizado.
Parte 2: Extraer el estado de paginación en la transformación
La transformación asigna los campos de origen de la actividad GET a la actividad de destino y utiliza un script para actualizar la variable global has_more según si quedan más páginas.
-
Abre la transformación que sigue a la actividad GET.
-
Asigna cada campo del array de origen
contactsa los campos de destino correspondientes. -
En la transformación, agrega un script al nivel raíz (fuera del nodo de bucle) que establezca
has_moresegún el valortotal_pagesde la respuesta:$total_pages = Source.total_pages; If($page >= $total_pages, $has_more = false);
Esto lee el valor total_pages de la respuesta y establece $has_more = false cuando la página actual es la última.
Consejo
Si la API no devuelve un recuento total de páginas sino simplemente devuelve menos registros que el tamaño de página cuando se alcanza la última página, utiliza el recuento de registros para detectar el final en su lugar:
If(Count(Source.contacts.id) < 100, $has_more = false);
Reemplaza 100 con el valor per_page configurado en la actividad GET.
Paginación basada en cursor
Algunas APIs devuelven un cursor o una URL next_page en la respuesta en lugar de un recuento total de páginas. Para adaptar este patrón para APIs basadas en cursor, reemplaza page con una variable global cursor (inicializada a ""), pasa cursor como un parámetro de solicitud llamado cursor, y en la transformación asigna el campo next_cursor de la respuesta a cursor. Establece has_more = false cuando cursor está vacío:
$cursor = Source.next_cursor;
If($cursor == "", $has_more = false);
Elimina el incremento $page++ del script del controlador descrito en la Parte 3.
Parte 3: Escribe el script del controlador
La operación del controlador contiene un único script que inicializa el estado del bucle y llama a la operación de obtención de página repetidamente hasta que se hayan procesado todas las páginas.
-
En el lienzo de diseño, crea una nueva operación que contenga solo un paso Script.
-
Haz doble clic en el script para abrir el editor e ingresa lo siguiente:
$page = 1; $has_more = true; While($has_more, If(!RunOperation("<TAG>operation:Fetch Page</TAG>"), RaiseError(GetLastError())); $page++; );Reemplaza
Fetch Pagecon el nombre exacto de la operación de obtención de página. -
Guarda el script.
Puntos clave sobre este script:
pageyhas_moreson variables globales heredadas por la operación de obtención de página en cada llamada sincrónicaRunOperation.- Después de procesar cada página, el controlador incrementa
pageantes de iniciar la siguiente iteración. RaiseError(GetLastError())detiene el bucle inmediatamente y expone el error si la operación de obtención de página devuelve un error.RunOperationtambién está sujeto a un límite separado a nivel de agente en llamadas sincrónicas realizadas dentro de un único bucleWhile(50por defecto). Si la API pagina más allá de 50 páginas, este bucle alcanza ese límite antes de quehas_morese vuelvafalse:RunOperationdevuelvefalse, yRaiseError(GetLastError())detiene la operación con el mensaje de error del límite en lugar de completar la sincronización. Consulta la nota bajoRunOperationpara saber cómo configurar o anular este límite.-
La función
Whileaplica un recuento máximo de iteraciones, que por defecto es 50,000. Para APIs con conjuntos de datos muy grandes, establece$jitterbit.scripting.while.max_iterationsen un límite apropiado antes del bucle:$jitterbit.scripting.while.max_iterations = 2000; $page = 1; $has_more = true; While($has_more, If(!RunOperation("<TAG>operation:Fetch Page</TAG>"), RaiseError(GetLastError())); $page++; );
Verifica la integración
Implementa y ejecuta la operación del controlador. Consulta los registros de operación: la operación de obtención de página aparece una vez por página, por lo que el recuento de entradas de registro confirma cuántas páginas se recuperaron. Verifica que el recuento total de registros en el destino coincida con el conjunto de datos completo esperado de la API.
Para probar la terminación anticipada antes de procesar un conjunto de datos completo, establece $jitterbit.scripting.while.max_iterations = 3 en el script del controlador en la primera ejecución. Esto limita el bucle a tres páginas y te permite confirmar que el incremento de página, la asignación de esquema y la lógica de has_more funcionan correctamente antes de eliminar el límite y ejecutar contra el conjunto de datos completo.
Para agregar reintentos automáticos si falla la obtención de una página, consulta Reintentar una operación fallida. Para obtener orientación sobre la construcción de cadenas de consulta con valores de cursor o filtro dinámicos, consulta Construir cadenas de consulta dinámicas para llamadas a API REST.