Thursday, July 26, 2012

Reading UTF-8 Characters From An Infinite Byte Stream

I’ve been playing with the twitter streaming API today. In very simple terms, you make an HTTP request and then sit on the response stream reading objects off it. The stream is a stream of UTF-8 characters and each object is a JSON encoded data structure terminated by \r\n. Simple I thought, I’ll just create a StreamReader and set up a while loop on its Read method. Here’s my first attempt …

using(var reader = new StreamReader(stream, Encoding.UTF8))
{
var messageBuilder = new StringBuilder();
var nextChar = 'x';
while (reader.Peek() >= 0)
{
nextChar = (char)reader.Read()
messageBuilder.Append(nextChar);

if (nextChar == '\r')
{
ProcessBuffer(messageBuilder.ToString());
messageBuilder.Clear();
}
}
}

Unfortunately it didn’t work. The StreamReader maintains a small internal buffer so I wouldn’t see the \r\n combination that marked the end of a new tweet until the next tweet came along and flushed the buffer.

OK, so let’s just read each byte from the stream and convert them one-by-one into UTF-8 characters. This works fine when your tweets are all in English, but UTF-8 can have multi-byte characters; any Japanese tweets I tried to read failed.

Thanks to ‘Richard’ on Stack Overflow the answer turned out to be the Decoder class. It  buffers the bytes of incomplete UTF-8 characters, allowing you to keep stacking up bytes until they are complete. Here’s revised example that works great with Japanese tweets:

int byteAsInt = 0;
var messageBuilder = new StringBuilder();
var decoder = Encoding.UTF8.GetDecoder();
var nextChar = new char[1];

while ((byteAsInt = stream.ReadByte()) != -1)
{
var charCount = decoder.GetChars(new[] {(byte) byteAsInt}, 0, 1, nextChar, 0);
if(charCount == 0) continue;

Console.Write(nextChar[0]);
messageBuilder.Append(nextChar);

if (nextChar[0] == '\r')
{
ProcessBuffer(messageBuilder.ToString());
messageBuilder.Clear();
}
}

Thursday, July 12, 2012

Tracing System.Net to debug HTTP Clients

If you are writing software that leverages the System.Net.WebRequest class, you’re probably familiar with tools like Fiddler or Wireshark. You can use these tools to see the actual HTTP requests and responses going back and forth between your client and the server. A nice alternative to these tools, that I only recently discovered, is the System.Net trace source. The System.Net source emits logging messages from the HttpWebRequest and HttpWebResponse classes that give a very similar experience to using Fiddler.

Here’s an example App.config file that configures the System.Net listener to output both to the console and a log file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

<system.diagnostics>

<trace autoflush="true" />

<sources>
<source name="System.Net" maxdatasize="1024">
<listeners>
<add name="MyTraceFile"/>
<add name="MyConsole"/>
</listeners>
</source>
</sources>

<sharedListeners>
<add
name="MyTraceFile"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log"
/>
<add name="MyConsole" type="System.Diagnostics.ConsoleTraceListener" />
</sharedListeners>

<switches>
<add name="System.Net" value="Information" />
<!-- <add name="System.Net" value="Verbose" />-->
</switches>

</system.diagnostics>

</configuration>

Here I’ve set up two listeners; ‘MyTraceFile’, that outputs the trace information to a log file; and ‘MyConsole’, that outputs to the console.

My favourite test tool is TestDriven.NET which allows you to run arbitrary methods and sends the output to the Visual Studio output console. Being able to run a test method (I’ve got F8 mapped to run tests, so it’s a single keystroke) and see the System.Net trace output immediately in Visual Studio is very cool.

Here’s some code which makes a GET request to www.google.com

var request = WebRequest.CreateDefault(new Uri("http://www.google.com/"));

request.Method = "GET";

var response = (HttpWebResponse)request.GetResponse();

