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));
        }
        public void Can_receive_and_process_same_reply_responses()
        {
            var called = 0;
            var mqHost = CreateMqServer();

            using (var conn = mqHost.ConnectionFactory.CreateConnection())
                using (var channel = conn.CreateModel())
                {
                    channel.PurgeQueue <Incr>();
                }

            mqHost.RegisterHandler <Incr>(m => {
                Debug.WriteLine("In Incr #" + m.GetBody().Value);
                Interlocked.Increment(ref called);
                return(m.GetBody().Value > 0 ? new Incr {
                    Value = m.GetBody().Value - 1
                } : null);
            });

            mqHost.Start();

            var mqClient = mqHost.CreateMessageQueueClient();

            var incr = new Incr {
                Value = 5
            };

            mqClient.Publish(incr);

            ExecUtils.RetryOnException(() =>
            {
                Assert.That(called, Is.EqualTo(1 + incr.Value));
                Thread.Sleep(100);
            }, TimeSpan.FromSeconds(5));
        }
Example #3
0
        public void Can_consume_messages_from_RabbitMQ_with_BasicConsume()
        {
            RabbitMqConfig.UsingChannel(channel => {
                var consumer = new RabbitMqBasicConsumer(channel);
                channel.BasicConsume(MqQueueNames <HelloRabbit> .Direct, false, consumer);
                string recvMsg = null;

                ExecUtils.ExecMultiThreading(1, () => PublishHelloRabbit(channel));

                while (true)
                {
                    try {
                        var e = consumer.Queue.Dequeue();
                        Console.WriteLine("Dequeued");
                        recvMsg = e.Body.FromUtf8Bytes();
                        // ... process the message
                        Console.WriteLine(recvMsg);

                        channel.BasicAck(e.DeliveryTag, false);
                        break;
                    } catch (OperationInterruptedException) {
                        // The consumer was removed, either through
                        // channel or connection closure, or through the
                        // action of IModel.BasicCancel().
                        Console.WriteLine("End of the road...");
                        break;
                    }
                }

                Assert.That(recvMsg, Is.Not.Null);
            });
        }
Example #4
0
        private static void RunHandlerOnMultipleThreads(int noOfThreads, int msgs)
        {
            using var mqHost = CreateMqServer();
            var timesCalled = 0;

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

            mqHost.Start();

            using var mqClient = mqHost.CreateMessageQueueClient();
            var dto = new Wait {
                ForMs = 100
            };

            msgs.Times(i => mqClient.Publish(dto));

            ExecUtils.RetryOnException(() =>
            {
                Thread.Sleep(300);
                Assert.That(timesCalled, Is.EqualTo(msgs));
            }, TimeSpan.FromSeconds(5));
        }
Example #5
0
        public void Only_allows_1_BgThread_to_run_at_a_time()
        {
            using (var mqServer = CreateMqServer()) {
                mqServer.RegisterHandler <Reverse>(x => {
                    return(new ReverseResponse {
                        Value = string.Join(",", x.GetBody().Value.Reverse())
                    });
                });
                mqServer.RegisterHandler <NothingHere>(x => {
                    return(new NothingHereResponse {
                        Value = x.GetBody().Value
                    });
                });

                ExecUtils.ExecMultiThreading(5, () => mqServer.Start());
                Assert.That(mqServer.GetStatus(), Is.EqualTo("Started"));
                Assert.That(mqServer.BgThreadCount, Is.EqualTo(1));

                ExecUtils.ExecMultiThreading(10, () => mqServer.Stop());
                Assert.That(mqServer.GetStatus(), Is.EqualTo("Stopped"));

                ExecUtils.ExecMultiThreading(1, () => mqServer.Start());
                Assert.That(mqServer.GetStatus(), Is.EqualTo("Started"));
                Assert.That(mqServer.BgThreadCount, Is.EqualTo(2));

                Console.WriteLine(mqServer.GetStats());
            }
        }
