We were using MongoDb in our project and Hangfire was working perfectly fine over there but after we have shifted to CosmosDb Hangfire has stopped working, we are using MongoClient only to connect to CosmosDB by passing CosmosDB connection string to MongoClient everything is fine with this MongoClient object but Hangfire is not working with this. It is creating Hangfire default collections into the CosmosDB and when we are trying to manually execute any of the jobs from Hangfire dashboard it gives us this error:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. MongoDB.Driver.MongoBulkWriteException`1[MongoDB.Bson.BsonDocument]: A bulk write operation resulted in one or more errors. WriteErrors: [ { Category : "DuplicateKey", Code : 11000, Message : "E11000 duplicate key error collection: bomHangfire2.core.hangfire.jobGraph. Failed _id or unique index constraint." } ]. at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass30_0.<BulkWrite>b__0(IClientSessionHandle session) at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl`1.BulkWrite(IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken) at Hangfire.Mongo.MongoWriteOnlyTransaction.Commit() at Hangfire.Mongo.MongoConnection.CreateExpiredJob(Job job, IDictionary`2 parameters, DateTime createdAt, TimeSpan expireIn) at Hangfire.Client.CoreBackgroundJobFactory.<>c__DisplayClass15_0.<CreateBackgroundJobTwoSteps>b__0(Int32 _) at Hangfire.Client.CoreBackgroundJobFactory.RetryOnException[T](Int32& attemptsLeft, Func`2 action) --- End of stack trace from previous location where exception was thrown --- at Hangfire.Client.CoreBackgroundJobFactory.RetryOnException[T](Int32& attemptsLeft, Func`2 action) at Hangfire.Client.CoreBackgroundJobFactory.CreateBackgroundJobTwoSteps(CreateContext context, Dictionary`2 parameters, DateTime createdAt, TimeSpan expireIn) at Hangfire.Client.CoreBackgroundJobFactory.Create(CreateContext context) at Hangfire.Client.BackgroundJobFactory.<>c__DisplayClass12_0.<CreateWithFilters>b__0() at Hangfire.Client.BackgroundJobFactory.InvokeClientFilter(IClientFilter filter, CreatingContext preContext, Func`1 continuation) at Hangfire.Client.BackgroundJobFactory.<>c__DisplayClass12_1.<CreateWithFilters>b__2() at Hangfire.Client.BackgroundJobFactory.CreateWithFilters(CreateContext context, IEnumerable`1 filters) at Hangfire.Client.BackgroundJobFactory.Create(CreateContext context) at Hangfire.RecurringJobExtensions.TriggerRecurringJob(IBackgroundJobFactory factory, JobStorage storage, IStorageConnection connection, IProfiler profiler, RecurringJobEntity recurringJob, DateTime now) at Hangfire.RecurringJobManager.TriggerJob(String recurringJobId) at Hangfire.RecurringJobManager.Trigger(String recurringJobId) at Hangfire.Dashboard.DashboardRoutes.<>c.<.cctor>b__6_27(IRecurringJobManager manager, String jobId) at Hangfire.Dashboard.RouteCollectionExtensions.<>c__DisplayClass4_0.<AddRecurringBatchCommand>b__0(DashboardContext context, String jobId) at Hangfire.Dashboard.BatchCommandDispatcher.Dispatch(DashboardContext context) at Hangfire.Dashboard.AspNetCoreDashboardMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
We have used this code into the Startup.cs file
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IMailService, MailService>();
services.AddHangfire(config =>
{
var opt = new CosmosStorageOptions
{
MigrationOptions = new MongoMigrationOptions
{
BackupStrategy = new NoneMongoBackupStrategy(),
MigrationStrategy = new DropMongoMigrationStrategy(),
},
Prefix = "job.hangfire",
};
var mongoClient = new MongoClient(Configuration.GetConnectionString("DefaultConnection"));
GlobalConfiguration.Configuration.UseCosmosStorage(mongoClient, "Hangfire", opt);
});
services.AddHangfireServer(serverOptions =>
{
serverOptions.ServerName = AppSettings.Environment.CurrentServer;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages(); endpoints.MapHangfireDashboard("/jobs", new DashboardOptions{});
});
RecurringJob.AddOrUpdate<IMailService>("sendEmails", h => h.SendMails(), $"0 1 * * *");
}
And we have Our method SendMails() which is sending mail.
Problem is that hangifre.jobgraph table is not handled by us and hangfire only inserts and updates that table and in cosmos _id key is made unique by default, so, how can we fix this issue.