using (var responseStream = response.GetResponseStream())
{
if (responseStream == null)
{
Console.Out.WriteLine("response stream is null");
return;
}

using (var reader = new StreamReader(responseStream))
{
// do something with the response body
var responseBody = reader.ReadToEnd();
}

}

When I run this code, I get the following trace output …

System.Net Information: 0 : [5752] Current OS installation type is 'Client'.
System.Net Information: 0 : [5752] RAS supported: True
System.Net Error: 0 : [5752] Can't retrieve proxy settings for Uri 'http://www.google.com/'. Error code: 12180.
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with ServicePoint#53977989
System.Net Information: 0 : [5752] Associating Connection#56846532 with HttpWebRequest#49685557
System.Net Information: 0 : [5752] Connection#56846532 - Created connection from 192.168.1.146:53202 to 173.194.67.99:80.
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with ConnectStream#19026863
System.Net Information: 0 : [5752] HttpWebRequest#49685557 - Request: GET / HTTP/1.1

System.Net Information: 0 : [5752] ConnectStream#19026863 - Sending headers
{
Host: www.google.com
Connection: Keep-Alive
}.
System.Net Information: 0 : [5752] Connection#56846532 - Received status line: Version=1.1, StatusCode=302, StatusDescription=Found.
System.Net Information: 0 : [5752] Connection#56846532 - Received headers
{
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.uk/
Set-Cookie: expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com,path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com,domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com,expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com,path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com,domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com,expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com,path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com,domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com,expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com,path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com,domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google...}.
System.Net Information: 0 : [5752] ConnectStream#10789400::ConnectStream(Buffered 221 bytes.)
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with ConnectStream#10789400
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with HttpWebResponse#11016073
System.Net Warning: 0 : [5752] HttpWebRequest#49685557::() - Error code 302 was received from server response.
System.Net Warning: 0 : [5752] HttpWebRequest#49685557::() - Resubmitting request.
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with ServicePoint#23936385
System.Net Information: 0 : [5752] Associating Connection#22196665 with HttpWebRequest#49685557
System.Net Information: 0 : [5752] Connection#22196665 - Created connection from 192.168.1.146:53203 to 173.194.67.94:80.
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with ConnectStream#57250404
System.Net Information: 0 : [5752] HttpWebRequest#49685557 - Request: GET / HTTP/1.1

System.Net Information: 0 : [5752] ConnectStream#57250404 - Sending headers
{
Host: www.google.co.uk
Connection: Keep-Alive
}.
System.Net Information: 0 : [5752] Connection#22196665 - Received status line: Version=1.1, StatusCode=200, StatusDescription=OK.
System.Net Information: 0 : [5752] Connection#22196665 - Received headers
{
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
Date: Thu, 12 Jul 2012 13:39:26 GMT
Expires: -1
Set-Cookie: NID=61=CTUlcAyhXQp63NVCOkXYWVgi2nMQiOUpyG-x1yRlw-Unhq3OyQ5zXCIxIJ9ctSN_qg6Lni90142sYKQzDZ7oZXBZxnWQbzhcjqVcKQEgCfBgMAjxhDgVLOfgXBR6IzTm; expires=Fri, 11-Jan-2013 13:39:26 GMT; path=/; domain=.google.co.uk; HttpOnly,PREF=ID=b7c02536ab59a395:FF=0:TM=1342100366:LM=1342100366:S=gqGT-3tWl96NIpdz; expires=Sat, 12-Jul-2014 13:39:26 GMT; path=/; domain=.google.co.uk,NID=61=CTUlcAyhXQp63NVCOkXYWVgi2nMQiOUpyG-x1yRlw-Unhq3OyQ5zXCIxIJ9ctSN_qg6Lni90142sYKQzDZ7oZXBZxnWQbzhcjqVcKQEgCfBgMAjxhDgVLOfgXBR6IzTm; expires=Fri, 11-Jan-2013 13:39:26 GMT; path=/; domain=.google.co.uk; HttpOnly
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
}.
System.Net Information: 0 : [5752] ConnectStream#42047594::ConnectStream(Buffered -1 bytes.)
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with ConnectStream#42047594
System.Net Information: 0 : [5752] Associating HttpWebRequest#49685557 with HttpWebResponse#47902635
System.Net Information: 0 : [5752] ContentLength=-1

