Filas (Queues)

Pra melhorar responsividade das consultas...

Índice

Tabela de banco relacional como fila

TODO

SQL

set nocount on declare @queueid int while (select count(*) from dbo.Queue with (updlock, readpast)) >= 1 begin begin tran Tran1 select top 1 @queueid = QueueId from -- updlock impede updates e deletes nas linhas selecionadas, mas permite leitura -- readpast ignora linhas com lock dbo.Queue with (updlock, readpast) print 'processing queueid # ' + cast(@queueid as varchar) -- account for delay in processing time waitfor delay '00:00:05' delete from dbo.Queue where QueueId = @queueid commit end

Service Broker (Corretor de Serviços)

TODO

SQL - Preparar para criar fila

-- Create a Basic Queue -- Create a KEY. This is *required* in order to send / receive messages -- The database master key is a symmetric key used to protect the private keys -- of certificates and asymmetric keys that are present in the database create MASTER KEY ENCRYPTION BY PASSWORD = 'Password1'; -- Create a message type -- This could enforce a schema, but in this case enforces that it is well formed xml create MESSAGE TYPE MyMessage VALIDATION = WELL_FORMED_XML; -- Create a contract -- This defines the messages that can be sent in a conversation -- and defines which side of the conversation can send what. -- In this case only 1 type of message can be sent, -- but both by the INITIATOR and the TARGET create CONTRACT MyContract (MyMessage SENT BY ANY);

SQL - Criar fila de envio

-- Creates a queue for sending the message, which is required to send a message create queue MySendingQueue with STATUS = on, RETENTION = off; -- Creates a sending service. This defines the queue that will send/receive -- messages, as defined by the contract. -- In this case it allows MySendingService to send (and receive) MyMessage create service MySendingService on queue MySendingQueue (MyContract);

SQL - Criar fila de recebimento

-- Creates a queue which will receive the message. In this case it is local, -- but this could equally be a remote queue. In this case we could create -- a route to the queue using create route create queue MyReceivingQueue with STATUS = on, RETENTION = off; -- Creates a receiving service. -- In this case it allows MyReceiveService to receive (and send) MyMessage create service MyReceivingService on queue MyReceivingQueue (MyContract); -- Creates a route to a service. This is not strictly required for local services -- but should be used to route to services on remote sql instances create route MyRoute with SERVICE_NAME = 'MyReceivingService', ADDRESS = 'LOCAL';

SQL - Inserir na fila

declare @handle uniqueidentifier; begin dialog conversation @handle from service MySendingService to service 'MyReceivingService' on contract MyContract; SEND ON conversation @handle MESSAGE TYPE MyMessage ('<message>hello world</message>')

SQL - Ler a fila

-- espia a fila select * from MyReceivingQueue; -- remove da fila receive top 1 * from MyReceivingQueue;

SQL - Fechar a fila

end conversation @handle with cleanup;

Message Queue (Mensageria)

TODO

Filas com Microsoft Message Queueing (MSMQ)

Primeiramente instalar no computador o MSMQ.

Escrever numa fila

using System; using System.Messaging; // incluir nas referências System.Messaging namespace MSMQ { class Program { static void Main(string[] args) { const string messageQueuePath = @".\Private$\nomeDaFila"; MessageQueue messageQueue = null; var messageQueueLabel = @"this is a test queue"; object message = @"This is a test message. Can it be anything?"; var messageLabel = @"label for the message"; try { if (MessageQueue.Exists(messageQueuePath)) { messageQueue = new MessageQueue(messageQueuePath); messageQueue.Label = messageQueueLabel; } else { MessageQueue.Create(messageQueuePath); messageQueue = new MessageQueue(messageQueuePath); messageQueue.Label = messageQueueLabel; } messageQueue.Send(message, messageLabel); } catch { throw; } finally { messageQueue.Dispose(); } } } }

Ler uma fila

using System; using System.Messaging; // incluir nas referências System.Messaging namespace MSMQ { class Program { static void Main(string[] args) { const string messageQueuePath = @".\Private$\nomeDaFila"; using (MessageQueue messageQueue = new MessageQueue(messageQueuePath)) { // usamos mensagem do tipo string, mas pode ser de qualquer classe, desde que ela seja marcada com o atributo [Serializable] messageQueue.Formatter = new XmlMessageFormatter( new Type[] { typeof(string) } ); Message[] messages = messageQueue.GetAllMessages(); foreach (var message in messages) { System.Diagnostics.Debug.WriteLine(message.Label); System.Diagnostics.Debug.WriteLine((string)message.Body); // fazer o cast equivalente se usar um tipo diferente de string } messageQueue.Purge(); } } } }

