Prácticas recomendadas para los reintentos de trabajos y puntos de control

Las tareas de trabajos individuales o incluso las ejecuciones de trabajos pueden fallar por varias razones. En esta página, se brindan prácticas recomendadas para manejar estas fallas, centradas en los reinicios de las tareas y los puntos de control de los trabajos.

Planifica los reinicios de las tareas de trabajos

Haz que tus trabajos sean idempotentes, de modo que el reinicio de una tarea no genere un resultado dañado o duplicado. Es decir, escribe una lógica repetible que tenga el mismo comportamiento para un conjunto de entradas determinado, sin importar cuántas veces se repita o cuándo se ejecute.

Escribe el resultado en una ubicación diferente a la de los datos de entrada y deja intactos estos últimos. De esta manera, si el trabajo se vuelve a ejecutar, puede repetir el proceso desde el principio y obtener el mismo resultado.

Evita duplicar los datos de salida mediante la reutilización del mismo identificador único o la verificación de si el resultado ya existe. Los datos duplicados representan la corrupción de datos a nivel de la colección.

Usa puntos de control

Siempre que sea posible, usa puntos de control en tus trabajos para que, si una tarea se reinicia después de una falla, pueda continuar desde donde se detuvo, en lugar de reiniciar el trabajo al comienzo. Esto acelerará tus trabajos y minimizará los costos innecesarios.

Escribe de forma periódica los resultados parciales y una indicación del progreso realizado en una ubicación de almacenamiento persistente, como Cloud Storage o una base de datos. Cuando comience la tarea, busca resultados parciales durante el inicio. Si se encuentran resultados parciales, comienza a procesar donde se dejaron.

Si tu trabajo no es adecuado para el punto de control, considera dividirlo en fragmentos más pequeños y ejecutar una mayor cantidad de tareas.

Ejemplo de punto de control 1: calcula pi

Si tienes un trabajo que ejecuta un algoritmo recurrente, como calcular pi a muchos decimales, y usa un paralelismo configurado en un valor de 1, haz lo siguiente:

  • Escribe el progreso cada 10 minutos o lo que permita la tolerancia del trabajo perdido en un objeto de Cloud Storage pi-progress.txt.
  • Cuando se inicia una tarea, consulta el objeto pi-progress.txt y carga el valor como punto de partida. Usa ese valor como la entrada inicial en tu función.
  • Escribe el resultado final en Cloud Storage como un objeto llamado pi-complete.txt para evitar la duplicación a través de la ejecución paralela o repetida, o pi-complete-DATE.txt a fin de diferenciarlo por fecha de finalización.

Ejemplo de punto de control 2: procesa 10,000 registros de Cloud SQL

Si tienes un trabajo que procesa 10,000 registros en una base de datos relacional, como Cloud SQL, haz lo siguiente:

  • Recupera los registros que se procesarán con una consulta de SQL, como SELECT * FROM example_table LIMIT 10000.
  • Escribe registros actualizados en lotes de 100 para que el trabajo de procesamiento significativo no se pierda en la interrupción.
  • Cuando se escriben registros, observa cuáles se procesaron. Puedes agregar una columna booleana procesada a la tabla que se establece en 1 solo si se confirma el procesamiento.
  • Cuando se inicia una tarea, la consulta que se usa a fin de recuperar los elementos para su procesamiento debe agregar la condición procesada = 0.
  • Además de los reintentos limpios, esta técnica también permite dividir el trabajo en tareas más pequeñas, como modificar tu consulta para seleccionar 100 registros a la vez: LIMIT 100 OFFSET $CLOUD_RUN_TASK_INDEX*100 y ejecutar 100 tareas con el fin de procesar los 10,000 registros. CLOUD_RUN_TASK_INDEX es una variable de entorno integrada presente dentro del contenedor que ejecuta trabajos de Cloud Run.

Con todas estas partes juntas, la consulta final podría verse así: SELECT * FROM example_table WHERE processed = 0 LIMIT 100 OFFSET $CLOUD_RUN_TASK_INDEX*100

¿Qué sigue?