Example #6
0
        public void Does_process_messages_sent_before_it_was_started()
        {
            var reverseCalled = 0;

            using (var mqServer = RabbitMqServerTests.CreateMqServer())
            {
                using (var conn = mqServer.ConnectionFactory.CreateConnection())
                    using (var channel = conn.CreateModel())
                    {
                        channel.PurgeQueue <Reverse>();
                    }

                mqServer.RegisterHandler <Reverse>(x => { Interlocked.Increment(ref reverseCalled); return(x.GetBody().Value.Reverse()); });

                using (var mqClient = mqServer.CreateMessageQueueClient())
                {
                    RabbitMqServerTests.Publish_4_messages(mqClient);

                    mqServer.Start();

                    ExecUtils.RetryOnException(() =>
                    {
                        Assert.That(mqServer.GetStats().TotalMessagesProcessed, Is.EqualTo(4));
                        Assert.That(reverseCalled, Is.EqualTo(4));
                        Thread.Sleep(100);
                    }, TimeSpan.FromSeconds(5));
                }
            }
        }
        public virtual RedisClient CreateRedisClient(RedisEndpoint config, bool master)
        {
            var client = ClientFactory(config);

            if (master && RedisConfig.VerifyMasterConnections)
            {
                var       firstAttempt  = DateTime.UtcNow;
                Exception firstEx       = null;
                var       retryTimeSpan = TimeSpan.FromMilliseconds(config.RetryTimeout);
                var       i             = 0;
                while (DateTime.UtcNow - firstAttempt < retryTimeSpan)
                {
                    try
                    {
                        client = GetValidMaster(client, config);
                        return(client);
                    }
                    catch (Exception ex)
                    {
                        if (!RedisConfig.RetryReconnectOnFailedMasters)
                        {
                            throw;
                        }

                        firstEx ??= ex;
                        ExecUtils.SleepBackOffMultiplier(++i);
                    }
                }
                throw new TimeoutException($"Could not resolve master instance within {config.RetryTimeout}ms RetryTimeout", firstEx);
            }

            return(client);
        }
        public void Only_allows_1_BgThread_to_run_at_a_time()
        {
            using (var mqHost = CreateMqServer())
            {
                mqHost.RegisterHandler <Reverse>(x => x.GetBody().Value.Reverse());
                mqHost.RegisterHandler <Rot13>(x => x.GetBody().Value.ToRot13());

                5.Times(x => ThreadPool.QueueUserWorkItem(y => mqHost.Start()));
                ExecUtils.RetryOnException(() =>
                {
                    Assert.That(mqHost.GetStatus(), Is.EqualTo("Started"));
                    Assert.That(mqHost.BgThreadCount, Is.EqualTo(1));
                    Thread.Sleep(100);
                }, TimeSpan.FromSeconds(5));

                10.Times(x => ThreadPool.QueueUserWorkItem(y => mqHost.Stop()));
                ExecUtils.RetryOnException(() =>
                {
                    Assert.That(mqHost.GetStatus(), Is.EqualTo("Stopped"));
                    Thread.Sleep(100);
                }, TimeSpan.FromSeconds(5));

                ThreadPool.QueueUserWorkItem(y => mqHost.Start());
                ExecUtils.RetryOnException(() =>
                {
                    Assert.That(mqHost.GetStatus(), Is.EqualTo("Started"));
                    Assert.That(mqHost.BgThreadCount, Is.EqualTo(2));
                    Thread.Sleep(100);
                }, TimeSpan.FromSeconds(5));

                //Debug.WriteLine(mqHost.GetStats());
            }
        }
Example #9
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);
        }
        // [Test] public void TestProtoTypes() => TestsConfig.BaseUri.CombineWith("/types/proto").GetStringFromUrl().Print();
        // [Test] // needs: listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
        public void UpdateProto()
        {
            Directory.GetCurrentDirectory().Print();
            var protoc = TestsConfig.BaseUri.CombineWith("/types/proto").GetStringFromUrl();

            protoc = protoc.Replace("ServiceStack.Extensions.Tests", "ServiceStack.Extensions.Tests.Protoc");

            Directory.SetCurrentDirectory("../../../Protoc");
            File.WriteAllText("services.proto", protoc);
            ExecUtils.ShellExec("x proto-csharp services.proto");
        }
