When you use queues, messages are read off in the order they are placed into the queue. This means that if there are 1000 messages in your queue, and now you want to send another message that is top priority, there’s no easy way to force it to the front of the queue.

The solution to this problem is to use “priority queues”. This allows high priority messages to get serviced immediately, irrespective of how many low priority messages are waiting.

There’s a few different options for how to implement priority queues in Azure Service Bus. We can choose how we partition the messages into priorities, either by using multiple queues, or multiple subscriptions on a topic. And we can also choose how we read from the queues – either with multiple concurrent listeners, or with a round-robin technique.

Sending Technique 1: Multiple Queues

A very simple way to achieve priority queues is to have two (or more) queues. One queue is for high priority messages, and the other for low priority. Whenever you send a message, you pick which queue to send it to. So this technique assumes that the code sending the message knows whether it should be high priority or not, and also knows how many priority queues there are.

In this simple code sample, we send three messages to the low priority queue and two to the high. We need two queue clients and to know the names of both queues to achieve this:

var clientHigh = QueueClient.CreateFromConnectionString(connectionString, "HighPriorityQueue");
var clientLow = QueueClient.CreateFromConnectionString(connectionString, "LowPriorityQueue");
clientLow.Send(new BrokeredMessage("Low 1"));
clientLow.Send(new BrokeredMessage("Low 2"));
clientLow.Send(new BrokeredMessage("Low 3"));
clientHigh.Send(new BrokeredMessage("High 1"));
clientHigh.Send(new BrokeredMessage("High 2"));

Sending Technique 2: One Topic with Multiple Subscriptions

An alternative approach is to make use of Azure Service Bus topics and subscriptions. With this approach, the messages are all sent to the same topic. But a piece of metadata is included with the message that can be used to partition the messages into high and low priorities.

So in this case we need a bit more setup. We’ll need a method to send messages with a Priority property attached:

void SendMessage(string body, TopicClient client, int priority)
{
    var message = new BrokeredMessage(body);
    message.Properties["Priority"] = priority;    
    client.Send(message);
}

And this allows us to send messages with priorities attached. We’ll send a few with priority 1, and a couple with priority 10:

var topicClient = TopicClient.CreateFromConnectionString(connectionString, "MyTopic");

SendMessage("Low 1", topicClient, 1);
SendMessage("Low 2", topicClient, 1);
SendMessage("Low 3", topicClient, 1);
SendMessage("High 1", topicClient, 10);
SendMessage("High 2", topicClient, 10);

But for this to work, we also need to have pre-created some subscriptions, that are set up to filter based on the Priority property. Here’s a helper method to ensure a subscription exists and has a single rule set on it:

SubscriptionClient CreateFilteredSub(string topicName, string subscriptionName, RuleDescription rule)
{
    if (!namespaceManager.SubscriptionExists(topicName, subscriptionName))
    {
        namespaceManager.CreateSubscription(topicName, subscriptionName);
    }
    var rules = namespaceManager.GetRules(topicName, subscriptionName);
    var subClient = SubscriptionClient.CreateFromConnectionString(connectionString, topicName, subscriptionName);
    foreach (var ruleName in rules.Select(r => r.Name))
    {
        subClient.RemoveRule(ruleName);
    }
    subClient.AddRule(rule);
    return subClient;
}

Now we can use this method to create our two filtered subscriptions, one for messages whose priority is >= 5, and one for those whose priority is < 5:

var subHigh = CreateFilteredSub("MyTopic", "HighPrioritySub", new RuleDescription("High", new SqlFilter("Priority >= 5")));
var subLow = CreateFilteredSub("MyTopic", "LowPrioritySub", new RuleDescription("Low", new SqlFilter("Priority < 5")));

Note that you must take care that your filters result in every message going to one or the other of the subscriptions. It would be possible if you weren’t careful with your filter clauses to lose messages or to double-process them.

So this technique is more work to set up, but removes knowledge of how many priority queues there are from the sending code. You could partition the priorities into more subscriptions, or change the rules about how priorities were determined to use different message metadata without necessarily having to change the code that sends the messages.

Receiving Technique 1: Simultaneous Listeners

We’ve seen how to partition our messages into high and low priority queues or subscriptions, but how do we go about receiving those messages and processing them?

Well, the easiest approach by far is simply to simultaneously listen on both queues (or subscriptions). For example, one thread is listening on the high priority queue and working through that, while another thread is listening on the low priority queue. You could assign more threads, or even separate machines to service each queue, using the “competing consumer pattern”.

