Tuesday, September 16, 2014

Fresh Coffee at Mailchimp

Ben: Here’s a guest post from Steven Sloan, a developer at MailChimp.

IMG_4456

Grounds for innovation

Here at MailChimp, we’re always trying to listen hard and change fast. Turns out, this requires a good bit of coffee. Each department has its own take on how to keep the stuff flowing, mostly with the standard Bunn-O-Matic commercial machines. A few folks regularly avail themselves of our espresso setup. The developers fill two airpots—one with regular, the other double strength.

And then there’s the marketing team and our precious Chemex.

We make a pour-over pot once every hour or so, all day long, 5 days a week, 50-something weeks a year. Last December, when we were gathering data for our annual report, we got curious about how many Fresh Pots that might amount to. We tried to count it up, but begrudgingly had to accept the fact we didn’t have a good measure beyond pounds consumed. We even tried to keep track with a bean counter, but that didn’t last long.

For a while, the exact nature of our coffee consumption seemed like it would remain just another mystery of the universe. But then one day, talking to Mark while waiting on yet another Fresh Pot, I said, “Hey, I bet we could track the temperature with a Raspberry Pi and post to the group chat when there’s a fresh one.”

I wasn’t too serious, but Mark’s response was one often heard around MailChimp when ridiculous projects are proposed: “Sounds great, just let me know what you need to get it done.”

A few days later, I had a materials list drawn up from Adafruit’s thermometer tutorial, and we were off to the races.

IMG_4442

A fresh Pi

With a Raspberry Pi in hand, the first thing I did was add a script to the boot process that sent an email using Mandrill with its IP so I could find it on our network without trouble.

Then, I had to tackle the problem of detecting pot states with only a single datapoint: current temperature. I hoped that comparing the running averages of different time spans would be enough to determine the pot’s status. (The average Chemex temperature over the course of a few minutes, for instance, would tell us something different than the average temperate over the course of an hour.)

Since this was a greenfield project, I wanted to work with an unfamiliar language. I felt like the more functional nature of Clojure would be a great fit for passing along a single piece of state. This turned out to be a great decision, and I’ll explain why in a minute.

Graph it home

I hacked together a quick program that would spit out the current temperature, minute’s running average, hour’s running average, and the running average’s rate of change to a log file so I could analyze them.

...  {"current":32.062, "minute":24.8747, "hour":23.5391, "running-rate":0.039508}  {"current":32.437, "minute":25.0008, "hour":23.5635, "running-rate":0.0423943}  {"current":32.875, "minute":25.1322, "hour":23.5897, "running-rate":0.045361}  {"current":33.625, "minute":25.2738, "hour":23.6177, "running-rate":0.048569}  {"current":33.625, "minute":25.413, "hour":23.6476, "running-rate":0.05159}  {"current":33.625, "minute":25.55, "hour":23.6793, "running-rate":0.054437}  ...  

Log files in hand, I temporarily turned back to Ruby using the wonderful Gruff charting library to visualize things and make patterns easier to spot.

A few batches of hot water gave me a decent idea what things should look like, so I moved our coffee equipment to my desk to get some live data. This let me check in with the actual running state of the program and compare it with the status of the pot (and led to some coworker laughs and a wonderful smell at my workspace all day).

07-c

A brewing or fresh pot is easy to recognize, but figuring out when the pot is empty turned out to be a little tricky. It takes a while for the Chemex to completely cool off, which means it could be empty and still warm, which I’m sure would lead to more than a few disappointing trips to the kitchen. Luckily, the rate a pot cools tells us if it is empty or not—for instance, a half-full pot stays warm longer than an empty one simply because of the coffee still in it. Always nice to have physics on your side.

Watchers for the win

Armed with the collection of datapoints (running averages, rate of change, etc.) for each of the pot’s states, I moved on to figuring out how to notify our department’s group chat room when a pot was brewing, ready, empty, or stale. This is where some of the built-in features of Clojure came in handy.

I already had a program that logged the current state of itself every second. By switching the actual state to an agent, I could apply watchers to it. These watchers get called whenever the agent changes, which is perfect for analyzing changes in state.

Another agent added was the pot itself. The watcher for the temperature would look for the above mentioned boundaries, and update the pot’s state, leaving another watcher to track the pot and notify our chat room. When it came time to pick an alias to deliver the notifications, Dave Grohl was the natural choice.

Here’s a simple example of the pot watcher looking for a brewing pot:

(def pot-status    (agent {:status "empty"}))    (defn pot-watcher [watcher status old_status new_status]    (if (= (:status new_status) "brewing")      (notify/is_brewing)))    (add-watch pot-status :pot-watcher pot-watcher)  

The great thing is the watcher only gets called when the status changes, not on each tick of the temperature. Using agents felt great to me in this case as they provided a clean way to watch state (without callbacks or a ton of boilerplate) and maintain separation of concern between different parts of the program.

hipchat1

Freshness into the future

I’m still working out a few kinks, tuning in the bounds, and keeping a log of pots. It’s been a fun experience and I learned a ton. Something tells me this won’t be the last time we work with Raspberry Pi on a project. What’s next, Fresh Pots in space? Luckily, we’ve got plenty of coffee to propel us.

tumblr_n9kwt5IBUt1ri8rtfo1_1280

Ben: Thanks to Steven and MailChimp for permission to use the post – we’re very pleased to see the Pi used as the tool of choice of coffee-hungry developers around the world! Coffee is important to us here at Pi Towers…

Trojan Room Coffee Pot

Blast from the past – remember this coffee pot? Click to read more

MailChimp is what I use to power Pi Weekly – my weekly Raspberry Pi news & projects email newsletter – check it out at piweekly.net!

No comments:

Post a Comment