You can see that Google users in the UK get a 302 redirect to www.google.co.uk. This is a special Google that refuses to say anything bad about Her Majesty and stops working to drink tea at exactly 11 am.

With the reporting level set at ‘Information’, you can see all the header HTTP information and some of the work that the underlying sockets are doing. Setting the level to ‘Verbose’ will give you the HTTP bodies as well.

For more information see the MSDN documentation here.

Happy HTTPing!

Tuesday, July 10, 2012

Playing with Twitter

My excellent clients, 15Below, are interested in exploring how social media, like Twitter and Facebook can work in their business area, travel communications. I’ve been tasked with investigating the technical side of this, in particular interacting with the Twitter API. Before I share what little I’ve learnt about talking to twitter with .NET, I’d like to throw a stone in the lake and ripple out some thoughts on life on planet Twitter.

The first conclusion I’ve come to is that a database of twitter handles isn’t very useful; there’s not much you can do with them. You can’t send more than 250 direct messages per day, and in any case the user has to be following you to receive them. So twitter as a point-to-point mass private communication channel, like email, is a non-starter. No spamming then. You can mention slightly more people, but once again you would soon start to hit the 1000 status updates per day limit with any serious targeted communications. You used to be able to get your application whitelisted by Twitter, which allows you higher API limits, but they’ve stopped that now.

We thought about creating multiple senders, but you can’t automate account creation and most of the limits are per account. Twitter is very strict about any application that they consider to be bending their rules, and you’ll soon find yourself blacklisted even if you manually set about creating multiple accounts for an application that’s deemed to be out of bounds.

The interesting scenarios coalesce around the core Twitter interaction use case; broadcasting to followers and joining in with conversations based around mentions. One idea we’re playing with is for an account that replies with status updates when you mention it with some kind of token, say a flight number or the name of a city. You’ve still got that 1000 tweets per day limit, but so long as the use case is partitioned correctly, that needn’t be a problem.

OK, that’s the ‘what’s it good for’ waffle out of the way, now for the interesting stuff: how easy is it to talk to Twitter from .NET?

I’ve been playing with the excellent TweetSharp library by Daniel Crenna, which makes basic twitter interaction pretty trivial. The only thing I had think at all hard about was the OAuth workflow.

OAuth is a protocol that allows a user to authorise an application for a subset of functionality on their account without giving away their password. Now I will probably be building server side components that automate a small set of twitter accounts, so I need an OAuth workflow that allows me to do a one-time configuration of the component to give it access to an account. This means I have to have a one-time OAuth tool, that allows me to harvest the OAuth tokens for a single account.

I’ve written a little console app to do just that …

class Program
{
// you get the consumer key and secret from Twitter when you register your app.
private const string consumerKey = " --- ";
private const string consumerSecret = " --- ";

static void Main(string[] args)
{
var service = new TwitterService(consumerKey, consumerSecret);
var requestToken = service.GetRequestToken();
var authorisationUri = service.GetAuthorizationUri(requestToken);

// open up a browser window and point it at the authorisationUri
Process.Start(authorisationUri.ToString());

Console.WriteLine("Input the verifier pin number from the web page:");
var verifier = Console.ReadLine();
var accessToken = service.GetAccessToken(requestToken, verifier);

// now output the access token and secret so that we can cut-n-paste them into our
// server side configuration.
Console.Out.WriteLine("accessToken.Token = {0}", accessToken.Token);
Console.Out.WriteLine("accessToken.TokenSecret = {0}", accessToken.TokenSecret);

// check that the access token and secret work.
service.AuthenticateWith(accessToken.Token, accessToken.TokenSecret);

Console.WriteLine(service.Response.Response);
}
}