Example #11
0
        // [Test] // needs: listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
        public void UpdateProto()
        {
            Directory.GetCurrentDirectory().Print();
            var protoc = "http://localhost:20000/types/proto".GetStringFromUrl();

            protoc = protoc.Replace("ServiceStack.Extensions.Tests", "ServiceStack.Extensions.Tests.Protoc");

            Directory.SetCurrentDirectory("../../../Protoc");
            File.WriteAllText("services.proto", protoc);
            ExecUtils.ShellExec("web proto-csharp services.proto");
        }
    public void Can_use_RefreshTokenCookie_to_authenticate_and_get_new_AccessToken()
    {
        string initialAccessToken = null;
        var    client             = new JsonServiceClient(Config.ListeningOn)
        {
            ResponseFilter = res => {
                if (initialAccessToken == null)
                {
                    var accessToken = res.Cookies[Keywords.TokenCookie];
                    Assert.That(accessToken.Value, Is.Not.Null);
                    initialAccessToken = accessToken.Value;
                    var refreshToken = res.Cookies[Keywords.RefreshTokenCookie];
                    Assert.That(refreshToken.Value, Is.Not.Null);
                }
            }
        };
        var authResponse = client.Post(new Authenticate {
            provider = "credentials",
            UserName = Username,
            Password = Password
        });

        var request = new Secured {
            Name = "test"
        };
        var response = client.Send(request);

        Assert.That(response.Result, Is.EqualTo(request.Name));

        var reqLogger        = HostContext.TryResolve <IRequestLogger>();
        var lastEntrySession = reqLogger.GetLatestLogs(1)[0]?.Session as AuthUserSession;

        Assert.That(lastEntrySession, Is.Not.Null);
        Assert.That(lastEntrySession.AuthProvider, Is.EqualTo("jwt"));
        Assert.That(lastEntrySession.UserName, Is.EqualTo(Username));

        string lastAccessToken = null;

        client.ResponseFilter = res => {
            var accessToken = res.Cookies[Keywords.TokenCookie];
            lastAccessToken = accessToken.Value;
        };
        var i = 0;

        do
        {
            var accessTokenResponse = client.Post(new GetAccessToken());
            ExecUtils.SleepBackOffMultiplier(++i); //need to wait for iat to tick +1s so JWT's are different
        }while (lastAccessToken == initialAccessToken);
    }
