Recuerda que en la informática cualquier problema casi siempre tiene varias soluciones, no obstante aquí enseñaremos lo más óptimo y eficiente.
Solución:
miraste InvisibilityTimeout
configuración de los documentos de Hangfire?
La implementación predeterminada de almacenamiento de trabajos de SQL Server utiliza una tabla normal como cola de trabajos. Para asegurarse de que un trabajo no se perderá en caso de una finalización inesperada del proceso, solo se elimina de una cola cuando finaliza con éxito.
Para hacerlo invisible para otros trabajadores, la instrucción UPDATE con la cláusula OUTPUT se usa para obtener un trabajo en cola y actualizar el valor FetchedAt (que indica a otros trabajadores que se obtuvo) de forma atómica. Otros trabajadores ven la marca de tiempo obtenida e ignoran un trabajo. Pero para manejar la finalización del proceso, ignorarán un trabajo solo durante un período de tiempo específico (el valor predeterminado es 30 minutos).
Aunque este mecanismo garantiza que se procesarán todos los trabajos, a veces puede provocar una latencia de reintento prolongada o provocar la ejecución de varios trabajos. Considere el siguiente escenario:
- El trabajador A buscó un trabajo (se ejecuta durante una hora) y lo inició a las 12:00.
- El trabajador B buscó el mismo trabajo a las 12:30, porque el tiempo de invisibilidad predeterminado había expirado.
- El trabajador C (no buscó) el mismo trabajo a las 13:00 porque (se eliminará después de un desempeño exitoso).
Si está utilizando tokens de cancelación, se establecerá para el Trabajador A a las 12:30 y a las 13:00 para el Trabajador B. Esto puede llevar al hecho de que su trabajo de ejecución prolongada nunca se ejecutará. Si no está utilizando tokens de cancelación, WorkerA y Worker B lo ejecutarán simultáneamente (desde las 12:30), pero Worker C no lo recuperará porque se eliminará después de un desempeño exitoso.
Por lo tanto, si tiene trabajos de ejecución prolongada, es mejor configurar el intervalo de tiempo de espera de invisibilidad:
var options = new SqlServerStorageOptions
InvisibilityTimeout = TimeSpan.FromMinutes(30) // default value
;
GlobalConfiguration.Configuration.UseSqlServerStorage("", options);
A partir de Hangfire 1.5, esta opción ahora está Obsolete
. Los trabajos en los que se está trabajando son invisibles para otros trabajadores.
Despídase del tiempo de espera de invisibilidad confuso con reintentos inesperados de trabajos en segundo plano después de 30 minutos (de forma predeterminada) cuando usa SQL Server. La nueva implementación de Hangfire.SqlServer utiliza transacciones simples y antiguas para obtener trabajos en segundo plano y ocultarlos de otros trabajadores.
Incluso después de un cierre inesperado, el trabajo estará disponible para otros trabajadores al instante, sin demoras.
Estaba teniendo problemas para encontrar documentación sobre cómo hacer esto correctamente para una base de datos de Postgresql, cada ejemplo que vi estaba usando sqlserver, descubrí que el tiempo de espera de invisibilidad era una propiedad dentro del objeto PostgreSqlStorageOptions, encontré esto aquí: https://github .com/frankhommers/Hangfire.PostgreSql/blob/master/src/Hangfire.PostgreSql/PostgreSqlStorageOptions.cs#L36. Afortunadamente, a través de prueba y error, pude darme cuenta de que UsePostgreSqlStorage tiene una sobrecarga para aceptar este objeto. Para .Net Core 2.0 cuando esté configurando la base de datos postgresql hangfire en el método ConfigureServices en la clase de inicio, agregue esto (el tiempo de espera predeterminado se establece en 30 minutos):
services.AddHangfire(config =>
config.UsePostgreSqlStorage(Configuration.GetConnectionString("Hangfire1ConnectionString"), new PostgreSqlStorageOptions
InvisibilityTimeout = TimeSpan.FromMinutes(720)
));
Tuve este problema al usar Hangfire.MemoryStorage como proveedor de almacenamiento. Con el almacenamiento de memoria, debe configurar el FetchNextJobTimeout
en el MemoryStorageOptions
de lo contrario, por defecto, los trabajos expirarán después de 30 minutos y se ejecutará un nuevo trabajo.
var options = new MemoryStorageOptions
FetchNextJobTimeout = TimeSpan.FromDays(1)
;
GlobalConfiguration.Configuration.UseMemoryStorage(options);
Aquí tienes las comentarios y valoraciones
Tienes la posibilidad difundir esta noticia si lograste el éxito.