This will pop up a browser window and present a pin number generated by Twitter that you then have to copy and paste. It then outputs the generated token and ‘token secret’ for that account.

Once you’ve got an access token and a token secret, you can use them for as long as you want. If you own the accounts your server side component is using, you don’t have to consider the workflow for when the user cancels your application’s access rights.

Sending a status update is trivial …

var service = new TwitterService(consumerKey, consumerSecret);
service.AuthenticateWith(previouslySavedToken, previouslySavedTokenSecret);
service.SendTweet(message);

My next challenge is getting to grips with the streaming API so that I can monitor mentions and reply to status update requests. I’ve got a working demo that polls the Twitter API, but it’s a very wasteful use of the scarce API access allowance.

So there you have it. Some very early thoughts on using Twitter for business and pleasure. I think there are some very exciting opportunities, especially for ‘you don’t have to install anything’ communication with remote applications scenario.

Tuesday, July 03, 2012

EasyNetQ: Continuous Delivery with TeamCity and NuGet

I recently applied to have EasyNetQ, my awesome RabbitMQ API for .NET, build on the CodeBetter TeamCity build server (you can log on as ‘guest’ with no password). The very helpful Anne Epstein set it up for me and all is now is building, testing and packaging nicely.
The bit I really like is that TeamCity can automatically push the EasyNetQ NuGet package up to NuGet.org on each build. So now EasyNetQ has continuous delivery, when you install or update it using NuGet you are getting the very latest version fresh from GitHub.
My attention was also drawn to MyGet.org, a personal-nuget-in-the-cloud service. For the moment, with EasyNetQ still very much a beta project, I’m happy to have the latest master always be available, but I can envisage some time in the future where I’ll want to have a bit more confidence before pushing a release up to NuGet.org; MyGet would allow me to publish beta packages for testing and then promote them to NuGet when they’ve passed all the QA barriers.
I now consider continuous deployment / delivery to be essential for any software project; It’s just brilliant being able to point anyone who cares to a test server that always has the very latest trunk build. It’s all a part of keeping development process cycles as tight as possible and always having working software.

Friday, June 22, 2012

When Should I Use An ORM?

I think like everyone, I go through the same journey whenever I find out about a new technology..

Huh? –> This is really cool –> I use it everywhere –> Hmm, sometimes it’s not so great

Remember when people were writing websites with XSLT transforms? Yes, exactly. XML is great for storing a data structure as a string, but you really don’t want to be coding your application’s business logic with it.

I’ve gone through a similar journey with Object Relational Mapping tools. After hand-coding my DALs, then code generating them, ORMs seemed like the answer to all my problems. I became an enthusiastic user of NHibernate through a number of large enterprise application builds. Even today I would still use an ORM for most classes of enterprise application.

However there are some scenarios where ORMs are best avoided. Let me introduce my easy to use, ‘when to use an ORM’ chart.

When_to_use_an_ORM

It’s got two axis, ‘Model Complexity’ and ‘Throughput’. The X-axis, Model Complexity, describes the complexity of your domain model; how many entities you have and how complex their relationships are. ORMs excel at mapping complex models between your domain and your database. If you have this kind of model, using an ORM can significantly speed up and simplify your development time and you’d be a fool not to use one.

The problem with ORMs is that they are a leaky abstraction. You can’t really use them and not understand how they are communicating with your relational model. The mapping can be complex and you have to have a good grasp of both your relational database, how it responds to SQL requests, and how your ORM comes to generate both the relational schema and the SQL that talks to it. Thinking of ORMs as a way to avoid getting to grips with SQL, tables, and indexes will only lead to pain and suffering. Their benefit is that they automate the grunt work and save you the boring task of writing all that tedious CRUD column to property mapping code.