The advantage of this approach is that conceptually it’s very simple. The disadvantage is that if both high and low priority queues are full, we’ll be simultaneously doing some high and some low priority work. That might be fine, but if there could be database contention introduced by the low priority work, you might prefer that all high priority messages are handled first, before doing any low priority work.

Receiving Technique 2: Round Robin Listening

So the second technique is simply to check the high priority queue for messages, and if there are any, process them. Once the high priority queue is empty, check the low priority queue for a message and process it. Then go back and check the high priority queue again.

Here’s a very simplistic implementation for two QueueClients (but it would be exactly the same for two SubscriptionClients if you were using a topic)

void PollForMessages(QueueClient clientHigh, QueueClient clientLow)
{
    bool gotAMessage = false;
    do
    {
        var priorityMessage = clientHigh.Receive(gotAMessage ? TimeSpan.FromSeconds(1) : TimeSpan.FromSeconds(30));
        if (priorityMessage != null)
        {
            gotAMessage = true;
            HandleMessage(priorityMessage);
        }
        else
        {
            var secondaryMessage = clientLow.Receive(TimeSpan.FromSeconds(1));
            if (secondaryMessage == null)
            {
                gotAMessage = false;
            }
            else
            {
                HandleMessage(secondaryMessage);
                gotAMessage = true;
            }
        }
    } while (true);
}

The only complex thing here is that I’m trying to change the timeouts on calls to Receive to avoid spending too much money if both queues are empty for prolonged periods. With Azure Service Bus you pay (a very small amount) for every call you make, so checking both queues every second might get expensive.

No doubt this algorithm could be improved on, and would need to be fine tuned for the specific needs of your application, but it does show that it’s not too hard to set up listeners that guarantee to process all available high priority messages before they begin working on the low priority messages.

Last week I wrote about so-called “best practices”, and one coding style that’s often promoted as a “best practice” is to “prefer convention over configuration”.

What exactly does this mean? Well the idea is that wherever possible we attempt to remove the need to explicitly configure things, and instead rely on sensible (but overridable) defaults.

A good example of this approach is ASP.NET. If I want to serve a page at /products then I create a class called ProductsController that inherits from Controller and add a method with the signature public ActionResult Index(). And the ASP.NET framework simply uses reflection to work out that any HTTP GET requests coming into that URL should create an instance of ProductsController and call the Index method. I don’t need to add a line of configuration somewhere to explicitly specify that this should happen.

There are a lot of advantages to this convention over configuration approach. First of all, it makes it very easy to add new components, simply by copying examples already present in the code. If I need a new orders controller, I can easily understand who to do it by looking at the other controllers. This can make it very easy for people new to the project to extend it.

This is also an excellent example of the “open closed principle” in action. A convention over configuration approach means that you can add a new feature without having to change any existing code at all. You simply add a new class that implements a certain interface or is named in a particular way. This has the side benefit of eliminating merge conflicts in classes or files that contain a lot of configuration, which usually experience a lot of “code churn”.

Convention over configuration is also used commonly with setting up message or command handlers. Simply implement the IHandle<T> interface, and some reflection code behind the scenes will discover your handler and wire it up appropriately. Again this makes a developer’s job very easy – need to add a new message or command handler? Just follow the pattern of the other ones.

So it would seem that “convention over configuration” makes a lot of sense. But are there any drawbacks?

One criticism is that this kind of approach can seem like “magic”– making it hard for new starters on a project to understand how it works. Often the IDE support to “find all references” will return nothing when these conventions are being used because reflection is typically used at run-time to discover the methods to be called. It can leave developers wondering “how on earth does this even work”?

Generally speaking, the more ubiquitous a convention is, the easier it will be for developers to learn and understand. The conventions in a framework like ASP.NET make sense because they are used over and over again – meaning the time invested in learning them is well spent. But beware of creating lots of conventions that only get used in one or two places. This introduces unnecessary additional learning for developers with minimal benefit.

A particularly painful point can be the mechanism by which you override the “sensible defaults” of the convention. How is a developer supposed to know how to do that? In ASP.NET there are attributes that can be used to override the route used by an action on a controller, which is fine because ASP.NET is well documented, but if it’s a bespoke convention you’ve invented for your project, you’ll need to make sure all the information about how your convention works is readily available.

Another disadvantage is that conventions can sometimes produce unexpected results. A good example is the fact that because ASP.NET uses reflection to find all classes that inherit from a base Controller class, if someone happens to reference an assembly from another project that also contains some controllers, you might find you’re exposing new endpoints that you weren’t intending to. This happened once on a project I worked on and opened up a serious security hole. This is the reason why some developers prefer the competing “best practice” of “explicit is better than implicit. So whenever you use conventions, try to build in protections against these types of unintended consequences.

