Exemple #1
0
            public EnterLock(IDbFactory db, IIntegrationDatabaseConfiguration configuration, DistributedMutexContext context, TimeSpan queryLockInterval, CancellationToken cancellationToken)
            {
                _db            = db;
                _configuration = configuration;

                _newLock = new DbDistributedMutexLock(context.Name)
                {
                    MachineName = Environment.MachineName,
                    Description = context.Description.MaxLength(255)
                };

                using (IDbSession session = db.OpenSession())
                {
                    TimeSpan waitTime   = context.WaitTime;
                    int      maxRetries = Math.Max((int)Math.Ceiling(waitTime.TotalMilliseconds / queryLockInterval.TotalMilliseconds), 1);
                    int      attempts   = 0;

                    DbDistributedMutexLock currentLock;

                    while (true)
                    {
                        if (TryEnterLock(session, out currentLock))
                        {
                            _onCancel = cancellationToken.Register(ReleaseLock);
                            return;
                        }

                        if (currentLock == null)
                        {
                            throw new InvalidOperationException($"Cannot obtain lock for '{_newLock.Name}', but current lock is null.");
                        }

                        if (++attempts >= maxRetries)
                        {
                            break;
                        }

                        context.OnWaiting($"{currentLock}. Waiting for {queryLockInterval} (attemt {attempts} of {maxRetries}).");

                        cancellationToken.WaitHandle.WaitOne(queryLockInterval);
                    }

                    throw new DistributedMutexTimeoutException($"Unable to acquire lock '{_newLock.Name}' within wait time ({waitTime}) using {attempts} attempts with a query interval of {queryLockInterval}. {currentLock}");
                }
            }
Exemple #2
0
            private bool TryEnterLock(IDbSession session, out DbDistributedMutexLock currentLock)
            {
                currentLock = session.Query <DbDistributedMutexLock>($@"
BEGIN TRY
    INSERT INTO [{_configuration.TableName(IntegrationDbTable.DistributedMutex)}] (Name, LockId, CreatedAt, MachineName, Description)
        VALUES (@Name, @LockId, @CreatedAt, @MachineName, @Description)
END TRY

BEGIN CATCH
    DECLARE @ErrorNumber AS INT
    SELECT @ErrorNumber = ERROR_NUMBER();

    IF @ErrorNumber = 2627 -- PRIMARY KEY VIOLATION
	    SELECT * FROM [{_configuration.TableName(IntegrationDbTable.DistributedMutex)}] WHERE (Name = @Name);
    ELSE
	    THROW
END CATCH",
                                                                     _newLock).FirstOrDefault();

                return(currentLock == null);
            }