예제 #1
0
        public void TestHostUnreachableResponseTime()
        {
            RedisServer.Kill();

            var stopWatch = new Stopwatch();

            try
            {
                using (var client = new QueueClient())
                {
                    var homemadeTask = new TaskMessage
                    {
                        Parameters = "params",
                        Queue = "TestQueue"
                    };

                    stopWatch.Start();
                    client.Enqueue(homemadeTask);
                    stopWatch.Stop();
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine("Elapsed time: {0} ms", stopWatch.ElapsedMilliseconds);
                Console.WriteLine(exception.ToString());
                RedisServer.Start();
                Assert.Pass();
            }
        }
예제 #2
0
		/// <summary>
		/// Adds a task to the queue specified in the task itself and sends a message to
		/// the associated channel, notifying any listeners.
		/// </summary>
		/// <param name="t"></param>
		public void Enqueue(TaskMessage t)
		{
			if (string.IsNullOrEmpty(t.Queue))
				throw new NoQueueSpecifiedException(
					"TaskMessage.Queue is empty or null. Cannot append task to queue.");

			var queue = new QueueName(t.Queue);

			TypedClient.Lists[queue.NameWhenPending].Add(t);
			SendMessage(QueueSystemMessages.TaskAvailable.ToString(), queue);

			Log.Info("New task in [" + queue.NameWhenPending + "]");
			Log.DebugFormat("Task Parameters: {0}", t.Parameters);
		}
		public void TestCachingCreatesAFile()
		{
			using (var client = new QueueClient())
			{
				var homemadeTask = new TaskMessage
				{
					Parameters = "params",
					Queue = "TestQueue"
				};

				client.Enqueue(homemadeTask);
				var retrievedTask = client.Reserve("TestQueue");

				Assert.That(File.Exists("redisCache.bin"));

				client.Fail(string.Empty);
				client.RemoveTask(client.AllTasks("TestQueue")[0]);
			}
		}
		public void TestCanEnqueueTaskInRedisAndReadItBack()
		{
			using(var client = new QueueClient())
			{
				var homemadeTask = new TaskMessage
				{
					Parameters = "params", 
					Queue = "TestQueue"
				};

				client.Enqueue(homemadeTask);
				var retrievedTask = client.Reserve("TestQueue");
			
				Assert.AreEqual(retrievedTask.Parameters, homemadeTask.Parameters);
				Assert.AreEqual(retrievedTask.Queue, homemadeTask.Queue);

				client.Fail(string.Empty);
				client.RemoveTask(client.AllTasks("TestQueue")[0]);
			}
		}
		public void TestProcessTaskWithNullTaskStorageSucceeds()
		{
			var monitor = new RedisMonitor();
			var task = new TaskMessage
			{
				Parameters = "Test Params",
				Queue = "TestQueue"
			};

			// Setup the Performer mock.
			var performerMock =new Mock<Performer>();
			performerMock.Setup(x => x.Perform(task.Parameters));
			performerMock.SetupGet(x => x.Status).Returns(new PerformResult
			{
				Data = string.Empty,
				Outcome = Outcome.Success,
				Reason = string.Empty
			});

			// Setup the Client mock.
			var clientMock = new Mock<QueueClient>();
			clientMock.Setup(x => x.Succeed());
			clientMock.SetupGet(x => x.RedisHost).Returns("127.0.0.1");
			clientMock.SetupGet(x => x.RedisPort).Returns(6379);
			
			monitor.Performer = performerMock.Object;
			monitor.MonitorClient = clientMock.Object;

			monitor.ProcessTask(task);

			Assert.That(performerMock.Object.TaskStorage == null);
			performerMock.Verify(x => x.Perform(task.Parameters));
			performerMock.VerifyGet(x => x.TaskStorage);
			performerMock.VerifyGet(x => x.Status);
			clientMock.Verify(x => x.Succeed());
		}
		public void TestMonitorCanRecoverFromRedisOutage()
		{
			var task = new TaskMessage
			{
				Parameters = "blah",
				Queue = "TestQueue"
			};
			
			var task2 = new TaskMessage
			{
				Parameters = "blah",
				Queue = "TestQueue"
			};

			var performerMock = new Mock<Performer>();
			performerMock.SetupGet(x => x.Status).Returns(new PerformResult
			{
				Data = string.Empty,
				Outcome = Outcome.Success,
				Reason = string.Empty
			});

			performerMock.Setup(x => x.Perform(task.Parameters));
			performerMock.Setup(x => x.Perform(task2.Parameters));

			var monitor = new RedisMonitor();
			monitor.Performer = performerMock.Object;

			monitor.Start();
			Assert.IsTrue(monitor.Running);

			using (var client = new QueueClient())
				client.Enqueue(task);

			Thread.Sleep(1500);
			RedisServer.Kill();
			
			Thread.Sleep(100);
			RedisServer.Start();
			
			Thread.Sleep(2000);
			using (var client = new QueueClient())
				client.Enqueue(task2);

			Thread.Sleep(10000);
			monitor.Stop();

			Assert.IsFalse(monitor.Running);
		}
예제 #7
0
        public void TestCachingCanPreserveTask()
        {
            using (var client = new QueueClient())
            {
                var homemadeTask = new TaskMessage
                {
                    Parameters = "params",
                    Queue = "TestQueue"
                };

                client.Enqueue(homemadeTask);
                var retrievedTask = client.Reserve("TestQueue");
            }

            using (var client = new QueueClient())
            {
                Assert.That(client.CurrentTask != null);
                client.Fail(string.Empty);
                client.RemoveTask(client.AllTasks("TestQueue")[0]);
            }
        }
		public void TestProcessPendingTasksForMultipleTasksMockingPerformerOnly()
		{
			#region Prepare Tasks and mock Performer for processing
			var monitor = new RedisMonitor();
			var performerMock = new Mock<Performer>();

			using (var client = new QueueClient())
			{
				for (var i = 0; i < 10; i++)
				{
					var task = new TaskMessage
					{
						Parameters = "Task " + i,
						Queue = "TestQueue"
					};

					client.Enqueue(task);
					performerMock.Setup(x => x.Perform(task.Parameters));
				}
			}

			// ensure all tasks will be successful.
			performerMock.SetupGet(x => x.Status).Returns(new PerformResult
			{
				Data = string.Empty,
				Outcome = Outcome.Success,
				Reason = string.Empty
			});
			#endregion

			monitor.Performer = performerMock.Object;
			monitor.Start();
			Thread.Sleep(2000);
			monitor.Stop();


			for (var i = 0; i < 10; i++)
				performerMock.Verify(x => x.Perform("Task " + i));

			performerMock.VerifyGet(x => x.TaskStorage);
			performerMock.VerifyGet(x => x.Status);

			using(var client = new QueueClient())
				Assert.AreEqual(client.PendingTasks("TestQueue").Count, 0);
		}
		public void TestMonitorWakesUpOnMessageReceived()
		{
			var task = new TaskMessage
			{
				Parameters = "blah",
				Queue = "TestQueue"
			};

			var performerMock = new Mock<Performer>();
			performerMock.SetupGet(x => x.Status).Returns(new PerformResult
			{
				Data = string.Empty,
				Outcome = Outcome.Success,
				Reason = string.Empty
			});

			performerMock.Setup(x => x.Perform(task.Parameters));

			var monitor = new RedisMonitor();
			monitor.Performer = performerMock.Object;

			var start = DateTime.Now;

			monitor.Start();
			Assert.IsTrue(monitor.Running);

			using (var client = new QueueClient())
				client.Enqueue(task);

			monitor.Stop();
			Assert.IsFalse(monitor.Running);

			var stop = DateTime.Now;
			Assert.Less((stop - start).TotalSeconds, 60);
		}
		public void TestProcessTaskWhenTaskPerformerThrowsException()
		{
			var monitor = new RedisMonitor();
			var task = new TaskMessage
			{
				Parameters = "Test Params",
				Queue = "TestQueue"
			};

			// Setup the Performer mock.
			var performerMock =new Mock<Performer>();
			var exception = new Exception("Test");
			performerMock.Setup(x => x.Perform(task.Parameters)).Throws(exception);
			performerMock.SetupGet(x => x.Status).Returns(new PerformResult
			{
				Data = string.Empty,
				Outcome = Outcome.Success,
				Reason = string.Empty
			});

			// Setup the Client mock.
			var clientMock = new Mock<QueueClient>();
			clientMock.SetupGet(x => x.RedisHost).Returns("127.0.0.1");
			clientMock.SetupGet(x => x.RedisPort).Returns(6379);
			clientMock.Setup(x => x.Fail(
				"The performer raised an exception: "
					+ exception.Message
					+ "\n"
					+ exception.StackTrace));
			
			monitor.Performer = performerMock.Object;
			monitor.MonitorClient = clientMock.Object;

			monitor.ProcessTask(task);

			performerMock.Verify(x => x.Perform(task.Parameters));
			performerMock.VerifyGet(x => x.TaskStorage);
			clientMock.Verify(x => x.Fail(
				"The performer raised an exception: "
					+ exception.Message
					+ "\n"
					+ exception.StackTrace));
		}
		public void TestProcessTaskCriticalFailure()
		{
			var monitor = new RedisMonitor();
			var task = new TaskMessage
			{
				Parameters = "Test Params",
				Queue = "TestQueue"
			};

			// Setup the Performer mock.
			var performerMock = new Mock<Performer>();
			performerMock.Setup(x => x.Perform(task.Parameters));
			performerMock.SetupGet(x => x.Status).Returns(new PerformResult
			{
				Data = string.Empty,
				Outcome = Outcome.CriticalFailure,
				Reason = "blah"
			});

			// Setup the Client mock.
			var clientMock = new Mock<QueueClient>();
			clientMock.Setup(x => x.CriticalFail("blah"));
			clientMock.SetupGet(x => x.RedisHost).Returns("127.0.0.1");
			clientMock.SetupGet(x => x.RedisPort).Returns(6379);

			monitor.Performer = performerMock.Object;
			monitor.MonitorClient = clientMock.Object;

			monitor.ProcessTask(task);

			performerMock.Verify(x => x.Perform(task.Parameters));
			performerMock.VerifyGet(x => x.TaskStorage);
			clientMock.Verify(x => x.CriticalFail("blah"));
		}
예제 #12
0
		/// <summary>
		/// Processes a single task and updates the queue accordingly.
		/// </summary>
		/// <param name="task"></param>
		protected internal void ProcessTask(TaskMessage task)
		{
			// Get the state of the task into the performer.
			Performer.TaskStorage = task.Storage;

			// Let the performer have a go with the task.
			try { Performer.Perform(task.Parameters); }
			catch (Exception exception)
			{
				// The performer has raised an exception while processing 
				// the task. We do what we can to preserve the task,
				// and set it back as failed.
				try { task.Storage = Performer.TaskStorage; }
				catch {}

				var message =
					"The performer raised an exception: "
					+ exception.Message
					+ "\n"
					+ exception.StackTrace;

				MonitorClient.Fail(message);
				Log.Error(message);

				return;
			}

			// Collect the task's state and save it back to the task.
			task.Storage = Performer.TaskStorage;

			// Collect the result of the perfomer's work and act on it.
			var result = Performer.Status;

			switch (result.Outcome)
			{
				case Outcome.Success:
					MonitorClient.Succeed();
					Log.Info("Task succeeded.");
					break;

				case Outcome.Failure:
					MonitorClient.Fail(result.Reason);
					Log.InfoFormat("Task failed. Reason: {0}", result.Reason);

					if (result.Data is Exception)
						Log.Error("Exception associated with task failure:", result.Data as Exception);

					if (result.Data is string)
						Log.InfoFormat("Additional Information: {0}", result.Data);

					break;

				case Outcome.CriticalFailure:
					MonitorClient.CriticalFail(result.Reason);
					Log.InfoFormat("Task failed critically. Reason: {0}", result.Reason);

					if (result.Data is string)
						Log.InfoFormat("Additional Information: {0}", result.Data);

					break;
			}
		}
예제 #13
0
        public void TestHostDifferentPort()
        {
            var stopWatch = new Stopwatch();

            try
            {
                using (var client = new QueueClient("localhost", 6377, false))
                {
                    var homemadeTask = new TaskMessage
                    {
                        Parameters = "params",
                        Queue = "TestQueue"
                    };

                    stopWatch.Start();
                    client.Enqueue(homemadeTask);
                    stopWatch.Stop();
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine("Elapsed time: {0} ms", stopWatch.ElapsedMilliseconds);
                Console.WriteLine(exception.ToString());
                Assert.Pass();
            }
        }
예제 #14
0
		public bool Equals(TaskMessage other)
		{
			if (ReferenceEquals(null, other)) return false;
			if (ReferenceEquals(this, other)) return true;
			return Equals(other._queue, _queue) && other.Identifier.Equals(Identifier) && Equals(other.Parameters, Parameters);
		}
예제 #15
0
        public void TestWriteLatencyForDifferentPayloads()
        {
            var stopWatch = new Stopwatch();

            using (var client = new QueueClient())
            {
                // Small message
                var homemadeTask = new TaskMessage
                {
                    Parameters = RandomString(1024),
                    Queue = "TestQueue"
                };

                stopWatch.Start();
                client.Enqueue(homemadeTask);
                stopWatch.Stop();

                Console.WriteLine("1K Message write latency (no network included): {0} ms", stopWatch.ElapsedMilliseconds);

                // Medium message
                homemadeTask = new TaskMessage
                {
                    Parameters = RandomString(1024 * 10),
                    Queue = "TestQueue"
                };

                stopWatch.Start();
                client.Enqueue(homemadeTask);
                stopWatch.Stop();

                Console.WriteLine("10K Message write latency (no network included): {0} ms", stopWatch.ElapsedMilliseconds);

                // Large message
                homemadeTask = new TaskMessage
                {
                    Parameters = RandomString(1024 * 100),
                    Queue = "TestQueue"
                };

                stopWatch.Start();
                client.Enqueue(homemadeTask);
                stopWatch.Stop();

                Console.WriteLine("100K Message write latency (no network included): {0} ms", stopWatch.ElapsedMilliseconds);
            }
        }
예제 #16
0
		/// <summary>
		/// Adds a task to the queue specified in the task itself and sends a message to
		/// the associated channel, notifying any listeners.
		/// </summary>
		/// <param name="t"></param>
		public void Enqueue(TaskMessage t)
		{
			if (string.IsNullOrEmpty(t.Queue))
				throw new NoQueueSpecifiedException(
					"TaskMessage.Queue is empty or null. Cannot append task to queue.");

			var queue = new QueueName(t.Queue);

		    try
		    {
                TypedClient.Lists[queue.NameWhenPending].Add(t);
                SendMessage(QueueSystemMessages.TaskAvailable.ToString(), queue);

                Log.Info("New task in [" + queue.NameWhenPending + "]");
                Log.DebugFormat("Task Parameters: {0}", t.Parameters);
            }
		    catch (IOException)
		    {
		        TasksNotEnqueuedLog.Info(new JsonSerializer<TaskMessage>().SerializeToString(t));
		        throw;
		    }
		    catch (RedisException)
		    {
		        TasksNotEnqueuedLog.Info(new JsonSerializer<TaskMessage>().SerializeToString(t));
		        throw;
		    }

		}
예제 #17
0
		private void removeTask(string queue, TaskMessage task)
		{
			var results = new List<TaskMessage>();
			TaskMessage t;
			while ((t = TypedClient.Lists[queue].RemoveStart()) != null)
			{
				if (t.Equals(task)) continue;
				results.Add(t);
			}

			if (results.Count > 0)
				TypedClient.Lists[queue].AddRange(results);
		}
예제 #18
0
		/// <summary>
		/// Removes a task with a specific task identifier.
		/// </summary>
		/// <param name="task"></param>
		public void RemoveTask(TaskMessage task)
		{
			var queueName = new QueueName(task.Queue);
			removeTask(queueName.NameWhenPending, task);
			removeTask(queueName.NameWhenFailed, task);
			removeTask(queueName.NameWhenSucceeded, task);
		}