Storage Queue API review feedback (#2801)
* fix * sample * CL * service version * fix * ACL
This commit is contained in:
parent
8cae42999e
commit
b8013185d0
@ -14,7 +14,6 @@
|
||||
- QueueClient::Create
|
||||
- QueueClient::CreateIfNotExists
|
||||
- QueueClient::Delete
|
||||
- QueueClient::DeleteIfExists
|
||||
- QueueClient::GetProperties
|
||||
- QueueClient::SetMetadata
|
||||
- QueueClient::GetAccessPolicy
|
||||
|
||||
@ -42,6 +42,7 @@ set(
|
||||
AZURE_STORAGE_QUEUE_SOURCE
|
||||
src/private/package_version.hpp
|
||||
src/queue_client.cpp
|
||||
src/queue_options.cpp
|
||||
src/queue_responses.cpp
|
||||
src/queue_rest_client.cpp
|
||||
src/queue_sas_builder.cpp
|
||||
@ -93,6 +94,7 @@ if(BUILD_STORAGE_SAMPLES)
|
||||
target_sources(
|
||||
azure-storage-sample
|
||||
PRIVATE
|
||||
sample/queue_encode_message.cpp
|
||||
sample/queue_getting_started.cpp
|
||||
)
|
||||
|
||||
|
||||
@ -53,6 +53,33 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
std::string m_value;
|
||||
}; // extensible enum GeoReplicationStatus
|
||||
|
||||
/**
|
||||
* @brief A peeked message object stored in the queue.
|
||||
*/
|
||||
struct PeekedQueueMessage final
|
||||
{
|
||||
/**
|
||||
* The content of the message.
|
||||
*/
|
||||
std::string MessageText;
|
||||
/**
|
||||
* A GUID value that identifies the message in the queue.
|
||||
*/
|
||||
std::string MessageId;
|
||||
/**
|
||||
* The time the message was inserted into the queue.
|
||||
*/
|
||||
Azure::DateTime InsertedOn;
|
||||
/**
|
||||
* The time that the message will expire and be automatically deleted from the queue.
|
||||
*/
|
||||
Azure::DateTime ExpiresOn;
|
||||
/**
|
||||
* The number of times the message has been dequeued.
|
||||
*/
|
||||
int64_t DequeueCount = 0;
|
||||
}; // struct PeekedQueueMessage
|
||||
|
||||
/**
|
||||
* @brief A queue item from the result of
|
||||
* #Azure::Storage::Queues::QueueServiceClient::ListQueues.
|
||||
@ -77,7 +104,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
/**
|
||||
* The content of the message.
|
||||
*/
|
||||
std::string Body;
|
||||
std::string MessageText;
|
||||
/**
|
||||
* A GUID value that identifies the message in the queue.
|
||||
*/
|
||||
@ -91,13 +118,11 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
*/
|
||||
Azure::DateTime ExpiresOn;
|
||||
/**
|
||||
* An opaque string that is required to delete or update a message. Empty if it's a peeked
|
||||
* message.
|
||||
* An opaque string that is required to delete or update a message.
|
||||
*/
|
||||
std::string PopReceipt;
|
||||
/**
|
||||
* The time that the message will again become visible in the queue. Invalid if it's a peeked
|
||||
* message.
|
||||
* The time that the message will again become visible in the queue.
|
||||
*/
|
||||
Azure::DateTime NextVisibleOn;
|
||||
/**
|
||||
@ -134,11 +159,11 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
/**
|
||||
* Date and time since when this policy is active.
|
||||
*/
|
||||
Azure::DateTime StartsOn;
|
||||
Azure::Nullable<Azure::DateTime> StartsOn;
|
||||
/**
|
||||
* Date and time the policy expires.
|
||||
*/
|
||||
Azure::DateTime ExpiresOn;
|
||||
Azure::Nullable<Azure::DateTime> ExpiresOn;
|
||||
/**
|
||||
* The permissions for this ACL policy.
|
||||
*/
|
||||
@ -346,7 +371,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
/**
|
||||
* A vector of peeked messages.
|
||||
*/
|
||||
std::vector<QueueMessage> Messages;
|
||||
std::vector<PeekedQueueMessage> Messages;
|
||||
}; // struct PeekMessagesResult
|
||||
|
||||
/**
|
||||
@ -1740,7 +1765,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
struct EnqueueMessageOptions final
|
||||
{
|
||||
Azure::Nullable<int32_t> Timeout;
|
||||
std::string Body;
|
||||
std::string MessageText;
|
||||
Azure::Nullable<std::chrono::seconds> VisibilityTimeout;
|
||||
Azure::Nullable<std::chrono::seconds> TimeToLive;
|
||||
}; // struct EnqueueMessageOptions
|
||||
@ -1993,7 +2018,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
|
||||
struct UpdateMessageOptions final
|
||||
{
|
||||
std::string Body;
|
||||
std::string MessageText;
|
||||
Azure::Nullable<int32_t> Timeout;
|
||||
std::string PopReceipt;
|
||||
std::chrono::seconds VisibilityTimeout;
|
||||
@ -2199,7 +2224,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
if (path.size() == 2 && path[0] == XmlTagName::k_QueueMessagesList
|
||||
&& path[1] == XmlTagName::k_QueueMessage)
|
||||
{
|
||||
ret.Messages.emplace_back(QueueMessageFromXml(reader));
|
||||
ret.Messages.emplace_back(PeekedQueueMessageFromXml(reader));
|
||||
path.pop_back();
|
||||
}
|
||||
}
|
||||
@ -2322,6 +2347,93 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PeekedQueueMessage PeekedQueueMessageFromXml(_internal::XmlReader& reader)
|
||||
{
|
||||
PeekedQueueMessage ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_MessageText,
|
||||
k_MessageId,
|
||||
k_InsertionTime,
|
||||
k_ExpirationTime,
|
||||
k_DequeueCount,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == _internal::XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == _internal::XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == _internal::XmlNodeType::StartTag)
|
||||
{
|
||||
if (node.Name == "MessageText")
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_MessageText);
|
||||
}
|
||||
else if (node.Name == "MessageId")
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_MessageId);
|
||||
}
|
||||
else if (node.Name == "InsertionTime")
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_InsertionTime);
|
||||
}
|
||||
else if (node.Name == "ExpirationTime")
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_ExpirationTime);
|
||||
}
|
||||
else if (node.Name == "DequeueCount")
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_DequeueCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
}
|
||||
else if (node.Type == _internal::XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_MessageText)
|
||||
{
|
||||
ret.MessageText = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_MessageId)
|
||||
{
|
||||
ret.MessageId = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_InsertionTime)
|
||||
{
|
||||
ret.InsertedOn
|
||||
= Azure::DateTime::Parse(node.Value, Azure::DateTime::DateFormat::Rfc1123);
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_ExpirationTime)
|
||||
{
|
||||
ret.ExpiresOn
|
||||
= Azure::DateTime::Parse(node.Value, Azure::DateTime::DateFormat::Rfc1123);
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_DequeueCount)
|
||||
{
|
||||
ret.DequeueCount = std::stoll(node.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QueueMessage QueueMessageFromXml(_internal::XmlReader& reader)
|
||||
{
|
||||
QueueMessage ret;
|
||||
@ -2394,7 +2506,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_MessageText)
|
||||
{
|
||||
ret.Body = node.Value;
|
||||
ret.MessageText = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_MessageId)
|
||||
{
|
||||
@ -2524,7 +2636,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "QueueMessage"});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "MessageText"});
|
||||
writer.Write(
|
||||
_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Body});
|
||||
_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.MessageText});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
}
|
||||
@ -2548,7 +2660,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "QueueMessage"});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "MessageText"});
|
||||
writer.Write(
|
||||
_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Body});
|
||||
_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.MessageText});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
}
|
||||
@ -2562,22 +2674,28 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Id});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "AccessPolicy"});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Start"});
|
||||
writer.Write(_internal::XmlNode{
|
||||
_internal::XmlNodeType::Text,
|
||||
std::string(),
|
||||
options.StartsOn.ToString(
|
||||
Azure::DateTime::DateFormat::Rfc3339,
|
||||
Azure::DateTime::TimeFractionFormat::AllDigits)});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Expiry"});
|
||||
writer.Write(_internal::XmlNode{
|
||||
_internal::XmlNodeType::Text,
|
||||
std::string(),
|
||||
options.ExpiresOn.ToString(
|
||||
Azure::DateTime::DateFormat::Rfc3339,
|
||||
Azure::DateTime::TimeFractionFormat::AllDigits)});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
if (options.StartsOn.HasValue())
|
||||
{
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Start"});
|
||||
writer.Write(_internal::XmlNode{
|
||||
_internal::XmlNodeType::Text,
|
||||
std::string(),
|
||||
options.StartsOn.Value().ToString(
|
||||
Azure::DateTime::DateFormat::Rfc3339,
|
||||
Azure::DateTime::TimeFractionFormat::AllDigits)});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
}
|
||||
if (options.ExpiresOn.HasValue())
|
||||
{
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Expiry"});
|
||||
writer.Write(_internal::XmlNode{
|
||||
_internal::XmlNodeType::Text,
|
||||
std::string(),
|
||||
options.ExpiresOn.Value().ToString(
|
||||
Azure::DateTime::DateFormat::Rfc3339,
|
||||
Azure::DateTime::TimeFractionFormat::AllDigits)});
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::EndTag});
|
||||
}
|
||||
writer.Write(_internal::XmlNode{_internal::XmlNodeType::StartTag, "Permission"});
|
||||
writer.Write(
|
||||
_internal::XmlNode{_internal::XmlNodeType::Text, std::string(), options.Permissions});
|
||||
|
||||
@ -112,25 +112,15 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
const CreateQueueOptions& options = CreateQueueOptions(),
|
||||
const Azure::Core::Context& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Marks the specified queue for deletion.
|
||||
*
|
||||
* @param options Optional parameters to execute this function.
|
||||
* @param context Context for cancelling long running operations.
|
||||
* @return A DeleteQueueResult if successful.
|
||||
*/
|
||||
Azure::Response<Models::DeleteQueueResult> Delete(
|
||||
const DeleteQueueOptions& options = DeleteQueueOptions(),
|
||||
const Azure::Core::Context& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Marks the specified queue for deletion if it exists.
|
||||
*
|
||||
* @param options Optional parameters to execute this function.
|
||||
* @param context Context for cancelling long running operations.
|
||||
* @return A DeleteQueueResult if successful.
|
||||
* @return DeleteQueueResult.Deleted will be true if successful, false if the queue doesn't
|
||||
* exist.
|
||||
*/
|
||||
Azure::Response<Models::DeleteQueueResult> DeleteIfExists(
|
||||
Azure::Response<Models::DeleteQueueResult> Delete(
|
||||
const DeleteQueueOptions& options = DeleteQueueOptions(),
|
||||
const Azure::Core::Context& context = Azure::Core::Context()) const;
|
||||
|
||||
|
||||
@ -17,6 +17,48 @@
|
||||
|
||||
namespace Azure { namespace Storage { namespace Queues {
|
||||
|
||||
/**
|
||||
* @brief API version for Storage Queue service.
|
||||
*/
|
||||
class ServiceVersion final {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Service Version object
|
||||
*
|
||||
* @param version The string version for Storage Queue Service.
|
||||
*/
|
||||
explicit ServiceVersion(std::string version) : m_version(std::move(version)) {}
|
||||
|
||||
/**
|
||||
* @brief Enable comparing between two versions.
|
||||
*
|
||||
* @param other Another service version to be compared.
|
||||
*/
|
||||
bool operator==(const ServiceVersion& other) const { return m_version == other.m_version; }
|
||||
|
||||
/**
|
||||
* @brief Enable comparing between two versions.
|
||||
*
|
||||
* @param other Another service version to be compared.
|
||||
*/
|
||||
bool operator!=(const ServiceVersion& other) const { return !(*this == other); }
|
||||
|
||||
/**
|
||||
* @brief Returns string representation.
|
||||
*
|
||||
*/
|
||||
std::string const& ToString() const { return m_version; }
|
||||
|
||||
/**
|
||||
* @brief API version 2018-03-28.
|
||||
*
|
||||
*/
|
||||
AZ_STORAGE_QUEUES_DLLEXPORT const static ServiceVersion V2018_03_28;
|
||||
|
||||
private:
|
||||
std::string m_version;
|
||||
};
|
||||
|
||||
struct QueueClientOptions final : Azure::Core::_internal::ClientOptions
|
||||
{
|
||||
/**
|
||||
@ -31,7 +73,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
/**
|
||||
* API version used by this client.
|
||||
*/
|
||||
std::string ApiVersion = _detail::ApiVersion;
|
||||
ServiceVersion ApiVersion{_detail::ApiVersion};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -132,11 +174,6 @@ 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.
|
||||
*/
|
||||
@ -152,6 +189,11 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
* positive number, as well as MessageNeverExpires indicating that the message does not expire
|
||||
*/
|
||||
Azure::Nullable<std::chrono::seconds> TimeToLive;
|
||||
|
||||
/**
|
||||
* @brief A TTL value representing the queue message does not expire.
|
||||
*/
|
||||
AZ_STORAGE_QUEUES_DLLEXPORT const static std::chrono::seconds MessageNeverExpires;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include <azure/core/base64.hpp>
|
||||
#include <azure/storage/queues.hpp>
|
||||
|
||||
#include "samples_common.hpp"
|
||||
|
||||
SAMPLE(QueuesEncodeMessage, QueuesEncodeMessage)
|
||||
void QueuesEncodeMessage()
|
||||
{
|
||||
using namespace Azure::Storage::Queues;
|
||||
std::string QueueName = "sample-queue";
|
||||
|
||||
auto queueClient = QueueClient::CreateFromConnectionString(GetConnectionString(), QueueName);
|
||||
queueClient.CreateIfNotExists();
|
||||
|
||||
// Binary message cannot be enqueued directly, we encode the message with Base64.
|
||||
std::vector<uint8_t> binaryMessage{0x00, 0x01, 0x02, 0x03};
|
||||
std::string encodedMessage = Azure::Core::Convert::Base64Encode(binaryMessage);
|
||||
queueClient.EnqueueMessage(encodedMessage);
|
||||
|
||||
auto receiveMessagesResult = queueClient.ReceiveMessages().Value;
|
||||
auto& receivedMessage = receiveMessagesResult.Messages[0];
|
||||
|
||||
std::cout << receivedMessage.MessageText << std::endl;
|
||||
|
||||
// Sometimes messages are Base64 encoded. Some other queue clients automatically encode the
|
||||
// message even it's in plaintext. We need to decode the message in that case.
|
||||
auto decodedMessage = Azure::Core::Convert::Base64Decode(receivedMessage.MessageText);
|
||||
assert(decodedMessage == binaryMessage);
|
||||
}
|
||||
@ -20,6 +20,15 @@ void ProducerFunc()
|
||||
std::string msg = "Message " + std::to_string(i);
|
||||
queueClient.EnqueueMessage(msg);
|
||||
}
|
||||
|
||||
for (int i = 5; i < 10; ++i)
|
||||
{
|
||||
std::string msg = "Message " + std::to_string(i);
|
||||
EnqueueMessageOptions options;
|
||||
options.TimeToLive = std::chrono::seconds(60 * 60 * 24);
|
||||
options.VisibilityTimeout = std::chrono::seconds(1);
|
||||
queueClient.EnqueueMessage(msg, options);
|
||||
}
|
||||
}
|
||||
|
||||
void ConsumerFunc()
|
||||
@ -29,12 +38,12 @@ void ConsumerFunc()
|
||||
int counter = 0;
|
||||
while (counter < 5)
|
||||
{
|
||||
auto msgResponse = queueClient.ReceiveMessages();
|
||||
if (!msgResponse.Value.Messages.empty())
|
||||
auto receiveMessagesResult = queueClient.ReceiveMessages().Value;
|
||||
if (!receiveMessagesResult.Messages.empty())
|
||||
{
|
||||
auto& msg = msgResponse.Value.Messages[0];
|
||||
auto& msg = receiveMessagesResult.Messages[0];
|
||||
|
||||
std::cout << msg.Body << std::endl;
|
||||
std::cout << msg.MessageText << std::endl;
|
||||
++counter;
|
||||
|
||||
queueClient.DeleteMessage(msg.MessageId, msg.PopReceipt);
|
||||
@ -52,10 +61,10 @@ void ConsumerFunc2()
|
||||
{
|
||||
ReceiveMessagesOptions receiveOptions;
|
||||
receiveOptions.MaxMessages = 3;
|
||||
auto msgResponse = queueClient.ReceiveMessages(receiveOptions);
|
||||
for (auto& msg : msgResponse.Value.Messages)
|
||||
auto receiveMessagesResult = queueClient.ReceiveMessages(receiveOptions).Value;
|
||||
for (auto& msg : receiveMessagesResult.Messages)
|
||||
{
|
||||
std::cout << msg.Body << std::endl;
|
||||
std::cout << msg.MessageText << std::endl;
|
||||
++counter;
|
||||
|
||||
auto updateResponse
|
||||
@ -75,4 +84,5 @@ void QueuesGettingStarted()
|
||||
|
||||
ProducerFunc();
|
||||
ConsumerFunc();
|
||||
ConsumerFunc2();
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
m_queueUrl.GetHost(), newOptions.SecondaryHostForRetryReads));
|
||||
perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>());
|
||||
perOperationPolicies.emplace_back(
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion));
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion.ToString()));
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
newOptions,
|
||||
_internal::QueueServicePackageName,
|
||||
@ -77,7 +77,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
credential, tokenContext));
|
||||
}
|
||||
perOperationPolicies.emplace_back(
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion));
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString()));
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
options,
|
||||
_internal::QueueServicePackageName,
|
||||
@ -95,7 +95,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
m_queueUrl.GetHost(), options.SecondaryHostForRetryReads));
|
||||
perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>());
|
||||
perOperationPolicies.emplace_back(
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion));
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString()));
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
options,
|
||||
_internal::QueueServicePackageName,
|
||||
@ -139,18 +139,11 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
const Azure::Core::Context& context) const
|
||||
{
|
||||
(void)options;
|
||||
_detail::QueueRestClient::Queue::DeleteQueueOptions protocolLayerOptions;
|
||||
return _detail::QueueRestClient::Queue::Delete(
|
||||
*m_pipeline, m_queueUrl, protocolLayerOptions, context);
|
||||
}
|
||||
|
||||
Azure::Response<Models::DeleteQueueResult> QueueClient::DeleteIfExists(
|
||||
const DeleteQueueOptions& options,
|
||||
const Azure::Core::Context& context) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Delete(options, context);
|
||||
_detail::QueueRestClient::Queue::DeleteQueueOptions protocolLayerOptions;
|
||||
return _detail::QueueRestClient::Queue::Delete(
|
||||
*m_pipeline, m_queueUrl, protocolLayerOptions, context);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
@ -216,7 +209,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
auto messagesUrl = m_queueUrl;
|
||||
messagesUrl.AppendPath("messages");
|
||||
_detail::QueueRestClient::Queue::EnqueueMessageOptions protocolLayerOptions;
|
||||
protocolLayerOptions.Body = std::move(messageText);
|
||||
protocolLayerOptions.MessageText = std::move(messageText);
|
||||
protocolLayerOptions.TimeToLive = options.TimeToLive;
|
||||
protocolLayerOptions.VisibilityTimeout = options.VisibilityTimeout;
|
||||
return _detail::QueueRestClient::Queue::EnqueueMessage(
|
||||
@ -262,7 +255,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
if (options.MessageText.HasValue())
|
||||
{
|
||||
_detail::QueueRestClient::Queue::UpdateMessageOptions protocolLayerOptions;
|
||||
protocolLayerOptions.Body = options.MessageText.Value();
|
||||
protocolLayerOptions.MessageText = options.MessageText.Value();
|
||||
protocolLayerOptions.PopReceipt = popReceipt;
|
||||
protocolLayerOptions.VisibilityTimeout = visibilityTimeout;
|
||||
return _detail::QueueRestClient::Queue::UpdateMessage(
|
||||
|
||||
11
sdk/storage/azure-storage-queues/src/queue_options.cpp
Normal file
11
sdk/storage/azure-storage-queues/src/queue_options.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/storage/queues/queue_options.hpp"
|
||||
|
||||
namespace Azure { namespace Storage { namespace Queues {
|
||||
|
||||
const ServiceVersion ServiceVersion::V2018_03_28(std::string("2018-03-28"));
|
||||
const std::chrono::seconds EnqueueMessageOptions::MessageNeverExpires{-1};
|
||||
|
||||
}}} // namespace Azure::Storage::Queues
|
||||
@ -48,7 +48,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
m_serviceUrl.GetHost(), newOptions.SecondaryHostForRetryReads));
|
||||
perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>());
|
||||
perOperationPolicies.emplace_back(
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion));
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(newOptions.ApiVersion.ToString()));
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
newOptions,
|
||||
_internal::QueueServicePackageName,
|
||||
@ -76,7 +76,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
credential, tokenContext));
|
||||
}
|
||||
perOperationPolicies.emplace_back(
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion));
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString()));
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
options,
|
||||
_internal::QueueServicePackageName,
|
||||
@ -96,7 +96,7 @@ namespace Azure { namespace Storage { namespace Queues {
|
||||
m_serviceUrl.GetHost(), options.SecondaryHostForRetryReads));
|
||||
perRetryPolicies.emplace_back(std::make_unique<_internal::StoragePerRetryPolicy>());
|
||||
perOperationPolicies.emplace_back(
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion));
|
||||
std::make_unique<_internal::StorageServiceVersionPolicy>(options.ApiVersion.ToString()));
|
||||
m_pipeline = std::make_shared<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
options,
|
||||
_internal::QueueServicePackageName,
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
auto peekedMessage = queueClient.PeekMessages().Value.Messages[0];
|
||||
|
||||
EXPECT_EQ(peekedMessage.Body, message);
|
||||
EXPECT_EQ(peekedMessage.MessageText, message);
|
||||
EXPECT_EQ(peekedMessage.MessageId, res.MessageId);
|
||||
EXPECT_EQ(peekedMessage.InsertedOn, res.InsertedOn);
|
||||
EXPECT_EQ(peekedMessage.ExpiresOn, res.ExpiresOn);
|
||||
@ -51,7 +51,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_TRUE(queueClient.PeekMessages().Value.Messages.empty());
|
||||
|
||||
enqueueOptions = Queues::EnqueueMessageOptions();
|
||||
enqueueOptions.TimeToLive = Queues::MessageNeverExpires;
|
||||
enqueueOptions.TimeToLive = Queues::EnqueueMessageOptions::MessageNeverExpires;
|
||||
res = queueClient.EnqueueMessage(message, enqueueOptions).Value;
|
||||
|
||||
const Azure::DateTime neverExpireDateTime = Azure::DateTime::Parse(
|
||||
@ -83,7 +83,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
receiveOptions.VisibilityTimeout = std::chrono::seconds(1);
|
||||
auto receivedMessage = queueClient.ReceiveMessages(receiveOptions).Value.Messages[0];
|
||||
|
||||
EXPECT_EQ(receivedMessage.Body, message);
|
||||
EXPECT_EQ(receivedMessage.MessageText, message);
|
||||
EXPECT_EQ(receivedMessage.MessageId, res.MessageId);
|
||||
EXPECT_EQ(receivedMessage.InsertedOn, res.InsertedOn);
|
||||
EXPECT_EQ(receivedMessage.ExpiresOn, res.ExpiresOn);
|
||||
@ -124,17 +124,17 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
receivedMessages = queueClient.ReceiveMessages(receiveOptions).Value.Messages;
|
||||
|
||||
EXPECT_EQ(receivedMessages.size(), static_cast<size_t>(receiveOptions.MaxMessages.Value()));
|
||||
EXPECT_EQ(receivedMessages[0].Body, message1);
|
||||
EXPECT_EQ(receivedMessages[0].MessageText, message1);
|
||||
|
||||
receivedMessages = queueClient.ReceiveMessages().Value.Messages;
|
||||
EXPECT_EQ(receivedMessages.size(), size_t(1));
|
||||
EXPECT_EQ(receivedMessages[0].Body, message2);
|
||||
EXPECT_EQ(receivedMessages[0].MessageText, message2);
|
||||
|
||||
receiveOptions.MaxMessages = 10;
|
||||
receivedMessages = queueClient.ReceiveMessages(receiveOptions).Value.Messages;
|
||||
EXPECT_EQ(receivedMessages.size(), size_t(2));
|
||||
EXPECT_EQ(receivedMessages[0].Body, message3);
|
||||
EXPECT_EQ(receivedMessages[1].Body, message4);
|
||||
EXPECT_EQ(receivedMessages[0].MessageText, message3);
|
||||
EXPECT_EQ(receivedMessages[1].MessageText, message4);
|
||||
|
||||
queueClient.Delete();
|
||||
}
|
||||
@ -152,13 +152,11 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
auto peekedMessage = queueClient.PeekMessages().Value.Messages[0];
|
||||
|
||||
EXPECT_EQ(peekedMessage.Body, message);
|
||||
EXPECT_EQ(peekedMessage.MessageText, message);
|
||||
EXPECT_EQ(peekedMessage.MessageId, res.MessageId);
|
||||
EXPECT_EQ(peekedMessage.InsertedOn, res.InsertedOn);
|
||||
EXPECT_EQ(peekedMessage.ExpiresOn, res.ExpiresOn);
|
||||
EXPECT_EQ(peekedMessage.DequeueCount, 0);
|
||||
EXPECT_TRUE(peekedMessage.PopReceipt.empty());
|
||||
EXPECT_EQ(peekedMessage.NextVisibleOn, Azure::DateTime());
|
||||
|
||||
queueClient.Delete();
|
||||
}
|
||||
@ -189,19 +187,19 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
peekedMessages = queueClient.PeekMessages(peekOptions).Value.Messages;
|
||||
|
||||
EXPECT_EQ(peekedMessages.size(), static_cast<size_t>(peekOptions.MaxMessages.Value()));
|
||||
EXPECT_EQ(peekedMessages[0].Body, message1);
|
||||
EXPECT_EQ(peekedMessages[0].MessageText, message1);
|
||||
|
||||
peekedMessages = queueClient.PeekMessages().Value.Messages;
|
||||
EXPECT_EQ(peekedMessages.size(), size_t(1));
|
||||
EXPECT_EQ(peekedMessages[0].Body, message1);
|
||||
EXPECT_EQ(peekedMessages[0].MessageText, message1);
|
||||
|
||||
peekOptions.MaxMessages = 10;
|
||||
peekedMessages = queueClient.PeekMessages(peekOptions).Value.Messages;
|
||||
EXPECT_EQ(peekedMessages.size(), size_t(4));
|
||||
EXPECT_EQ(peekedMessages[0].Body, message1);
|
||||
EXPECT_EQ(peekedMessages[1].Body, message2);
|
||||
EXPECT_EQ(peekedMessages[2].Body, message3);
|
||||
EXPECT_EQ(peekedMessages[3].Body, message4);
|
||||
EXPECT_EQ(peekedMessages[0].MessageText, message1);
|
||||
EXPECT_EQ(peekedMessages[1].MessageText, message2);
|
||||
EXPECT_EQ(peekedMessages[2].MessageText, message3);
|
||||
EXPECT_EQ(peekedMessages[3].MessageText, message4);
|
||||
|
||||
queueClient.Delete();
|
||||
}
|
||||
@ -222,7 +220,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_TRUE(IsValidTime(updateRes.NextVisibleOn));
|
||||
|
||||
auto peekedMessage = queueClient.PeekMessages().Value.Messages[0];
|
||||
EXPECT_EQ(peekedMessage.Body, message);
|
||||
EXPECT_EQ(peekedMessage.MessageText, message);
|
||||
|
||||
Queues::UpdateMessageOptions updateOptions;
|
||||
updateOptions.MessageText = updatedMessage;
|
||||
@ -232,7 +230,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1200));
|
||||
peekedMessage = queueClient.PeekMessages().Value.Messages[0];
|
||||
EXPECT_EQ(peekedMessage.Body, updatedMessage);
|
||||
EXPECT_EQ(peekedMessage.MessageText, updatedMessage);
|
||||
|
||||
queueClient.Delete();
|
||||
}
|
||||
|
||||
@ -10,7 +10,10 @@ namespace Azure { namespace Storage { namespace Queues { namespace Models {
|
||||
|
||||
bool operator==(const SignedIdentifier& lhs, const SignedIdentifier& rhs)
|
||||
{
|
||||
return lhs.Id == rhs.Id && lhs.StartsOn == rhs.StartsOn && lhs.ExpiresOn == rhs.ExpiresOn
|
||||
return lhs.Id == rhs.Id && lhs.StartsOn.HasValue() == rhs.StartsOn.HasValue()
|
||||
&& (!lhs.StartsOn.HasValue() || lhs.StartsOn.Value() == rhs.StartsOn.Value())
|
||||
&& lhs.ExpiresOn.HasValue() == rhs.ExpiresOn.HasValue()
|
||||
&& (!lhs.ExpiresOn.HasValue() || lhs.ExpiresOn.Value() == rhs.ExpiresOn.Value())
|
||||
&& lhs.Permissions == rhs.Permissions;
|
||||
}
|
||||
|
||||
@ -64,7 +67,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
queueClient = Azure::Storage::Queues::QueueClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
{
|
||||
auto response = queueClient.DeleteIfExists();
|
||||
auto response = queueClient.Delete();
|
||||
EXPECT_FALSE(response.Value.Deleted);
|
||||
}
|
||||
{
|
||||
@ -80,7 +83,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_FALSE(response.Value.Created);
|
||||
}
|
||||
{
|
||||
auto response = queueClient.DeleteIfExists();
|
||||
auto response = queueClient.Delete();
|
||||
EXPECT_TRUE(response.Value.Deleted);
|
||||
}
|
||||
}
|
||||
@ -130,18 +133,36 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
queueClient.Create();
|
||||
|
||||
std::vector<Queues::Models::SignedIdentifier> signedIdentifiers;
|
||||
Queues::Models::SignedIdentifier identifier;
|
||||
identifier.Id = RandomString(64);
|
||||
identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(1);
|
||||
identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(1);
|
||||
identifier.Permissions = "r";
|
||||
signedIdentifiers.emplace_back(identifier);
|
||||
identifier.Id = RandomString(64);
|
||||
identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(2);
|
||||
identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(2);
|
||||
/* cspell:disable-next-line */
|
||||
identifier.Permissions = "raup";
|
||||
signedIdentifiers.emplace_back(identifier);
|
||||
{
|
||||
Queues::Models::SignedIdentifier identifier;
|
||||
identifier.Id = RandomString(64);
|
||||
identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(1);
|
||||
identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(1);
|
||||
identifier.Permissions = "r";
|
||||
signedIdentifiers.emplace_back(identifier);
|
||||
}
|
||||
{
|
||||
Queues::Models::SignedIdentifier identifier;
|
||||
identifier.Id = RandomString(64);
|
||||
identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(2);
|
||||
identifier.ExpiresOn.Reset();
|
||||
/* cspell:disable-next-line */
|
||||
identifier.Permissions = "raup";
|
||||
signedIdentifiers.emplace_back(identifier);
|
||||
}
|
||||
{
|
||||
Queues::Models::SignedIdentifier identifier;
|
||||
identifier.Id = RandomString(64);
|
||||
identifier.Permissions = "r";
|
||||
signedIdentifiers.emplace_back(identifier);
|
||||
}
|
||||
{
|
||||
Queues::Models::SignedIdentifier identifier;
|
||||
identifier.Id = RandomString(64);
|
||||
identifier.StartsOn = std::chrono::system_clock::now() - std::chrono::minutes(1);
|
||||
identifier.ExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(1);
|
||||
signedIdentifiers.emplace_back(identifier);
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW(queueClient.SetAccessPolicy(signedIdentifiers));
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
auto queueServiceClient = Queues::QueueServiceClient(queueServiceUrl + sas);
|
||||
const std::string newQueueName = LowercaseRandomString();
|
||||
EXPECT_NO_THROW(queueServiceClient.CreateQueue(newQueueName));
|
||||
queueServiceClient0.GetQueueClient(newQueueName).DeleteIfExists();
|
||||
queueServiceClient0.GetQueueClient(newQueueName).Delete();
|
||||
};
|
||||
|
||||
auto verifyQueueDelete = [&](const std::string& sas) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user