public void Can_handle_requests_concurrently_in_4_threads(int noOfThreads, int msgs)
        {
            var timesCalled = 0;

            using var mqHost = new ServiceBusMqServer(ConnectionString);
            var queueNames = QueueNames <Wait> .AllQueueNames.Select(SafeQueueName).ToList();

#if NETCOREAPP2_1
            queueNames.ForEach(q => mqHost.ManagementClient.DeleteQueueAsync(q).GetAwaiter().GetResult());
#else
            queueNames.ForEach(q => mqHost.NamespaceManager.DeleteQueue(q));
#endif

            mqHost.RegisterHandler <Wait>(m => {
                Interlocked.Increment(ref timesCalled);
                Thread.Sleep(m.GetBody().ForMs);
                return(null);
            }, noOfThreads);

            mqHost.Start();

            var dto = new Wait {
                ForMs = 100
            };
            using var mqClient = mqHost.CreateMessageQueueClient();
            msgs.Times(i => mqClient.Publish(dto));

            ExecUtils.RetryUntilTrue(() => timesCalled == msgs, TimeSpan.FromSeconds(5));
        }
Example #2
0
        public RedisLock(IRedisClient redisClient, string key, TimeSpan?timeout)
        {
            this._redisClient = redisClient;
            this._key         = key;

            bool LockAction()
            {
                // This pattern is taken from the redis command for SETNX http://redis.io/commands/setnx

                // Calculate a unix time for when the lock should expire
                var realSpan   = timeout ?? new TimeSpan(365, 0, 0, 0); // if nothing is passed in the timeout hold for a year
                var expireTime = DateTime.UtcNow.Add(realSpan);
                var lockString = (expireTime.ToUnixTimeMs() + 1).ToString();

                // Try to set the lock, if it does not exist this will succeed and the lock is obtained
                var nx = redisClient.SetValueIfNotExists(key, lockString);

                if (nx)
                {
                    return(true);
                }

                // If we've gotten here then a key for the lock is present. This could be because the lock is
                // correctly acquired or it could be because a client that had acquired the lock crashed (or didn't release it properly).
                // Therefore we need to get the value of the lock to see when it should expire

                redisClient.Watch(key);
                var lockExpireString = redisClient.Get <string>(key);

                if (!long.TryParse(lockExpireString, out var lockExpireTime))
                {
                    redisClient.UnWatch(); // since the client is scoped externally
                    return(false);
                }

                // If the expire time is greater than the current time then we can't let the lock go yet
                if (lockExpireTime > DateTime.UtcNow.ToUnixTimeMs())
                {
                    redisClient.UnWatch(); // since the client is scoped externally
                    return(false);
                }

                // If the expire time is less than the current time then it wasn't released properly and we can attempt to
                // acquire the lock. The above call to Watch(_lockKey) enrolled the key in monitoring, so if it changes
                // before we call Commit() below, the Commit will fail and return false, which means that another thread
                // was able to acquire the lock before we finished processing.
                using (var trans = redisClient.CreateTransaction()) {
                    // we started the "Watch" above; this tx will succeed if the value has not moved
                    trans.QueueCommand(r => r.Set(key, lockString));
                    return(trans.Commit()); // returns false if Transaction failed
                }
            }

            ExecUtils.RetryUntilTrue(LockAction, timeout);
        }
Example #3
0
        internal long AtomicIncDec(string key, long amount)
        {
            long count   = 0;
            bool updated = false;

            ExecUtils.RetryUntilTrue(() =>
            {
                var entry = GetEntry(key);

                if (entry == null)
                {
                    count = amount;
                    entry = CreateTableEntry(key, Serialize(count));
                    try
                    {
                        updated = table.Execute(TableOperation.Insert(entry)).HttpStatusCode == (int)HttpStatusCode.NoContent;
                    }
                    catch (StorageException ex)
                    {
                        if (!ex.InnerException.HasStatus(HttpStatusCode.Conflict))
                        {
                            throw;
                        }
                    }
                }
                else
                {
                    count      = Deserialize <long>(entry.Data) + amount;
                    entry.Data = Serialize <long>(count);
                    var op     = TableOperation.Replace(entry);
                    try
                    {
                        var result = table.Execute(op).HttpStatusCode;
                        updated    = result == (int)HttpStatusCode.OK || result == (int)HttpStatusCode.NoContent;
                    }
                    catch (StorageException ex)
                    {
                        if (!ex.InnerException.HasStatus(HttpStatusCode.PreconditionFailed))
                        {
                            throw;
                        }
                    }
                }

                return(updated);
            }, TimeSpan.FromSeconds(30));

            return(count);
        }
Example #4
0
        public void RedisLock(IRedisClient redisClient, string key, TimeSpan?timeOut)
        {
            //this.redisClient = redisClient;
            //this.key = key;
            ExecUtils.RetryUntilTrue(delegate
            {
                TimeSpan value    = timeOut ?? new TimeSpan(365, 0, 0, 0);
                DateTime dateTime = DateTime.UtcNow.Add(value);
                string lockString = (dateTime.ToUnixTimeMs() + 1).ToString();
                if (redisClient.SetValueIfNotExists(key, lockString))
                {
                    return(true);
                }
                redisClient.Watch(key);
                long result = -1L;
                string s    = redisClient.Get <string>(key);
                if (!long.TryParse(s, out result))
                {
                    redisClient.UnWatch();
                    return(false);
                }

                if (result <= DateTime.UtcNow.ToUnixTimeMs())
                {
                    using (IRedisTransaction redisTransaction = redisClient.CreateTransaction())
                    {
                        redisTransaction.QueueCommand((IRedisClient r) => r.Set(key, lockString));

                        System.Threading.Thread.Sleep(5 * 1000);

                        bool ok         = redisTransaction.Commit();
                        var lockString2 = redisClient.Get <string>(key);
                        if (lockString2 != lockString)
                        {
                        }

                        return(ok);
                    }
                }
                redisClient.UnWatch();
                return(false);
            }, timeOut);
        }
Example #5
0
 public virtual void WaitForWorkersToStop(TimeSpan?timeout = null)
 {
     ExecUtils.RetryUntilTrue(
         () => Interlocked.CompareExchange(ref status, 0, 0) == WorkerStatus.Stopped,
         timeout);
 }