CCR tips and tricks - part 11

A very common pattern in CCR is the use of a result port. That means that you have a port you give (or get from) a method you want to call and that method will post a result on the result port. However sometimes a bug leads to a situation where no result is ever posted back. This can be very hard to detect of ju just use a standard result/exception portset. If you're in the DSS environment you know that each operation typically has a timeout that is handled by DSS but in CCR you need to deal with this yourself. I've previously mentioned that a SmartPort could be used. But this is what it would look like with a timeout:

   1: private void DoSomething(SuccessFailurePort resultPort)
  2: {
  3:     // never posts a response.
  4: }
  5:  
  6: private void CallingSomething(TimeSpan timeout)
  7: {
  8:     var mre = new ManualResetEvent(false);
  9:     Exception error = null;
 10:     var resultPort = new SuccessFailurePort();
 11:     var timeoutPort = new Port<DateTime>();
 12:     Arbiter.Activate(
 13:         dispatcherQueue,
 14:         Arbiter.Choice(
 15:             Arbiter.Receive<SuccessResult>(false, resultPort, s => mre.Set()),
 16:             Arbiter.Receive<Exception>(
 17:                 false,
 18:                 resultPort,
 19:                 e =>
 20:                     {
 21:                         error = e;
 22:                         mre.Set();
 23:                     }),
 24:             Arbiter.Receive(
 25:                 false,
 26:                 timeoutPort,
 27:                 e =>
 28:                     {
 29:                         error = new Exception("Timeout when waiting for DoSomething");
 30:                         mre.Set();
 31:                     })));
 32:     Arbiter.Activate(
 33:         dispatcherQueue, 
 34:         Arbiter.FromHandler(() => this.DoSomething(resultPort)));
 35:     dispatcherQueue.EnqueueTimer(timeout, timeoutPort);
 36:     mre.WaitOne();
 37:     if (error != null)
 38:     {
 39:         throw error;
 40:     }
 41: }
 42:  
 43: [TestMethod]
 44: public void UsingTimeoutToDetectWhenSomethingIsNotPostingBack()
 45: {
 46:     try
 47:     {
 48:         this.CallingSomething(TimeSpan.FromSeconds(1));
 49:         Assert.Fail("Expected exception to be thrown");
 50:     }
 51:     catch (Exception e)
 52:     {
 53:         Assert.IsTrue(e.Message.Contains("Timeout"));
 54:     }
 55: }

The lines to pay most attention to are lines 14 through 31.