@nleach

month

November 2012

1 post

Improvising

You know the feeling you get when you touch down in Mumbai and you realize you left your AeroPress filters safely tucked away in your kitchen 7797 miles away? Ugh.

My solution: empty tea bags.

A few notes about this particular MacGyver setup:

  • Rinse the bags thoroughly
  • I double-up with paper from two bags of tea
  • The extra paper can be unwieldy when screwing the screen on to the Aeropress (cut to-size if possible)
  • These particular tea bags are surprisingly water-impermeable. This is fine for the Aeropress because you have pressure from the plunger, but I don’t think this approach would work well for, say, pour-over

Us coffee nerds are obsessed with all the little details of the kit. Grinder, brewer, kettle, timer, thermometer, etc. But despite all the pomp and circumstance we include around our sacred ritual, coffee itself is a fairly simple. Fresh coffee + hot water + attention = delicious.

Nov 04, 20120 notes
#coffee

October 2012

1 post

De-sharding Redis

Pre-sharding is a common technique for preemptively managing the growth of your Redis infrastructure. At StepOut we’ve been running on a cluster of 64 pre-sharded Redis nodes for quite a while without any real pain to speak of. That said, in an effort to trim some of the fat from our systems resource allocation I started looking at some alternatives to our current setup. What I arrived at was a fairly different topology than we started with, consisting of only 8 shards on a single host box (replicated for performance and durability).

* Based on Rackspace cloud pricing

The only (significant) downside to the proposed configuration is that we would need to re-shard our data. Ugh. I considered upgrading to the Redis 2.6RC early in order to take advantage of the new dump and restore commands, but it seemed like too big of a gamble to introduce both pre-release software and a major infrastructural change. Luckily, the final solution was actually much more simple.

Thanks to the structure of the Redis AOF, you can concatenate individual backups into a single file.

It’s also pretty handy to run the redis-check-aof tool to verify that the process was completed correctly.

Then in the application, we just had to make a slight change to our key hashing function:

Becomes:

The approach requires some downtime, but it ended up being fairly minimal, especially when considering some of the alternative solutions. Anecdotally, I’ve also noticed some performance improvements dealing with fewer instances, although it’s still a little early to call that conclusively.

Discussion on Hacker News.

Oct 02, 20122 notes
#Redis #code #sysadmin

September 2012

1 post

Redis Mutex in PHP

When you think about PHP, “concurrency” probably isn’t among the first things that come to mind. Fortunately (unfortunately?) we live in a world where distributed applications are the de-facto standard which means that not even humble, single-threaded PHP is immune to the woes of concurrent programming. Standing on the shoulders of giants, and inspired by the work of many before me, I’ve built a very simple redis-backed mutex:

Suppose in your application that you are interacting with an API that doesn’t allow partial updates. You would use the mutex as follows:

This implementation is far from unique, but it is very functional and hopefully simple enough to be dropped-in to most projects with only minor customizations.

Discussion on hacker news.

Sep 10, 20120 notes
#code #php #Redis

February 2012

2 posts

Don't Commit Syntax Errors

Add this as an alias in your .gitconfig file:

Now, before you commit a batch of changes, you can run git syntax-check. Simple!

For a few other git niceties, take a look at my full .gitconfig

Feb 24, 20120 notes
#git #php #code
On Browser Support

No one likes it, and we all look for ways to get out of it. At StepOut the dev team has been fighting the good fight to try to deprecate support for IE6 and IE7. Unfortunately, it’s a tough business sell. No one wants to hear that they’re going to lose n% of their visits, regardless of what n happens to be.

Admittedly we should have thought to look at this sooner, but instead of simply comparing visits and pageviews, we started to dive into site usage metrics across our major browsers. The data was striking:

Full-sized image

When you see the absolute numbers (redacted), it’s really quite astounding. The relative measures still tell the story though. Essentially, on our site, IE6 and IE7 users are 80% less engaged. Now that is data you can pitch.

Feb 14, 20120 notes
#analytics #web

January 2012

2 posts

Odometer-style Counter using jQuery

A couple months back I had to implement an odometer-style counter for the new StepOut landing page. I found a few implementations here and there, but I didn’t really like any of them so I decided to roll my own. It’s not the most elegant code I’ve ever written, but it seems to work fairly well and is nice and succinct.

So how does it work?