So, should you adopt “convention over configuration” for your own frameworks? Well it comes back to the question of what problem you are trying to avoid. If it’s about eliminating repetitive and redundant configuration code, then it only makes sense to introduce if the convention is going to be applied many times. If its just once or twice, it may not be worth it.

As I said in my “best practices” post, there isn’t one clear right way to approach every problem in software development. Conventions remove some problems, but introduce others. So you need to understand the trade-offs in order to make a decision about what makes sense for you. Used judiciously, conventions can help developers fall into the “pit of success” – it should be easier to get it right than to get it wrong.

Let me know in the comments how you’ve got on with custom conventions in your own frameworks? Did they make things better? Or did every new developer complain that they couldn’t understand how the code works?

0 Comments

There’s no such thing as a “best practice”. At least in software development. I’ve read countless articles on the “best practices” for database design, software architecture, deployment, API design, security, etc and it’s pretty clear that (a) no one can agree on what the best practices actually are, and (b) last year’s “best practice” frequently turns into this year’s “antipattern”.

I can however understand the motivation for wanting to define “best practices”. We know that there are a lot of pitfalls in programming. It’s frighteningly easy to shoot yourself in the foot. It makes sense to know in advance of starting out, how best to avoid making those mistakes. We’re also in such a rapidly moving industry, that we’re frequently stepping out into uncharted territory. Many of the tools, frameworks and technologies I’m using today I knew nothing about just five years ago. How can I be expected to know what the best way to use them is? I frequently find myself googling for “technology X best practices”.

So-called “best practices” emerge not by being definitively proved to be the “best” way of doing something, but simply by virtue of being better than another way. We tried approach A and it went horribly wrong after two weeks, so we tried approach B and got further. Now approach B is the “best practice”. But before long we’re in a real mess again, and now we’re declaring that approach C is the “best practice”.

A better name for “best practices” would be “better practices”. They emerge as a way of avoiding a particular pitfall. And because of this, it’s very unhelpful to present a set of “best practices” without also explaining what problem each practice is intended to protect us from.

When we understand what problem a particular best practice is attempting to save us from, it allows us to make an informed decision on whether or not that “best practice” is relevant in our case. Maybe the problem it protects us from is a performance issue at massive scale. That may not be something that needs to concern us on a project that will only ever deal with small amounts of data.

You might declare that a best practice is “create a nuget package for every shared assembly”. Or “only use immutable classes”. Or “no code must be written without writing a failing test for it first”. These might be excellent pieces of guidance that can greatly improve your software. But blindly followed without understanding the reasoning behind them, they could actually result in making our codebase worse.

Most “best practices” are effective in saving you from a particular type of problem. But often they simply trade off one type of problem for another. Consider a monolithic architecture versus a distributed architecture. Both present very different problems and challenges to overcome. You need to decide which problems you can live with, and which you want to avoid at all costs.

In summary, even though I once created a Pluralsight course with “best practices” in the title, I don’t really think “best practices” exist. At best they are a way of helping you avoid some common pitfalls. But don’t blindly apply them all. Understand what they are protecting you from, and you will be able to make an informed decision about whether they apply to your project. And you may even be able to come up with even “better practices” that meet the specific needs and constraints of your own project.

0 Comments

When you play audio with NAudio, you pass an audio stream (which is an implementation of IWaveProvider) to the output device. The output device will call the Read method many times a second asking for new buffers of audio to play. When the Read method returns 0, that means we’ve reached the end of the stream, and playback will stop.

So for example, the audio file reader classes in NAudio such as WavFileReader, Mp3FileReader, AudioFileReader etc, all implement IWaveProvider and their Read method returns the number of bytes asked for until the the end is reached, after which it returns 0 and playback will stop. Because these classes also inherit from WaveStream they also support repositioning, so if you repositioned back to the start just before reaching the end, you’d be able to keep playback going for longer than the duration of the file.

But some classes in NAudio produce never-ending streams of audio. For example the SignalGenerator class is an ISampleProvider which continuously produces a signal such as a sine wave. If you pass this to a playback device (you can pass either IWaveProvider or ISampleProvider to an output device in NAudio), playback will continue indefinitely because you’ve given it a never-ending stream.

There are also some classes in NAudio whose behaviour is configurable. The MixingSampleProvider and BufferedWaveProvider are like this. If their ReadFully property is set to true, they will always return the number of bytes/samples asked for in the Read method. This is off by default with MixingSampleProvider, meaning that once you’ve reached the end of all the inputs to the mixer, playback will end. But if you turn it on, then it means you’ll continue to play silence even though the mixer has no more inputs. This can be useful if you want to dynamically add more inputs to the mixer later on.

