Example #1
0
        private async Task EnqueueCalls(RpcQueue queue, int threadNumber, int threadsCount, int callsCount)
        {
            for (int i = threadNumber; i < callsCount; i += threadsCount)
            {
                await queue.Enqueue(new RpcCall());

                if (threadNumber == 0)
                {
                    await Task.Delay(10); // Task 0 is slow for testing
                }
            }
        }
Example #2
0
        public async Task Enqueue_LoadTest_SingleThread()
        {
            int count = 10_000;
            var queue = await RpcQueue.Create(targetPeerID : null, backlog : null);

            // As fast as possible, enqueue all items
            for (int i = 0; i < count; i++)
            {
                await queue.Enqueue(new RpcCall());
            }
            // Check all items are here
            Assert.AreEqual(count, queue.Count);
        }
Example #3
0
        public async Task Create_RestoreFromBacklog()
        {
            var    backlog      = new JsonFileRpcBacklog(new DirectoryInfo(backlogDir));
            string targetPeerID = "TestClient";
            int    callsCount   = 10;
            // Create queue and enqueue
            var queue = await RpcQueue.Create(targetPeerID, backlog);

            for (int i = 0; i < callsCount; i++)
            {
                await queue.Enqueue(CreateCall("TestMethod", targetPeerID));
            }
            // Recreate queue and check contents
            queue = await RpcQueue.Create(targetPeerID, backlog);

            Assert.AreEqual(callsCount, queue.Count);
        }
Example #4
0
        /// <summary>
        /// Creates a new queue for the given client ID or null for the server,
        /// using the optional backlog implementation for permanent storage of remaining calls.
        /// </summary>
        public static async Task <RpcQueue> Create(string?targetPeerID, IRpcBacklog?backlog)
        {
            var ret = new RpcQueue(targetPeerID, backlog);

            if (backlog != null)
            {
                // Restore queue from backlog
                await ret.semaphore.WaitAsync();

                foreach (var call in await backlog.ReadAll(targetPeerID))
                {
                    call.ResetStartTimeAndResult();
                    ret.queue.Enqueue(call);
                }
                ret.semaphore.Release();
            }
            return(ret);
        }
Example #5
0
        public async Task Enqueue_And_Peek_And_Dequeue_CorrectOrder()
        {
            int    callsCount   = 100;
            string targetPeerID = "TestClient";
            var    backlog      = new JsonFileRpcBacklog(new DirectoryInfo(backlogDir));
            var    queue        = await RpcQueue.Create(targetPeerID, backlog);

            var allTasks = new List <Task>();

            // Enqueue
            allTasks.Add(Task.Run(async() => {
                await Task.Delay(1000); // Wait a moment, so that the test starts with an empty backlog
                for (int iCall = 0; iCall < callsCount; iCall++)
                {
                    await queue.Enqueue(CreateCall("TestMethod", targetPeerID));
                    await Task.Delay(50);
                }
            }));
            // Peek and dequeue, with checking the order
            allTasks.Add(Task.Run(async() => {
                ulong lastID           = 0;
                int receivedCallsCount = 0;
                while (receivedCallsCount < callsCount)
                {
                    if (await queue.Peek() is RpcCall peekedCall)
                    {
                        // Check that the ID is higher than the last one
                        Assert.IsTrue(peekedCall.Method.ID > lastID);
                        // Dequeue
                        var dequeuedCall = await queue.Dequeue();
                        // Dequeued call must be the same call (same ID) as the previously peeked call
                        Assert.AreEqual(dequeuedCall !.Method.ID, peekedCall.Method.ID);
                        lastID = dequeuedCall.Method.ID;
                        receivedCallsCount++;
                    }
                    await Task.Delay(50);
                }
            }));
            // Wait until tasks are finished
            await Task.WhenAll(allTasks);

            // Backlog must also be empty now
            Assert.AreEqual(0, (await backlog.ReadAll(targetPeerID)).Count);
        }
Example #6
0
        public async Task Enqueue_LoadTest_MultipleThreads()
        {
            int count        = 10_000;
            int threadsCount = 100;
            var queue        = await RpcQueue.Create(targetPeerID : null, backlog : null);

            // As fast as possible, enqueue all items
            List <Task> allTasks = new List <Task>();

            for (int i = 0; i < threadsCount; i++)
            {
                var task = EnqueueCalls(queue, i, threadsCount, count);
                allTasks.Add(task);
            }
            await Task.WhenAll(allTasks);

            // Check all items are here
            Assert.AreEqual(count, queue.Count);
        }
Example #7
0
        public async Task Enqueue_RemoveObsolete()
        {
            int    callsCount         = 100;
            string targetPeerID       = "TestClient";
            var    retryLatestMethods = new HashSet <string> {
                "Method5", "Method8"
            };
            var backlog = new JsonFileRpcBacklog(new DirectoryInfo(backlogDir));
            var queue   = await RpcQueue.Create(targetPeerID, backlog);

            var allCalls = new List <RpcCall>();

            // Enqueue
            for (int iCall = 0; iCall < callsCount; iCall++)
            {
                string methodName = "Method" + random.Next(10);
                var    retry      = retryLatestMethods.Contains(methodName)
                    ? RpcRetryStrategy.RetryLatest : RpcRetryStrategy.Retry;
                var call = CreateCall(methodName, targetPeerID, retry);
                allCalls.Add(call);
                await queue.Enqueue(call);

                await Task.Delay(50);
            }
            // Test backlog: Only last call of the RetryLatest methods must be there
            var backlogCalls = await backlog.ReadAll(targetPeerID);

            var callsWithoutObsolete = allCalls.Where((call, index) => {
                if (call.RetryStrategy == RpcRetryStrategy.RetryLatest)
                {
                    return(allCalls.FindLastIndex(it => it.Method.Name == call.Method.Name) == index);
                }
                return(true);
            }).ToList();

            CollectionAssert.AreEqual(callsWithoutObsolete, backlogCalls);
            // Test queue: All methods must still be there
            Assert.AreEqual(allCalls.Count, queue.Count);
            for (int i = 0; i < allCalls.Count; i++)
            {
                Assert.AreEqual(allCalls[i], await queue.Dequeue());
            }
        }