diff --git a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp index 3d84a9a31..cf4b7b86d 100644 --- a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp +++ b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/protocol/queue_rest_client.hpp @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -1738,8 +1739,8 @@ namespace Azure { namespace Storage { namespace Queues { { Azure::Nullable Timeout; std::string Body; - Azure::Nullable VisibilityTimeout; - Azure::Nullable TimeToLive; + Azure::Nullable VisibilityTimeout; + Azure::Nullable TimeToLive; }; // struct EnqueueMessageOptions static Azure::Response EnqueueMessage( @@ -1769,12 +1770,12 @@ namespace Azure { namespace Storage { namespace Queues { if (options.VisibilityTimeout.HasValue()) { request.GetUrl().AppendQueryParameter( - "visibilitytimeout", std::to_string(options.VisibilityTimeout.Value())); + "visibilitytimeout", std::to_string(options.VisibilityTimeout.Value().count())); } if (options.TimeToLive.HasValue()) { request.GetUrl().AppendQueryParameter( - "messagettl", std::to_string(options.TimeToLive.Value())); + "messagettl", std::to_string(options.TimeToLive.Value().count())); } auto pHttpResponse = pipeline.Send(request, context); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1798,7 +1799,7 @@ namespace Azure { namespace Storage { namespace Queues { { Azure::Nullable Timeout; Azure::Nullable MaxMessages; - Azure::Nullable VisibilityTimeout; + Azure::Nullable VisibilityTimeout; }; // struct ReceiveMessagesOptions static Azure::Response ReceiveMessages( @@ -1822,7 +1823,7 @@ namespace Azure { namespace Storage { namespace Queues { if (options.VisibilityTimeout.HasValue()) { request.GetUrl().AppendQueryParameter( - "visibilitytimeout", std::to_string(options.VisibilityTimeout.Value())); + "visibilitytimeout", std::to_string(options.VisibilityTimeout.Value().count())); } auto pHttpResponse = pipeline.Send(request, context); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; @@ -1951,7 +1952,7 @@ namespace Azure { namespace Storage { namespace Queues { { Azure::Nullable Timeout; std::string PopReceipt; - int32_t VisibilityTimeout; + std::chrono::seconds VisibilityTimeout; }; // struct UpdateMessageVisibilityOptions static Azure::Response UpdateMessageVisibility( @@ -1971,7 +1972,7 @@ namespace Azure { namespace Storage { namespace Queues { request.GetUrl().AppendQueryParameter( "popreceipt", _internal::UrlEncodeQueryParameter(options.PopReceipt)); request.GetUrl().AppendQueryParameter( - "visibilitytimeout", std::to_string(options.VisibilityTimeout)); + "visibilitytimeout", std::to_string(options.VisibilityTimeout.count())); auto pHttpResponse = pipeline.Send(request, context); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; UpdateMessageResult response; @@ -1993,7 +1994,7 @@ namespace Azure { namespace Storage { namespace Queues { std::string Body; Azure::Nullable Timeout; std::string PopReceipt; - int32_t VisibilityTimeout; + std::chrono::seconds VisibilityTimeout; }; // struct UpdateMessageOptions static Azure::Response UpdateMessage( @@ -2023,7 +2024,7 @@ namespace Azure { namespace Storage { namespace Queues { request.GetUrl().AppendQueryParameter( "popreceipt", _internal::UrlEncodeQueryParameter(options.PopReceipt)); request.GetUrl().AppendQueryParameter( - "visibilitytimeout", std::to_string(options.VisibilityTimeout)); + "visibilitytimeout", std::to_string(options.VisibilityTimeout.count())); auto pHttpResponse = pipeline.Send(request, context); Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse; UpdateMessageResult response; diff --git a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp index ad01dab75..c745bf8b8 100644 --- a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp +++ b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_client.hpp @@ -238,7 +238,7 @@ namespace Azure { namespace Storage { namespace Queues { Azure::Response UpdateMessage( const std::string& messageId, const std::string& popReceipt, - int32_t visibilityTimeout, + std::chrono::seconds visibilityTimeout, const UpdateMessageOptions& options = UpdateMessageOptions(), const Azure::Core::Context& context = Azure::Core::Context()) const; diff --git a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp index 4763e9bea..4fd36f450 100644 --- a/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp +++ b/sdk/storage/azure-storage-queues/inc/azure/storage/queues/queue_options.hpp @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -131,6 +132,11 @@ namespace Azure { namespace Storage { namespace Queues { { }; + /** + * @brief A TTL value representing the queue message does not expire. + */ + constexpr static std::chrono::seconds MessageNeverExpires{-1}; + /** * Optional parameters for #Azure::Storage::Queues::QueueClient::EnqueueMessages. */ @@ -139,13 +145,13 @@ namespace Azure { namespace Storage { namespace Queues { /** * Specifies how long the message should be invisible to dequeue and peek operations. */ - Azure::Nullable VisibilityTimeout; + Azure::Nullable VisibilityTimeout; /** * Specifies the time-to-live interval for the message. The maximum time-to-live can be any - * positive number, as well as -1 indicating that the message does not expire + * positive number, as well as MessageNeverExpires indicating that the message does not expire */ - Azure::Nullable TimeToLive; + Azure::Nullable TimeToLive; }; /** @@ -161,7 +167,7 @@ namespace Azure { namespace Storage { namespace Queues { * After the messages have been retrieved, they are not visible to other clients for the time * interval specified by this parameter. */ - Azure::Nullable VisibilityTimeout; + Azure::Nullable VisibilityTimeout; }; /** diff --git a/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp b/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp index 60b3d0d18..8129a584f 100644 --- a/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp +++ b/sdk/storage/azure-storage-queues/sample/queue_getting_started.cpp @@ -57,7 +57,8 @@ void ConsumerFunc2() std::cout << msg.Body << std::endl; ++counter; - auto updateResponse = queueClient.UpdateMessage(msg.MessageId, msg.PopReceipt, 30); + auto updateResponse + = queueClient.UpdateMessage(msg.MessageId, msg.PopReceipt, std::chrono::seconds(30)); queueClient.DeleteMessage(msg.MessageId, updateResponse.Value.PopReceipt); } diff --git a/sdk/storage/azure-storage-queues/src/queue_client.cpp b/sdk/storage/azure-storage-queues/src/queue_client.cpp index 26649880f..3a7cfa1af 100644 --- a/sdk/storage/azure-storage-queues/src/queue_client.cpp +++ b/sdk/storage/azure-storage-queues/src/queue_client.cpp @@ -252,7 +252,7 @@ namespace Azure { namespace Storage { namespace Queues { Azure::Response QueueClient::UpdateMessage( const std::string& messageId, const std::string& popReceipt, - int32_t visibilityTimeout, + std::chrono::seconds visibilityTimeout, const UpdateMessageOptions& options, const Azure::Core::Context& context) const { diff --git a/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp b/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp index f4a761943..adef49ac9 100644 --- a/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp +++ b/sdk/storage/azure-storage-queues/test/ut/queue_client_messages_test.cpp @@ -32,6 +32,42 @@ namespace Azure { namespace Storage { namespace Test { queueClient.Delete(); } + TEST_F(QueueClientTest, EnqueueMessageTTL) + { + auto queueClient = Azure::Storage::Queues::QueueClient::CreateFromConnectionString( + StandardStorageConnectionString(), LowercaseRandomString()); + queueClient.Create(); + + const std::string message = "message content."; + Queues::EnqueueMessageOptions enqueueOptions; + enqueueOptions.VisibilityTimeout = std::chrono::seconds(1); + enqueueOptions.TimeToLive = std::chrono::seconds(2); + auto res = queueClient.EnqueueMessage(message, enqueueOptions).Value; + + EXPECT_TRUE(queueClient.PeekMessages().Value.Messages.empty()); + std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + EXPECT_FALSE(queueClient.PeekMessages().Value.Messages.empty()); + std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + EXPECT_TRUE(queueClient.PeekMessages().Value.Messages.empty()); + + enqueueOptions = Queues::EnqueueMessageOptions(); + enqueueOptions.TimeToLive = Queues::MessageNeverExpires; + res = queueClient.EnqueueMessage(message, enqueueOptions).Value; + + const Azure::DateTime neverExpireDateTime = Azure::DateTime::Parse( + "Fri, 31 Dec 9999 23:59:59 GMT", Azure::DateTime::DateFormat::Rfc1123); + + EXPECT_EQ(res.ExpiresOn, neverExpireDateTime); + auto peekRes = queueClient.PeekMessages(); + ASSERT_FALSE(peekRes.Value.Messages.empty()); + EXPECT_EQ(peekRes.Value.Messages[0].ExpiresOn, neverExpireDateTime); + auto receiveRes = queueClient.ReceiveMessages(); + ASSERT_FALSE(receiveRes.Value.Messages.empty()); + EXPECT_EQ(receiveRes.Value.Messages[0].ExpiresOn, neverExpireDateTime); + + queueClient.Delete(); + } + TEST_F(QueueClientTest, ReceiveMessage) { auto queueClient = Azure::Storage::Queues::QueueClient::CreateFromConnectionString( @@ -44,7 +80,7 @@ namespace Azure { namespace Storage { namespace Test { auto res = queueClient.EnqueueMessage(message).Value; Queues::ReceiveMessagesOptions receiveOptions; - receiveOptions.VisibilityTimeout = 1; + receiveOptions.VisibilityTimeout = std::chrono::seconds(1); auto receivedMessage = queueClient.ReceiveMessages(receiveOptions).Value.Messages[0]; EXPECT_EQ(receivedMessage.Body, message); @@ -180,7 +216,8 @@ namespace Azure { namespace Storage { namespace Test { const std::string updatedMessage = "MESSAGE CONTENT2"; auto res = queueClient.EnqueueMessage(message).Value; - auto updateRes = queueClient.UpdateMessage(res.MessageId, res.PopReceipt, 0).Value; + auto updateRes + = queueClient.UpdateMessage(res.MessageId, res.PopReceipt, std::chrono::seconds(0)).Value; EXPECT_FALSE(updateRes.PopReceipt.empty()); EXPECT_TRUE(IsValidTime(updateRes.NextVisibleOn)); @@ -189,7 +226,8 @@ namespace Azure { namespace Storage { namespace Test { Queues::UpdateMessageOptions updateOptions; updateOptions.MessageText = updatedMessage; - queueClient.UpdateMessage(res.MessageId, updateRes.PopReceipt, 1, updateOptions); + queueClient.UpdateMessage( + res.MessageId, updateRes.PopReceipt, std::chrono::seconds(1), updateOptions); EXPECT_TRUE(queueClient.PeekMessages().Value.Messages.empty()); std::this_thread::sleep_for(std::chrono::milliseconds(1200)); diff --git a/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp b/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp index b5a9eb8cd..980a86e6c 100644 --- a/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp +++ b/sdk/storage/azure-storage-queues/test/ut/queue_sas_test.cpp @@ -55,7 +55,10 @@ namespace Azure { namespace Storage { namespace Test { auto sendReceipt = queueClient0.EnqueueMessage("message 0").Value; auto queueClient = Queues::QueueClient(queueUrl + sas); auto updateReceipt - = queueClient.UpdateMessage(sendReceipt.MessageId, sendReceipt.PopReceipt, 0).Value; + = queueClient + .UpdateMessage( + sendReceipt.MessageId, sendReceipt.PopReceipt, std::chrono::seconds(0)) + .Value; queueClient0.DeleteMessage(sendReceipt.MessageId, updateReceipt.PopReceipt); };