Beispiel #1
0
        public async Task AcquireLock()
        {
            MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString());

            IAcquire acq = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(0));

            Assert.IsTrue(acq.Acquired);
        }
Beispiel #2
0
        public async Task Acquire_WaitUntilExpire_Acquire()
        {
            MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString());

            IAcquire acq1 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(0));

            Assert.IsTrue(acq1.Acquired);

            IAcquire acq2 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(0));

            Assert.IsFalse(acq2.Acquired);

            await Task.Delay(TimeSpan.FromSeconds(10));

            IAcquire acq3 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(0));

            Assert.IsTrue(acq3.Acquired);
        }
Beispiel #3
0
        public async Task Acquire_BlockFor5Secounds_Release_Acquire()
        {
            MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString());

            IAcquire acq1 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0));

            Assert.IsTrue(acq1.Acquired);

            IAcquire acq2 = await InTimeRange(() => mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5)), 4000, 6000);

            Assert.IsFalse(acq2.Acquired);

            await mongoLock.ReleaseAsync(acq1);

            IAcquire acq3 = await InTimeRange(() => mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5)), 0, 1500);

            Assert.IsTrue(acq3.Acquired);
        }
Beispiel #4
0
        public async Task Acquire_Block_Release_And_Acquire()
        {
            MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString());

            IAcquire acq1 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0));

            Assert.IsTrue(acq1.Acquired);

            IAcquire acq2 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0));

            Assert.IsFalse(acq2.Acquired);

            await mongoLock.ReleaseAsync(acq1);

            IAcquire acq3 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0));

            Assert.IsTrue(acq3.Acquired);
        }
Beispiel #5
0
        /// <summary>
        ///  Releases an exclusive lock for the specified acquire. If lock isn't exist or already released, there will be no exceptions throwed
        /// </summary>
        /// <param name="acquire">IAcquire object returned by AcquireAsync</param>
        /// <returns></returns>
        public async Task ReleaseAsync(IAcquire acquire)
        {
            if (acquire == null)
            {
                throw new ArgumentNullException(nameof(acquire));
            }
            if (acquire.Acquired == false)
            {
                return;
            }

            var updateResult = await _locks.UpdateOneAsync(
                filter : _builder.And(_builder.Eq(x => x.Id, _id), _builder.Eq(x => x.AcquireId, acquire.AcquireId)), // x => x.Id == _id && x.AcquireId == acquire.AcquireId,
                update : new UpdateDefinitionBuilder <LockAcquire <T> >().Set(x => x.Acquired, false));

            if (updateResult.IsAcknowledged && updateResult.ModifiedCount > 0)
            {
                await _signals.InsertOneAsync(new ReleaseSignal { AcquireId = acquire.AcquireId });
            }
        }
Beispiel #6
0
        // C# 7.1 requires for async Main
        static async Task Main(string[] args)
        {
            const string сonnectionString = "--mognodb connection string--";

            MongoClient    client   = new MongoClient(сonnectionString);
            IMongoDatabase database = client.GetDatabase("sample");

            // Regular collection, not a capped!
            IMongoCollection <LockAcquire <Guid> > locks = database.GetCollection <LockAcquire <Guid> >("locks");

            // This collection should be a capped! https://docs.mongodb.com/manual/core/capped-collections/
            // The size of the cappred collection should be enough to put all active locks.
            // One ReleaseSignal is about 32 bytes, so for 100,000 simultaneously locks, you need a capped collection size ~3 megabytes
            IMongoCollection <ReleaseSignal> signals = database.GetCollection <ReleaseSignal>("signals");

            Guid lockId = Guid.Parse("BF431614-4FB0-4489-84AA-D3EFEEF6BE7E");
            // Guid lockId is a name of your distributed lock. You can also use string, int, etc.
            MongoLock <Guid> mongoLock = new MongoLock <Guid>(locks, signals, lockId);

            // Try to acquire exclusve lock. Lifetime for created lock is 30 secounds
            IAcquire acquire = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(10));

            try
            {
                if (acquire.Acquired)
                {
                    // critical section, it cannot be executed by more than one thread on any server at a time
                    // ...
                    // ...
                }
                else
                {
                    // Timeout! Maybe another thread did not release the lock... We can try again or throw excepton
                }
            }
            finally
            {
                // if (acquire.Acquired) no need to do it manually
                await mongoLock.ReleaseAsync(acquire);
            }
        }
Beispiel #7
0
        public void Synchronize_CriticalSection_For_4_Threads()
        {
            MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString());

            List <Task> tasks  = new List <Task>();
            List <int>  bucket = new List <int>()
            {
                0
            };
            Random random = new Random(DateTime.UtcNow.GetHashCode());

            for (int i = 0; i < 4; i++)
            {
                tasks.Add(Task.Run(async delegate
                {
                    for (int j = 0; j < 100; j++)
                    {
                        IAcquire acq = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(10));
                        try
                        {
                            int count = bucket.Count;
                            Thread.Sleep(random.Next(0, 10));

                            int value = bucket[count - 1];
                            bucket.Add(value + 1);
                        }
                        finally
                        {
                            await mongoLock.ReleaseAsync(acq);
                        }
                    }
                }));
            }


            Task.WaitAll(tasks.ToArray());
            Assert.IsTrue(bucket.SequenceEqual(Enumerable.Range(0, 401)));
        }