Each digit in the counter is represented with the following HTML:

<span class="digit">
    <span title="3">3</span>
    <hr />
</span>

We store the value of each digit and replace the value of the inner span with a list of numbers 0-9 (well, really 1-9, padded with 0s). We then change the position of that span so that the original number is visible. During each ‘tick’, we animate the top property of the span so that the next digit becomes visible, and wrap around once we hit 0.

The process ended up being fairly straightforward, so I hope the code will be at least somewhat legible.

I haven’t done much to generalize the code, so a bit of coaxing might be required to get it to work in your environment. I do have a working jsFiddle set up though. That said, all of this is provided without warranty. I mostly hope that this can serve as an interesting reference or starting point for someone else in the future.

HTML

JS

CSS

Result

Jan 17, 201212 notes
#code
2011 in Coffee

One Year of Coffee

That’s 49 bags (probably around 30 pounds) of glorious, caffeinating goodness. Over the past year I tried to catalogue all of the coffee I brewed, and while I probably missed a few bags here and there, this is a pretty representative sample of what kept me percolating in 2011.

It was a great year for tasting and learning. Local spots like Porto Rico Importing Co. and subscription services like Craft Coffee and Tonx provided the opportunity to try different coffees from all over the world. I started the year dead set on dark roasts, but as my brew technique improved I started to appreciate the complexity across the gamut. For months, every new coffee I tried I’d declare the best in the world.

Coffee of the Year

Looking back over the year, was there a single stand out? You bet!

Tonx Coffee - El Salvador Finca Montery Bambu

I’d like to say this was a difficult decision, and while more than a few exceptional coffees hit my cup, none came close to the El Salvador Finca Montery Bambu from Tonx. The Coffee Adventures review of this coffee pretty much sums it up for me:

I enjoyed this coffee more than I can put words together to describe this feeling.

The aroma alone convinced fellow developer Bob Patterson to give coffee a second chance. To paraphrase his reaction, “I had no idea coffee had actual flavor”.

I thought I’d have this whole coffee thing figured out in no time, but, just like so many great pursuits, the deeper you go, the more you realize you still have to learn. It’s been a lot of fun experimenting, learning, sharing and of course, enjoying a year full of coffee.

Jan 07, 20128 notes
#coffee

June 2011

1 post

My Perfect Cup
The Beans

I was lucky enough to get in on one of Tonx Coffee’s first roasts, and let me tell you, it’s some seriously good stuff. These beans came from Finca Matalapa in El Salvador.

Co-founder Nik Bauman told me that this particular roast came out a little darker than they would have liked. You can see that the beans are a really nice, chocholatey brown color. Despite being a little on the dark side, I still think this roast makes a phenomenal cup.

The Grind

Earlier this year I picked up a Hario Slim Mill and it’s definitely the MVP of my coffee setup. It produces an excellent, consistent grind, and I’ve come to really enjoy hand grinding (although it does get tiring if you have to do more than one cup at a time). I also have an electric burr grinder when I’m brewing several cups at once, but it really doesn’t come close to the quality of the Hario.

The Brew

I’ve been using a Clever Coffee Dripper which really nicely marries the full-immersion brewing of a press pot, with the crisp, clean cup of a pour over. The cleanup is also much easier than with the press pot, which is a huge win in my book.

I’ve tried a few different techniques with the Clever Coffee Dripper, all with pretty good results. The one I’ve settled on is fairly simple:

  1. Pre-soak your filter and pre-heat your cup
  2. Using 200° F water, completely soak your grinds
  3. Let stand for 2:30, gently stir, and drain

The entire brew process takes around five minutes, and is (in my opinion) the best combination of simplicity and predicable results.

The Cup

Is all this work worth it? You bet it is! Proof below:

Jun 19, 20112 notes
#coffee #coffee #coffee

May 2011

2 posts

The Tyler Hayes: The Case for A Towing Company API → thetylerhayes.com

thetylerhayes:

I get really excited when I hear business ideas that don’t rely on the “we’ll get a lot of users and then make money” approach. It’s not that it can’t work so much as it can not work.

tl;dr: Reduce overhead for towing companies (they don’t have to send out their trucks). Increase revenue for towing companies by increasing total fees paid, via basic turn-around time psychology like is used in mail-in rebates. Reduce stress and average fees paid-per-person.

