This document discusses building concurrent programs using agents. It introduces agents and describes how they exchange messages and react in a reactive way. Inside an agent's brain, the document explains how agents can have a single state or multiple states implemented as a state machine. Agents communicate through messages and events to decouple them. Reusable agents like a bulking agent and blocking queue agent are presented. The document concludes with discussing how to organize large networks of agents using patterns like worker agents, layered networks, and pipeline processing.
6. Agent-based concurrency
Programs compose from agents
Instead of functions or objects
Agents exchange messages
Receive message and react
Reactive system
Handle inputs while running
Emit results while running
8. Functional loop with single state
Single state
Same reaction to all messages
Implemented using recursive loop
What if reaction depends on the state?
What if agent cannot handle some message?
Immutable state
Maintained as parameter of recursive function
Can use mutable collections for performance
9. Hiding agent’s brain
Accessing agent directly
Exposes implementation details
Users can call wrong methods (e.g. Receive)
Encapsulating agent
Agent as a private filed
Add methods for all (public) messages
Expose asynchronous calls first
13. Inside agent’s brain
Single state
Accept and react
to all messages
Example: Twitter status agent with pause
Resume
Pause
d
Running
Resume Status
Pause
Multiple states
Agent implements a
state machine
15. State and state transitions
Accepting all messages
Asynchronously Receive and use pattern matching
Waiting for specific message
Other messages stay in the queue
Writing message handling using Scan
let rec state = agent.Scan(function
| Message -> Some <| async {
handleMessage()
return! newState }
| _ -> None )
17. Inter-agent communication
Direct links between agents
Complicates reusability and reconfiguration
Decoupling using events
Expose event instead of sending message
We used events in the previous example!
18. Types of agent’s members
Send message to the agent
Members of type: 'T -> unit
Notifications from the agent
Exposed as events or observables: IObservable<'T>
No synchronization and no thread guarantees
Send and wait for a reply
Uses asynchronous reply channels from F# library
Takes arguments and returns result: 'T -> Async<'R>
19. Connecting agents
Sending message in response to notification
Alternatively, Observable.subscribe supports removal
Connecting agents with asynchronous actions
Create and start asynchronous workflow
source.Notification |> Observable.add target.Action
async { while true do
let! value = source.AsyncAction()
do! target.Action(value) }
|> Async.Start
21. Reusable agents I.
Aggregating messages into bulks
Bulk specified number of messages
Emit bulk after timeout
Uses of bulking agent
Grouping data for further processing
Writing live data to a database
new BulkingAgent : int -> int -> BulkingAgent
member Enqueue : 'T -> unit
member BulkProduced : Event<'T[]>
23. Reusable agents II.
Blocking queue with limited size
Block reader when queue is empty
Block adder when queue is full
Uses of blocking queue agent
The producer consumer pattern
Immediate buffer in pipeline processing
new BlockingQueueAgent : int -> BlockingQueueAgent
member AsyncGet : unit -> Async<'T>
member AsyncAdd : 'T -> Async<unit>
25. Managing intelligence network
Lots of things going on!
How to keep a big picture?
Using loosely coupled connections
Agents don’t reference each other directly
Common ways of organizing agents
Worker agent – Single agent does all the work
Layered network – Agent uses agents from lower level
Pipeline processing – Step-by-step processing
26. Pipeline processing
Values processed in multiple steps
Worker takes value, processes it, and sends it
Worker is blocked when source is empty
Worker is blocked when target is full
Steps of the pipeline run in parallel
28. Summary
Why use agent-based concurrency?
Easy to understand reactive applications
Elegant implementation of concurrent patterns
How to write an agent-based application?
State machine using recursive functions
Encapsulate and provide communication points
(send and send & reply methods and notifications)
Use reusable agents for recurring patterns