Является ли это хорошим/предпочтительным шаблоном построения очереди Azure для шаблона T4?

StackOverflow https://stackoverflow.com/questions/4771818

Вопрос

Я создаю шаблон T4, который поможет людям единообразным и простым образом создавать очереди Azure.Я хотел бы сделать это самодокументированным и в некоторой степени последовательным.

  1. Сначала я разместил имя очереди в верхней части файла, имена очередей должны быть в нижнем регистре, поэтому я добавил ToLower().

  2. Открытый конструктор использует встроенные API StorageClient для доступа к строкам подключения.Я видел много разных подходов к этому и хотел бы получить что-то, что работает практически во всех ситуациях.(идеи?поделитесь)

  3. Мне не нравятся ненужные HTTP-запросы для проверки того, созданы ли очереди, поэтому я сделал это static bool .Я не реализовал Lock(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 правильно сообщает, что делает класс, хотя вы не можете запрашивать его.

Если вы хотите оставаться более согласованным с принятые языки шаблонов, Шаблоны архитектуры корпоративных приложений вызывает любой класс, который инкапсулирует доступ к внешней системе для шлюз, хотя более конкретно вы можете использовать термин Канал на языке Шаблоны корпоративной интеграции - вот что бы я сделал.

Вопрос:Является ли плохой практикой называть имя действия очереди так, как это сделал я?

Ну это конечно плотно пары имя очереди для класса.Это означает, что если вы позже решите, что хотите их отделить, вы не сможете этого сделать.

В качестве общего замечания я думаю, что этому классу могло бы помочь попытаться сделать меньше.Использование очереди — это не то же самое, что управление ею, поэтому вместо того, чтобы хранить там весь этот код управления очередью, я бы предложил инъекция CloudQueue в экземпляр.Вот как я реализую свой конструктор 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