The Y-axis in the chart, Throughput, describes the transactional throughput of your system. At very high levels, hundreds of transactions per second, you need hard-core DBA foo to get out of the deadlocked hell where you will inevitably find yourself. When you need this kind of scalability you can’t treat your ORM as anything other than a very leaky abstraction. You will have to tweak both the schema and the SQL it generates. At very high levels you’ll need Ayende level NHibernate skills to avoid grinding to a halt.

If you have a simple model, but very high throughput, experience tells me that an ORM is more trouble than it’s worth. You’ll end up spending so much time fine tuning your relational model and your SQL that it simply acts as an unwanted obfuscation layer. In fact, at the top end of scalability you should question the choice of a relational ACID model entirely and consider an eventually-consistent event based architecture.

Similarly, if your model is simple and you don’t have high throughput, you might be better off using a simple data mapper like SimpleData.

So, to sum up, ORMs are great, but think twice before using one where you have a simple model and high throughput.

Tuesday, June 19, 2012

Use AutoResetEvent To Unit Test Multi-Threaded Code

I’ve been guilty of using a very nasty pattern recently to write unit (and integration) tests for EasyNetQ. Because I’m dealing with inherently multi-threaded code, it’s difficult to know when a test will complete. Up to today, I’d been inserting Thread.Sleep(x) statements to give my tests time to complete before the test method itself ended.

Here’s a contrived example using a timer:

[Test]
public void SampleTestWithThreadSleep()
{
var timerFired = false;

new Timer(x =>
{
timerFired = true;
}, null, someAmountOfTime, Timeout.Infinite);

Thread.Sleep(2000);
timerFired.ShouldBeTrue();
}

I don’t know what ‘someAmountOfTime’ is, so I’m guessing a reasonable interval and then making the thread sleep before doing the asserts. In most cases the ‘someAmountOfTime’ is probably far less than the amount of time I’m allowing. It pays to be conservative in this case :)

My excellent colleague Michael Steele suggested that I use an AutoResetEvent instead. To my shame, I’d never spent the time to really understand the thread synchronisation methods in .NET, so it was back to school for a few hours while I read bits of Joseph Albahari’s excellent Threading in C#.

An AutoResetEvent allows you to block one thread while waiting for another thread to complete some task; ideal for this scenario.

Here’s my new test:

[Test]
public void SampleTestWithAutoResetEvent()
{
var autoResetEvent = new AutoResetEvent(false);
var timerFired = false;

new Timer(x =>
{
timerFired = true;
autoResetEvent.Set();
}, null, someAmountOfTime, Timeout.Infinite);

autoResetEvent.WaitOne(2000);
timerFired.ShouldBeTrue();
}

If you create an AutoResetEvent by passing false into its constructor it starts in a blocked state, so my test will run as far as the WaitOne line then block. When the timer fires and the Set method is called, the AutoResetEvent unblocks and the assert is run. This test only runs for ‘someAmountOfTime’ not for the two seconds that the previous one took; far better all round.

Have a look at my EasyNetQ commit where I changed many of my test methods to use this new pattern.

Monday, June 04, 2012

EasyNetQ: Introducing the Advanced API

EasyNetQ is an easy to use .NET API for RabbitMQ. Check out our new homepage at easynetq.com.
EasyNetQ's mission is to provide the simplest possible API for RabbitMQ based messaging. The core IBus interface purposefully avoids exposing AMQP concepts such as exchanges, bindings, and queues; instead you get a Publish method and a Subscribe method, and a Request method and a Respond method, simple to use bus also a rather opinionated take on the most common messaging patterns.
For users who understand AMQP and want the flexibility to create their own exchange-binding-queue topology this can be quite limiting; you still want to use EasyNetQ’s connection management, subscription handling, serialization, and error handling, but you want to do something outside of EasyNetQ’s pub/sub request/response patterns. For these users we’ve provided the ‘advanced’ API.
The advanced API is implemented with the IAdvancedBus interface. An instance of this interface can be accessed via the Advanced property of IBus:
var advancedBus = RabbitHutch.CreateBus("host=localhost").Advanced;

