Download framework here.
All posts are here:
- Part I – Workers and ParallelWorkers
- Part II – Agents and control messages
- Part III – Default error management
- Part IV – Custom error management
- Part V – Timeout management
- Part VI – Hot swapping of code
- Part VII – An auction framework
- Part VIII – Implementing MapReduce (user model)
- Part IX – Counting words …
Agents are entities that process messages and keep state between one message and the next. As such they need to be initialized with a lambda that takes a message and a state and returns a new state. In F# pseudo code: msg –> state –> newState. For example the following:
let counter = spawnAgent (fun msg state -> state + msg) 0
This is a counter that starts from 0 and gets incremented by the value of the received message. Let’s make it print something when it receives a message:
let counter1 = spawnAgent
(fun msg state -> printfn "From %i to %i" state (state + msg); state + msg) 0 counter1 <-- 3 counter1 <-- 4
From 0 to 3
From 3 to 7
There is no spawnParallelAgent, because I couldn’t figure out its usage patterns. Maybe I don’t have enough creativity. Obviously msg and state could be of whatever type (in real application they end up being tuples more often than not).
You can do things to agents. I’m always adding to them but at this stage they are:
type Command = | Restart | Stop | SetManager of AsyncAgent | SetName of string
Plus some others. I’ll describe most of them later on, right now I want to talk about Restart and Stop. You use the former like this:
counter1 <-- Restart counter1 <-- 3
From 0 to 3
This should be somehow surprising to you. You would have thought that you could just post integers to a counter. This is not the case. You can post whatever object. This is useful because it allows to have a common model for passing all sort of messages, it allows for the agent not to be parameterized by the type of the message (and of state) so that you can store them in data structures and allows advanced scenarios (i.e. hot swapping of code).
This is a debatable decision. I tried to get the best of strongly typing and dynamic typing, while keeping simplicity of usage. The implementation of this is kind of a mess though. We’ll get there.
BTW: you use Stop just by posting Stop, which stops the agent (forever).