Example #13
0
        internal async Task <long> AtomicIncDecAsync(string key, long amount, CancellationToken token = default)
        {
            long count   = 0;
            bool updated = false;

            await ExecUtils.RetryUntilTrueAsync(async() =>
            {
                var entry = await GetEntryAsync(key, token);

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

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

            return(count);
        }
Example #14
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 #15
0
        public static string AssertDirectory(string dirPath, int timeoutMs = 1000)
        {
            if (string.IsNullOrEmpty(dirPath))
            {
                return(null);
            }

            ExecUtils.RetryOnException(() => {
                if (!Directory.Exists(dirPath))
                {
                    Directory.CreateDirectory(dirPath);
                }
            }, TimeSpan.FromMilliseconds(timeoutMs));
            return(dirPath);
        }
Example #16
0
        // async version of ExecUtils.RetryUntilTrue
        private static async ValueTask RetryUntilTrue(Func <CancellationToken, ValueTask <bool> > action,
                                                      TimeSpan?timeOut = null, CancellationToken token = default)
        {
            var i            = 0;
            var firstAttempt = DateTime.UtcNow;

            while (timeOut == null || DateTime.UtcNow - firstAttempt < timeOut.Value)
            {
                token.ThrowIfCancellationRequested();
                i++;
                if (await action(token).ConfigureAwait(false))
                {
                    return;
                }
                await Task.Delay(ExecUtils.CalculateFullJitterBackOffDelay(i)).ConfigureAwait(false);
            }

            throw new TimeoutException($"Exceeded timeout of {timeOut.Value}");
        }
Example #17
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 #18
0
        public IDictionary <string, T> GetAll <T>(IEnumerable <string> keys)
        {
            foreach (var client in cacheClients)
            {
                try
                {
                    var result = client.GetAll <T>(keys);
                    if (result != null)
                    {
                        return(result);
                    }
                }
                catch (Exception ex)
                {
                    ExecUtils.LogError(client.GetType(), "Get", ex);
                }
            }

            return(new Dictionary <string, T>());
        }
Example #19
0
        public void Can_consume_messages_with_BasicConsumer()
        {
            RabbitMqConfig.UsingChannel(channel => {
                OperationInterruptedException lastEx = null;

                channel.Close();

                void CallBack()
                {
                    try {
                        PublishHelloRabbit(channel);
                    } catch (Exception ex) {
                        lastEx = ex as OperationInterruptedException;
                        Console.WriteLine("Caught {0}: {1}", ex.GetType().Name, ex);
                    }
                }

                ExecUtils.ExecMultiThreading(1, CallBack);
                Assert.That(lastEx, Is.Not.Null);
            });
        }
Example #20
0
        public void Can_receive_and_process_standard_request_reply_combo()
        {
            using (var mqHost = CreateMqServer())
            {
                using (var conn = mqHost.ConnectionFactory.CreateConnection())
                    using (var channel = conn.CreateModel())
                    {
                        channel.PurgeQueue <Hello>();
                        channel.PurgeQueue <HelloResponse>();
                    }

                string messageReceived = null;

                mqHost.RegisterHandler <Hello>(m =>
                                               new HelloResponse {
                    Result = "Hello, " + m.GetBody().Name
                });

                mqHost.RegisterHandler <HelloResponse>(m =>
                {
                    messageReceived = m.GetBody().Result; return(null);
                });

                mqHost.Start();

                using (var mqClient = mqHost.CreateMessageQueueClient())
                {
                    var dto = new Hello {
                        Name = "ServiceStack"
                    };
                    mqClient.Publish(dto);

                    ExecUtils.RetryOnException(() =>
                    {
                        Thread.Sleep(300);
                        Assert.That(messageReceived, Is.EqualTo("Hello, ServiceStack"));
                    }, TimeSpan.FromSeconds(5));
                }
            }
        }
 /// <summary>
 /// Sleep using AWS's recommended Exponential BackOff with Full Jitter from:
 /// https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
 /// </summary>
 /// <param name="retriesAttempted"></param>
 internal static void SleepBackOffMultiplier(this int retriesAttempted) =>
 Thread.Sleep(ExecUtils.CalculateFullJitterBackOffDelay(retriesAttempted));
Example #22
0
 public virtual void WaitForWorkersToStop(TimeSpan?timeout = null)
 {
     ExecUtils.RetryUntilTrue(
         () => Interlocked.CompareExchange(ref status, 0, 0) == WorkerStatus.Stopped,
         timeout);
 }
Example #23
0
        public void Does_retry_messages_with_errors_by_RetryCount()
        {
            var retryCount   = 1;
            var totalRetries = 1 + retryCount; //in total, inc. first try

            using (var mqHost = RabbitMqServerTests.CreateMqServer(retryCount))
            {
                using (var conn = mqHost.ConnectionFactory.CreateConnection())
                    using (var channel = conn.CreateModel())
                    {
                        channel.PurgeQueue <Reverse>();
                        channel.PurgeQueue <Rot13>();
                        channel.PurgeQueue <AlwaysThrows>();
                    }

                var reverseCalled = 0;
                var rot13Called   = 0;

                mqHost.RegisterHandler <Reverse>(x => { Interlocked.Increment(ref reverseCalled); return(x.GetBody().Value.Reverse()); });
                mqHost.RegisterHandler <Rot13>(x => { Interlocked.Increment(ref rot13Called); return(x.GetBody().Value.ToRot13()); });
                mqHost.RegisterHandler <AlwaysThrows>(x => { throw new Exception("Always Throwing! " + x.GetBody().Value); });
                mqHost.Start();

                using (var mqClient = mqHost.CreateMessageQueueClient())
                {
                    mqClient.Publish(new AlwaysThrows {
                        Value = "1st"
                    });
                    mqClient.Publish(new Reverse {
                        Value = "Hello"
                    });
                    mqClient.Publish(new Reverse {
                        Value = "World"
                    });
                    mqClient.Publish(new Rot13 {
                        Value = "ServiceStack"
                    });

                    ExecUtils.RetryOnException(() =>
                    {
                        Assert.That(mqHost.GetStats().TotalMessagesFailed, Is.EqualTo(1 * totalRetries));
                        Assert.That(mqHost.GetStats().TotalMessagesProcessed, Is.EqualTo(2 + 1));
                        Thread.Sleep(100);
                    }, TimeSpan.FromSeconds(5));

                    5.Times(x => mqClient.Publish(new AlwaysThrows {
                        Value = "#" + x
                    }));

                    mqClient.Publish(new Reverse {
                        Value = "Hello"
                    });
                    mqClient.Publish(new Reverse {
                        Value = "World"
                    });
                    mqClient.Publish(new Rot13 {
                        Value = "ServiceStack"
                    });
                }
                //Debug.WriteLine(mqHost.GetStatsDescription());

                ExecUtils.RetryOnException(() =>
                {
                    Assert.That(mqHost.GetStats().TotalMessagesFailed, Is.EqualTo((1 + 5) * totalRetries));
                    Assert.That(mqHost.GetStats().TotalMessagesProcessed, Is.EqualTo(6));

                    Assert.That(reverseCalled, Is.EqualTo(2 + 2));
                    Assert.That(rot13Called, Is.EqualTo(1 + 1));

                    Thread.Sleep(100);
                }, TimeSpan.FromSeconds(5));
            }
        }
Example #24
0
        public void Does_process_all_messages_and_Starts_Stops_correctly_with_multiple_threads_racing()
        {
            using (var mqHost = RabbitMqServerTests.CreateMqServer())
            {
                using (var conn = mqHost.ConnectionFactory.CreateConnection())
                    using (var channel = conn.CreateModel())
                    {
                        channel.PurgeQueue <Reverse>();
                        channel.PurgeQueue <Rot13>();
                    }

                var reverseCalled = 0;
                var rot13Called   = 0;

                mqHost.RegisterHandler <Reverse>(x =>
                {
                    "Processing Reverse {0}...".Print(Interlocked.Increment(ref reverseCalled));
                    return(x.GetBody().Value.Reverse());
                });
                mqHost.RegisterHandler <Rot13>(x =>
                {
                    "Processing Rot13 {0}...".Print(Interlocked.Increment(ref rot13Called));
                    return(x.GetBody().Value.ToRot13());
                });

                using (var mqClient = mqHost.CreateMessageQueueClient())
                {
                    mqClient.Publish(new Reverse {
                        Value = "Hello"
                    });
                    mqClient.Publish(new Reverse {
                        Value = "World"
                    });
                    mqClient.Publish(new Rot13 {
                        Value = "ServiceStack"
                    });

                    mqHost.Start();

                    ExecUtils.RetryOnException(() =>
                    {
                        Assert.That(mqHost.GetStatus(), Is.EqualTo("Started"));
                        Assert.That(mqHost.GetStats().TotalMessagesProcessed, Is.EqualTo(3));
                        Thread.Sleep(100);
                    }, TimeSpan.FromSeconds(5));

                    mqClient.Publish(new Reverse {
                        Value = "Foo"
                    });
                    mqClient.Publish(new Rot13 {
                        Value = "Bar"
                    });

                    10.Times(x => ThreadPool.QueueUserWorkItem(y => mqHost.Start()));
                    Assert.That(mqHost.GetStatus(), Is.EqualTo("Started"));

                    5.Times(x => ThreadPool.QueueUserWorkItem(y => mqHost.Stop()));
                    ExecUtils.RetryOnException(() =>
                    {
                        Assert.That(mqHost.GetStatus(), Is.EqualTo("Stopped"));
                        Thread.Sleep(100);
                    }, TimeSpan.FromSeconds(5));

                    10.Times(x => ThreadPool.QueueUserWorkItem(y => mqHost.Start()));
                    ExecUtils.RetryOnException(() =>
                    {
                        Assert.That(mqHost.GetStatus(), Is.EqualTo("Started"));
                        Thread.Sleep(100);
                    }, TimeSpan.FromSeconds(5));

                    Debug.WriteLine("\n" + mqHost.GetStats());

                    Assert.That(mqHost.GetStats().TotalMessagesProcessed, Is.GreaterThanOrEqualTo(5));
                    Assert.That(reverseCalled, Is.EqualTo(3));
                    Assert.That(rot13Called, Is.EqualTo(2));
                }
            }
        }
Example #25
0
        public void Does_process_all_messages_and_Starts_Stops_correctly_with_multiple_threads_racing()
        {
            using (var mqServer = RabbitMqServerTests.CreateMqServer()) {
                void Action0(IModel channel)
                {
                    channel.PurgeQueue <Reverse>();
                    channel.PurgeQueue <NothingHere>();
                }

                RabbitMqConfig.UsingChannel(mqServer.ConnectionFactory, Action0);

                var reverseCalled     = 0;
                var nothingHereCalled = 0;

                mqServer.RegisterHandler <Reverse>(x => {
                    Console.WriteLine("Processing Reverse {0}...", Interlocked.Increment(ref reverseCalled));
                    return(new ReverseResponse {
                        Value = string.Join(",", x.GetBody().Value.Reverse())
                    });
                });
                mqServer.RegisterHandler <NothingHere>(x => {
                    Console.WriteLine("Processing NothingHere {0}...", Interlocked.Increment(ref nothingHereCalled));
                    return(new NothingHereResponse {
                        Value = x.GetBody().Value
                    });
                });

                using (var mqClient = mqServer.CreateMessageQueueClient()) {
                    mqClient.Publish(new Reverse {
                        Value = "Hello"
                    });
                    mqClient.Publish(new Reverse {
                        Value = "World"
                    });
                    mqClient.Publish(new NothingHere {
                        Value = "HelloWorld"
                    });

                    mqServer.Start();

                    Thread.Sleep(1500);
                    Assert.That(mqServer.GetStatus(), Is.EqualTo("Started"));
                    Assert.That(mqServer.GetStats().TotalMessagesProcessed, Is.EqualTo(3));

                    mqClient.Publish(new Reverse {
                        Value = "Foo"
                    });
                    mqClient.Publish(new NothingHere {
                        Value = "Bar"
                    });

                    ExecUtils.ExecMultiThreading(10, () => mqServer.Start());
                    Assert.That(mqServer.GetStatus(), Is.EqualTo("Started"));

                    ExecUtils.ExecMultiThreading(5, () => mqServer.Stop());
                    Assert.That(mqServer.GetStatus(), Is.EqualTo("Stopped"));

                    ExecUtils.ExecMultiThreading(10, () => mqServer.Start());
                    Assert.That(mqServer.GetStatus(), Is.EqualTo("Started"));

                    Console.WriteLine("\n" + mqServer.GetStats());

                    Assert.That(mqServer.GetStats().TotalMessagesProcessed, Is.GreaterThanOrEqualTo(5));
                    Assert.That(reverseCalled, Is.EqualTo(3));
                    Assert.That(nothingHereCalled, Is.EqualTo(2));
                }
            }
        }
Example #26
0
 internal static async Task SleepBackOffMultiplierAsync(this int retriesAttempted, CancellationToken token = default) =>
 await Task.Delay(ExecUtils.CalculateFullJitterBackOffDelay(retriesAttempted), token);