public void TestIdleSessionKiller()
        {
            // This makes sure that for the Semaphore5 lock initial 4 tickets are taken with the default
            // application name and therefore won't be counted or killed
            this._lockProvider.CreateLock(nameof(TestIdleSessionKiller));

            var applicationName = this._lockProvider.Strategy.Db.SetUniqueApplicationName();
            var @lock           = this._lockProvider.CreateLock(nameof(TestIdleSessionKiller));

            // go through one acquire/dispose cycle to ensure all commands are prepared. Due to
            // https://github.com/npgsql/npgsql/issues/2912 in Postgres, we get NRE on the post-kill Dispose()
            // call rather than the DbException we expected.
            @lock.Acquire().Dispose();

            using var handle = @lock.Acquire();
            this._lockProvider.Strategy.Db.CountActiveSessions(applicationName).ShouldEqual(1);

            using var idleSessionKiller = new IdleSessionKiller(this._lockProvider.Strategy.Db, applicationName, idleTimeout: TimeSpan.FromSeconds(.1));
            var stopwatch = Stopwatch.StartNew();

            while (true)
            {
                Thread.Sleep(TimeSpan.FromSeconds(.02));
                if (this._lockProvider.Strategy.Db.CountActiveSessions(applicationName) == 0)
                {
                    break;
                }
                if (stopwatch.Elapsed > TimeSpan.FromSeconds(5))
                {
                    Assert.Fail("Timed out waiting for idle session to be killed");
                }
            }

            Assert.Catch <DbException>(() => handle.Dispose());
        }
예제 #2
0
        [NonParallelizable, Retry(5)] // timing-sensitive
        public void TestKeepaliveProtectsFromIdleSessionKiller()
        {
            var applicationName = this._lockProvider.Strategy.SetUniqueApplicationName();

            this._lockProvider.Strategy.KeepaliveCadence = TimeSpan.FromSeconds(.05);
            var @lock = this._lockProvider.CreateLock(Guid.NewGuid().ToString()); // use unique name due to retry

            var handle = @lock.Acquire();

            using var idleSessionKiller = new IdleSessionKiller(this._lockProvider.Strategy.Db, applicationName, idleTimeout: TimeSpan.FromSeconds(.5));
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Assert.DoesNotThrow(() => handle.Dispose());
        }
예제 #3
0
        [NonParallelizable, Retry(tryCount: 5)] // this test is somewhat timing sensitive
        public void TestKeepaliveProtectsFromIdleSessionKillerAfterFailedUpgrade()
        {
            var applicationName = this._lockProvider.Strategy.SetUniqueApplicationName();

            this._lockProvider.Strategy.KeepaliveCadence = TimeSpan.FromSeconds(.1);
            var @lock = this._lockProvider.CreateUpgradeableReaderWriterLock(Guid.NewGuid().ToString());

            using var idleSessionKiller = new IdleSessionKiller(this._lockProvider.Strategy.Db, applicationName, idleTimeout: TimeSpan.FromSeconds(.5));

            using (@lock.AcquireReadLock())
            {
                var handle = @lock.AcquireUpgradeableReadLock();
                handle.TryUpgradeToWriteLock().ShouldEqual(false);
                handle.TryUpgradeToWriteLockAsync().Result.ShouldEqual(false);
                Thread.Sleep(TimeSpan.FromSeconds(1));
                Assert.DoesNotThrow(() => handle.Dispose());
            }
        }