internal FluentNHibernateDistributedLock Acquire() { var finish = DateTime.Now.Add(_timeout); while (true) { _cancellationToken.ThrowIfCancellationRequested(); if (SqlUtil.WrapForTransaction(() => { lock (Mutex) { using (var session = _storage.GetSession()) { using (var transaction = session.BeginTransaction(IsolationLevel.Serializable)) { var utcNow = session.Storage.UtcNow; var count = session.CreateQuery(SqlUtil.GetCreateDistributedLockStatement()) .SetParameter(SqlUtil.ResourceParameterName, _resource) .SetParameter(SqlUtil.ExpireAtAsLongParameterName, utcNow.Add(_timeout).ToUnixDate()) .SetParameter(SqlUtil.NowParameterName, utcNow) .SetParameter(SqlUtil.NowAsLongParameterName, utcNow.ToUnixDate()); if (count.ExecuteUpdate() > 0) { transaction.Commit(); return(true); } } } } return(false); })) { Logger.DebugFormat("Granted distributed lock for {0}", _resource); _acquired = true; return(this); } if (finish > DateTime.Now) { _cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses); } else { throw new FluentNHibernateDistributedLockException("cannot acquire lock"); } } }
public void Execute(CancellationToken cancellationToken) { DateTime cutOffDate; using (var session = _storage.GetSession()) { cutOffDate = session.Storage.UtcNow; } var actionQueue = new ExpirationActionQueue(_storage, cutOffDate, cancellationToken); actionQueue.EnqueueDeleteJobDetailEntity <_JobState>(); actionQueue.EnqueueDeleteJobDetailEntity <_JobQueue>(); actionQueue.EnqueueDeleteJobDetailEntity <_JobParameter>(); actionQueue.EnqueueDeleteEntities <_DistributedLock>((session, cutoff) => { var unixDate = cutoff.ToUnixDate(); var idList = session.Query <_DistributedLock>() .Where(i => i.ExpireAtAsLong < unixDate) .Select(i => i.Id) .ToList(); return(session.DeleteByInt32Id <_DistributedLock>(idList)); }); actionQueue.EnqueueDeleteExpirableEntity <_AggregatedCounter>(); actionQueue.EnqueueDeleteExpirableEntity <_Job>(); actionQueue.EnqueueDeleteExpirableEntity <_List>(); actionQueue.EnqueueDeleteExpirableEntity <_Set>(); actionQueue.EnqueueDeleteExpirableEntity <_Hash>(); actionQueue.Run(); cancellationToken.WaitHandle.WaitOne(_storage.Options.JobExpirationCheckInterval); }
private void EnqueueBatchDelete <T>(List <Action> actions, CancellationToken cancellationToken, Func <SessionWrapper, long> deleteFunc) { actions.Add(() => { try { var entityName = typeof(T).Name; Logger.InfoFormat("Removing outdated records from table '{0}'...", entityName); long removedCount = 0; while (true) { try { using (new FluentNHibernateDistributedLock(_storage, DistributedLockKey, DefaultLockTimeout, cancellationToken).Acquire()) { using (var session = _storage.GetSession()) { removedCount = deleteFunc(session); } } Logger.InfoFormat("removed records count={0}", removedCount); } catch (FluentNHibernateDistributedLockException) { // do nothing } catch (Exception ex) { Logger.Error(ex.ToString()); } if (removedCount <= 0) { break; } Logger.Info(string.Format("Removed {0} outdated record(s) from '{1}' table.", removedCount, entityName)); cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses); cancellationToken.ThrowIfCancellationRequested(); } } catch (Exception) when(cancellationToken.IsCancellationRequested) { //do nothing } }); }
public void EnqueueDeleteEntities <T>(Func <SessionWrapper, DateTime, long> deleteFunc) { Enqueue(() => { try { var entityName = typeof(T).Name; Logger.InfoFormat("Removing outdated records from table '{0}'...", entityName); long removedCount = 0; while (true) { try { using (new FluentNHibernateDistributedLock(_storage, ExpirationManager.DistributedLockKey, ExpirationManager.DefaultLockTimeout, _cancellationToken).Acquire()) { using (var session = _storage.GetSession()) { removedCount = deleteFunc(session, _cutOffDate); } } Logger.InfoFormat("removed records count={0}", removedCount); } catch (FluentNHibernateDistributedLockException ex) { Logger.Warn(string.Concat("Can't delete : ", ex.ToString())); } catch (Exception ex) { Logger.Error(ex.ToString()); } if (removedCount <= 0) { break; } Logger.Info(string.Format("Removed {0} outdated record(s) from '{1}' table.", removedCount, entityName)); _cancellationToken.WaitHandle.WaitOne(ExpirationManager.DelayBetweenPasses); _cancellationToken.ThrowIfCancellationRequested(); } } catch (Exception) when(_cancellationToken.IsCancellationRequested) { Logger.Warn("Cancellation was requested"); } }); }
public void Execute(CancellationToken cancellationToken) { var actions = new List <Action>(); DateTime jobExpireDate; using (var session = _storage.GetSession()) { jobExpireDate = session.Storage.UtcNow; } EnqueueBatchDeleteJobChild <_JobState>(actions, cancellationToken, jobExpireDate); EnqueueBatchDeleteJobChild <_JobQueue>(actions, cancellationToken, jobExpireDate); EnqueueBatchDeleteJobChild <_JobParameter>(actions, cancellationToken, jobExpireDate); EnqueueBatchDelete <_DistributedLock>(actions, cancellationToken, session => { var idList = session.Query <_DistributedLock>() .Where(i => i.ExpireAtAsLong < jobExpireDate.ToUnixDate()) .Select(i => i.Id) .ToList(); return(session.DeleteByInt32Id <_DistributedLock>(idList)); }); EnqueueBatchDelete <_AggregatedCounter>(actions, cancellationToken, DeleteExpirableWithId <_AggregatedCounter>); EnqueueBatchDelete <_Job>(actions, cancellationToken, DeleteExpirableWithId <_Job>); EnqueueBatchDelete <_List>(actions, cancellationToken, DeleteExpirableWithId <_List>); EnqueueBatchDelete <_Set>(actions, cancellationToken, DeleteExpirableWithId <_Set>); EnqueueBatchDelete <_Hash>(actions, cancellationToken, DeleteExpirableWithId <_Hash>); foreach (var action in actions) { if (cancellationToken.IsCancellationRequested) { break; } action(); } cancellationToken.WaitHandle.WaitOne(_checkInterval); }