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 } } }
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); }
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); }
/// <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); }
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); }
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); }
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()); } }