My Daily WTF: Is Timer Broken?

I’ve been working with Task Parallel Library quite extensively lately, and one common thing I need to do is to schedule my tasks with some kind of timing intervals, and System.Threading.Timer is the exact tool for this.

Problem starts when my task randomly just go to a mysteriously halt. The problem with doing asynchronous stuff is the premise of asynchronous itself: when any of your tasks is in a wait state, it will drop its current thread back to the thread pool, and therefore you won’t find anything in the debugger when your tasks do come to a mysterious halt. There’s no facility in the Visual Studio debugger that allows you to possibly find the last call-stacks of your halting tasks.

I spent almost the whole day sprinkling a lot of Trace information all over the code, and I finally managed to narrow down to my little Delay() method that uses System.Threading.Timer. For some reason, my Timer would occassionaly fail to fire back.


new Timer(_=> Trace.WriteLine("fired back"), null, timespan, TimeSpan.FromMilliseconds(-1));

Most of the times, the timer fires back successfully, except in some rare occasions where apparently it never comes back at all. After pulling my hair in frustration until I had little left, I decided to make a desperate stab and change the code to this:


new Timer(_=> Trace.WriteLine("fired back")).Change(timespan, TimeSpan.FromMilliseconds(-1));

I wasn’t expecting anything magical to come out of this, but it did! It fixed the bug. My timer now reliably fires back 100% of the times! I can’t explain why, but I’ll definitely file a bug report to Microsoft and see if they can come up with any logical explanation. I can’t provide a reproduction test for this though, as this bug only happens when I plug a lot of moving parts to the system. Whenever I try to reduce the complexities (to isolate the issue), the bug disappears. It almost seems like a dirty secret that the universe doesn’t want you to see.

Anyway, that has been an utterly frustrating 10 hours, and I’m not sure whether it’s a relief or anger that I’m feeling right now, but at least this pile of coffee mugs will finally clear out.

Advertisements

NHibernate: Linq-ing Calculated Properties

Some properties are mapped onto database columns, while others are calculated. Here’s one simple example:

public class Parcel
{
   public PackagingType PackagingType {get; set;}
   public ParcelType ParcelType  {get; set; }
   public float Weight {get; set;}
   public decimal Fee
   {
      get {return (Weight - PackagingType.TareWeight) * ParcelType.FeePerWeight;
   }
}

“Fee” is a calculated property. You cannot use this property as a part of your Linq query. For instance, if you want to query Parcels with Fees above certain values:

var expensiveParcels = from parcel in Session.Query<Parcel> where parcel.Fee > 1000 select parcel;

Obviously that wouldn’t work because NHibernate does not recognize this “Fee” property.

There are 3 (conventional) ways to resolve this, you can choose either one of these:

  1. Change all your queries to avoid “Fee” property, and repeat the calculation logic (every time) instead.
    var expensiveParcels = from parcel in Session.Query<Parcel>
          where (parcel.Weight - parcel.PackagingType.TareWeight) * parcel.ParcelType.FeePerWeight > 1000
          select parcel;
    
  2. A slightly better way is to map “Fee” property with SQL Formula. It’s better because you do not have to repeat Fee calculation on every Linq query. E.g., in FluentNHibernate:
    Map(x=> x.Fee).Access.Readonly().Formula( // Raw SQL ->
        @"((select Weight - (select TareWeight from PackagingType p where  p.Id = PackagingId))
              * (select FeePerWeight from ParcelType pt where pt.Id = ParcelTypeId))");
    );
    
  3. Alternatively, you could also write an ILinqToHqlGenerator implementation.
    Since version 3.0, NHibernate has been utilizing ReLinq for its Linq-provider, which greatly improves its extensibility. It allows you to register your own ILinqToHqlGenerator, where you basically take a specific Linq expression and return whatever HqlTree expression you desire. For instance, in this example, we build our Hql expression like so:

    public class ParcelFeeLinqGenerator: BaseHqlGeneratorForProperty
    {
       public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
       {
          var parcel = visitor.Visit(expression).AsExpression();
          return treeBuilder.Multiply(
              treeBuilder.Subtract(
                 treeBuilder.Dot(parcel, treeBuilder.Ident("Weight")),
                 treeBuilder.Dot(treeBuilder.Dot(parcel, treeBuilder.Ident("PackagingType")), treeBuilder.Ident("TareWeight"))
              ),
              treeBuilder.Dot(treeBuilder.Dot(parcel, treeBuilder.Ident("ParcelType")), treeBuilder.Ident("FeePerWeight"))
          );
       }
    }
    

    And you register this generator into NHibernate runtime to handle our Fee property:

    registry.RegisterGenerator(ReflectionHelper.GetProperty<Parcel, decimal>(x=> x.Fee), new ParcelFeeLinqGenerator());
    

All those 3 approaches do the job just fine, but whichever one you pick you’ll still end up duplicating your Fee calculation logic one way or another. You’ll either be repeating your logic in C# expressions (option#1), in SQL expression (option #2), or in HQL expression (option #3). That seems to violate DRY. It’s easy to forget to change your querying logic whenever your pricing rule changes (e.g. tax).

Better Way?

The ideal solution is to eliminate logic duplication. We want to be able to write the calculation logic only once to be shared both by the property as well as by Linq queries. I’ll be using approach#3 while employing a pattern to avoid duplicating our logic.

First step, I create this generic ILinqToHqlGenerator plumbing that I can reuse for all calculated properties in my projects.

public class CalculatedPropertyGenerator<T, TResult> : BaseHqlGeneratorForProperty
{
   public static void Register(ILinqToHqlGeneratorsRegistry registry, Expression<Func<T, TResult>> property, Expression<Func<T, TResult>> calculationExp)
   {
      registry.RegisterGenerator(ReflectionHelper.GetProperty(property), new CalculatedPropertyGenerator<T, TResult>{_calculationExp = calculationExp});
   }
   private CalculatedPropertyGenerator(){} // Private constructor

   private readonly Expression<Func<T, TResult>> _calculationExp;
   public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
   {
      return visitor.Visit(_calculationExp);
   }
}

Once we got that plumbing class in place, we’ll then modify my parcel class slightly to look like the following:

public class Parcel
{
   public PackagingType PackagingType {get; set;}
   public ParcelType ParcelType  {get; set; }
   public float Weight {get; set;}

   /// <summary>
   /// To be reused for (NHibernate) Linq generator
   /// </summary>
   public static readonly Expression<Func<Parcel, decimal>> CalculateFeeExpression = x =>
          (x.Weight - x.PackagingType.TareWeight) / x.ParcelType.FeePerWeight;

   private static readonly Func<Parcel, decimal> CalculateFee = CalculateFeeExpression.Compile();
   public decimal Fee
   {
      get {return CalculateFee(this);
   }
}

Now you register this FeeCalculationExpression to NHibernate registry so that NHibernate can now translate Fee property using the same fee-calculation expression used by the Parcel class itself.

CalculatedPropertyGenerator<Parcel, double>.Register(registry, x=> x.Fee, Parcel.CalculateFeeExpression);

Now this Linq query works. NHibernate knows how to handle Fee property in the query.

var expensiveParcels = from parcel in Session.Query<Parcel> where parcel.Fee > 1000 select parcel;

We are reusing the same business-rule for calculating Fee property as well as to generate our NHibernate queries. There’s no duplication, and it requires very little setup as well (once you get the CalculatedPropertyGenerator plumbing class in place). This so far has been my favorite approach to map calculated-properties to NHibernate.