Not sure if the economics are actually right, but this totally nails the conceptual model for entrepreneurship. It’s an industry where there is significant pain (bonus points for the pain exiting for both the consumer and provider) and there is a very obvious, very direct way in which to make money.

I dig it.

May 19, 20117 notes
#entrepreneurship
The Truth about Clones
  • locks: well, code a clone of yourself
  • Judofyr: but if he's *just* like me…
  • Judofyr: … he won't do shit either
  • Judofyr: he'll just code *another* clone
May 07, 20115 notes

April 2011

4 posts

“The K-cup was designed to save incompetent adults the trouble of wiping up coffee grounds from their counter top in the morning. I find it disturbing that such a “green company” can even justify the continued production of such an irresponsible and unnecessary product.” —

Love Keurig? Nope.

I’m not sure how I feel about the phrase “incompetent adults”, but the article does make some great points around the unsustainable actions of the commercial coffee industry

Apr 24, 201117 notes
#coffee #sustainability
Hashify Is Neato → bit.ly

thetylerhayes:

Entire documents contained within shortened URLs. Talk about utter utility (in a good way).

Apr 19, 20116 notes
Magic Memcached

I had a pretty standard pattern for memcaching expensive method calls:

$key = "MyKey";
if(!$data = MC::get($key)){
    $data = some_expensive_function();
    MC::set($key, $data);
}

do_stuff($data);

But I guess I copied and pasted that pattern one too many times, and decided that there really has to be a better way. Thanks to the overloading methods in PHP 5 and late static bindings in PHP 5.3.0, there is!

Let’s take a look at the code:

This class uses PHP’s __call and __callStatic magic methods to intercept any method call which does not result in a method actually being executed. We then look for two prefixes, mc_ or mcd_ to determine if the method call was intended to be processed through our cache wrapper. If we find one of those prefixes, we rewrite the method name and attempt to call the new method and cache the result.

Pretty simple concept, and super easy to use. To use this on a pre-existing class, just extend the Memcacheable class and you’re good-to-go. Here’s a fairly contrived example of a class that is now magically memcached:

And an example of how you would actually interact with the caching mechanisms:

As always, I have a few notes:

  • mc_ will cache the code, mcd_ will delete the code from the cache
  • __callStatic and get_called_class() require PHP 5.3.0 or greater, if you don’t care about caching calls to static methods you can remove the __callStatic block from Memcacheable.php and it should all work in PHP 5.0 or greater
  • I’m referencing an imaginary Memcached wrapper class called MC, you’ll need to replace these calls with calls to your own cache wrapper. I’ve provided a terribly simplistic implementation in the gist so that the code can all be run together
  • One of the downsides of the approach is that __call prevents errors about calls to undefined methods from being thrown. It’s fine because we can throw our own error, but it feels fairly sloppy

Discussion on Hacker News

Apr 16, 201110 notes
#php #code #memcached
Activity Feed in Redis (using PHP)

Recently there was an article floating around Hacker News about using Redis to store an activity feed. I recently implemented something pretty similar in PHP for SpotOn in PHP, which I thought I’d share.

First off, why Redis? It’s fast, our data model allows us to store minimal data in each feed entry, and Redis’ data-types are pretty well suited for an activity feed. Lists might seem like an obvious choice and could work for a basic feed implementation, but we ended up using sorted sets for two reasons:

  1. If you use a timestamp as the score parameter, you can really easily query for feed items based on time
  2. You can easily get the union of multiple sorted sets in order to generate an aggregated “friend feed”

Alright, gimme the code:

And an example of how the feed might be used:

The code should be fairly straightforward, but there are a few points worth mentioning:

  • I’m using the iRedis library which acts as a very thin wrapper to the redis protocol. It’s very lightweight but doesn’t handle much for you which is why we have to reformat the data returned by redis in the _activity method
  • I’m using zrevrangebyscore to pull back the items from the set. This, along with using time as our score will return feed items in reverse chronological order. If for some reason you wanted to interact with the feed in chronological order, all you would have to do is call zrangebyscore instead
  • This code requires Redis version 2.1.6 or greater because of zrevrangebyscore. You can achieve the same end result with an earlier version of Redis by using zrangebyscore and reversing the output using array_reverse

