benjii.me

SuperQ – A Portable Persistent .NET Queue

I'm considering buying this T-Shirt

Step #1 – Ensure you have SQL Compact Edition 4 Installed

To let SuperQ build a database automatically in your App_Data folder, we have opted to use SQL Compact Edition 4.

Use the Web Platform Installer to download and install SQL Compact Edition 4. If you’ve never used Web Platform Installer, I strongly urge you to try it, it makes installing common software a breeze.

Otherwise you can download SQL Compact Edition 4 directly from here: http://www.microsoft.com/downloads/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&displaylang=en

Step #2 – Reference the SuperQ Library

Download and reference the SuperQ library from here: http://github.com/downloads/bjcull/SuperQ/SuperQ_v0.3.dll

If you’re interested in the inner workings of the queue, or would like to help out, please feel free to jump over to http://github.com/bjcull/SuperQ and grab the latest source code for yourself.

On a side note, either me or lukencode will probably be doing a blog post on how to implement some of the features that SuperQ makes use of such as Async Callbacks and SQL Compact DB Creation, soon.

Step #3 – Use the Queue

UPDATE (8 Sep 2010): I’ve now implemented class level generics instead of method level, as suggested by James Curran.

You now have access to one of the most abbreviated and super of queues known to man. Here are a few common methods to get you going:

Create or Open a Queue

REXML could not parse this XML/HTML: 
<pre class="prettyprint");</pre>
This will create a queue in your data folder (Usually App_Data) with the name provided. If it already exists it just opens it. Since SuperQ can only handle one type per queue, you must specify it when calling GetQueue, as above.

Sorry about the namespace, it might be changed in future.

Push a message onto the queue

// OR

var queue = SuperQ.SuperQ<int>.GetQueue(“MyQueueInt”);queue.PushMessage(45);

// OR

var queue = SuperQ.SuperQ<MyClass>.GetQueue(“MyQueueClass”); queue.PushMessage( new MyClass() { Name = “Ben”, Status = “Awesome”, Amount = 10000.00 } );</pre> Yep, you can push whatever class you like onto the queue and you’re guaranteed to get it back.

Get a message off the queue

REXML could not parse this XML/HTML: 
<pre class="prettyprint">var message = queue.GetMessage();

// Payload will be the same type you specify above MyClass result = message.Payload;

 

// Instead of using get message, you can call get payload to just get the next payload

var payload = queue.GetPayload(); </pre> Keep in mind that SuperQ is designed to use only one type at a time per queue. Please also remember to delete the message from the queue once you have successfully processed it. See Below.

Delete the message from the queue

queue.DeleteMessage(message);
To make sure that the queue message will survive even if your program crashes, you must delete the message from the queue within 30 seconds (soon to be an option) otherwise the message will become available to other GetMessage calls.

Automatically receive a callback when a message arrives

If you do not want to poll the queue manually, you can setup a callback method that will be called each time there is a message waiting to be processed.

First create the callback method like so:

protected void MessageReceived(QueueMessage<MyClass> message)
{
    Console.WriteLine("Message Received: " + message.Payload.Name);
    queue.DeleteMessage(message);
}
Now you can start and stop the callback like so:
REXML could not parse this XML/HTML: 
<pre class="prettyprint">// Start receiving messages
queue.StartReceiving(MessageReceived);

// Run for as long as you like here

//Stop receiving messages queue.StopReceiving();</pre>

Can I have an example of all of the above?

No problem imaginary heading friend, SuperQ can help. Here’s a quick Console App combining all the above methods:
REXML could not parse this XML/HTML: 
<pre class="prettyprint">    class Program
    {
        private static SuperQ.SuperQ&lt;string&gt; queue;

    static void Main(string[] args)
    {
        queue = SuperQ.SuperQ&lt;string&gt;.GetQueue("MyQueue");
        queue.StartReceiving(MessageReceived);

        bool running = true;
        while (running)
        {
            var key = Console.ReadKey(true);
            if (key.Key == ConsoleKey.Enter)
                running = false;
            else if (key.Key == ConsoleKey.P)
            {
                Console.WriteLine("Message Pushed");
                queue.PushMessage(new QueueMessage&lt;string&gt;("P was pressed in message form"));
            }
            else if (key.Key == ConsoleKey.G)
            {
                var message = queue.GetMessage();
                if (message != null)
                    Console.WriteLine("Message: " + message.Payload);
                else
                    Console.WriteLine("No Message Received...");
            }
            else if (key.Key == ConsoleKey.L)
            {
                Console.WriteLine("Payload Pushed");
                queue.PushMessage("P was pressed in Payload form");
            }
            else if (key.Key == ConsoleKey.V)
            {
                var payload = queue.GetPayload();
                if (payload != null)
                    Console.WriteLine("Payload: " + payload);
                else
                    Console.WriteLine("No Payload Received...");
            }

        }

        queue.StopReceiving();
    }

    static void MessageReceived(QueueMessage&lt;string&gt; message)
    {
        Console.WriteLine("Message Received: " + message.Payload);
        queue.DeleteMessage(message);
    }
}</pre>