这是T4模板的Azure队列结构的好/优选图案吗?
-
23-10-2019 - |
题
我正在构建一个T4模板,该模板将帮助人们以一致和简单的方式构建Azure队列。我想做这个自我记录,并且有些一致。
首先,我在文件顶部制作了队列名称,队列名称必须在小写字母中,因此我添加了Tolower()
公共构造函数使用内置的StorageClient API访问连接字符串。我已经看到了许多不同的方法,并希望获得几乎所有情况下有效的东西。 (想法?分享)
我不需要不需要的HTTP请求来检查队列是否已创建,所以我做了一个
static bool
。我没有实现锁(MonitorObject),因为我认为不需要一个锁。与其使用字符串并用逗号解析(如大多数MSDN文档),我在将对象传递到队列时序列化。
为了进一步优化,我正在使用 JSON序列化扩展方法 充分利用8K限制。不确定编码是否有助于对此进行优化
添加了重试逻辑以处理队列中发生的某些方案(请参阅HTML链接)
问: 此类的“ DataContext”适当名称是适当的名称吗?
问: 以我所做的方式命名队列动作名称是一种糟糕的做法吗?
您认为我应该做什么其他更改?
public class AgentQueueDataContext
{
// Queue names must always be in lowercase
// Is named like a const, but isn't one because .ToLower won't compile...
static string AGENT_QUEUE_ACTION_NAME = "AgentQueueActions".ToLower();
static bool QueuesWereCreated { get; set; }
DataModel.SecretDataSource secDataSource = null;
CloudStorageAccount cloudStorageAccount = null;
CloudQueueClient cloudQueueClient = null;
CloudQueue queueAgentQueueActions = null;
static AgentQueueDataContext()
{
QueuesWereCreated = false;
}
public AgentQueueDataContext() : this(false)
{
}
public AgentQueueDataContext(bool CreateQueues)
{
// This pattern of setting up queues is from:
// ttp://convective.wordpress.com/2009/11/15/queues-azure-storage-client-v1-0/
//
this.cloudStorageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
this.cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient();
this.secDataSource = new DataModel.SecretDataSource();
queueAgentQueueActions = cloudQueueClient.GetQueueReference(AGENT_QUEUE_ACTION_NAME);
if (QueuesWereCreated == false || CreateQueues)
{
queueAgentQueueActions.CreateIfNotExist();
QueuesWereCreated = true;
}
}
// This is the method that will be spawned using ThreadStart
public void CheckQueue()
{
while (true)
{
try
{
CloudQueueMessage msg = queueAgentQueueActions.GetMessage();
bool DoRetryDelayLogic = false;
if (msg != null)
{
// Deserialize using JSON (allows more data to be stored)
AgentQueueEntry actionableMessage = msg.AsString.FromJSONString<AgentQueueEntry>();
switch (actionableMessage.ActionType)
{
case AgentQueueActionEnum.EnrollNew:
{
// Add to
break;
}
case AgentQueueActionEnum.LinkToSite:
{
// Link within Agent itself
// Link within Site
break;
}
case AgentQueueActionEnum.DisableKey:
{
// Disable key in site
// Disable key in AgentTable (update modification time)
break;
}
default:
{
break;
}
}
//
// Only delete the message if the requested agent has been missing for
// at least 10 minutes
//
if (DoRetryDelayLogic)
{
if (msg.InsertionTime != null)
if (msg.InsertionTime < DateTime.UtcNow + new TimeSpan(0, 10, 10))
continue;
// ToDo: Log error: AgentID xxx has not been found in table for xxx minutes.
// It is likely the result of a the registratoin host crashing.
// Data is still consistent. Deleting queued message.
}
//
// If execution made it to this point, then we are either fully processed, or
// there is sufficent reason to discard the message.
//
try
{
queueAgentQueueActions.DeleteMessage(msg);
}
catch (StorageClientException ex)
{
// As of July 2010, this is the best way to detect this class of exception
// Description: ttp://blog.smarx.com/posts/deleting-windows-azure-queue-messages-handling-exceptions
if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound")
{
// pop receipt must be invalid
// ignore or log (so we can tune the visibility timeout)
}
else
{
// not the error we were expecting
throw;
}
}
}
else
{
// allow control to fall to the bottom, where the sleep timer is...
}
}
catch (Exception e)
{
// Justification: Thread must not fail.
//Todo: Log this exception
// allow control to fall to the bottom, where the sleep timer is...
// Rationale: not doing so may cause queue thrashing on a specific corrupt entry
}
// todo: Thread.Sleep() is bad
// Replace with something better...
Thread.Sleep(9000);
}
解决方案
问:此类的“ datacontext”适当名称吗?
在.NET中,我们有很多Datacontext类,因此从某种意义上说,您希望名称适当地传达课程的作用,我认为 XyzQueueDataContext
正确地传达了班级的作用 - 尽管您无法从中查询。
如果您想保持与 接受的图案语言, 企业应用程序体系结构的模式 调用任何封装访问外部系统的类 网关, ,虽然更具体地说,您可能想使用该术语 渠道 用语言 企业集成模式 - 这就是我要做的。
问:以我所做的方式命名队列动作名称是一种糟糕的做法吗?
好吧,当然 紧密的夫妻 班级的队列名称。这意味着,如果您稍后决定要解除它们,则不能。
作为一般评论,我认为这堂课可能会从尝试少做的事情中受益。使用队列与管理与管理不同,因此我建议使用所有队列管理代码,而是建议 注射 实例中的云端。这是我实现Azurechannel构造函数的方式:
private readonly CloudQueue queue;
public AzureChannel(CloudQueue queue)
{
if (queue == null)
{
throw new ArgumentNullException("queue");
}
this.queue = queue;
}
这更好地适合 单一责任原则 现在,您可以自己(可重复使用)类实现队列管理。