Yes, I stole that idea from RavenDb, thanks Ayende  :)
To create a bespoke exchange-binding-queue topology use the classes in the EasyNetQ.Topology namespace. In this example I’m binding a durable queue to a direct exchange:
var queue = Queue.DeclareDurable("my.queue.name");
var exchange = Exchange.DeclareDirect("my.exchange.name");
queue.BindTo(exchange, "my.routing.key");

Once you’ve defined your topology, you can use the Publish and Subscribe methods on the IAdvancedBus. To publish, first create a new message. Note we have a new Message<T> class that exposes the AMQP basic properties:
var myMessage = new MyMessage {Text = "Hello from the publisher"};
var message = new Message<MyMessage>(myMessage);
message.Properties.AppId = "my_app_id";
message.Properties.ReplyTo = "my_reply_queue";

Now we can publish our message to the exchange that we declared above:
using (var channel = advancedBus.OpenPublishChannel())
{
    channel.Publish(exchange, routingKey, message);
}

Here’s how we subscribe to the queue we defined:
advancedBus.Subscribe<MyMessage>(queue, (msg, messageReceivedInfo) => 
    Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Got Message: {0}", msg.Body.Text);
        Console.WriteLine("ConsumerTag: {0}", messageReceivedInfo.ConsumerTag);
        Console.WriteLine("DeliverTag: {0}", messageReceivedInfo.DeliverTag);
        Console.WriteLine("Redelivered: {0}", messageReceivedInfo.Redelivered);
        Console.WriteLine("Exchange: {0}", messageReceivedInfo.Exchange);
        Console.WriteLine("RoutingKey: {0}", messageReceivedInfo.RoutingKey);
    }));

Note that we also get an IMessageReceivedInfo instance that gives us information about the message context, such as the exchange, the routing key and the redelivered flag.
So as you can see, you get a lot more control and access to various AMQP entities, but still with much less complexity than using the RabbitMQ .NET C# client directly.
For more on the advanced API check out the EasyNetQ documentation. Happy messaging!

Friday, May 11, 2012

Time To Consider Node.js?

Unless you’ve been living under a rock for the past couple of years, you’ll have heard the buzz about Node.js, a platform for building network applications in Javascript. If, like me, you’re a .NET developer working on Windows, you’ll have thought, ‘that’s nice, now back to work’. But I think it’s now time to consider adopting Node as a core part of our toolkit. It allows us to do some things far easier than we can with our existing tools, and it’s now mature enough on Windows that you don’t have to jump through hoops in order to use it. There’s a very nice IIS integration story now with iisnode.

Here’s a little example. I needed to write a little web service that simply waited for a second before responding. I wanted a harness to test the asynchronous IO handling in EasyNetQ. I’d written something to do this in .NET previously. Here’s my IHttpHandler implementation…

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace TestHttpHandler
{
public class TimerHandler : IHttpAsyncHandler
{
public void ProcessRequest(HttpContext context)
{
throw new InvalidOperationException("This handler cannot be called synchronously");
}

public bool IsReusable
{
get { return false; }
}

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback, object state)
{
var taskCompletionSouce = new TaskCompletionSource<bool>(state);
var task = taskCompletionSouce.Task;

var timer = new Timer(timerState =>
{
context.Response.Write("OK");
callback(task);
taskCompletionSouce.SetResult(true);
});
timer.Change(1000, Timeout.Infinite);

return task;
}

public void EndProcessRequest(IAsyncResult result)
{
// nothing to do
}
}
}

It’s not trivial to write a non-blocking server like this. You have to have a good handle on the TPL and APM, something that’s beyond many mid-level .NET developers. In order to run this on a server I have to set up a new Web Application in IIS and configure the Web.config file. OK, it’s not a huge amount of work, but it’s still friction for a small throw-away experiment.
 
