public void Init() { var accountId = Environment.GetEnvironmentVariable("SQS_ACCOUNT_ID"); if(string.IsNullOrEmpty(accountId)) { accountId = "accountid"; } var publicKey = Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID"); if(string.IsNullOrEmpty(publicKey)) { publicKey = "publickey"; } var privateKey = Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY"); if(string.IsNullOrEmpty("privatekey")) { privateKey = "privatekey"; } _client = new SqsClient(SqsClientConfig.From(new XDoc("sqs-config") .Elem("endpoint", "default") .Elem("accountid", accountId) .Elem("publickey", publicKey) .Elem("privatekey", privateKey))); TEST_QUEUE = new SqsQueueName("steveb-events"); // purge the queue while(true) { var messages = _client.ReceiveMessages(TEST_QUEUE, 1.Seconds(), SqsUtils.MAX_NUMBER_OF_MESSAGES_TO_FETCH); if(messages.None()) { break; } _client.DeleteMessages(TEST_QUEUE, messages); } }
public IEnumerable<SqsMessageId> DeleteMessages(SqsQueueName queueName, IEnumerable<SqsMessage> messages) { foreach(var message in messages) { DeleteMessage(queueName, message.MessageReceipt); } return new SqsMessageId[0]; }
private void AssertQueueIsNotNull(SqsQueueName queueName, List <QueueEntry> queue) { if (queue == null) { throw new InMemorySqsNullQueueException(string.Format("Queue '{0}' is null", queueName)); } }
/// <summary> /// Send one or more message to a named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBodies">Enumeration of message bodies.</param> /// <returns>Enumeration of message bodies that failed to send.</returns> public IEnumerable <string> SendMessages(SqsQueueName queueName, IEnumerable <string> messageBodies) { if (messageBodies.Count() > SqsUtils.MAX_NUMBER_OF_BATCH_SEND_MESSAGES) { throw new ArgumentException(string.Format("messageBodies is larger than {0}, which is the maximum", SqsUtils.MAX_NUMBER_OF_BATCH_SEND_MESSAGES)); } var msgId = 1; var attributes = GetQueueNameAttribute(queueName.Value); var sendEntries = (from messageBody in messageBodies select new SendMessageBatchRequestEntry { MessageBody = messageBody, Id = string.Format("msg-{0}", msgId++), MessageAttributes = attributes }).ToList(); var response = Invoke(() => _client.SendMessageBatch(new SendMessageBatchRequest { QueueUrl = GetQueueUrl(queueName.Value), Entries = sendEntries }), queueName, SENDING_BATCH_MESSAGES); AssertSuccessfulStatusCode(response.HttpStatusCode, queueName, SENDING_BATCH_MESSAGES); if (response.Failed.None()) { return(Enumerable.Empty <string>()); } var messagesById = sendEntries.ToDictionary(entry => entry.Id, entry => entry.MessageBody); return(response.Failed.Select(failed => messagesById.TryGetValue(failed.Id, null)).Where(messageBody => messageBody != null).ToArray()); }
//--- Class Methods --- private static void AssertSuccessfulStatusCode(HttpStatusCode statusCode, SqsQueueName queueName, string sqsOperation) { if (statusCode != HttpStatusCode.OK) { throw new SqsException(string.Format("Got a '{0}' response while '{1}' from SQS queue '{2}'", statusCode, sqsOperation, queueName.Value), null); } }
//--- Methods --- /// <summary> /// Receive zero or more messages from name queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="waitTimeSeconds">Max amount of time to wait until this method returns.</param> /// <param name="maxNumberOfMessages">Max number of messages to request.</param> /// <returns>Enumeration of received messages.</returns> public IEnumerable <SqsMessage> ReceiveMessages(SqsQueueName queueName, TimeSpan waitTimeSeconds, uint maxNumberOfMessages) { // Check preconditions if (waitTimeSeconds.TotalSeconds > SqsUtils.MAX_LONG_POLL_WAIT_TIME.TotalSeconds) { throw new ArgumentException(string.Format("The argument waitTimeSeconds is larger than '{0}', which is the maximum value allowed", SqsUtils.MAX_LONG_POLL_WAIT_TIME.TotalSeconds)); } if (maxNumberOfMessages > SqsUtils.MAX_NUMBER_OF_MESSAGES_TO_FETCH) { throw new ArgumentException(string.Format("The argument maxNumberOfMessages is larger than '{0}', which is the maximum value allowed", SqsUtils.MAX_NUMBER_OF_MESSAGES_TO_FETCH)); } // Perform request var response = Invoke(() => _client.ReceiveMessage(new ReceiveMessageRequest { QueueUrl = GetQueueUrl(queueName.Value), WaitTimeSeconds = (int)waitTimeSeconds.TotalSeconds, MaxNumberOfMessages = (int)maxNumberOfMessages }), queueName, RECEIVING_MESSAGE ); AssertSuccessfulStatusCode(response.HttpStatusCode, queueName, RECEIVING_MESSAGE); return(response.Messages.Select(msg => new SqsMessage(new SqsMessageId(msg.MessageId), new SqsMessageReceipt(msg.ReceiptHandle), msg.Body)).ToArray()); }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="callback">Callback for received SQS messages.</param> /// <param name="longPollInterval">Max amount of time to wait for SQS message to arrive.</param> /// <param name="maxNumberOfMessages">Max number of SQS messages to request.</param> /// <param name="waitTimeOnError">Amount of time to wait until trying again to listen after an error occurred.</param> public SqsPollingClientSettings(SqsQueueName queueName, Action <IEnumerable <SqsMessage> > callback, TimeSpan longPollInterval, uint maxNumberOfMessages, TimeSpan waitTimeOnError) { if (callback == null) { throw new ArgumentNullException("callback"); } if (longPollInterval == null) { throw new ArgumentNullException("longPollInterval"); } if (longPollInterval > 20.Seconds()) { throw new ArgumentException("longPollInterval exceeds the limit allowed"); } if (waitTimeOnError == null) { throw new ArgumentNullException("waitTimeOnError"); } if (waitTimeOnError < 0.Seconds() || waitTimeOnError > 5.Minutes()) { throw new ArgumentException("waitTimeOnError must be greater than 0 up to 5 minutes"); } this.QueueName = queueName; this.Callback = callback; this.LongPollInterval = longPollInterval; this.MaxNumberOfMessages = maxNumberOfMessages; this.WaitTimeOnError = waitTimeOnError; }
private List <QueueEntry> GetQueue(SqsQueueName queueName) { lock (_queues) { List <QueueEntry> msgQueue; _queues.TryGetValue(queueName, out msgQueue); return(msgQueue); } }
//--- Methods --- /// <summary> /// Delete messages from named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messages">Enumeration of messages to delete.</param> /// <returns>Enumeration of messages that failed to delete.</returns> public IEnumerable <SqsMessageId> DeleteMessages(SqsQueueName queueName, IEnumerable <SqsMessage> messages) { foreach (var message in messages) { DeleteMessage(queueName, message.MessageReceipt); } return(new SqsMessageId[0]); }
public void sending_a_message_to_unknown_queue_throws_an_amazon_sqs_exception() { // Setup var queue = new SqsQueueName("unknown-queue"); // Act _client.SendMessage(queue, new XDoc("event").Attr("id", 1).ToCompactString()); }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="client">ISqsClient instance.</param> public SqsQueueClient(SqsQueueName queueName, ISqsClient client) { if(client == null) { throw new ArgumentNullException("client"); } this.QueueName = queueName; _client = client; }
/// <summary> /// Send one or more message to a named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBodies">Enumeration of message bodies.</param> /// <returns>Enumeration of message bodies that failed to send.</returns> public IEnumerable <string> SendMessages(SqsQueueName queueName, IEnumerable <string> messageBodies) { foreach (var messageBody in messageBodies) { SendMessage(queueName, messageBody); } return(Enumerable.Empty <string>()); }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="client">ISqsClient instance.</param> /// <param name="queueName">Queue name.</param> /// <param name="timerFactory">TimerFactory instance.</param> public SqsQueueDelayedSendClient(ISqsClient client, SqsQueueName queueName, TaskTimerFactory timerFactory) { if(client == null) { throw new ArgumentNullException("client"); } this.QueueName = queueName; _client = client; _timedSendAccumulator = new TimedAccumulator<KeyValuePair<int, string>>(items => AsyncUtil.ForkBackgroundSender(() => BatchSendMessages(items)), SqsUtils.MAX_NUMBER_OF_BATCH_SEND_MESSAGES, AUTOFLUSH_TIME, timerFactory); }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="client">ISqsClient instance.</param> public SqsQueueClient(SqsQueueName queueName, ISqsClient client) { if (client == null) { throw new ArgumentNullException("client"); } this.QueueName = queueName; _client = client; }
private static T Invoke <T>(Func <T> function, SqsQueueName queueName, string sqsOperation) { try { return(function()); } catch (AmazonSQSException e) { throw new SqsException(string.Format("There was an SQS error '{0}', from the '{1}' SQS queue", sqsOperation, queueName.Value), e); } catch (Exception e) { throw new SqsException(string.Format("There was an error '{0}', from the '{1}' SQS queue", sqsOperation, queueName.Value), e); } }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="client">ISqsClient instance.</param> /// <param name="queueName">Queue name.</param> /// <param name="timerFactory">TimerFactory instance.</param> public SqsQueueDelayedSendClient(ISqsClient client, SqsQueueName queueName, TaskTimerFactory timerFactory) { if (client == null) { throw new ArgumentNullException("client"); } this.QueueName = queueName; _client = client; _timedSendAccumulator = new TimedAccumulator <KeyValuePair <int, string> >(items => AsyncUtil.ForkBackgroundSender(() => BatchSendMessages(items)), SqsUtils.MAX_NUMBER_OF_BATCH_SEND_MESSAGES, AUTOFLUSH_TIME, timerFactory); }
/// <summary> /// Delete a named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>True if the named queue was deleted</returns> public bool DeleteQueue(SqsQueueName queueName) { lock (_queues) { if (_queues.ContainsKey(queueName)) { _queues.Remove(queueName); } return(true); } }
/// <summary> /// Send message on named queue with a visibility delay. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBody">Message body.</param> /// <param name="delay">Time to wait until the message becomes visible.</param> public void SendMessage(SqsQueueName queueName, string messageBody, TimeSpan delay) { var msgQueue = GetQueue(queueName); AssertQueueIsNotNull(queueName, msgQueue); lock (msgQueue) { var entry = new QueueEntry(new SqsMessage(new SqsMessageId(Guid.NewGuid().ToString()), new SqsMessageReceipt(Guid.NewGuid().ToString()), messageBody), DateTime.MinValue); msgQueue.Add(entry); } }
/// <summary> /// Create a new named queue and gets its URI. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>True if the named queue was created.</returns> public bool CreateQueue(SqsQueueName queueName) { lock (_queues) { if (!_queues.ContainsKey(queueName)) { _queues[queueName] = new List <QueueEntry>(); } return(true); } }
public void Can_round_trip_message_through_queue() { var sqs = new InMemorySqsClient(); var queueName = new SqsQueueName("bar"); sqs.CreateQueue(queueName); sqs.SendMessage(queueName, "msg body"); var messages = sqs.ReceiveMessages(queueName, 0.Seconds(), 10); Assert.AreEqual(1, messages.Count()); var received = messages.First(); Assert.AreEqual("msg body", received.Body); }
/// <summary> /// Delete a named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>True if the named queue was deleted</returns> public bool DeleteQueue(SqsQueueName queueName) { var response = Invoke(() => _client.DeleteQueue(new DeleteQueueRequest { QueueUrl = GetQueueUrl(queueName.Value) }), queueName, DELETING_QUEUE ); return(response.HttpStatusCode == HttpStatusCode.OK); }
/// <summary> /// Create a new named queue and gets its URI. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>True if the named queue was created.</returns> public bool CreateQueue(SqsQueueName queueName) { var response = Invoke(() => _client.CreateQueue(new CreateQueueRequest { QueueName = queueName.Value }), queueName, CREATING_QUEUE ); return(response.HttpStatusCode == HttpStatusCode.OK); }
public void Can_create_and_delete_queues() { var sqs = new InMemorySqsClient(); var queueName = new SqsQueueName("bar"); sqs.CreateQueue(queueName); var queues = sqs.ListQueues(null); Assert.AreEqual(1, queues.Count()); Assert.AreEqual("bar", queues.First()); sqs.DeleteQueue(queueName); queues = sqs.ListQueues(null); Assert.IsFalse(queues.Any()); }
public void sending_a_message_with_a_delay_works() { // Setup var queue = new SqsQueueName("unknown-queue"); // Act for(int i = 0; i < 10; i++) { _client.SendMessage(queue, new XDoc("event") .Start("page") .Elem("page", "/a/b/c") .End().ToCompactString(), 30.Seconds()); } }
/// <summary> /// Get enumeration of all messages that are currently held by the in-memory named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>Enumeration of messages.</returns> public IEnumerable <SqsMessage> InspectQueue(SqsQueueName queueName) { lock (_queues) { var msgQueue = GetQueue(queueName); if (msgQueue == null) { return(new SqsMessage[0]); } lock (msgQueue) { return(msgQueue.Select(x => x.Message).ToArray()); } } }
/// <summary> /// Removed all messages from named queue. /// </summary> /// <param name="queueName">Queue name</param> public void ClearQueue(SqsQueueName queueName) { lock (_queues) { var msgQueue = GetQueue(queueName); if (msgQueue == null) { return; } lock (msgQueue) { msgQueue.Clear(); } } }
/// <summary> /// Send message on named queue with a visibility delay. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBody">Message body.</param> /// <param name="delay">Time to wait until the message becomes visible.</param> public void SendMessage(SqsQueueName queueName, string messageBody, TimeSpan delay) { var response = Invoke(() => _client.SendMessage(new SendMessageRequest { QueueUrl = GetQueueUrl(queueName.Value), MessageBody = messageBody, DelaySeconds = (int)delay.TotalSeconds, MessageAttributes = GetQueueNameAttribute(queueName.Value) }), queueName, SENDING_MESSAGE); AssertSuccessfulStatusCode(response.HttpStatusCode, queueName, SENDING_MESSAGE); }
/// <summary> /// Delete single message from named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageReceipt">Message receipt.</param> /// <returns>True if message was deleted.</returns> public bool DeleteMessage(SqsQueueName queueName, SqsMessageReceipt messageReceipt) { var response = Invoke(() => _client.DeleteMessage(new DeleteMessageRequest { QueueUrl = GetQueueUrl(queueName.Value), ReceiptHandle = messageReceipt.Value }), queueName, DELETING_MESSAGE ); AssertSuccessfulStatusCode(response.HttpStatusCode, queueName, DELETING_MESSAGE); return(response.HttpStatusCode == HttpStatusCode.OK); }
/// <summary> /// Delete single message from named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageReceipt">Message receipt.</param> /// <returns>True if message was deleted.</returns> public bool DeleteMessage(SqsQueueName queueName, SqsMessageReceipt messageReceipt) { var msgQueue = GetQueue(queueName); AssertQueueIsNotNull(queueName, msgQueue); lock (msgQueue) { var entry = msgQueue.FirstOrDefault(x => x.Message.MessageReceipt == messageReceipt); if (entry != null) { msgQueue.Remove(entry); } } return(true); }
public void creating_a_queue_that_is_already_created_multiple_times_always_returns_http_200_responses() { // This assumes that'test-queue' is a queue that has already been created // And that you can create queues in SQS var queueName = new SqsQueueName("test-queue"); // Create the queue for the first time var queue1Success = _client.CreateQueue(queueName); Assert.IsTrue(queue1Success, "Creating queue first time failed"); // Try to create the queue for the second time var queue2Success = _client.CreateQueue(queueName); Assert.IsTrue(queue2Success, "Creating queue second time failed"); }
/// <summary> /// Get delegate for enqueuing messages asynchronously to named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>Delegate for enqueuing message asynchronously.</returns> public Action <string> GetEnqueueMessageCallback(SqsQueueName queueName) { repeat: SqsQueueDelayedSendClient queue; var directory = _directory; if (!directory.TryGetValue(queueName.Value, out queue)) { var newDirectory = new Dictionary <string, SqsQueueDelayedSendClient>(directory); newDirectory[queueName.Value] = queue = new SqsQueueDelayedSendClient(_client, queueName, _timerFactory); if (!SysUtil.CAS(ref _directory, directory, newDirectory)) { goto repeat; } } return(queue.EnqueueMessage); }
public void polling_client_pulls_from_sqs_and_calls_callback() { var mockSqsClient = new MockSqsClient(); mockSqsClient.FillQueue(15); var pollster = new SqsPollingClient(mockSqsClient); Assert.AreEqual(15, mockSqsClient.Queued.Count, "queue was accessed prematurely"); var posted = new List<SqsMessage>(); var fooQueue = new SqsQueueName("foo"); pollster.Listen(new SqsPollingClientSettings( queueName: fooQueue, callback: messages => { posted.AddRange(messages); foreach(var msg in messages) { mockSqsClient.DeleteMessage(fooQueue, msg.MessageReceipt); } }, longPollInterval: 0.Seconds(), maxNumberOfMessages: SqsUtils.MAX_NUMBER_OF_MESSAGES_TO_FETCH, waitTimeOnError: 1.Seconds())); Assert.IsTrue(Wait.For(() => mockSqsClient.Queued.Count == 0, 10.Seconds()), "queue did not get depleted in time"); Assert.IsTrue( Wait.For(() => mockSqsClient.ReceiveCalled > 0, 5.Seconds()), string.Format("receive called the wrong number of times: Expected {0} != {1}", 3, mockSqsClient.ReceiveCalled) ); Assert.AreEqual(15, mockSqsClient.Delivered.Count, "delivered has the wrong number of messages"); // Compare delivered and deleted Assert.AreEqual(mockSqsClient.Delivered.Count(), mockSqsClient.Deleted.Count(), "The count of delivered messages and deleted messages does not match and it must"); for(var i = 0; i < mockSqsClient.Delivered.Count(); i++) { Assert.AreEqual( mockSqsClient.Delivered[i].MessageReceipt, mockSqsClient.Deleted[i], "delivered message and deleted message don't match on index " + i); } Assert.AreEqual(mockSqsClient.Delivered.Count(), posted.Count(), "The number of delivered messages and posted messages does not match and it should"); for(var i = 0; i < mockSqsClient.Delivered.Count(); i++) { Assert.AreEqual( mockSqsClient.Delivered[i], posted[i], "delivered and posted don't match"); } }
/// <summary> /// Delete messages from named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messages">Enumeration of messages to delete.</param> /// <returns>Enumeration of messages that failed to delete.</returns> public IEnumerable <SqsMessageId> DeleteMessages(SqsQueueName queueName, IEnumerable <SqsMessage> messages) { if (messages.Count() > SqsUtils.MAX_NUMBER_OF_BATCH_DELETE_MESSAGES) { throw new ArgumentException(string.Format("messageReceipts is larger than {0}, which is the maximum", SqsUtils.MAX_NUMBER_OF_BATCH_DELETE_MESSAGES)); } var deleteEntries = messages.Distinct(message => message.MessageId.Value).Select(message => new DeleteMessageBatchRequestEntry { Id = message.MessageId.Value, ReceiptHandle = message.MessageReceipt.Value }).ToList(); var response = Invoke(() => _client.DeleteMessageBatch(new DeleteMessageBatchRequest { QueueUrl = GetQueueUrl(queueName.Value), Entries = deleteEntries }), queueName, BATCH_DELETING_MESSAGES); AssertSuccessfulStatusCode(response.HttpStatusCode, queueName, BATCH_DELETING_MESSAGES); return(response.Failed.Select(failed => new SqsMessageId(failed.Id)).ToArray()); }
//--- Constructors --- /// <summary> /// Constructor for creating an instance. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="callback">Callback for received SQS messages.</param> /// <param name="longPollInterval">Max amount of time to wait for SQS message to arrive.</param> /// <param name="maxNumberOfMessages">Max number of SQS messages to request.</param> /// <param name="waitTimeOnError">Amount of time to wait until trying again to listen after an error occurred.</param> public SqsPollingClientSettings(SqsQueueName queueName, Action<IEnumerable<SqsMessage>> callback, TimeSpan longPollInterval, uint maxNumberOfMessages, TimeSpan waitTimeOnError) { if(callback == null) { throw new ArgumentNullException("callback"); } if(longPollInterval == null) { throw new ArgumentNullException("longPollInterval"); } if(longPollInterval > 20.Seconds()) { throw new ArgumentException("longPollInterval exceeds the limit allowed"); } if(waitTimeOnError == null) { throw new ArgumentNullException("waitTimeOnError"); } if(waitTimeOnError < 0.Seconds() || waitTimeOnError > 5.Minutes()) { throw new ArgumentException("waitTimeOnError must be greater than 0 up to 5 minutes"); } this.QueueName = queueName; this.Callback = callback; this.LongPollInterval = longPollInterval; this.MaxNumberOfMessages = maxNumberOfMessages; this.WaitTimeOnError = waitTimeOnError; }
/// <summary> /// Receive zero or more messages from name queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="waitTimeSeconds">Max amount of time to wait until this method returns.</param> /// <param name="maxNumberOfMessages">Max number of messages to request.</param> /// <returns>Enumeration of received messages.</returns> public IEnumerable <SqsMessage> ReceiveMessages(SqsQueueName queueName, TimeSpan waitTimeSeconds, uint maxNumberOfMessages) { var start = GlobalClock.UtcNow; // keep checking for messages until the wait-timeout kicks in while (true) { var msgQueue = GetQueue(queueName); AssertQueueIsNotNull(queueName, msgQueue); QueueEntry[] entries; var now = GlobalClock.UtcNow; lock (msgQueue) { var visibilityTimeout = 30.Seconds(); entries = msgQueue .Where(x => x.VisibleTime <= now) .OrderBy(x => _random.Next()) .Take(10) .ToArray(); foreach (var entry in entries) { entry.VisibleTime = now + visibilityTimeout; } } if (entries.Any()) { return(entries.Select(e => new SqsMessage(e.Message.MessageId, e.Message.MessageReceipt, e.Message.Body)).ToArray()); } if ((now - start) > waitTimeSeconds) { return(Enumerable.Empty <SqsMessage>()); } // no message found; go to sleep for 100ms and try again AsyncUtil.Sleep(100.Milliseconds()); } }
/// <summary> /// Send message on named queue with a visibility delay. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBody">Message body.</param> /// <param name="delay">Time to wait until the message becomes visible.</param> public void SendMessage(SqsQueueName queueName, string messageBody, TimeSpan delay) { var msgQueue = GetQueue(queueName); AssertQueueIsNotNull(queueName, msgQueue); lock(msgQueue) { var entry = new QueueEntry(new SqsMessage(new SqsMessageId(Guid.NewGuid().ToString()), new SqsMessageReceipt(Guid.NewGuid().ToString()), messageBody), DateTime.MinValue); msgQueue.Add(entry); } }
/// <summary> /// Receive zero or more messages from name queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="waitTimeSeconds">Max amount of time to wait until this method returns.</param> /// <param name="maxNumberOfMessages">Max number of messages to request.</param> /// <returns>Enumeration of received messages.</returns> public IEnumerable<SqsMessage> ReceiveMessages(SqsQueueName queueName, TimeSpan waitTimeSeconds, uint maxNumberOfMessages) { var start = GlobalClock.UtcNow; // keep checking for messages until the wait-timeout kicks in while(true) { var msgQueue = GetQueue(queueName); AssertQueueIsNotNull(queueName, msgQueue); QueueEntry[] entries; var now = GlobalClock.UtcNow; lock(msgQueue) { var visibilityTimeout = 30.Seconds(); entries = msgQueue .Where(x => x.VisibleTime <= now) .OrderBy(x => _random.Next()) .Take(10) .ToArray(); foreach(var entry in entries) { entry.VisibleTime = now + visibilityTimeout; } } if(entries.Any()) { return entries.Select(e => new SqsMessage(e.Message.MessageId, e.Message.MessageReceipt, e.Message.Body)).ToArray(); } if((now - start) > waitTimeSeconds) { return Enumerable.Empty<SqsMessage>(); } // no message found; go to sleep for 100ms and try again AsyncUtil.Sleep(100.Milliseconds()); } }
/// <summary> /// Get enumeration of all messages that are currently held by the in-memory named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>Enumeration of messages.</returns> public IEnumerable<SqsMessage> InspectQueue(SqsQueueName queueName) { lock(_queues) { var msgQueue = GetQueue(queueName); if(msgQueue == null) { return new SqsMessage[0]; } lock(msgQueue) { return msgQueue.Select(x => x.Message).ToArray(); } } }
/// <summary> /// Removed all messages from named queue. /// </summary> /// <param name="queueName">Queue name</param> public void ClearQueue(SqsQueueName queueName) { lock(_queues) { var msgQueue = GetQueue(queueName); if(msgQueue == null) { return; } lock(msgQueue) { msgQueue.Clear(); } } }
private void AssertQueueIsNotNull(SqsQueueName queueName, List<QueueEntry> queue) { if(queue == null) { throw new InMemorySqsNullQueueException(string.Format("Queue '{0}' is null", queueName)); } }
public bool DeleteQueue(SqsQueueName queueName) { throw new NotImplementedException(); }
public void polling_client_pulls_from_sqs_and_calls_callback_but_does_not_automatically_deletes_messages() { var mockSqsClient = new MockSqsClient(); mockSqsClient.FillQueue(15); var pollster = new SqsPollingClient(mockSqsClient); Assert.AreEqual(15, mockSqsClient.Queued.Count, "queue was accessed prematurely"); var posted = new List<SqsMessage>(); var queueName = new SqsQueueName("foo"); pollster.Listen(new SqsPollingClientSettings( queueName: queueName, callback: posted.AddRange, longPollInterval: 10.Seconds(), maxNumberOfMessages: SqsUtils.MAX_NUMBER_OF_MESSAGES_TO_FETCH, waitTimeOnError: 1.Seconds())); Assert.IsTrue(Wait.For(() => mockSqsClient.Queued.Count == 0, 10.Seconds()), "queue did not get depleted in time"); Assert.IsTrue( Wait.For(() => mockSqsClient.ReceiveCalled > 0, 5.Seconds()), string.Format("receive called the wrong number of times: {0} != {1}", 3, mockSqsClient.ReceiveCalled) ); Assert.AreEqual(15, mockSqsClient.Delivered.Count, "delivered has the wrong number of messages"); Assert.AreNotEqual( mockSqsClient.Delivered.Count, mockSqsClient.Deleted.Count, "delivered and deleted don't match"); Assert.AreEqual( mockSqsClient.Delivered.Count, posted.Count, "delivered and posted don't match"); }
public IEnumerable<string> SendMessages(SqsQueueName queueName, IEnumerable<string> messageBodies) { throw new NotImplementedException(); }
//--- Methods --- /// <summary> /// Enqueue message for batched, asynchronous delivery. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBody">Message body.</param> public void EnqueueMessage(SqsQueueName queueName, string messageBody) { GetEnqueueMessageCallback(queueName)(messageBody); }
/// <summary> /// Get delegate for enqueuing messages asynchronously to named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>Delegate for enqueuing message asynchronously.</returns> public Action<string> GetEnqueueMessageCallback(SqsQueueName queueName) { repeat: SqsQueueDelayedSendClient queue; var directory = _directory; if(!directory.TryGetValue(queueName.Value, out queue)) { var newDirectory = new Dictionary<string, SqsQueueDelayedSendClient>(directory); newDirectory[queueName.Value] = queue = new SqsQueueDelayedSendClient(_client, queueName, _timerFactory); if(!SysUtil.CAS(ref _directory, directory, newDirectory)) { goto repeat; } } return queue.EnqueueMessage; }
public void SendMessage(SqsQueueName queueName, string messageBody) { throw new NotImplementedException(); }
/// <summary> /// Send message on named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBody">Message body.</param> public void SendMessage(SqsQueueName queueName, string messageBody) { SendMessage(queueName, messageBody, TimeSpan.Zero); }
/// <summary> /// Send one or more message to a named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageBodies">Enumeration of message bodies.</param> /// <returns>Enumeration of message bodies that failed to send.</returns> public IEnumerable<string> SendMessages(SqsQueueName queueName, IEnumerable<string> messageBodies) { foreach(var messageBody in messageBodies) { SendMessage(queueName, messageBody); } return Enumerable.Empty<string>(); }
public IEnumerable<SqsMessage> ReceiveMessages(SqsQueueName queueName, TimeSpan waitTimeSeconds, uint maxNumberOfMessages) { ReceiveCalled++; var take = (int)Math.Min(10, maxNumberOfMessages); var taken = Queued.Take(take).ToArray(); _log.DebugFormat("receive returning {0} messages", taken.Length); Delivered.AddRange(taken); Queued.RemoveRange(0, taken.Length); return taken; }
private List<QueueEntry> GetQueue(SqsQueueName queueName) { lock(_queues) { List<QueueEntry> msgQueue; _queues.TryGetValue(queueName, out msgQueue); return msgQueue; } }
/// <summary> /// Create a new named queue and gets its URI. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>True if the named queue was created.</returns> public bool CreateQueue(SqsQueueName queueName) { lock(_queues) { if(!_queues.ContainsKey(queueName)) { _queues[queueName] = new List<QueueEntry>(); } return true; } }
/// <summary> /// Delete single message from named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <param name="messageReceipt">Message receipt.</param> /// <returns>True if message was deleted.</returns> public bool DeleteMessage(SqsQueueName queueName, SqsMessageReceipt messageReceipt) { var msgQueue = GetQueue(queueName); AssertQueueIsNotNull(queueName, msgQueue); lock(msgQueue) { var entry = msgQueue.FirstOrDefault(x => x.Message.MessageReceipt == messageReceipt); if(entry != null) { msgQueue.Remove(entry); } } return true; }
public bool DeleteMessage(SqsQueueName queueName, SqsMessageReceipt messageReceipt) { _log.DebugFormat("deleting {0}", messageReceipt); Deleted.Add(messageReceipt); return true; }
/// <summary> /// Delete a named queue. /// </summary> /// <param name="queueName">Queue name.</param> /// <returns>True if the named queue was deleted</returns> public bool DeleteQueue(SqsQueueName queueName) { lock(_queues) { if(_queues.ContainsKey(queueName)) { _queues.Remove(queueName); } return true; } }