Also, while this technique is fast and simple, it isn’t without its downsides:

  • Sorted sets in Redis are very memory inefficient (relative to the other data-types). I know that the Redis team is working to improve this, but it should be approached carefully - you don’t want your Redis server blowing up on you in production
  • In this example I’m just storing and returning strings for the activity data. You’d probably want to store richer data which should be serialized in some way or another, keeping in mind that you really want to keep your memory footprint as low as possible
  • You could probably optimize the usersActivity method such that multiple successive calls pull back from the $usersKey that is created instead of repopulating it. Perhaps you set an expire time on the key when you first create it and only re-generate it when it doesn’t exist, or maybe that key is primed asynchronously on some regular interval

Feel free to use, modify, or scoff at the code in any way you see fit!

Apr 03, 20118 notes
#php #redis #code

March 2011

1 post

git sync

Here’s a handy git alias I’ve been using like crazy recently:

It’s a really simply shorthand way of pulling then pushing the current branch from/to a remote repo. If there’s a merge error on the pull, it won’t continue with the push.

I’ve added it to my global .gitconfig file (~/.gitconfig), and I’ve saved about a bazillion keystrokes saving myself from typing git push … git pull; git push many, many times a day.

Mar 09, 20110 notes
#git #programming

February 2011

1 post

Apple's Three Laws of Developers

yourhead:

  1. A developer may not injure Apple or, through inaction, allow Apple to come to harm.
  2. A developer must obey any orders given to it by Apple, except where such orders would conflict with the First Law.
  3. A developer must protect its own existence as long as such protection does not conflict with the First or Second Law.

— I. Developer

Feb 16, 20111,084 notes

January 2011

1 post

Tracking Remote Branches

Git allows you to associate local branches to remote branches (this is called tracking), and tracking a branch which already exists in the remote repository is super easy:

git branch --track branch_name repo/branch_name

But what do you do if you created the branch locally, then pushed to the remote repo?

git branch -f branch_name repo/branch_name

Note: You can’t execute that command while you’re currently in the branch you want to track. IE - git checkout to another branch first.

“Why?” you might ask. If you have branch tracking set up, you can leave off the last two arguments from git push and git pull:

git push repo branch_name

becomes

git push

Nice, eh?

Jan 21, 20110 notes
#git #code #tips #remember

December 2010

3 posts

Truncate Multiple Files

There’s a good chance there’s a more correct way of doing this, but I just stumbled upon a pretty easy way to truncate multiple files at once:

The tee command is actually really pretty handy. man tee to see for yourself!

Dec 28, 20100 notes
#linux
Timestampin'

Unix timestamp converters - every developer has one. For the longest time I’ve used unixtimestamp.com and even played around with Epoch Converter but loading a website just to turn some numbers into other numbers felt pretty cumbersome (okay, sometimes there are letters involved, but still!). My solution: two JavaScript bookmarklets that live in my bookmark bar.

To unixtime:

From unixtime:

Dec 11, 20100 notes
#code
Fun with Yelp

I’ve been playing around with some data scraping, and Yelp has been my first test subject. Their DOM makes light (read: uninteresting) work of extracting most data. I did stumble across something pretty useful this evening though.

On every venue page, Yelp adds a property called json_biz to thewindow object. You can access it through your favorite JS console, which is handy if you’re trying to manipulate data through your browser, the real win here is that the JSON representation of this object is inlined in a <script> tag near the bottom of the page.

One of the major caveats (or advantages) to accessing this data over the data presented in the DOM is the categories are referenced by ID, not by name. With a little searching through Yelp’s JavaScript I was able to find a JSON representation of their category structure, which relates these IDs to their corresponding names. I also (sloppily) wrote a function to parse this structure and return a name for a given ID.

Obviously, YMMV with this technique, and please respect Yelp’s data, along with everyone else’s for that matter.

Dec 09, 20101 note
#data scraping #code
Next page →
2011 2012
  • January 2
  • February 2
  • March
  • April
  • May
  • June
  • July
  • August
  • September 1
  • October 1
  • November 1
  • December
2010 2011 2012
  • January 1
  • February 1
  • March 1
  • April 4
  • May 2
  • June 1
  • July
  • August
  • September
  • October
  • November
  • December
2010 2011
  • January 3
  • February
  • March 1
  • April 2
  • May
  • June
  • July
  • August 1
  • September 3
  • October 1
  • November 6
  • December 3