private JobDto CreateJobInState(HangfireDbContext database, int jobId, string stateName) { var job = Job.FromExpression(() => SampleMethod("wrong")); var jobState = new StateDto { CreatedAt = database.GetServerTimeUtc(), Data = stateName == EnqueuedState.StateName ? string.Format(" {{ 'EnqueuedAt': '{0}' }}", database.GetServerTimeUtc().ToString("o")) : "{}", JobId = jobId }; database.State.InsertOne(jobState); var jobDto = new JobDto { Id = jobId, InvocationData = JobHelper.ToJson(InvocationData.Serialize(job)), Arguments = "['Arguments']", StateName = stateName, CreatedAt = database.GetServerTimeUtc(), StateId = jobState.Id }; database.Job.InsertOne(jobDto); var jobQueueDto = new JobQueueDto { FetchedAt = null, Id = jobId * 10, JobId = jobId, Queue = DefaultQueue }; if (stateName == FetchedStateName) { jobQueueDto.FetchedAt = database.GetServerTimeUtc(); } database.JobQueue.InsertOne(jobQueueDto); return jobDto; }
public MongoDistributedLock(string resource, TimeSpan timeout, HangfireDbContext database, MongoStorageOptions options) { if (String.IsNullOrEmpty(resource) == true) throw new ArgumentNullException("resource"); if (database == null) throw new ArgumentNullException("database"); if (options == null) throw new ArgumentNullException("options"); _resource = resource; _database = database; _options = options; try { // Remove dead locks database.DistributedLock.Remove(Query.And(Query<DistributedLockDto>.EQ(_ => _.Resource, resource), Query<DistributedLockDto>.LT(_ => _.Heartbeat, database.GetServerTimeUtc().Subtract(options.DistributedLockLifetime)))); // Check lock DateTime lockTimeoutTime = DateTime.Now.Add(timeout); bool isLockedBySomeoneElse; bool isFirstAttempt = true; do { isLockedBySomeoneElse = database .DistributedLock .FindOne(Query.And(Query<DistributedLockDto>.EQ(_ => _.Resource, resource), Query<DistributedLockDto>.NE(_ => _.ClientId, _options.ClientId))) != null; if (isFirstAttempt == true) isFirstAttempt = false; else Thread.Sleep((int)timeout.TotalMilliseconds / 10); } while ((isLockedBySomeoneElse == true) && (lockTimeoutTime >= DateTime.Now)); // Set lock if (isLockedBySomeoneElse == false) { database.DistributedLock.FindAndModify(new FindAndModifyArgs { Query = Query<DistributedLockDto>.EQ(_ => _.Resource, resource), Update = Update.Combine( Update<DistributedLockDto>.Set(_ => _.ClientId, _options.ClientId), Update<DistributedLockDto>.Inc(_ => _.LockCount, 1), Update<DistributedLockDto>.Set(_ => _.Heartbeat, database.GetServerTimeUtc()) ), Upsert = true }); StartHeartBeat(); } else { throw new MongoDistributedLockException(String.Format("Could not place a lock on the resource '{0}': {1}.", _resource, "The lock request timed out")); } } catch (Exception ex) { if (ex is MongoDistributedLockException) throw; else throw new MongoDistributedLockException(String.Format("Could not place a lock on the resource '{0}': {1}.", _resource, "Check inner exception for details"), ex); } }
private static int CreateJobQueueRecord(HangfireDbContext connection, string jobId, string queue) { var jobQueue = new JobQueueDto { JobId = int.Parse(jobId), Queue = queue, FetchedAt = connection.GetServerTimeUtc() }; connection.JobQueue.Insert(jobQueue); return jobQueue.Id; }
private static JobQueueDto CreateJobQueueDto(HangfireDbContext connection, string queue, bool isFetched) { var state = new StateDto(); AsyncHelper.RunSync(() => connection.State.InsertOneAsync(state)); var job = new JobDto { CreatedAt = connection.GetServerTimeUtc(), StateId = state.Id }; AsyncHelper.RunSync(() => connection.Job.InsertOneAsync(job)); var jobQueue = new JobQueueDto { Queue = queue, JobId = job.Id }; if (isFetched) { jobQueue.FetchedAt = connection.GetServerTimeUtc().AddDays(-1); } AsyncHelper.RunSync(() => connection.JobQueue.InsertOneAsync(jobQueue)); return jobQueue; }
/// <summary> /// Creates MongoDB distributed lock /// </summary> /// <param name="resource">Lock resource</param> /// <param name="timeout">Lock timeout</param> /// <param name="database">Lock database</param> /// <param name="options">Database options</param> public MongoDistributedLock(string resource, TimeSpan timeout, HangfireDbContext database, MongoStorageOptions options) { if (String.IsNullOrEmpty(resource) == true) throw new ArgumentNullException("resource"); if (database == null) throw new ArgumentNullException("database"); if (options == null) throw new ArgumentNullException("options"); _resource = resource; _database = database; _options = options; try { // Remove dead locks database.DistributedLock.DeleteManyAsync( Builders<DistributedLockDto>.Filter.Eq(_ => _.Resource, resource) & Builders<DistributedLockDto>.Filter.Lt(_ => _.Heartbeat, database.GetServerTimeUtc().Subtract(options.DistributedLockLifetime))); // Check lock DateTime lockTimeoutTime = DateTime.Now.Add(timeout); bool isLockedBySomeoneElse; bool isFirstAttempt = true; do { isLockedBySomeoneElse = AsyncHelper.RunSync(() => database.DistributedLock .Find(Builders<DistributedLockDto>.Filter.Eq(_ => _.Resource, resource) & Builders<DistributedLockDto>.Filter.Ne(_ => _.ClientId, _options.ClientId)) .FirstOrDefaultAsync()) != null; if (isFirstAttempt == true) isFirstAttempt = false; else Thread.Sleep((int)timeout.TotalMilliseconds / 10); } while ((isLockedBySomeoneElse == true) && (lockTimeoutTime >= DateTime.Now)); // Set lock if (isLockedBySomeoneElse == false) { AsyncHelper.RunSync(() => database.DistributedLock.FindOneAndUpdateAsync( Builders<DistributedLockDto>.Filter.Eq(_ => _.Resource, resource), Builders<DistributedLockDto>.Update.Combine( Builders<DistributedLockDto>.Update.Set(_ => _.ClientId, _options.ClientId), Builders<DistributedLockDto>.Update.Inc(_ => _.LockCount, 1), Builders<DistributedLockDto>.Update.Set(_ => _.Heartbeat, database.GetServerTimeUtc()) ), new FindOneAndUpdateOptions<DistributedLockDto> { IsUpsert = true })); StartHeartBeat(); } else { throw new MongoDistributedLockException(String.Format("Could not place a lock on the resource '{0}': {1}.", _resource, "The lock request timed out")); } } catch (Exception ex) { if (ex is MongoDistributedLockException) throw; else throw new MongoDistributedLockException(String.Format("Could not place a lock on the resource '{0}': {1}.", _resource, "Check inner exception for details"), ex); } }