我正在构建一个T4模板,该模板将帮助人们以一致和简单的方式构建Azure队列。我想做这个自我记录,并且有些一致。

  1. 首先,我在文件顶部制作了队列名称,队列名称必须在小写字母中,因此我添加了Tolower()

  2. 公共构造函数使用内置的StorageClient API访问连接字符串。我已经看到了许多不同的方法,并希望获得几乎所有情况下有效的东西。 (想法?分享)

  3. 我不需要不需要的HTTP请求来检查队列是否已创建,所以我做了一个 static bool 。我没有实现锁(MonitorObject),因为我认为不需要一个锁。

  4. 与其使用字符串并用逗号解析(如大多数MSDN文档),我在将对象传递到队列时序列化。

  5. 为了进一步优化,我正在使用 JSON序列化扩展方法 充分利用8K限制。不确定编码是否有助于对此进行优化

  6. 添加了重试逻辑以处理队列中发生的某些方案(请参阅HTML链接)

  7. 问: 此类的“ DataContext”适当名称是适当的名称吗?

  8. 问: 以我所做的方式命名队列动作名称是一种糟糕的做法吗?

您认为我应该做什么其他更改?

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;
}

这更好地适合 单一责任原则 现在,您可以自己(可重复使用)类实现队列管理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top