LAgent: an agent framework in F# – Part III – Default error management - Luca Bolognese

LAgent: an agent framework in F# – Part III – Default error management

Luca -

☕ 2 min. read

Download frame­work here.

All posts are here:

Default er­ror man­age­ment

What hap­pens when an er­ror oc­curs? Well, ide­ally you want to no­tify some­one and con­tinue pro­cess­ing mes­sages. By de­fault you want to print the er­ror and as much in­for­ma­tion as you can about it.

Let’s first see what hap­pens if you pass the wrong mes­sage type:

counter1 <-- "fst"

Generates:

**> The ex­cep­tion be­low oc­curred on agent Undefined at state 3 with mes­sage fst”. The agent was started with state 0.

System.InvalidCastException: Specified cast is not valid.

   at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source)

   at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unit­Var)

   at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)**

You get in­for­ma­tion about the cur­rent state of the agent, the mes­sage that gen­er­ated the er­ror, the ini­tial state of the agent and the ex­cep­tion that was gen­er­ated. But, in a sys­tem with sev­eral agents, you’d like to know which one agent failed. Then you need to name your agent:

counter1 <-- SetName("Bob")
counter1 <-- "fadfad"

Now you get (important part in blue):

**> The ex­cep­tion be­low oc­curred on agent Bob at state 3 with mes­sage fadfad”. The agent was started with state 0.

System.InvalidCastException: Specified cast is not valid.

   at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source)

   at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unit­Var)

   at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)**

The im­por­tant thing is that the agent con­tin­ues run­ning. It lives to fight an­other day. Hence:

counter1 <-- 3

Produces:

From 3 to 6

Which shows that the agent is run­ning and that it has kept its cur­rent state. Also er­rors can oc­cur in­side the mes­sage han­dler with a sim­i­lar re­sult:

(spawnAgent (fun msg state -> state / msg) 100) <-- 0

Produces:

**> The ex­cep­tion be­low oc­curred on agent Undefined at state 100 with mes­sage 0. The agent was started with state 100.

System.DivideByZeroException: Attempted to di­vide by zero.

   at FSI_0013.it@48-3.Invoke(Int32 msg, Int32 state)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2)

   at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unit­Var)

   at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)**

But this might not be what you want. You might want to cus­tomize what hap­pens when an er­ror oc­curs. We’ll talk about that next.

1 Comment

Comments

DotNetShoutout

2009-06-15T09:45:47Z

Thank you for submitting this cool story - Trackback from DotNetShoutout

0 Webmentions

These are webmentions via the IndieWeb and webmention.io.