/// <summary>
        /// Gets a collections of module updates that have already been applied
        /// to the system.
        /// </summary>
        private async Task <ICollection <ModuleVersion> > GetUpdateVersionHistoryAsync()
        {
            var query = @"
                if (exists (select * 
                                 from information_schema.tables 
                                 where table_schema = 'Cofoundry' 
                                 and  table_name = 'ModuleUpdate'))
                begin
                    select Module, MAX([Version]) as Version
	                from  Cofoundry.ModuleUpdate
	                group by Module
	                order by Module
                end";

            var moduleVersions = await _db.ReadAsync(query, r =>
            {
                var moduleVersion     = new ModuleVersion();
                moduleVersion.Module  = (string)r["Module"];
                moduleVersion.Version = (int)r["Version"];

                return(moduleVersion);
            });

            return(moduleVersions);
        }
        public async Task LockAsync(Guid lockingId)
        {
            await EnsureDistributedLockInfrastructureExistsAsync();

            var query = @" 
                declare @DateNow datetime2(7) = GetUtcDate()

                update Cofoundry.DistributedLock 
                set LockingId = @LockingId, LockDate = @DateNow, ExpiryDate = dateadd(second, @TimeoutInSeconds, @DateNow)
                where DistributedLockId = @DistributedLockId
                and (LockingId is null or ExpiryDate < @DateNow)

                select DistributedLockId, LockingId, LockDate, ExpiryDate 
                from Cofoundry.DistributedLock
                where DistributedLockId = @DistributedLockId
                ";

            var distributedLock = (await _db.ReadAsync(query,
                                                       MapDistributedLock,
                                                       new SqlParameter("DistributedLockId", DISTRIBUTED_LOCK_ID),
                                                       new SqlParameter("LockingId", lockingId),
                                                       new SqlParameter("TimeoutInSeconds", _autoUpdateSettings.ProcessLockTimeoutInSeconds)
                                                       ))
                                  .SingleOrDefault();

            if (distributedLock == null)
            {
                throw new Exception($"Distributed lock record missing for the auto update process. DistributedLockId: {DISTRIBUTED_LOCK_ID}");
            }

            if (distributedLock.LockingId != lockingId)
            {
                throw new AutoUpdateProcessLockedException(distributedLock);
            }
        }
Exemple #3
0
        /// <summary>
        /// Creates a lock for the specified definition using a unique
        /// lock id that represents the running process. You can
        /// query the returned DistributedLock instance to determine if
        /// the lock was successful.
        /// </summary>
        /// <typeparam name="TDefinition">
        /// The definition type that conmtains the locking parameters that
        /// represent the process to be run.
        /// </typeparam>
        /// <returns>
        /// Returns the current state of the lock for the specified
        /// definition. If the lock could not be made then the state will
        /// contain information about the existing lock, if the lock was
        /// successful then the new lock will be returned. You can
        /// query the returned object to determine if the lock was successful.
        /// </returns>
        public async Task <DistributedLock> LockAsync <TDefinition>()
            where TDefinition : IDistributedLockDefinition
        {
            var distributedLockDefinition = _distributedLockDefinitionRepository.Get <TDefinition>();

            EntityNotFoundException.ThrowIfNull(distributedLockDefinition, typeof(TDefinition));

            var lockingId = Guid.NewGuid();
            var query     = @" 
                declare @DateNow datetime2(7) = GetUtcDate();

                with data as (select @DistributedLockId as DistributedLockId, @DistributedLockName as [Name])
                merge Cofoundry.DistributedLock t
                using data s on s.DistributedLockId = t.DistributedLockId
                when not matched by target
                then insert (DistributedLockId, [Name]) 
                values (s.DistributedLockId, s.[Name]);

                update Cofoundry.DistributedLock 
                set LockingId = @LockingId, LockDate = @DateNow, ExpiryDate = dateadd(second, @TimeoutInSeconds, @DateNow)
                where DistributedLockId = @DistributedLockId
                and (LockingId is null or ExpiryDate < @DateNow)

                select DistributedLockId, LockingId, LockDate, ExpiryDate 
                from Cofoundry.DistributedLock
                where DistributedLockId = @DistributedLockId
                ";

            var distributedLock = (await _db.ReadAsync(query,
                                                       MapDistributedLock,
                                                       new SqlParameter("DistributedLockId", distributedLockDefinition.DistributedLockId),
                                                       new SqlParameter("DistributedLockName", distributedLockDefinition.Name),
                                                       new SqlParameter("LockingId", lockingId),
                                                       new SqlParameter("TimeoutInSeconds", distributedLockDefinition.Timeout.TotalSeconds)
                                                       ))
                                  .SingleOrDefault();

            if (distributedLock == null)
            {
                throw new Exception($"Unknown error creating a distributed lock with a DistributedLockId of '{distributedLockDefinition.DistributedLockId}'");
            }

            distributedLock.RequestedLockingId = lockingId;

            return(distributedLock);
        }