computational entity • Completely isolated from other actors ◦ No shared memory or state • Draws messages from a Mailbox • Possible reactions to a message ◦ Sends messages to other actors (asynchronously!) ◦ Creates new actors ◦ Change its behavior for future messages
• Follows the “Actor model” ◦ Communicates via messages • Can hold state (and share nothing) • Can fail in isolation Process 1 Process 2 send pid_p2, “Hello” Mailbox ... receive do msg -> IO.puts msg end
• Links are bidirectional • Monitors are unidirectional Process 1 Process 2 spawn_link(Module, :fun, []) ... Crash exit signal • Processes may be linked
if they fail • Allows for “let it crash”-philosophy ◦ Explicit definition of what happens in case of failure ◦ Mix applications can have a central application supervisor mix new --sup <name>
provides a GenServer-ish interface • Provides: ◦ Sending messages to users / channels ◦ Invoking functions on events that we care about • Let’s check out some code!
OTP behavior that makes it easy to define servers ◦ Not as in web server, but in “long running, serving requests” • Abstracts away all the hard stuff about servers ◦ State ◦ Messaging (synchronous = “call” / asynchronous = “cast”) ◦ Tracing / error handling / supervision
Standup Session for Anna Standup Session for Will Cron library Hey, 9 o’clock! Time to start a Standup for Will! Starting standup sessions - StandupSession.Supervisor
that gets started by Supervisor ◦ triggered by Cron library (or manually) • Keeps track of already given answers • Reacts to new messages / message changes • Triggers status report as soon as it runs out of questions to ask • CODE?
of scheduled standups • Writes a binary file to disk / reads it on startup ◦ for persistence across application restarts! • Registers jobs in Cron library (called Quantum)
test that our bot sends DMs correctly? • Neither do we want to connect to real Slack on test runs • We swap out “adapters” through configuration ◦ Behaviours can ensure a common interface! • And write a fake adapter that we can assert on
web applications • Ideally, your interface (Slack, HTTP API, Command line?) is a thin layer • Gives you clearer testing boundaries • Maybe even portability to another platform?
is a pain to test • Especially on multi-step test cases • Separating application logic from the state-bearing GenServer ◦ Allows you to have more reliable tests! • If your GenServer is only a thin layer of storage, no significance lost!