Here’s the same thing in Node:
var http = require('http');

http.createServer(function (req, res) {
setTimeout(function () {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK');
}, 1000);
}).listen(1338);

console.log('LongRunningServer is at http://localhost:1338/');

First of all, it’s less lines of  code. Node is asynchronous out of the box, you don’t have to understand anything more than standard Javascript programming idioms in order to write this service. I’m a total Node novice, but I was able to put this together far faster than the .NET example above.

But the runtime story is very nice too. Once I’ve installed Node (which is now just a question of running the Windows installer) all I have to do is open a command prompt and write:

node LongRunningServer.js

I don’t think I’m going to abandon .NET just yet, but I do think that I’ll be considering Node solutions as an integral part of my .NET applications.

Wednesday, May 09, 2012

EasyNetQ: A Breaking Change, IPublishChannel

EasyNetQ is my high-level .NET API for RabbitMQ.

Until recently, to publish a message using EasyNetQ you would create an instance of IBus and then call the publish method on it:

bus.Publish(message);

The IBus instance is the logical representation of a connection to a RabbitMQ server. Generally you should open a connection to the RabbitMQ server when your service (or application) starts and close it when the service shuts down. AMQP (the messaging protocol that RabbitMQ implements) multiplexes operations over the connection using channels, so while the connection is open, multiple channels can be opened and closed to carry out AMQP operations.

Initially I’d hoped to hide channels from EasyNetQ users. With subscriptions this makes sense - after the client creates a subscription, EasyNetQ looks after the channel and the subscription consuming thread. But publishing turned out to be more complex. Channels cannot be shared between threads, so EasyNetQ initially used a ThreadLocal channel for all publish calls. A new thread meant a new channel.

This problem manifested itself with a nasty operational bug we suffered. We had a service which woke up on a timer, created some threads, and published messages on them. Although the threads ended, the channels didn’t close, and each timer interval added another few open channels. After a period of time the channel count exceeded the allowed maximum and our RabbitMQ server died. Initially we considered finding some way of discovering when a thread ends and then disposing the channels based on some trigger, but after a discussion on Stack Overflow, we came around to the view that a sensible API design hands the responsibility of managing the channel lifetime to the API’s consumer (thanks to Martin James for being the main persuader).

So let me introduce you to my new friend, IPublishChannel. Instead of calling Publish directly on the IBus instance, EasyNetQ clients now have to create an instance of IPublishChannel and call its Publish method instead. IPublishChannel, as its name suggests, represents a channel. The channel is opened when it’s created, and disposed when it’s disposed.

Here’s how you use it:

using (var publishChannel = bus.OpenPublishChannel())
{
publishChannel.Publish(message);
}

So a little more API complexity, but a lot more transparency about how channels are created and disposed.

The request/response API has also changed to include IPublishChannel:

using (var publishChannel = bus.OpenPublishChannel())
{
publishChannel.Request<TestRequestMessage, TestResponseMessage>(request, response =>
Console.WriteLine("Got response: '{0}'", response.Text));
}

The EasyNetQ version has been bumped to 0.5 to reflect the breaking change.

Happy messaging!

Monday, May 07, 2012

The Configuration Complexity Clock

When I was a young coder, just starting out in the big scary world of enterprise software, an older, far more experienced chap gave me a stern warning about hard coding values in my software. “They will have to change at some point, and you don’t want to recompile and redeploy your application just to change the VAT tax rate.” I took this advice to heart and soon every value that my application needed was loaded from a huge .ini file. I still think it’s good advice, but be warned, like most things in software, it’s good advice up to a point. Beyond that point lies pain.

Let me introduce you to my ‘Configuration Complexity Clock’.

ConfigurationComplexityClock

