<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bill Shupp</title>
	<atom:link href="http://blog.shupp.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.shupp.org</link>
	<description>Software engineer, musician, space enthusiast</description>
	<lastBuildDate>Tue, 15 May 2012 22:47:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>2011 Year in Review</title>
		<link>http://blog.shupp.org/2012/01/01/2011-year-in-review/</link>
		<comments>http://blog.shupp.org/2012/01/01/2011-year-in-review/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 01:50:48 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Kestrel]]></category>
		<category><![CDATA[Space]]></category>
		<category><![CDATA[Travel]]></category>
		<category><![CDATA[Year In Review]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=9502</guid>
		<description><![CDATA[Welcome to my third annual Year in Review!  2011 was the year of NASA Tweetups for me, attending 4 in total (plus a JPL open house), including the launch of the Juno mission to Jupiter.  It was also a year of some firsts including buying an electric car and a hot air balloon ride. January I started [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton9502" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2012%2F01%2F01%2F2011-year-in-review%2F&amp;text=2011%20Year%20in%20Review&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2012%2F01%2F01%2F2011-year-in-review%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>Welcome to my third annual Year in Review!  2011 was the year of NASA Tweetups for me, attending 4 in total (plus a JPL open house), including the launch of the <a title="NASA Juno Mission" href="http://www.nasa.gov/mission_pages/juno/main/index.html">Juno</a> mission to Jupiter.  It was also a year of some firsts including buying an electric car and a hot air balloon ride.<span id="more-9502"></span></p>
<div id="attachment_9525" class="wp-caption alignright" style="width: 234px"><a href="http://blog.shupp.org/wp-content/uploads/2012/01/photo.jpg"><img class="size-medium wp-image-9525" title="Juno Mission ready for launch!" src="http://blog.shupp.org/wp-content/uploads/2012/01/photo-224x300.jpg" alt="Juno Mission ready for launch!" width="224" height="300" /></a><p class="wp-caption-text">Juno Mission ready for launch!</p></div>
<ul>
<li>January</li>
<ul>
<li>I started out the year continuing to work as lead developer for <a href="http://www.empowercampaigns.com">Empower Campaigns</a>.</li>
</ul>
<li>February</li>
<ul>
<li>I was fortunate enough to attend the NASA Ames Tweetup on "Planet Hunting".  There I heard from a number of great speakers, but the standout one to me was the Kepler Mission's co-investigator <a title="Natalie Batalha" href="http://www.nasa.gov/centers/ames/research/2009/batalha.html">Natalie Batalha</a>.  Not only is Kepler a fascinating mission (that ended up having a <a title="First Earth Like Planet" href="http://www.nasa.gov/mission_pages/kepler/news/kepscicon-briefing.html">stellar</a> <a title="Two Earth Sized Planets Article" href="http://www.nytimes.com/2011/12/21/science/space/nasas-kepler-spacecraft-discovers-2-earth-size-planets.html">year</a>), but Batalha is a remarkably passionate and inspiring speaker.  The event also included a tour of the research center, which was fascinating.</li>
<li>I also wrote about <a title="PHP Step Debugging in VIM" href="http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/">PHP step debugging in VIM</a>.</li>
</ul>
<li>March</li>
<ul>
<li>I wrote about organizing <a title="Organizing PHP Batch Jobs" href="http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/">PHP batch jobs</a> and also <a title="Serving Static Content Efficiently" href="http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/">serving static content efficiently</a> from an application.</li>
<li>March also included my attendance of the <a title="Sun Earth Day Tweetup" href="http://sunearthday.nasa.gov/2011/about/tweetup.php">NASA Sun Earth Day Tweetup</a> at Goddard Space Flight Center.  It was a blast to tour Goddard!  Since the event was in the the DC area, I was able to visit family and attend my youngest niece's second birthday party.</li>
<li>The month wrapped up with a trip to New Orleans for the state-side wedding reception of my sister in law, who was married in New Zealand the previous November.</li>
</ul>
<li>April</li>
<ul>
<li>On Easter I made <a title="Joe Elliot Soundboard" href="http://rockofages.shupp.org/">this</a>.  You're welcome.</li>
</ul>
<li>May</li>
<ul>
<li>In early May I decided to take the plunge in electric cars and <a title="Reserved a Leaf tweet" href="https://twitter.com/#!/shupp/status/66551690597376000">reserved a Nissan Leaf</a>.  The wait was expected to be 4 months.</li>
<li>Though it wasn't a NASA Tweetup, I did make it down to JPL's annual open house in mid May, which was a bit crowded, but still spectacular.  I got to see the <a title="Curiosity in the Clean Room" href="https://twitter.com/#!/shupp/status/69817710351101952">Mars rover Curiosity in a clean room</a> before its <a title="MSL" href="http://www.nasa.gov/mission_pages/msl/multimedia/msl20111126b.html">launch</a> the following November.  I also got to walk through the <a title="Space Flight Operations Center at JPL" href="https://twitter.com/#!/shupp/status/69842757291749376">Space Flight Operations Center</a>.</li>
<li>I wrote about working with <a title="Getting Started with Kestrel from a PHP application" href="http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/">Kestrel from a PHP application</a> since there didn't seem to be any other documentation on the topic.</li>
<li>We also ran into some further plumbing issues at home that month, but decided to <a title="Our First Foray into do-it-yourself Plumbing Repairs" href="http://blog.shupp.org/2011/05/30/our-first-foray-into-do-it-yourself-plumbing-repairs/">tackle the problem ourselves</a>.</li>
</ul>
<li>June</li>
<ul>
<li>In June my wife and I celebrated our 4th wedding anniversary!</li>
<li>We also documented another small home repair, <a title="More Do It Yourself home Improvement" href="http://blog.shupp.org/2011/06/05/more-do-it-yourself-home-improvement-fun-garbage-disposal-replacement/">replacing the garbage disposal</a>.</li>
</ul>
<li>July</li>
<ul>
<li>July included a second trip back to VA, this time just to visit family.</li>
<li>Unfortunately, soon after that we got the bad news that one of our beloved cats, Linus, suffers from chronic kidney disease.  He's currently doing well at a stable weight (roughly 3/4 of his previous weight) through medication and diet, and we're hoping to keep him as comfortable as possible.  There is not a known cure.</li>
<li>I also finally broke down and bought my first serious telescope, a <a title="NexStar 8SE" href="https://twitter.com/#!/shupp/status/92375611946975232">Celestron NexStar 8SE</a>.  It's pretty rad.  I'm hoping to get into astrophotography this year.</li>
</ul>
<li>August</li>
<ul>
<li>In August I was lucky enough to attend the launch of <a title="NASA Juno" href="http://www.nasa.gov/mission_pages/juno/main/index.html">NASA's Juno mission</a> during my 3rd tweetup of the year.  We heard from lots of great folks on the Juno teams as well as NASA Administrator Charles Bolden, who was a really inspiring speaker.</li>
<li>Later that month, a <a href="http://twitpic.com/6379og">book</a> that myself and a few other former Digg employees contributed to nearly 2 years before  finally came out.</li>
<li>That month I attended my first TEDxNASA event "<a title="TEDxNASA &quot;Extreme Green&quot;" href="http://tedxnasa.com/silicon-valley/">Extreme Green</a>", which was a blast.  Lots of great speakers.   One of the more impressive talks of the day was Ed Lu's <a title="Ed Lu's talk" href="http://www.youtube.com/watch?v=FXyaTwS5N10&amp;list=PL74DC4D2389038DB0&amp;index=9">talk</a> about how inexpensive it really would be to set up an asteroid monitoring system to help prevent a major collision, perhaps the worst natural disaster imaginable.</li>
<li>Another <a title="30 Day Challenges talk" href="http://www.ted.com/talks/matt_cutts_try_something_new_for_30_days.html">TED talk</a> on 30 day challenges inspired me to try cutting out Diet Coke (and all sodas) for 30 days.  Four and a half months later, I still haven't gone back.</li>
</ul>
<li>September</li>
<ul>
<li>I bough my first 100% electric car, a <a href="https://twitter.com/#!/shupp/status/114506442433773570">Nissan Leaf</a>, which was delivered right on schedule.  The car is such a dream to drive.  It's nearly silent.  I can't wait until electric vehicles are the norm!</li>
<li>Later that month I wrote about <a href="http://blog.shupp.org/2011/09/25/speeding-up-satellite-predictions-in-php-with-hiphop/">speeding up satellite predictions in PHP with hiphop</a> which coincided with my release of <a title="Predict" href="https://github.com/shupp/Predict">Predict</a>, a library for modeling and predicting satellite orbits.  The use case for this is a project of mine called "<a title="Where the ISS at?" href="http://wheretheiss.at">Where the ISS at?</a>", which is currently in the beta testing phase and should be public very soon.</li>
</ul>
<li>October</li>
<ul>
<li>October included attending my final NASA Tweetup of the year, the <a title="SOFIA Telescope" href="http://www.sofia.usra.edu/">SOFIA Telescope</a> Tweetup back at NASA Ames.  We got a chance to <a title="Up close and personal with SOFIA" href="https://twitter.com/#!/shupp/status/124930194879422465">tour</a> the telescope, which was parked there at Ames.  It too was pretty rad.</li>
</ul>
<li>November</li>
<ul>
<li>In November we decided to take a third trip back to VA for Thanksgiving, and I finally got a chance to visit <a title="Trip to Monticello" href="https://foursquare.com/shupp/checkin/4ecab2319a52756c596d104f?s=7KqTZlDbebbPHkqrOdbOoj4ao1Y">Monticello</a>.
<p><div id="attachment_9527" class="wp-caption alignright" style="width: 281px"><a href="http://blog.shupp.org/wp-content/uploads/2012/01/402351_10150413977130826_709320825_8914854_734717942_n.jpeg"><img class="size-medium wp-image-9527" title="Hot Air Balloon Ride in Sonoma" src="http://blog.shupp.org/wp-content/uploads/2012/01/402351_10150413977130826_709320825_8914854_734717942_n-271x300.jpg" alt="Hot Air Balloon Ride in Sonoma" width="271" height="300" /></a><p class="wp-caption-text">Hot Air Balloon Ride in Sonoma!</p></div></li>
</ul>
<li>December</li>
<ul>
<li>December saw us both reaching our 40th birthdays.  For some reason, I kind of dreaded this milestone.  But once I reached it, I was actually pretty relieved.  It seems the anticipation of turning 40 was much worse than the actual birthday.  The good news is that my wife arranged our first ride in a hot air balloon up in Sonoma to celebrate.  Once you got used to the sound and awesome heat of each of the 15 million BTU burners powering the balloon, the views were nothing short of breathtaking.</li>
<li>In December I also accepted a job as Engineering Manager at <a title="OpenDNS" href="http://opendns.com">OpenDNS</a>, something I'm very excited start in the beginning of January.</li>
</ul>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2012/01/01/2011-year-in-review/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Speeding up satellite predictions in PHP with HipHop</title>
		<link>http://blog.shupp.org/2011/09/25/speeding-up-satellite-predictions-in-php-with-hiphop/</link>
		<comments>http://blog.shupp.org/2011/09/25/speeding-up-satellite-predictions-in-php-with-hiphop/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 02:55:57 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Space]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=9044</guid>
		<description><![CDATA[Background Seeing something in space fly overhead with the naked eye is pretty awesome.  It's not only a technical marvel to enjoy, but for me it helps keep things in perspective and my thoughts on the big picture.  Ever since the first time I saw the International Space Station fly by, I've felt that it [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton9044" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F09%2F25%2Fspeeding-up-satellite-predictions-in-php-with-hiphop%2F&amp;text=Speeding%20up%20satellite%20predictions%20in%20PHP%20with%20HipHop&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F09%2F25%2Fspeeding-up-satellite-predictions-in-php-with-hiphop%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_9064" class="wp-caption alignright" style="width: 310px"><a href="http://blog.shupp.org/wp-content/uploads/2011/09/Screen-shot-2011-09-24-at-12.50.58-AM.png"><img class="size-medium wp-image-9064" title="ISS flyover data plotted on Google maps" src="http://blog.shupp.org/wp-content/uploads/2011/09/Screen-shot-2011-09-24-at-12.50.58-AM-300x283.png" alt="" width="300" height="283" /></a><p class="wp-caption-text">ISS flyover data plotted on Google maps</p></div>
<p><strong>Background</strong></p>
<p>Seeing something in space fly overhead with the naked eye is pretty awesome.  It's not only a technical marvel to enjoy, but for me it helps keep things in perspective and my thoughts on the big picture.  Ever since the first time I saw the International Space Station fly by, I've felt that it is something everyone should experience.   I started looking at existing software to help remind me (and others) when the next pass of the ISS would be, and while there are a few good websites out there for satellite prediction, none of them did exactly what I wanted.  So a few months ago I decided to try and build my own.  The biggest piece of my project was going to be getting the actual satellite data.  So I looked around for existing data APIs that I could use, but couldn't find anything other than scraping existing sites (which is not only fragile, but some have no published data policy).  So, the first step was to figure out how to to generate the predictions myself.<span id="more-9044"></span></p>
<p><strong>How satellite predictions work</strong></p>
<p>The process involves calculating the coordinates (position and velocity) of the observer, the satellite, and the sun at a given point in time using a common coordinate system called Earth Centered Intertial (ECI).  Then, you need to convert those coordinates to a topocentric-horizon or azimuth-elevation coordinate system that can be used to pinpoint the object in the sky.  But before you can do this, you first need to know the orbital path of the satellite.  <a title="NORAD" href="http://en.wikipedia.org/wiki/North_American_Aerospace_Defense_Command">NORAD</a>, which has responsibility for tracking all man-made objects in orbit around Earth, uses the the <a title="SSN" href="http://en.wikipedia.org/wiki/Space_Surveillance_Network">Space Surveillance Network</a> for collecting observational data of these objects.  It then distributes these observations as Keplerian orbital elements in the  <a title="TLE" href="http://en.wikipedia.org/wiki/Two-line_element_set">Two Line Element Set</a> (TLE) format.    (You can download these very small TLE files through sites like <a title="Lifestream" href="http://celestrak.com">Celestrak</a>).  The TLE data can then be used to  predict a satellite's position and velocity using <a title="SGP4" href="http://en.wikipedia.org/wiki/SGP4">Simplified Perturbations Models</a> (SGP/SGP4/SDP4).  (NOTE: Since these models trade computational speed for accuracy, you need to update your TLE files every few days to make sure your predictions are accurate).  Dr. T.S. Kelso, who runs Celestrak, has a great series of <a title="Celestrak Columns" href="http://celestrak.com/columns/">columns</a>  explaining all of this in detail.  I highly recommend them.</p>
<p><strong>The library and performance problems</strong></p>
<p>I couldn't find a suitable  or mature library in python or PHP implementing the SGP models, so I decided to port code from <a title="Gpredict" href="http://gpredict.oz9aec.net/">Gpredict</a>, a real time satellite tracker application written in C.  Gpredict had almost everything I needed, the SGP model implementation, the prediction logic, etc..  The only thing I needed to add was the ability to determine the apparent magnitude (brightness) of an object, and I'd be set.  Though it took a few weeks, I finally got a web friendly PHP <a title="Predict" href="http://github.com/shupp/Predict">port</a> of Gpredict working that produced prediction data which matched not only what the Gpredict application produced, but what other websites produced as well (including apparent magnitude for the ISS that I added).  While generating a snapshot or single pass was fast enough for my needs (under 50 milliseconds), generating predictions for the next 10 days was excruciatingly slow - in the order of several seconds.  After doing some profiling, I found there really wasn't much left to optimize.  PHP just wasn't fast at doing a LOT of math.  So this left me with a few options:  put the code into a php extension (which would be a fair amount of work), try a different language implementation of the SGP models (such as porting the Gpredict code to a web service, or creating a web service out of existing java code), or try Facebook's PHP to C++ transformation tool, <a title="HipHop for PHP blog post" href="https://developers.facebook.com/blog/post/358/">HipHop for PHP</a>.</p>
<p><strong>HipHop for PHP to the rescue</strong></p>
<p>I decided to try HipHop first since it would likely be the least amount of work and accomplish the biggest performance boost.  And though setting it up took some time to get right, the difference was <em>very</em> impressive.  A 10 day prediction that took 1866 milliseconds on my macbook pro in PHP took only 221 milliseconds when transformed and compiled with HipHop.  <em>That's 88% less time! </em> Initially I was concerned that, since HipHop does not yet support PHP 5.3, I might have to do some refactoring.  But luckily only a few lines needed changing.  Further, HipHop does a great job of pointing out problems in the code.  Code that it doesn't understand (such as newer PHP 5.3 only code), as well as code that does not execute, or other general problems, are clearly logged during compile time.  It found a couple of bugs from my port of Gpredict that I hadn't run into yet, which was really helpful.  But as I mentioned before, HipHop for PHP is not terribly easy to set up.  It took me several hours from start to finish to get it installed and a program compiled and working.  Here's a quick list of things I ran into and you might want to watch out for:</p>
<ul>
<li>HipHop for PHP doesn't work on Mac OS X, only Linux or FreeBSD.  If you run a mac, install Linux via VirtualBox or another VM tool and work there.</li>
<li>It won't compile on 32 bit Linux, only 64 bit is supported.</li>
<li>The README file is not up to date (it even says so).   Use the <a title="Github Wiki for HipHop" href="https://github.com/facebook/hiphop-php/wiki">wiki pages</a> on github instead.</li>
<li>The wiki includes some installation instructions for common distributions.  Do yourself a favor and use them.  There are also wiki pages covering how to use HipHop, which you'll need to read as well.</li>
<li>Make sure you have sufficient memory if you're running your compiled php program as a daemon.  I was using a small 512MB VPS, and it would routinely crash until I upped the memory to 1GB.</li>
</ul>
<p>Had I known the above tips in advance, I probably could have done my install and had a program up and running in less than half the time that it took me.  But still, I'm pretty impressed with HipHop.  I have it running as a daemon locally, and make HTTP requests to it only for the long running prediction processes.  One cool thing is that I can return serialized php from the HipHop web service, deserialize the results in the client PHP process, and continue using those objects.  It made moving the predictions process from local to HipHop  a trivial change in my existing application.</p>
<p><strong>Conclusion</strong></p>
<p>Learning about how satellite tracking works and how to track them myself has been a blast.  But running into such a performance problem after spending time porting the prediction code to PHP was disappointment.  However, HipHop for PHP was a perfect fit for solving this, and I'm happy with how well it works for my needs.</p>
<p>The application I set out to build isn't public just yet, but I did put up a prototype of real time ISS tracking using my newly ported <a title="Predict" href="http://github.com/shupp/Predict">Predict library</a>, which you can view <a title="Real time ISS tracker" href="http://shupp.org/tracker">here</a>.  Since I was new to satellite tracking, I needed some help understanding what needed to be done.  I would like to thank a few people who graciously lent their time to this process: <a title="David Lowe" href="http://www.het.brown.edu/people/lowe/">David Lowe</a> for helping to steer me in the right direction from the beginning (and putting up with a lot of questions), <a title="Dan Copeland" href="http://about.me/dpc47">Dan Copeland</a> for helping work through the math for calculating apparent magnitude as well as being a helpful second set of eyes, and <a title="T.S. Kelso" href="http://celestrak.com/webmaster.asp">T.S. Kelso</a> for not only running Celestrak, but for being responsive and helpful in answering my questions and pointing me to additional information on the topic.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/09/25/speeding-up-satellite-predictions-in-php-with-hiphop/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>More do it yourself home improvement fun &#8211; garbage disposal replacement</title>
		<link>http://blog.shupp.org/2011/06/05/more-do-it-yourself-home-improvement-fun-garbage-disposal-replacement/</link>
		<comments>http://blog.shupp.org/2011/06/05/more-do-it-yourself-home-improvement-fun-garbage-disposal-replacement/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 23:44:20 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[House Repairs]]></category>
		<category><![CDATA[Plumbing]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8358</guid>
		<description><![CDATA[Ever since we moved into this place over three years ago, our garbage disposal has been a bit noisy, and more recently has started to smell bad.  The model we had, the In-Sink-Erator Badger 5 Plus, was not easy to clean since the black rubber flap at in the drain was not removable.  Since the [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton8358" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F06%2F05%2Fmore-do-it-yourself-home-improvement-fun-garbage-disposal-replacement%2F&amp;text=More%20do%20it%20yourself%20home%20improvement%20fun%20%26%238211%3B%20garbage%20disposal%20replacement&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F06%2F05%2Fmore-do-it-yourself-home-improvement-fun-garbage-disposal-replacement%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><div id="attachment_8360" class="wp-caption alignleft" style="width: 220px"><a href="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1335.jpg"><img class="size-medium wp-image-8360  " title="The new and improved in-sink-erator, with sound insulation" src="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1335-300x278.jpg" alt="" width="210" height="195" /></a><p class="wp-caption-text">The new and improved in-sink-erator, with sound insulation</p></div>
<p>Ever since we moved into this place over three years ago, our garbage disposal has been a bit noisy, and more recently has started to smell bad.  The model we had, the In-Sink-Erator Badger 5 Plus, was not easy to clean since the black rubber flap at in the drain was not removable.  Since the disposal was pretty old, we decided to replace it.<span id="more-8358"></span></p>
<div id="attachment_8365" class="wp-caption alignright" style="width: 244px"><a href="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1330.jpg"><img class="size-medium wp-image-8365  " title="The old noisy, stinky Badger 5 Plus" src="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1330-234x300.jpg" alt="" width="234" height="300" /></a><p class="wp-caption-text">The old noisy, stinky Badger 5 Plus</p></div>
<p>The disposal we chose as a replacement is the <a href="http://www.lowes.com/webapp/wcs/stores/servlet/ProductDisplay?langId=-1&amp;storeId=10151&amp;catalogId=10051&amp;cId=SEARCH&amp;productId=3065641&amp;cm_mmc=SCE_gps-_-gps-_-gps-_-InSinkErator%205/8%20HP%20Garbage%20Disposal%20with%20Sound%20Insulation%20SPACESAVER">In-Sink-Erator Evolution Space Saver</a> w/ sound insulation.  The sound insulation is partially achieved by using a rubber connector between the waste tube and the disposal, rather than connecting it directly to the unit.  Further, the rubber flap in the sink is not only removable (and thus easier to clean), but it's designed to absorb sound coming into the sink with it's sharp angles.  Pretty slick.</p>
<p>Installation would require plumber's putty and adjustable pliers, which I picked up as well.  The whole operation only took about an hour and a half, and probably 30 minutes of that was spent getting the old flange separated from the sink.  It also assumes you are replacing an existing disposal, as you have to wire the old power cable to the new disposal.  It turns out I didn't need the adjustable pliers, as our plumber recently replaced the trap with one that can be tightened by hand.  (The old disposal initially was installed BELOW the height of the drain vent, allowing water to sit in the disposal itself rather than the trap.  Our home inspector caught this, so we had the drain lowered by our plumber).  One thing I did learn, though, is that it's a bad a idea to leave your instructions under the trap pipe when you disconnect it.  There's water in there.  <em>By design</em>.</p>
<div class="wp-caption alignright" style="width: 249px"><a href="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1331.jpg"><img class=" " title="Disposal removed.  You can see the original drain above the water valves, the lowered one below." src="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1331-239x300.jpg" alt="" width="239" height="300" /></a><p class="wp-caption-text">Disposal removed.  You can see the original drain above the water valves, the lowered one below.</p></div>
<p>Once installation was complete, we were quite pleased with how quiet the new disposal is - a <em>big</em> difference.  And I gotta say, these kinds of do it yourself improvements are kind of fun to do.</p>
<div id="attachment_8367" class="wp-caption alignnone" style="width: 234px"><a href="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1336.jpg"><img class="size-medium wp-image-8367   " title="The new quiet, odor-free Evolution Space Saver" src="http://blog.shupp.org/wp-content/uploads/2011/06/IMG_1336-224x300.jpg" alt="" width="224" height="300" /></a><p class="wp-caption-text">The new quiet, odor-free Evolution Space Saver</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/06/05/more-do-it-yourself-home-improvement-fun-garbage-disposal-replacement/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP&#8217;s interactive shell as your application console</title>
		<link>http://blog.shupp.org/2011/06/01/phps-interactive-shell-as-your-application-console/</link>
		<comments>http://blog.shupp.org/2011/06/01/phps-interactive-shell-as-your-application-console/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 05:17:59 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8316</guid>
		<description><![CDATA[When developing a web application, it's common for your feature development to be ahead of any data administration tools you might need.  While some frameworks, such as django, have built in admin tools for managing your application's data, many don't.  At my current job we use Zend Framework, and have rolled our own lightweight model [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton8316" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F06%2F01%2Fphps-interactive-shell-as-your-application-console%2F&amp;text=PHP%26%238217%3Bs%20interactive%20shell%20as%20your%20application%20console&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F06%2F01%2Fphps-interactive-shell-as-your-application-console%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>When developing a web application, it's common for your feature development to be ahead of any data administration tools you might need.  While some frameworks, such as <a href="https://www.djangoproject.com/">django</a>, have built in admin tools for managing your application's data, many don't.  At my current job we use <a href="http://framework.zend.com">Zend Framework</a>, and have rolled our own <a href="http://github.com/empower/Deneb">lightweight model layer</a> which does not have any fancy automatic admin tools.  In addition to supporting database pools and selectors for partitioning of data, it also has transparent caching of data.  While this is good for speed, it precludes you from making any data storage changes without going through this model layer or the cache will get out of sync.  For now, rather than doing any DB queries directly, we do them through <a href="http://blog.shupp.org/?p=7802">CLI jobs</a> built for a specific task (batch updates, etc).  This works fairly well, but often things come up that aren't yet supported in the application's admin tools, such as changing a user's status bits, etc..  Things that a CLI console would be useful for.<span id="more-8316"></span></p>
<p>I was playing with django's shell recently, and I realized that with the way we have our bootstrapping setup, it's actually pretty trivial to get full access to our data models from PHP's interactive shell.  Because we have multiple entry points to our application (primary entry point, media entry point, testing from CLI, etc), we already consolidated the generic bootstrapping into an init.php file that is used by all of the entry points.  This file contains most of the usual things you'll find in a Zend Framework application's default index.php, such as setting up environment definitions, setting the include path, setting up autoload, etc.  The only thing the entry points do really is instantiate the application and run it.  With our current setup, I can start the interactive shell, require the init.php file, and instantiate and bootstrap the application.  From that point on, I have full access to the application's models, and any changes will keep caching in sync with its data.</p>
<p>Here's an example of changing my password from the console:</p>
<div class="dean_ch" style="white-space: wrap;">$ APPLICATION_ENV=<span class="st0">'development'</span> php -a<br />
Interactive shell</p>
<p>php &gt; <span class="kw1">require_once</span> <span class="st0">'./init.php'</span>;<br />
php &gt; EC::<span class="me2">getApplication</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">bootstrap</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
php &gt; <span class="re0">$user</span> = <span class="kw2">new</span> Model_User<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'username'</span> =&gt; <span class="st0">'shupp'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
php &gt; <span class="re0">$user</span>-&gt;<span class="me1">setPasswordFromClear</span><span class="br0">&#40;</span><span class="st0">'foobar'</span><span class="br0">&#41;</span>;<br />
php &gt; <span class="re0">$user</span>-&gt;<span class="me1">update</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
php &gt; quit</div>
<p>&nbsp;</p>
<p>Here's an example of looping over a collection of users and modifying their status bits:</p>
<div class="dean_ch" style="white-space: wrap;">$ APPLICATION_ENV=<span class="st0">'development'</span> php -a<br />
Interactive shell</p>
<p>php &gt; <span class="kw1">require_once</span> <span class="st0">'./public/init.php'</span>;<br />
php &gt; EC::<span class="me2">getApplication</span><span class="br0">&#40;</span><span class="br0">&#41;</span>-&gt;<span class="me1">bootstrap</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
php &gt; <span class="re0">$users</span> = <span class="kw2">new</span> Model_UserCollection<span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'username'</span> =&gt; <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'shupp'</span>, <span class="st0">'dwayne'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
php &gt; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$users</span> <span class="kw1">as</span> <span class="re0">$user</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
php <span class="br0">&#123;</span> &nbsp; &nbsp; <span class="re0">$user</span>-&gt;<span class="me1">setStatus</span><span class="br0">&#40;</span>Model_User::<span class="me2">STATUS_PASSWORD_EXPIRED</span><span class="br0">&#41;</span>;<br />
php <span class="br0">&#123;</span> &nbsp; &nbsp; <span class="re0">$user</span>-&gt;<span class="me1">update</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
php <span class="br0">&#123;</span> <span class="br0">&#125;</span><br />
php &gt; quit</div>
<p>&nbsp;</p>
<p>The interactive shell supports tab completion of file names for things like <em>require_once</em>, which is nice.   It also has history support between sessions, so you can use the up arrow to easily navigate to previous lines you've typed.  Pretty handy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/06/01/phps-interactive-shell-as-your-application-console/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Our first foray into do-it-yourself plumbing repairs</title>
		<link>http://blog.shupp.org/2011/05/30/our-first-foray-into-do-it-yourself-plumbing-repairs/</link>
		<comments>http://blog.shupp.org/2011/05/30/our-first-foray-into-do-it-yourself-plumbing-repairs/#comments</comments>
		<pubDate>Tue, 31 May 2011 04:19:24 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[House Repairs]]></category>
		<category><![CDATA[Plumbing]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8292</guid>
		<description><![CDATA[Last week our drain in the garage got stopped up during a washing machine cycle, spilling water onto the floor. While the dishwasher was also affected, the rest of the house (kitchen sink and bathroom) were unaffected. This is good news since just a few months ago we had some major plumbing work done.  It [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton8292" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F05%2F30%2Four-first-foray-into-do-it-yourself-plumbing-repairs%2F&amp;text=Our%20first%20foray%20into%20do-it-yourself%20plumbing%20repairs&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F05%2F30%2Four-first-foray-into-do-it-yourself-plumbing-repairs%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>Last week our drain in the garage got stopped up during a washing machine cycle, spilling water onto the floor.  While the dishwasher was also affected, the rest of the house (kitchen sink and bathroom) were unaffected.  This is good news since just a few months ago we had some major <a href="https://twitter.com/#!/shupp/status/26107674458329089">plumbing work</a> done.  It meant that the sewer line was clear, and the blockage was somewhere in our internal pipes.  We decided to try out a new plumber since we had some minor issues with the previous work.  But since they wanted $225 to snake the drain, we decided to take a stab at fixing it ourselves.  If we failed, all we would lose most likely was some time and effort.</p>
<div id="attachment_8293" class="wp-caption alignright" style="width: 234px"><a href="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1311.jpg"><img class="size-medium wp-image-8293" title="Peg guiding the rented powered auger" src="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1311-224x300.jpg" alt="" width="224" height="300" /></a><p class="wp-caption-text">Peg guiding the rented powered auger</p></div>
<p><span id="more-8292"></span>The first step was to pick up a hand powered <a title="Drain Auger" href="http://www.lowes.com/pd_347513-319-LX-86250_4294821970_4294937087_?productId=3376010&amp;Ns">drain auger</a> (snake).  At around $25, it wasn't too big of an investment, and a handy thing to have around.  Unfortunately, we couldn't get it to go into the drain from the exposed intake for the washer.  Instead, it insisted on going up a different pipe with led to the air intake from the roof.  So it was time to get direct access to the cleanout.</p>
<p>The cleanout is underneath a wooden platform that holds our washer and dryer about 6" above the floor.  Whoever built the platform left an access hole in the platform from the front so that you wouldn't have to move the washer and dryer to get to it.  Awesome idea, right?  Unfortunately, this design was useless for two reasons.  First, they didn't bring the cleanout to the edge of the platform.  Instead, they left it about 18" in, making it impossible to work with.  (We tried buying a telescoping basin wrench, but that was useless.)    Second, once we unhooked our washer and dryer and removed the platform, the cleanout cap wouldn't budge anyway.  Luckily, it was attached to the cast iron pipe with flex coupler that was easily removed.  So now we were able to get our auger into the drain.  But we soon found we were having no luck clearing it.  The hand powered wire auger wasn't going to cut it for this clog.  It was time to get serious.</p>
<p>We went down to the Home Depot Pro shop and rented a powered auger, or "rooter" as they call it.  For a total of about $57 including tax and insurance, we rented it for 4 hours (overnight since we got it late in the day), and with only minimum cursing learning to operate the thing, we got our drain cleared!  The hardest part was actually cleaning the rooter before returning it.  Those things are wily!</p>
<div id="attachment_8294" class="wp-caption alignright" style="width: 253px"><a href="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1312.jpg"><img class="size-medium wp-image-8294" title="The new extended cleanout" src="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1312-243x300.jpg" alt="" width="243" height="300" /></a><p class="wp-caption-text">The new extended cleanout</p></div>
<p>&nbsp;</p>
<p>With the drain clear, we decided to not only replace the cleanout with one that worked, but to extend it out 18" so that the next time the drain got clogged, we wouldn't have to move the washer and dryer to get to it.  So we headed off to Lowes and $32 and about 100 questions later, we had the parts we needed:</p>
<ul>
<li>2' length of 2" diameter  ABS pipe</li>
<li>Cleanout cap and coupler</li>
<li>Flex coupler to connect it to the original pipe</li>
<li>Hack saw to cut the pipe (Lowe's won't cut it under 10' for some reason)</li>
<li>ABS cleaning solution</li>
<li>ABS cement</li>
<li>Caulk to fix some leaky joints we found along the way</li>
</ul>
<p>&nbsp;</p>
<p>It didn't take too long to build the new cleanout and caulk the joints, but we had to wait until the next day for them to dry and be ready for testing.  So we took the opportunity to set up some fans and dry out the entire area over night, which would also make it easier to see if our handy work was successful.</p>
<div id="attachment_8295" class="wp-caption alignright" style="width: 310px"><a href="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1318.jpg"><img class="size-medium wp-image-8295" title="The extended cleanout is now flush with the platform and accessible" src="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1318-300x161.jpg" alt="" width="300" height="161" /></a><p class="wp-caption-text">The extended cleanout is now flush with the platform and accessible</p></div>
<p>Our test the next day was completely successful!  No evidence of leaking from the new cleanout or the joints we caulked.  When we put the platform back in place and re-connected the washer and dryer, the cleanout was flush with the access point in the platform.  If we encounter any problems in the future, it will be <em>much</em> easier to deal with.  And since the existing rug got damaged, we replaced it with something more festive.</p>
<p>All in all, it was a fair amount of work, but we only spent around $125.  And now we have a few extra tools, an improved cleanout, and a <em>lot</em> more experience (or "character" as <a href="http://en.wikipedia.org/wiki/Calvin_and_Hobbes">Calvin's</a> dad would call it) to apply to future problems.</p>
<p>Let the washing begin!</p>
<div id="attachment_8296" class="wp-caption aligncenter" style="width: 234px"><a href="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1326.jpg"><img class="size-medium wp-image-8296" title="The finished product" src="http://blog.shupp.org/wp-content/uploads/2011/05/IMG_1326-224x300.jpg" alt="" width="224" height="300" /></a><p class="wp-caption-text">The finished product</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/05/30/our-first-foray-into-do-it-yourself-plumbing-repairs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting started with Kestrel from a PHP application</title>
		<link>http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/</link>
		<comments>http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/#comments</comments>
		<pubDate>Sun, 08 May 2011 00:15:49 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Kestrel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8235</guid>
		<description><![CDATA[We've been using Twitter's kestrel queue server for a while now at work, but only from our service layer, which is written in python.  Now that we have some queueing needs from our application layer, written in PHP, I spent a few days this week adding queue support to our web application.  I thought I'd [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton8235" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F05%2F07%2Fgetting-started-with-kestrel-from-a-php-application%2F&amp;text=Getting%20started%20with%20Kestrel%20from%20a%20PHP%20application&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F05%2F07%2Fgetting-started-with-kestrel-from-a-php-application%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>We've been using Twitter's <a title="Kestrel" href="https://github.com/robey/kestrel">kestrel queue server</a> for a while now at work, but only from our service layer, which is written in python.  Now that we have some queueing needs from our application layer, written in PHP, I spent a few days this week adding queue support to our web application.  I thought I'd share what I learned, and how I implemented it.</p>
<p><strong>Goals</strong></p>
<p>The kestrel server itself was pretty straightforward to get up and running.  The only thing I would point out is that I recommend sticking to release branches, as master was fairly unstable when I tried to use it.  Regarding implementing the client, there were a few goals I had in mind when I started:</p>
<ul>
<li>Since kestrel is built on the memcache protocol, try and leverage an existing memcache client rather than build one from scratch</li>
<li>Utilize our existing batch job infrastructure, which I covered previously <a title="Organizing PHP Batch Jobs" href="http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/">here</a>, and make sure our multi-tenant needs are met</li>
<li>Keep the queue interface generic in case we change queue servers later</li>
<li>Utilize existing kestrel management tools, only build out the the functionality we need</li>
</ul>
<p>With these goals in mind, I ended up with 4 components: a kestrel client, a producer, a consumer, and a very small CLI harness for running the consumer.  But before I even coded anything, I set up <a title="Kestrel Web" href="https://github.com/matterkkila/kestrelweb">kestrel web</a>, a web UI for kestrel written by my co-worker Matt Erkkila.  Kestrel web allows you to view statistics on kestrel, manage queues, as well as sort and filter queues based on manual inputs.  Having this tool up and running from the get go made it easy to watch jobs get added and consumed from my test queue, and also easily flush out the queues as needed.<span id="more-8235"></span></p>
<p><strong>The Kestrel Client</strong></p>
<p>I couldn't find any existing kestrel clients for PHP, so I started looking at the two memcache extensions: the older memcache, and Andrei Zmievski's memcached, the latter of which is based on the libmemcached library.  I started with memcache, and while it worked fine initially, I quickly found that I could not modify timeouts.  This interfered with the way  kestrel recommends you poll it for new jobs, and I would see timeout errors from the memcache extension if you tried to set the poll timeout to 1 second or higher (the memcache default).  The memcached extension does not have these issues, so I went with it.</p>
<p>The first gotcha I ran into was serialization.  You can use memcached's serializer for writing to kestrel, but when it reads the data back, it doesn't recognize that it is serialized.  So I just serialize the data manually in my client, and things work fine.  One other thing to note is that you'll want to disable compression, or do it manually, as the memcached extension will automatically compress anything over 100 bytes by default, and will not decompress it when reading from kestrel.</p>
<p>The other issue is that if you want to use any custom kestrel commands, you can't.  Since the application layer doesn't need anything fancy, the memcached extension will work fine for it.  Once we need support for the upcoming monitor (batching) in kestrel 2, we may need to implement a kestrel client from scratch.  Kestrel web supplies everything else we need right now.</p>
<p>Once the decision was made to use memcached, I wrote a light decorator for it, EC_KestrelClient.  This handles instantiation of the memcached client, serialization, and helpers for some kestrel specific options to the GET command.  It also has support for passing memcached specific options through it.  The class ended up looking like this:</p>
<p><script src="https://gist.github.com/960968.js?file=EC_KestrelClient.php"></script></p>
<p><strong>The Producer</strong></p>
<p>The producer is very simple.  It just formats the data into a standard structure, including current tenant information, namespaces the queue so it doesn't collide with other projects, and adds it to the queue.  The producer looks like this:</p>
<p><script src="https://gist.github.com/960963.js?file=EC_Producer.php"></script></p>
<p><strong>The Consumer</strong></p>
<p>The consumer has a bit more to it, though still pretty straightforward.  It's intended to be run from a monitoring tool like <a title="Daemontools" href="http://cr.yp.to/daemontools.html">daemontools</a> or <a title="Supervisord" href="http://supervisord.org/">supervisord</a>, so there is a very small CLI harness that just passes the CLI arguments into EC_Consumer and runs it.  After parsing the CLI arguments, EC_Consumer polls kestrel for new jobs, and runs them through our standard batch job infrastructure.  Until we have more confidence in PHP's long running process ability, I added an optional maxium jobs argument, which will stop the consumer from processing more than X jobs and then terminate.  The monitoring service (supervisord) will then just restart it in a matter of seconds.  I also added an optional debug argument for testing, so you can see every action as it happens.  The CLI harness looks like this:</p>
<p><script src="https://gist.github.com/960957.js?file=consumer_cli.php"></script></p>
<p>And the main consumer class, EC_Consumer, looks something like this:</p>
<p><script src="https://gist.github.com/960974.js?file=EC_Consumer.php"></script></p>
<p><strong>Putting it together</strong></p>
<p>Now that all the pieces are put together, let's take a look at in action.  Adding example job "HelloWorld" to the queue "hello_world" from within our application looks something like this:</p>
<p><script src="https://gist.github.com/960980.js?file=gistfile1.php"></script></p>
<p>And finally, here's an example of running the consumer from the CLI harness, along with some example debug output of processing the job:</p>
<p><script src="https://gist.github.com/960979.js?file=example.txt"></script></p>
<p>That's it!  I'd be interested to hear how other folks are interfacing with kestrel from PHP.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More on step debugging in PHP</title>
		<link>http://blog.shupp.org/2011/04/18/more-on-step-debugging-in-php/</link>
		<comments>http://blog.shupp.org/2011/04/18/more-on-step-debugging-in-php/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 06:43:27 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>
		<category><![CDATA[VIM]]></category>
		<category><![CDATA[Xdebug]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8170</guid>
		<description><![CDATA[Having recently wrote about PHP step debugging in VIM, I thought I'd share a couple of things I've come across since writing it. First, I find that I often need step debugging when writing unit tests, as that's when I'm really scrutinizing logic.  It turns out it's pretty easy to do.  All you need is [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton8170" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F04%2F18%2Fmore-on-step-debugging-in-php%2F&amp;text=More%20on%20step%20debugging%20in%20PHP&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F04%2F18%2Fmore-on-step-debugging-in-php%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>Having recently wrote about <a href="http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/">PHP step debugging in VIM</a>, I thought I'd share a couple of things I've come across since writing it.</p>
<p>First, I find that I often need step debugging when writing unit tests, as that's when I'm really scrutinizing logic.  It turns out it's pretty easy to do.  All you need is to set the XDEBUG_CONFIG environment variable like so:</p>
<p><code>XDEBUG_CONFIG="idekey=session_name" php bin/phpunit.php tests/FooTest.php</code></p>
<p>When debugging from VIM, you'll want to have two shells open.  One running the debugger, and another executing the tests.  Also, note that in a shared environment, you can still pass in xdebug ini settings like so:</p>
<p><code>XDEBUG_CONFIG="idekey=session_name" \<br />
    php -d xdebug.remote_host=10.0.0.1 bin/phpunit.php tests/FooTest.php</code></p>
<p>Second, for step debugging in VIM, I've settled on <a title="VIM Plugin" href="http://www.vim.org/scripts/script.php?script_id=2508">this plugin</a> (there are many versions out there).  It seems to solve problems with tab handling that I was seeing with older versions.</p>
<p>Cheers,</p>
<p>Bill</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/04/18/more-on-step-debugging-in-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Preparing your application for serving static content efficiently</title>
		<link>http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/</link>
		<comments>http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 03:49:17 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7898</guid>
		<description><![CDATA[(Reposted from the Empower Campaigns blog) Most web applications have static content such as CSS, JS, images, etc.  To save on bandwidth costs and improve load times for your users, it's a good idea to tell the client to cache these items for a long period of time.  But even though your static content changes [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton7898" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F03%2F21%2Fpreparing-your-application-for-serving-static-content-efficiently%2F&amp;text=Preparing%20your%20application%20for%20serving%20static%20content%20efficiently&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F03%2F21%2Fpreparing-your-application-for-serving-static-content-efficiently%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p><em>(Reposted from the Empower Campaigns <a title="Orignal Post" href="http://blog.empowercampaigns.com/post/4007131732/preparing-your-application-for-serving-static-content">blog</a>)</em></p>
<p>Most web applications have static content such as CSS, JS, images,  etc.  To save on bandwidth costs and improve load times for your users,  it's a good idea to tell the client to cache these items for a long  period of time.  But even though your static content changes  infrequently, when it does, the cached content needs to be invalidated.   In addition, high traffic sites often want to go a step further and  take advantage of a <a title="Content Delivery Network" href="http://en.wikipedia.org/wiki/Content_delivery_network">CDN</a> to offload static content delivery.  Below I'll share the method we used here at <a title="Empower Campaigns" href="http://empowercampaigns.com">Empower Campaigns</a> to accomplish both of these things.<img src="http://assets.tumblr.com/javascript/tiny_mce_3_3_3/plugins/pagebreak/img/trans.gif" alt="" /><span id="more-7898"></span></p>
<p><strong>Version your content</strong></p>
<p><strong> </strong>The first step to getting control of cache  invalidation is to manage the version of your content, usually included  as part of the URL.  In the past I've seen things like incrementing a  single counter for your JS and CSS files that effectively changed the  URL of these files and invalidated the cache.  But this updates the URL  for ALL of the files that use that counter, which is not very  efficient.  A better approach is to version each file (or bundle, if you  deliver files in groups) so that you control the cache invalidation of  each item individually.  One way to do this is with a hash like <a title="Cyclic redundancy check" href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC32</a>.   If the content is stored on a file system, such as JS, CSS, or image  files often are, you could hash the file upon the first read, and store  that hash in a cache that gets purged during a production code push.   For PHP users, <a title="APC" href="http://us.php.net/manual/en/book.apc.php">APC</a> is a great tool for this.  This reduces the hashing overhead to one  time per web node in your cluster per code release.  If your content is  stored somewhere outside of your code base, you might consider storing  the hash of the content at write time.  For example, when I worked at <a title="Digg" href="http://digg.com">Digg</a>, we stored user profile images in <a title="MogileFS" href="http://danga.com/mogilefs/">MogileFS</a>.   So when a user added or changed their profile image, we would hash the  image at that time and store the hash with that user's profile data in <a title="Cassandra" href="http://cassandra.apache.org/">Cassandra</a>.   This was even better because the content was hashed only once.  The  same type of thing could be done with locally stored content, it just  depends how fancy you'd like to get.  Note that when constructing your  versioned URL, avoid using the version in the query string, as some CDNs  strip query strings (ex:  media.yourdomain.com/v/8bba8b90/css/960.min.css rather than  media.yourdomain.com/css/960.min.css?v=8bba8b90)</p>
<p><strong>Minify/Compress your content</strong></p>
<p>In a production environment, you want to deliver static content as  quickly as possible.  Two ways to help with this is minification and  compression.  For minification, we use Google's <a title="Google Closure" href="http://code.google.com/closure/">Closure</a> for JS, and <a title="YUI Compressor" href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> for CSS, both of which are run during the deployment process.  You'll  also want to enable compression in your web server as well, such as  mod_deflate in Apache, to make the files as small as possible during  transit.<strong> </strong></p>
<p><strong>Increase cache time</strong></p>
<p>Once you have your content versioning in place, you'll want to  increase the cache time for those files.  We use a cache time of one  year, and set that at the web server level like so using mod_rewrite:</p>
<p><script src="https://gist.github.com/879761.js?file=gistfile1.txt"></script></p>
<p><strong>Use a dedicated domain name</strong></p>
<p>If you want to be ready to move to a CDN at any time, consider  putting your static content on a dedicated virtual host, such as  media.yourdomain.com.  This way, you can simply point that domain to a  CDN at any time, and you'll be up and running.  Also, this has the added  benefit of allowing the client's browser to make more parallel requests  for your content, as they often limit the number of parallel requests  they'll make to any one domain.  By spreading your content over more  than one domain, the client can make more requests in parallel, speeding  up the the time for the document to be ready.  One other benefit is  that by using another domain for your media, you can reduce the number  of cookies sent with media requests, which reduces the size of each  request.  Our rewrite rules for ignoring version numbers in our media host ended up looking like this:  <script src="https://gist.github.com/879762.js?file=gistfile1.txt"></script></p>
<p>With  the above steps in mind, we wrote a view helper that handles hashing  and url writing called mediaURL().  It can also look at our config and  determine if SSL URLs should be used, if a given page in our application  requires it.  The view helper looks like this:</p>
<p><script src="https://gist.github.com/879949.js?file=gistfile1.php"></script> And the call to the helper from our view looks like this:  <script src="https://gist.github.com/879805.js?file=gistfile1.html"></script></p>
<p><strong>Conclusion</strong></p>
<p>By following the steps above, you'll have static content that is  dynamically versioned, compressed, and cacheable by the client.  And if  you're serving it on a dedicated domain, you'll speed up overall page  load times and be ready to provision a CDN if you ever need it.</p>
<p>Cheers,</p>
<p>Bill Shupp, Lead Developer (twitter: <a title="My Twitter Account" href="http://twitter.com/shupp">http://twitter.com/shupp</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Organizing PHP Batch Jobs</title>
		<link>http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/</link>
		<comments>http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/#comments</comments>
		<pubDate>Wed, 16 Mar 2011 06:50:00 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7802</guid>
		<description><![CDATA[This week at work I got the chance to address the growing number of batch oriented CLI scripts for our main web application.  While they weren't quite unmanageable yet, they were heading in that direction.  There was too much common code, especially with bootstrapping the application and parsing options.  Also,  the location of scripts didn't [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton7802" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F03%2F15%2Forganizing-php-batch-jobs%2F&amp;text=Organizing%20PHP%20Batch%20Jobs&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F03%2F15%2Forganizing-php-batch-jobs%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>This week at work I got the chance to address the growing number of batch oriented CLI scripts for our main web application.  While they weren't quite unmanageable yet, they were heading in that direction.  There was too much common code, especially with bootstrapping the application and parsing options.  Also,  the location of scripts didn't really make sense... <code>./bin/bar.php</code>,  <code>./cron/foo.php</code>, etc.  So I decided to carve out some time and clean it up.</p>
<p>The goals were pretty straight forward:</p>
<ul>
<li>Everything must use the application's <a title="Deneb" href="http://github.com/empower/Deneb">model layer</a>.  This is mostly so that the built in caching will be consistent, but also to enforce that all data access goes through the same code.</li>
<li>Centralize all CLI option parsing, application bootsrapping, error handling, and multi-tenant logic (this is a multi-tenant SaaS application)</li>
<li>Keep the jobs themselves very simple.</li>
</ul>
<p>With the above in mind, I ended up splitting things up into 3 parts:<span id="more-7802"></span></p>
<ul>
<li><code>./bin/ecli.php</code>, the only PHP CLI script which does minimal bootstrapping, collects the options/arguments, and runs <code>EC_CLI</code></li>
<li><code>EC_CLI</code>, a class that does the actual option parsing (via <code>Zend_Console_Getopt</code>), application bootstrapping, error handling, and multi-tenant runs (recursively calls <code>./bin/ecli.php</code> for each tenant), and runs the actual job</li>
<li><code>EC_Job_Abstract</code>, the Job interface that collects job specific arguments and runs the job.</li>
</ul>
<p>Now, when I need to create a new batch job <code>EC_Job_Foo</code>, I just put the contents in <code>EC_Job_Foo::run()</code>, and execute it like so:</p>
<p><code>./bin/ecli.php --environment production --instance clienta,clientb --job Foo</code></p>
<p>The <code>ecli.php</code> script ends up looking like this:<br />
<script src="https://gist.github.com/872101.js?file=ecli.php"></script></p>
<p>Pretty easy, huh?  It makes testing all the components really easy as well.</p>
<p>Finally, we made the decision to use <a title="Jenkins CI" href="http://jenkins-ci.org/">Jenkins</a> instead of the traditional cron scheduler for recurring jobs.  This has a few advantages: It's got a simple web interface for managing the job, you plug it into your existing Jenkins notifications (email, jabber, etc), console tailing, job dependencies, etc... It works really well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PHP step debugging in VIM</title>
		<link>http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/</link>
		<comments>http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/#comments</comments>
		<pubDate>Sun, 13 Feb 2011 00:17:55 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[VIM]]></category>
		<category><![CDATA[Xdebug]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7182</guid>
		<description><![CDATA[When debugging problems in PHP, most of the time it's easiest to just add var_dump($foo); exit; in the middle of your script, and you can see the contents of $foo right in your browser.  But if you have to do much more, this approach gets cumbersome pretty quickly.  I've recently been using step debugging for [...]]]></description>
			<content:encoded><![CDATA[<div id="tweetbutton7182" class="tw_button" style="float:right;margin-left:10px;"><a href="http://twitter.com/share?url=http%3A%2F%2Fblog.shupp.org%2F2011%2F02%2F12%2Fphp-step-debugging-in-vim%2F&amp;text=PHP%20step%20debugging%20in%20VIM&amp;related=shupp&amp;lang=en&amp;count=horizontal&amp;counturl=http%3A%2F%2Fblog.shupp.org%2F2011%2F02%2F12%2Fphp-step-debugging-in-vim%2F" class="twitter-share-button"  style="width:55px;height:22px;background:transparent url('http://blog.shupp.org/wp-content/plugins/wp-tweet-button/tweetn.png') no-repeat  0 0;text-align:left;text-indent:-9999px;display:block;">Tweet</a></div><p>When debugging problems in PHP, most of the time it's easiest to just add <code>var_dump($foo); exit;</code> in the middle of your script, and you can see the contents of <code>$foo</code> right in your browser.  But if you have to do much more, this approach gets cumbersome pretty quickly.  I've recently been using <a title="Program Animation" href="http://en.wikipedia.org/wiki/Program_animation">step debugging</a> for harder to track down problems.  It allows me to examine the state of things all the way through execution of a request, line by line, or skipping ahead to break points.  This process also gives you more insight into everything else happening in a request, which can be useful when you're using frameworks or other 3rd party code in your application.<span id="more-7182"></span></p>
<p>With PHP, the common extension for this is <a title="Xdebug" href="http://xdebug.org">Xdebug</a>.  (See the remote debugging documentation <a title="Xdebug remote documentation" href="http://www.xdebug.org/docs/remote">here</a>).  Since my main text editor is <a title="VIM" href="http://vim.org">VIM</a>, I had to find a suitable plugin to talk to Xdebug.  It turns out there are a few good blog posts already on this topic, so I won't duplicate the information here.  <a title="VIM/Xdebug tutotrial" href="http://2bits.com/articles/using-vim-and-xdebug-dbgp-for-debugging-drupal-or-any-php-application.html">This post</a> does a great job of covering installation and usage of the Xdebug plugin for VIM by Seng Woo Shin, though it links to an older version of it.  Here's a <a title="xdebug plugin" href="http://www.vim.org/scripts/script.php?script_id=1929">link</a> to a newer one that Xdebug also links to.  The Xdebug site links to <a title="Xdebug/VIM tutorial" href="http://tech.blog.box.net/2007/06/20/how-to-debug-php-with-vim-and-xdebug-on-linux/">another tutorial</a> that's worth a read too.</p>
<p>Beyond the links above, I've discovered a couple of things that are worth sharing.  First, there's a new FireFox extension, <a title="Firefix Extension" href="https://addons.mozilla.org/en-US/firefox/addon/58688">easy Xdebug</a>, that is a real lifesaver.  You just click the green bug on the bottom right, and it will try to start an Xdebug session with any request (rather than having to add XDEBUG_SESSION_START=1 to the query string parameters myself).  This is particularly handy when dealing with POST or or AJAX requests.  The Xdebug <a title="Xdebug remote documentation" href="http://www.xdebug.org/docs/remote">docs</a> also link to similar tools for Chrome, Safari, and Opera.</p>
<p>Now, my debugging work flow looks like this:</p>
<ul>
<li>Start the Xdebug session in FF by clicking the green bug</li>
<li>Set breakpoints in VIM</li>
<li>Press F5 in VIM to start listening for the request (it waits 5 seconds)</li>
<li>Perform that action I want to debug in FF</li>
<li>Press enter in VIM to enter the debug session</li>
<li>Debug</li>
<li>Press F6 to exit debugger, and fix the problem</li>
</ul>
<p>The one gotcha that I keep running into is how to set breakpoints correctly.  <strong>When you use this VIM plugin, you must put a breakpoint on executable code</strong>.  If you put it on a blank line, or even on a line with just an opening <code>try</code> statement, your breakpoint will not work.  Instead, you'll end up with an "error 5".  This topic is briefly covered <a title="breakpoint issue" href="http://ubuntuforums.org/showthread.php?t=1074820">here</a> and <a title="breakpoint issue" href="http://xdebug.org/archives/xdebug-general/1202.html">here</a>.</p>
<p>Now, when I find myself using more than one or two <code>var_dump()</code> statements to debug something, I usually walk through the work flow above, and have things sorted out much more quickly than I used to.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

