Capturing MSBuild output w/Pulse

At work, we use Zutubi Pulse as a build server across the enterprise.  Since the majority of the applications we build are not written in .NET, Pulse is a good choice.  Seems to do a lot of things well, has a nice user interface, and has some advanced features.  I wish we used something that was a little more .NET friendly (like TeamCity), but with a little work I was able to have some success at making it feel that way.

 

Since it supports external executables for building projects, we just use batch scripts to build our .NET projects.  This works fine except that when a build fails, Pulse does not capture the reason why in its UI, instead you have to drill into the console output to find the cause.  I dug into Pulse’s documentation and found out that it has a post processor that meets this need.  The post processor will parse the log output and capture any errors and warnings.  All that is needed is a regular expression to capture the error and warning lines.  Here is why I use for MSBuild:

 

   1: <regex.pp name="compiler.processor">
   2:     <pattern category="error" expression="^(.*)\\\.cs\\\(\\\d+,\\\d+\\\): error(.*)\$"/>
   3:     <pattern category="warning" expression="^(.*)Microsoft.Common.targets : warning(.*)\$"/>
   4:     <pattern category="warning" expression="^(.*)\\\.cs\\\(\\\d+,\\\d+\\\): warning (.*)\$"/>
   5: </regex.pp>

 

This will capture compiler errors and warnings, and also capture warnings from MSBuild itself. 

 

In order to capture the output from our unit tests, I a wrote a converter that converts MSTest XML into JUnit XML so that Pulse can report on our unit tests.   Pulse supports JUnit natively, so converting the MSTest XML was not that complex of a task.  Unfortunately, I cannot share that code.

Ubuntu 7.10 to 8.04 Upgrade – Networking issues

I have an Ubuntu server that I use a file server for imaging my other machines.  After upgrading, networking no longer seemed to work.  I also kept getting an error when trying to run sudo:

 

unable to resolve host mymachinename

 

After a bit of searching, I landed on this bug which apparently has affected a number of people:

 

https://bugs.launchpad.net/ubuntu/+source/linux-meta/+bug/195308

 

Using ‘gksu gedit’ and fixing /etc/hosts solved my problem.  To get Internet connectivity back, I had to disable IPv6:

 

https://help.ubuntu.com/community/WebBrowsingSlowIPv6IPv4

Implementing a Dead Letter Channel for NServiceBus

 

I’ve been spending some time working with NServiceBus lately as we are looking for an open source publish/subscribe framework written in .NET.  I like what I have seen so far, although I think that the development model could be a little simpler.  My biggest gripe is that messages have to implement an IMessage interface and there is no mechanism for supporting headers on message envelopes.  That aside, Udi’s responsiveness (and politeness) to everyone who posts on the NServiceBus forum is refreshing and he seems to listen to people who make good suggestions.

 

A discussion came up on the list about implementing a retry strategy for when a message handler fails to execute (maybe a database is down for instance).  The nice thing about NServiceBus is that adding something like this is just a matter of doing some simple programming.  No worries implementing of custom behaviors or adding XML required.

 

My simple solution (which is just some prototype code):

 

   1: public interface IReplayableMessage : IMessage
   2: {
   3:   int RetryCount { get; set; }
   4:   DateTime LastReplayAttempt { get; set; }
   5: }
   6:  
   7: public abstract class RetryMessageHandler<TMessage> : IMessageHandler<TMessage>
   8:   where TMessage : IReplayableMessage
   9: {
  10:  
  11:   public IBus Bus { get; set; }
  12:  
  13:   public void HandleMessage(TMessage message)
  14:   {
  15:     if (DateTime.Now - message.LastReplayAttempt < 5.Seconds())
  16:     {
  17:       Bus.HandleMessageLater();
  18:       return;
  19:     }
  20:     try
  21:     {
  22:       HandleMessageInternal(message);
  23:     }
  24:     catch (Exception e)
  25:     {
  26:       if (message.RetryCount < 5)
  27:       {
  28:         message.RetryCount = message.RetryCount++;
  29:         message.LastReplayAttempt = DateTime.Now;
  30:         Bus.Send(message);
  31:       }
  32:       else
  33:      {
  34:        ..log error and move to dead letter queue..
  35:      }
  36:     }
  37:   }
  38:  
  39:   public abstract void HandleMessageInternal(TMessage message);
  40:  
  41: }

 

 

This is just some simple prototype code, but as you can see, NServiceBus handlers are easy to write and test.  For a more complicated implementation, Apache Camel has an implementation of the dead letter channel pattern to get some ideas from.  It keeps the message in memory while trying to retry and sleeps while waiting to reprocess.  The example I gave sends the message back to the end of the queue.