With BufferedWaveProvider, ReadFully is set to true by default. That’s because it’s designed to help you play audio you receive over the network. If there’s audio in the buffer, it gets played, but if there’s no audio in the buffer (maybe because of poor network connectivity), we don’t want to stop playback, we just want to play silence until we’ve received some audio to play.

It’s possible to take an never-ending stream and give it a finite duration. A good example of this is the OffsetSampleProvider which can “take” a set duration of audio from an input sample provider. There are some extension methods in NAudio to make this easy to use. So for example, to get 5 seconds of a 500Hz sine wave you can do this:

var sine5Seconds = new SignalGenerator() { Gain = 0.2, Frequency = 500 }.Take(TimeSpan.FromSeconds(5));

If you play this, it will stop after 5 seconds:

using (var wo = new WaveOutEvent())
{
    wo.Init(sine5Seconds);
    wo.Play();
    while (wo.PlaybackState == PlaybackState.Playing)
    {
        Thread.Sleep(500);
    }
}

You can also go the other way, and make  make a regular wave provider endless either by extending it with silence, or by looping it. I’ve written before on how to implement looping in NAudio.

Hopefully this has helped clarify why in NAudio playback sometimes doesn’t stop when you wanted it to (you accidentally created an endless stream), or how you can can keep a single playback session running continuously without needing to keep opening and closing the output device. This allows you to easily implement a fire and forget audio playback engine where you can play sounds by adding them to a mixer, which will just produce a never-ending stream of silence if no sounds are currently active. So never-ending streams can be a good thing.

“But let justice roll on like a river, righteousness like a never-ending stream!” Amos 5:24

Want to get up to speed with the the fundamentals principles of digital audio and how to got about writing audio applications with NAudio? Be sure to check out my Pluralsight courses, Digital Audio Fundamentals, and Audio Programming with NAudio.

0 Comments

Azure offers a number of “databases” as a service. There’s SQL Azure, which is a great choice when you want a relational database that you can use with Entity Framework or query with your own custom SQL.

There’s also Azure DocumentDb which is Microsoft’s “NoSQL” offering – giving you the benefits of a schemaless document database approach, while retaining powerful querying capabilities. If you’re familiar with using NoSql databases like MongoDb then it’s an ideal choice.

And then there’s Azure Table Storage, which Microsoft describes as a “NoSQL key/attribute store”. This means that it’s got a schemaless design, and each table has rows that are made up of key value pairs. Because it’s schemaless, each row doesn’t have to contain the same keys.

But compared to DocumentDb, Table Storage is very rudimentary. There are only two indexed columns on our tables – RowKey and PartitionKey, which together uniquely identify each row. So it’s not great if you need to perform complex queries. In DocumentDb, each “document” is a JSON object that can have an arbitrarily deep structure. But in Table Storage, you’d need to manage serialization to JSON (or XML) yourself if you wanted to store complex objects or arrays inside columns.

So, compared to the more powerful capabilities of DocumentDb, Table Storage might seem a bit pointless. Does it have any advantages?

Well the main big advantage is cost. Even for the cheapest DocumentDb database, you are looking at $23 a month for a single “collection” plus a small amount more for the total data stored. This may be reasonable for production apps, but for small experiments or prototypes, it can add up quite quickly and probably force you to try to store the documents for multiple apps in the same DocumentDb collection which could get messy.

With Table Storage, you don’t pay a monthly fee, but instead pay very small amounts for the amount of data stored and the number of transactions you use. This means that for prototypes and proof of concepts it works out insanely cheap. It’s currently the only database choice in Azure that follows the “serverless” pricing model of paying only for what you actually use.

This means that Table Storage can be a good choice as a “poor man’s” NoSql database. I’ve been using it on a number of projects where I just need a couple of simple tables, and where my querying requirements are not complex. Another advantage is that it integrates very nicely with Azure Functions, making it a great choice if you want to quickly build out a “serverless” prototype.

Of course, Table Storage is also designed to be able to store huge volumes of data. So another use case it’s great for is for storing logs and diagnostic information. In fact, a several Azure services (like Azure Functions for example) use Table Storage as the backing store for their own logs.

So although Table Storage may not be the most exciting or flexible database option, if you know what it’s strengths are, it can be a useful tool to have at your disposal. There’s a helpful tutorial available if you want to get started with Table Storage using C#.

Want to learn more about how easy it is to get up and running with Azure Functions? Be sure to check out my Pluralsight course Azure Functions Fundamentals.