Cloud

TODO

Microsoft Azure queues

App.config

<configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <appSettings> <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key" /> </appSettings> </configuration> <-- ou se dev --> <add key="StorageConnectionString" value="UseDevelopmentStorage=true;" />

C#

using Microsoft.Azure; // Namespace for CloudConfigurationManager using Microsoft.WindowsAzure.Storage; // Namespace for CloudStorageAccount using Microsoft.WindowsAzure.Storage.Queue; // Namespace for Queue storage types // Parse the connection string and return a reference to the storage account. CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") ); CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); // Retrieve storage account from connection string. CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") ); // Create the queue client. CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); // Retrieve a reference to a container. CloudQueue queue = queueClient.GetQueueReference("myqueue"); // Create the queue if it doesn't already exist queue.CreateIfNotExists(); // insert message // Retrieve storage account from connection string. CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") ); // Create the queue client. CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); // Retrieve a reference to a queue. CloudQueue queue = queueClient.GetQueueReference("myqueue"); // Create the queue if it doesn't already exist. queue.CreateIfNotExists(); // Create a message and add it to the queue. CloudQueueMessage message = new CloudQueueMessage("Hello, World"); queue.AddMessage(message); // peek next message // Retrieve storage account from connection string CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") ); // Create the queue client CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); // Retrieve a reference to a queue CloudQueue queue = queueClient.GetQueueReference("myqueue"); // Peek at the next message CloudQueueMessage peekedMessage = queue.PeekMessage(); // Display message. Console.WriteLine(peekedMessage.AsString); // de-queue (shift) // Retrieve storage account from connection string CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString") ); // Create the queue client CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient(); // Retrieve a reference to a queue CloudQueue queue = queueClient.GetQueueReference("myqueue"); // Get the next message CloudQueueMessage retrievedMessage = queue.GetMessage(); //Process the message in less than 30 seconds, and then delete the message queue.DeleteMessage(retrievedMessage); // use async await // Create the queue if it doesn't already exist if(await queue.CreateIfNotExistsAsync()) { Console.WriteLine("Queue '{0}' Created", queue.Name); } else { Console.WriteLine("Queue '{0}' Exists", queue.Name); } // Create a message to put in the queue CloudQueueMessage cloudQueueMessage = new CloudQueueMessage("My message"); // Async enqueue the message await queue.AddMessageAsync(cloudQueueMessage); Console.WriteLine("Message added"); // Async dequeue the message CloudQueueMessage retrievedMessage = await queue.GetMessageAsync(); Console.WriteLine("Retrieved message with content '{0}'", retrievedMessage.AsString); // Async delete the message await queue.DeleteMessageAsync(retrievedMessage); Console.WriteLine("Deleted message");

AWS Simple Queue Service

App.config

<configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> <configSections> <section name="aws" type="Amazon.AWSSection, AWSSDK"/> </configSections> <aws profileName="{my_profile}"/> </configuration>

C#

AmazonSQSConfig amazonSQSConfig = new AmazonSQSConfig(); amazonSQSConfig.ServiceURL = "http://sqs.us-west-2.amazonaws.com"; // AmazonSQSConfig amazonSQSConfig = new AmazonSQSConfig(); // amazonSQSConfig.ServiceURL = "http://sqs.cn-north-1.amazonaws.com"; amazonSQSClient = new AmazonSQSClient(amazonSQSConfig); CreateQueueRequest createQueueRequest = new CreateQueueRequest(); createQueueRequest.QueueName = "MySQSQueue"; createQueueRequest.DefaultVisibilityTimeout = 10; CreateQueueResponse createQueueResponse = amazonSQSClient.CreateQueue(createQueueRequest); sendMessageRequest.QueueUrl = myQueueURL; sendMessageRequest.MessageBody = "{YOUR_QUEUE_MESSAGE}"; // mensagem até 64kb de tamanho SendMessageResponse sendMessageResponse = amazonSQSClient.SendMessage(sendMessageRequest); ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(); receiveMessageRequest.QueueUrl = myQueueURL; ReceiveMessageResponse receiveMessageResponse = amazonSQSClient.ReceiveMessage(receiveMessageRequest); if (result.Message.Count != 0) { for (int i = 0; i < result.Message.Count; i++) { if (result.Message[i].Body == messageBody) { receiptHandle = result.Message[i].ReceiptHandle; } } } DeleteMessageRequest deleteMessageRequest = new DeleteMessageRequest(); deleteMessageRequest.QueueUrl = queueUrl; deleteMessageRequest.ReceiptHandle = recieptHandle; DeleteMessageResponse response = amazonSQSClient.DeleteMessage(deleteMessageRequest);