links for 2008-04-28

GhostDoc

Besides ReSharper, there is only one other Visual Studio plugin that I cannot live without — GhostDoc.  If you have not used it before, it basically generates XML comments on your code and makes a best guess on what the comment summary should be.  This feature is pretty standard for Java IDEs (except for the actually generation of the summary for you), but it is yet another thing that is missing in Visual Studio. 

 

If you follow good naming conventions in your code, then you should get pretty decent results on the summary it generates.  It is definately a keystroke saver and makes documenting your code somewhat infectious.  When I see code that is undocumented, it is really hard for me not to hit Ctrl-Shift-D and have GhostDoc document it.

 

There are a number of different features/options and I am definitely not doing it justice in this short post.  The best way to find out if you like it is to try it out.  Small download and quick installation.

Castle ActiveRecord SessionScope and WCF

If you are familiar with NHibernate flushing semantics, then you know you usually want to treat a group of database operations as a single unit of work.  For one reason, flushing is expensive because it requires checking all of your entities for changes to see if they should be persisted to the database.  Second, you often want to treat all of your database operations as an atomic transaction.  Third, any entities that have lazy loaded properties can take advantage of the existing session.  ActiveRecord provides a nice abstraction for treating multiple database operations as a unit of work called SessionScope.  For instance, if all of your database operations are grouped together in one location, you would use SessionScope like:

 

var person = ...
var child = ...
using (SessionScope scope = new SessionScope)
{
  person.Save();
  child.Save();
}

In this case the neither the person or child is saved to the database until the Dispose() is called on the SessionScope.  For  the simple scenarios, this works fine, but in most cases you are doing your database operations in a DAO or Repository class — so you do not know how the database operations are going to be used or what other operations are going to be used with them.

If you are using ActiveRecord with MonoRail or another MVC framework, odds are you are using the built in SessionScopeWebModule to manage the SessionScope for you.  The web module begins a session when an HTTP request begins and ends it when the request has been processed.  Internally, the module uses HttpContext.Current.Items to store the current SessionScope in a thread local while the request is being processed.  If you are hosting your WCF services under IIS, you can take advantage of the web module to manage your SessionScope for you. 

If you are hosting not hosting your WCF services under IIS, then you need another mechanism for managing the SessionScope.  Fortunately, WCF provides a hook for just this type of scenario, ICallContextInitializer.  The WCF examples taking about using this extension point for managing thread context culture or impersonation scenarios.  First you need to implement ICallContextInitializer (I have removed documentation and logging for brevity, but I would recommend putting logging statements in so you can see what is going on at runtime):

    public class ARSessionScopeCallContextlInitializer : ICallContextInitializer
    {

        private const string ActiveRecordSessionScopeKey = "wcf.ar.sessionscope";

        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        {
            SessionScope scope = Local.Data[ActiveRecordSessionScopeKey] as SessionScope;
            if (scope == null)
            {
                Logger.Debug("Creating new ActiveRecord SessonScope");
                scope = new SessionScope();
                Local.Data[ActiveRecordSessionScopeKey] = scope;
            }
            return scope;
        }

        public void AfterInvoke(object correlationState)
        {
            SessionScope scope = Local.Data[ActiveRecordSessionScopeKey] as SessionScope;
            if (scope != null)
            {
                scope.Dispose();
            }
        }

    }

 

You can find the Local.Data class in Ayende’s rhino-commons library, but it just a simple wrapper around thread local storage.  Next, you need to implement IEndpointBehavior to add the initializer to your service:

    public class ARSessionScopeBehavior : IEndpointBehavior
    {

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
            {
                 operation.CallContextInitializers.Add(new ARSessionScopeContextCallInitializer());
            }
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

    }

And finally, an example for configuring your service:

            var uri = new Uri("net.tcp://localhost/TestSessionScope");
            var host = new WindsorServiceHost(typeof(AuthorizationService));
            var endpointAddress = new EndpointAddress(uri);
            var endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof (ITestService)), new NetTcpBinding(), endpointAddress);
            endpoint.Behaviors.Add(new ARSessionScopeBehavior());
            _host.Description.Endpoints.Add(endpoint);
            _host.Open();

 

And that’s it.  If you want to be more explcit about your flushing behavior — for instance creating a ReadOnlySessionScope that never flushes for read only operations, you can modify the EndpointBehavior to work declaritively with attributes so that you could mark individual WCF methods with configuration information such as [ReadOnly].  I have read some discussions about poor performance do to flushing of read only operations, so this might be worth looking into if you are doing a lot of read only operations on a large object graph.

links for 2008-02-15

links for 2008-02-13

links for 2008-01-31

links for 2008-01-18