This clock tells a story. We start at midnight, 12 o’clock, with a simple new requirement which we quickly code up as a little application. It’s not expected to last very long, just a stop-gap in some larger strategic scheme, so we’ve hard-coded all the application’s values. Months pass, the application becomes widely used, but there’s a problem, some of the business values change, so we find ourselves rebuilding and re-deploying it just to change a few numbers. This is obviously wrong. The solution is simple, we’ll move those values out into a configuration file, maybe some appsettings in our App.config. Now we’re at 2 on the clock.

Time passes and our application is now somewhat entrenched in our organisation. The business continues to evolve and as it does, more values are moved to our configuration file. Now appsettings are no longer sufficient, we have groups of values and hierarchies of values. If we’re good, by now we will have moved our configuration into a dedicated XML schema that gets de-serialized into a configuration model. If we’re not so good we might have shoe-horned repeated and multi-dimensional values into some strange tilda and pipe separated strings. Now we’re at 4 or 5 on the clock.

More time passes, the irritating ‘chief software architect’ has been sacked and our little application is now core to our organisation. The business rules become more complex and so does our configuration. In fact there’s now a considerable learning curve before a new hire can successfully carry out a deployment. One of our new hires is a very clever chap, he’s seen this situation before. “What we need is a business rules engine” he declares. Now this looks promising. The configuration moves from its XML file into a database and has its own specialised GUI. Initially there was hope that non-technical business users would be able to use the GUI to configure the application, but that turned out to be a false hope; the mapping of business rules into the engine requires a level of expertise that only some members of the development team possess. We’re now at 6 on the clock.

Frustratingly there are still some business requirements that can’t be configured using the new rules engine. Some logical conditions simply aren’t configurable using its GUI, and so the application has to be re-coded and re-deployed for some scenarios. Help is at hand, someone on the team reads Ayende’s DSLs book. Yes, a DSL will allow us to write arbitrarily complex rules and solve all our problems. The team stops work for several months to implement the DSL. It’s a considerable technical accomplishment when it’s completed and everyone takes a well earned break. Surely this will mean the end of arbitrary hard-coded business logic? It’s now 9am on the clock.

Amazingly it works. Several months go by without any changes being needed in the core application. The team spend most of their time writing code in the new DSL. After some embarrassing episodes, they now go through a complete release cycle before deploying any new DSL code. The DSL text files are version controlled and each release goes through regression testing before being deployed. Debugging the DSL code is difficult, there’s little tooling support, they simply don’t have the resources to build an IDE or a ReSharper for their new little language. As the DSL code gets more complex they also start to miss being able to write object-oriented software. Some of the team have started to work on a unit testing framework in their spare time.

In the pub after work someone quips, “we’re back where we started four years ago, hard coding everything, except now in a much crappier language.”

They’ve gone around the clock and are back at 12.

Why tell this story? To be honest, I’ve never seen an organisation go all the way around the clock, but I’ve seen plenty that have got to 5, 6, or 7 and feel considerable pain. My point is this:

At a certain level of complexity, hard-coding a solution may be the least evil option.

You already have a general purpose programming language, before you go down the route of building a business rules engine or a DSL, or even if your configuration passes a certain level of complexity, consider that with a slicker build-test-deploy cycle, it might be far simpler just to hard code it.

As you go clockwise around the clock, the technical implementation becomes successively more complex. Building a good  rules engine is hard, writing a DSL is harder still. Each extra hour you travel clockwise will lead to more complex software with more bugs and a harder learning curve for any new hires. The more complex the configuration, the more control and testing it will need before deployment. Soon enough you’ll find that there’s little difference in the length of time it takes between changing a line of code and changing a line of configuration. Rather than a commonly available skill, such as coding C#, you find that your organisation relies on a very rare skill: understanding your rules engine or DSL.

I’m not saying that it’s never appropriate to implement complex configuration, a rules-engine or a DSL, Indeed I would jump at the chance of building a DSL given the right requirements, but I am saying that you should understand the implications and recognise where you are on the clock before you go down that route.