<?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>Hello, I am Sean Murphy &#187; Work</title>
	<atom:link href="http://iamseanmurphy.com/category/work/feed/" rel="self" type="application/rss+xml" />
	<link>http://iamseanmurphy.com</link>
	<description>Thoughts, news, code by Sean Murphy</description>
	<lastBuildDate>Wed, 19 Aug 2009 17:40:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Better HAProxy Health Check For Dynamic Websites</title>
		<link>http://iamseanmurphy.com/2009/04/22/a-better-haproxy-health-check-for-dynamic-websites/</link>
		<comments>http://iamseanmurphy.com/2009/04/22/a-better-haproxy-health-check-for-dynamic-websites/#comments</comments>
		<pubDate>Wed, 22 Apr 2009 16:14:50 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[fcgi]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[high availablity]]></category>
		<category><![CDATA[load balancing]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web server]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2009/04/22/a-better-haproxy-health-check-for-dynamic-websites/</guid>
		<description><![CDATA[Nobody wants their website to go down, or worse, for users to notice the site is down. Because of this most larger websites will run on multiple servers to provide some level of high availability. In a multi-server architecture there is typically a load balancer (or cluster of load balancers) to distribute the load among [...]


Related posts:<ol><li><a href='http://iamseanmurphy.com/2009/03/02/high-performance-comet-on-a-shoestring/' rel='bookmark' title='Permanent Link: High Performance Comet on a Shoestring'>High Performance Comet on a Shoestring</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Nobody wants their website to go down, or worse, for users to <em>notice</em> the site is down. Because of this most larger websites will run on multiple servers to provide some level of high availability. In a multi-server architecture there is typically a load balancer (or cluster of load balancers) to distribute the load among a pool of web servers. When a server goes down it&#8217;s taken out of the pool until it is once again ready to handle requests. HAProxy (a software load balancer) has the ability to perform this task by doing periodic health checks on all the servers in a cluster. The default settings, though, could give false positives in some cases, and thus create a bad user experience by allowing ill application servers to continue receiving requests.</p>
<p><span id="more-33"></span><br />
When in HTTP mode HAProxy&#8217;s default health check is a simple OPTIONS request. This has the advantage of being a very lightweight request, and is easy to identify and filter from server logs. Consider this scenario though: HAProxy balances the load between several web servers running nginx and PHP-FastCGI. If nginx is up but PHP-FastCGI goes down, nginx will still properly handle the OPTIONS request from HAProxy, giving the impression that all is well. HAProxy continues sending requests to the ill server which in turn get a 504 Gateway Timeout (or similar) response. Not a very good situation.</p>
<p>A solution would be to use a deeper health check, one that goes beyond nginx to the PHP-FastCGI process. That way if PHP-FastCGI goes down, the whole server is presumed &#8216;down&#8217;.</p>
<pre>
backend appservers

 mode http

 option httpchk HEAD /health_check.php HTTP/1.1\r\nHost:\ example.com

 server web1 x.x.x.x:80 weight 5 check inter 2000

 server web2 x.x.x.x:80 weight 5 check inter 2000

 server web3 x.x.x.x:80 weight 5 check inter 2000</pre>
<p>In the above example I&#8217;m using a custom health check request which will be processed by PHP-FastCGI. health_check.php is a lightweight script that contains simply <code>&lt;?php echo "I'm healthy"; ?&gt;</code>. I also added a host header so that the health check will be handled by a specific nginx virtual host. The nginx vhost config has this in it:</p>
<pre>
location = /health_check.php {

 access_log		off;

 fastcgi_pass	127.0.0.1:9000;

 fastcgi_index	index.php;

 include	/etc/nginx/fastcgi_params;

}</pre>
<p>And there you have it&#8211;a better HAProxy health check for dynamic websites.</p>


<p>Related posts:<ol><li><a href='http://iamseanmurphy.com/2009/03/02/high-performance-comet-on-a-shoestring/' rel='bookmark' title='Permanent Link: High Performance Comet on a Shoestring'>High Performance Comet on a Shoestring</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2009/04/22/a-better-haproxy-health-check-for-dynamic-websites/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Taking The Pain Out Of Domain Hunting</title>
		<link>http://iamseanmurphy.com/2009/03/30/taking-the-pain-out-of-domain-hunting/</link>
		<comments>http://iamseanmurphy.com/2009/03/30/taking-the-pain-out-of-domain-hunting/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 17:22:45 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[domains]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[trionym]]></category>
		<category><![CDATA[whois]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2009/03/30/taking-the-pain-out-of-domain-hunting/</guid>
		<description><![CDATA[
Coming up with a suitable name for a business, product, or website is something I do on a fairly regular basis. In brainstorming a name I often make lists of words I&#8217;d like to use, like adjectives and nouns than relate the product. Then I start combining the words to create a unique name and [...]


Related posts:<ol><li><a href='http://iamseanmurphy.com/2009/04/22/a-better-haproxy-health-check-for-dynamic-websites/' rel='bookmark' title='Permanent Link: A Better HAProxy Health Check For Dynamic Websites'>A Better HAProxy Health Check For Dynamic Websites</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://iamseanmurphy.com/wp-content/uploads/2009/04/screenshot.jpg" alt="Trionym Screenshot" /></p>
<p>Coming up with a suitable name for a business, product, or website is something I do on a fairly regular basis. In brainstorming a name I often make lists of words I&#8217;d like to use, like adjectives and nouns than relate the product. Then I start combining the words to create a unique name and check to see if the related domain is taken or not. The problem is that even though I may have come up with a name I really like, if the domain name is taken, it isn&#8217;t worth keeping.</p>
<p><span id="more-29"></span><br />
These days a LOT of domains are taken, either by people using them or companies squatting them. So to make this whole process a little easier I built a website that takes most of the work out of hunting for a good domain: <a href="http://trionym.org" onclick="javascript:pageTracker._trackPageview ('/outbound/trionym.org');">Trionym</a>.The idea is fairly simple: enter up to three lists of words, choose which Top-Level Domains you&#8217;re willing to use, and search. Trionym will then create all the possible word combinations and check whois databases to see if the domains are registered. It&#8217;s relatively simple for now, but I&#8217;m considering adding more options, so if there&#8217;s a feature you&#8217;d like to see just let me know.</p>


<p>Related posts:<ol><li><a href='http://iamseanmurphy.com/2009/04/22/a-better-haproxy-health-check-for-dynamic-websites/' rel='bookmark' title='Permanent Link: A Better HAProxy Health Check For Dynamic Websites'>A Better HAProxy Health Check For Dynamic Websites</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2009/03/30/taking-the-pain-out-of-domain-hunting/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>.htaccess File Causes 500 Internal Server Error on Network Solutions</title>
		<link>http://iamseanmurphy.com/2009/02/21/htaccess-file-causes-500-internal-server-error-on-network-solutions/</link>
		<comments>http://iamseanmurphy.com/2009/02/21/htaccess-file-causes-500-internal-server-error-on-network-solutions/#comments</comments>
		<pubDate>Sat, 21 Feb 2009 20:16:19 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[500]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_php]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2009/02/21/htaccess-file-causes-500-internal-server-error-on-network-solutions/</guid>
		<description><![CDATA[How&#8217;s that for a search engine friendly title, eh?
This is just a quick note for anyone who has to deal with Network Solutions hosting (for clients or otherwise). Apperantly Network Solutions doesn&#8217;t run PHP with Apache&#8217;s mod_php, but rather as a CGI application. That means if you try to put PHP configuration directives in a [...]


Related posts:<ol><li><a href='http://iamseanmurphy.com/2009/03/02/high-performance-comet-on-a-shoestring/' rel='bookmark' title='Permanent Link: High Performance Comet on a Shoestring'>High Performance Comet on a Shoestring</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>How&#8217;s that for a search engine friendly title, eh?</p>
<p>This is just a quick note for anyone who has to deal with Network Solutions hosting (for clients or otherwise). Apperantly Network Solutions doesn&#8217;t run PHP with Apache&#8217;s mod_php, but rather as a CGI application. That means if you try to put PHP configuration directives in a .htaccess file it will cause a 500 Internal Server Error. My helpful reference: <a href="http://www.nerdliness.com/article/2008/07/29/because-network-solutions-sucks#comment-4925" onclick="javascript:pageTracker._trackPageview ('/outbound/www.nerdliness.com');">Because Network Solutions Sucks</a>.</p>
<p>You have been warned.</p>


<p>Related posts:<ol><li><a href='http://iamseanmurphy.com/2009/03/02/high-performance-comet-on-a-shoestring/' rel='bookmark' title='Permanent Link: High Performance Comet on a Shoestring'>High Performance Comet on a Shoestring</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2009/02/21/htaccess-file-causes-500-internal-server-error-on-network-solutions/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>LongURL Integration For Your Website</title>
		<link>http://iamseanmurphy.com/2008/10/10/longurl-integration-for-your-website/</link>
		<comments>http://iamseanmurphy.com/2008/10/10/longurl-integration-for-your-website/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 05:26:42 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[longurl]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[tinyurl]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2008/10/10/longurl-integration-for-your-website/</guid>
		<description><![CDATA[I wasn&#8217;t sure it could be done, but I&#8217;ve done it. I&#8217;m happy to say that I&#8217;ve made it even easier to use the LongURL web service, specifically on your own site. Today I wrote a jQuery plugin that allows you to add LongURL support to a website in like, I don&#8217;t know, 30 seconds?! [...]


Related posts:<ol><li><a href='http://iamseanmurphy.com/2008/08/28/longurlrestoring-order-to-the-universe/' rel='bookmark' title='Permanent Link: LongURL&mdash;Restoring Order to the Universe'>LongURL&mdash;Restoring Order to the Universe</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I wasn&#8217;t sure it could be done, but I&#8217;ve done it. I&#8217;m happy to say that I&#8217;ve made it <em>even easier</em> to use the LongURL web service, specifically on your own site. Today I wrote a jQuery plugin that allows you to add LongURL support to a website in like, I don&#8217;t know, 30 seconds?! It really depends on how fast you are, but the point is that it&#8217;s really easy.</p>
<p>I noticed that Twitter search lets you expand URLs from some of the most popular shortening services (though, if they used LongURL they could support a whole lot more <img src='http://iamseanmurphy.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ). I liked their UI approach; it&#8217;s clear, simple, and effective. So I pretty much mimicked their UI for my plugin.</p>
<p><span id="more-21"></span><br />
So here it is, you can add support for LongURL to your site in just a few lines of code:</p>
<pre name="code" class="js">&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://longurl.org/static/jquery.longurl.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
$(function() {
    $('a').longurl();
});
&lt;/script&gt;</pre>
<p>Yup, that&#8217;s it. Also, if you don&#8217;t like the Ajax working indicator that I chose, you can use your own like so:</p>
<pre name="code" class="js">$(function() {
    $('a').longurl({working_image: 'http://example.com/images/ajaxy_animation.gif'});
});</pre>
<p>So, that&#8217;s how you use the plugin. You can see a <a href="http://longurl.org/static/jquery_demo.html" onclick="javascript:pageTracker._trackPageview ('/outbound/longurl.org');">demo</a> of it in action, and <a href="http://plugins.jquery.com/project/longurl" onclick="javascript:pageTracker._trackPageview ('/outbound/plugins.jquery.com');">download it</a> from the jQuery site. Hope you find it useful.</p>


<p>Related posts:<ol><li><a href='http://iamseanmurphy.com/2008/08/28/longurlrestoring-order-to-the-universe/' rel='bookmark' title='Permanent Link: LongURL&mdash;Restoring Order to the Universe'>LongURL&mdash;Restoring Order to the Universe</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2008/10/10/longurl-integration-for-your-website/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CouchDB View Generation</title>
		<link>http://iamseanmurphy.com/2008/09/08/couchdb-view-generation/</link>
		<comments>http://iamseanmurphy.com/2008/09/08/couchdb-view-generation/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 03:38:16 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[views]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2008/09/08/couchdb-view-generation/</guid>
		<description><![CDATA[An alternative technology quickly gaining popularity these days is CouchDB, a document-based database system for semi-structured data. I wasn&#8217;t sure what that meant at first, so I read as much as I could about it. The result? I couldn&#8217;t wait to use it.
I decided CouchDB would be a good fit for my next project (which [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>An alternative technology quickly gaining popularity these days is <a href="http://incubator.apache.org/couchdb/" onclick="javascript:pageTracker._trackPageview ('/outbound/incubator.apache.org');">CouchDB</a>, a document-based database system for semi-structured data. I wasn&#8217;t sure what that meant at first, so I read as much as I could about it. The result? I couldn&#8217;t wait to use it.</p>
<p>I decided CouchDB would be a good fit for my next project (which I should be releasing sometime this week BTW) and rolled up my sleeves. Because of the amount of data I&#8217;m working with, I hit a few snags along the way with regard to CouchDB view performance. Some of the things I learned, although they make sense, were not what I was expecting initially (even after reading all the docs). So for the benefit of others, I thought it&#8217;d be a good idea to share my current understanding of the way views work in CouchDB, and share some of the tips &amp; tricks <a href="http://jan.prima.de/" onclick="javascript:pageTracker._trackPageview ('/outbound/jan.prima.de');">Jan</a>, <a href="http://jchris.mfdz.com/" onclick="javascript:pageTracker._trackPageview ('/outbound/jchris.mfdz.com');">Chris</a>, and others have given me along the way.</p>
<p><span id="more-20"></span></p>
<h2>Importing Data for Speed and Glory</h2>
<p>Most of the work I&#8217;ve done with CouchDB this past week has been related to importing a fair amount of data (600k+ documents). Initially I tried creating one document at a time. This worked, but each request has associated with it a certain amount of overhead and latency. For example, creating 33,847 documents, one at a time, took 726 seconds (~12 min). Thankfully CouchDB has a bulk create mode. Creating the same documents 1,000 at a time took 58 seconds. That&#8217;s a 1,250% improvement! An added benefit of using bulk create is that it consumes less hard disk space (28.2MB vs 213.2MB).</p>
<h2>CouchDB Views vs RDBMS Tables</h2>
<p>Now that I could get my data in the database in a decent amount of time, I wanted to aggregate some of it together in a view. Before I get into too many details, let me explain how I think about CouchDB views. I&#8217;m a very spatial thinker, and so visualizing the similarities and differences between CouchDB views and traditional RDBMS tables helps me to understand how they work. It may be stupid, it may be naive, it may even be wrong, but here goes: Imagine a RDBMS database. Imagine a handful of tables in that database, each with different columns. Now imagine that <em>every</em> row in <em>every</em> one of those tables is just a document in CouchDB, all lumped into the same bucket (database) and with no hierarchy. <em>Views</em> are what filter and aggregate documents together to create (in a very limited sense) the equivalent of a <em>table</em>.</p>
<p>You don&#8217;t join views with each other because you&#8217;re already essentially <a href="http://www.cmlenz.net/archives/2007/10/couchdb-joins" onclick="javascript:pageTracker._trackPageview ('/outbound/www.cmlenz.net');">&#8220;joining&#8221; documents</a> (rows) to create the view. This might get you thinking that CouchDB views relate better to RDBMS views. In some ways that is true, but RDBMS views are a one-time snapshot of the underlying tables, and so for the sake of this discussion I&#8217;m leaving RDBMS views out.</p>
<h2>Indexing, the  Slowdown</h2>
<p>CouchDB view indexes are generated when the view is first called. More than one view can be stored inside a design document, but as long as they&#8217;re in the same doc they get generated (and updated) at the same time. After that initial creation, updating the view indexes is incremental based on what documents in the database are added, edited, or deleted. Notice I said indexes are updated based on what documents are modified in the <em>database</em>. <em>This is an important point!</em>, something that wasn&#8217;t obvious to me initially.  There are no tables. This is no hierarchy. No isolation. Modifying any documents in the database means that <em>all</em> view indexes in all design documents have to be updated.</p>
<p>The only time view generation is isolated is when a new design document is created or updated. In this case, though, the process is <em>not</em> incremental. For this reason, if you plan to store a large number of documents I strongly suggest that you work out and create your design documents before populating your database. Although CouchDB is a schema-less database, creating views for a large data set is currently much like designing a schema: you mostly do it before filling your database with data, and you generally don&#8217;t change it often. Why? Because generating views is currently a slow process, and gets slower the more documents you have. As a point of reference, for my example of 33,847 documents it took me 6,705 seconds (~1.86 hours) to generate a view for the first time. Retrieving the view after that took 0.006 seconds.</p>
<h2>Improving Speed Now, and in the Future</h2>
<p>In some cases it is possible speed up view generation by priming the view as you create documents. This method has great results. For example, if I create 33,847 documents in batches of 1,000, calling my view after every bulk create, the whole process takes 219 seconds (~3.65 min). If we compare the time it takes to insert the documents and then generate a view separately vs doing them at the same time, the latter is 3,088% faster (58 + 6,705 / 219 = 30.88).</p>
<p>CouchDB uses an implementation of <a href="http://en.wikipedia.org/wiki/MapReduce" onclick="javascript:pageTracker._trackPageview ('/outbound/en.wikipedia.org');">MapReduce</a> for generating views. Currently though, view generation cannot be distributed across several nodes. I&#8217;ve been told this feature is on the development roadmap, and so chances are view generation will get much, much faster in the (hopefully) not too distant future. Also worth noting, is that CouchDB has not yet been optimized, and <a href="http://damienkatz.net/2007/12/thoughts_on_opt.html" onclick="javascript:pageTracker._trackPageview ('/outbound/damienkatz.net');">Damien is quite optimistic</a> about its potential, as am I.</p>
<p>Now, I have only been working with CouchDB for a week, so it&#8217;s quite possible my understanding of something might be off. If so, please correct me. Working with CouchDB has been a load of fun (and education). I&#8217;m really looking forward to where it goes in the future, and I hope to do what I can get help get it there.</p>
<p><strong>UPDATE: </strong>For anyone that might be interested, you can get the import script I&#8217;m using from my <a href="http://bazaar.launchpad.net/~seanmurphy/otherwords/trunk/annotate/head%3A/libs/load_thesaurus.php" onclick="javascript:pageTracker._trackPageview ('/outbound/bazaar.launchpad.net');">Launchpad.net repository</a>. Depending on what you&#8217;re doing it might be a decent start. The script has a few nice features like resuming interrupted imports, bulk inserts with priming, and graceful handling of failed bulk inserts.</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2008/09/08/couchdb-view-generation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>LongURL&#8212;Restoring Order to the Universe</title>
		<link>http://iamseanmurphy.com/2008/08/28/longurlrestoring-order-to-the-universe/</link>
		<comments>http://iamseanmurphy.com/2008/08/28/longurlrestoring-order-to-the-universe/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 02:41:22 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[longurl]]></category>
		<category><![CDATA[short urls]]></category>
		<category><![CDATA[tinyurl]]></category>
		<category><![CDATA[ubiquity]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2008/08/28/longurlrestoring-order-to-the-universe/</guid>
		<description><![CDATA[It&#8217;s been two weeks since I conceptualized LongURL, and a productive two weeks at that! Last Monday I officially launched the service (which provides a handy REST API) with support for a dozen or so shortening services like TinyURL.com. Once I stepped away from the problem for a little while I realized there was a [...]


Related posts:<ol><li><a href='http://iamseanmurphy.com/2008/10/10/longurl-integration-for-your-website/' rel='bookmark' title='Permanent Link: LongURL Integration For Your Website'>LongURL Integration For Your Website</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been two weeks since I conceptualized <a href="http://longurl.org" title="The Universal Way to Expand Shortened URLs" onclick="javascript:pageTracker._trackPageview ('/outbound/longurl.org');">LongURL</a>, and a productive two weeks at that! Last Monday I officially launched the service (which provides a handy REST API) with support for a dozen or so shortening services like TinyURL.com. Once I stepped away from the problem for a little while I realized there was a better way to go about solving it. Thankfully the way I designed the service didn&#8217;t make it very difficult to swap out that bit of business logic, so this week I rolled-out an update that adds support for <strong>all</strong> shortening services.</p>
<p>After getting feedback from some helpful beta testers (thanks <a href="http://marjoleinkatsma.com/personal/cv.html" onclick="javascript:pageTracker._trackPageview ('/outbound/marjoleinkatsma.com');">Marjolein</a> and <a href="http://forteller.net" onclick="javascript:pageTracker._trackPageview ('/outbound/forteller.net');">Børge</a>!) and making a few tweaks I was happy yesterday to release the LongURL Mobile Expander <a href="http://userscripts.org/scripts/show/32115" onclick="javascript:pageTracker._trackPageview ('/outbound/userscripts.org');">Greasemokey script</a> and <a href="https://addons.mozilla.org/en-US/firefox/addon/8636" onclick="javascript:pageTracker._trackPageview ('/outbound/addons.mozilla.org');">Firefox extension</a> which use the LongURL API to expand shortened URLs on <strong>any</strong> web page. I haven&#8217;t had much feedback from others yet, but for me personally, the extension tremendously improves my user experience. Sorry guys, no more rickrolling <em>me</em>!</p>
<p><span id="more-19"></span><br />
Also, with the release of the incredibly awesome <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/" onclick="javascript:pageTracker._trackPageview ('/outbound/labs.mozilla.com');">Ubiquity</a> extension from Mozilla Labs, I started work on a LongURL command which <strike>I hope to finish/release in the next day or so</strike> I just released. You can subscribe to the command from the <a href="http://longurl.org/tools" onclick="javascript:pageTracker._trackPageview ('/outbound/longurl.org');">LongURL Tools</a> page. Does that sound like something that would be of interest to you? Have any ideas on how you&#8217;d like it to work? If so, leave a comment.</p>
<p>I would like to mention too that this has been the first time I&#8217;ve really used the <a href="http://launchpad.net" onclick="javascript:pageTracker._trackPageview ('/outbound/launchpad.net');">launchpad.net</a> platform for managing my project. It&#8217;s been a super experience; I don&#8217;t know why I didn&#8217;t start using it sooner, especially since I&#8217;ve been so <a href="http://elliotmurphy.com" onclick="javascript:pageTracker._trackPageview ('/outbound/elliotmurphy.com');">close to it</a>. And bazaar? Well, let me just say that I&#8217;ll no longer be using Subversion as my VCS of choice. Bazaar rocks, and if you haven&#8217;t given it a try, I strongly suggest you do so. You won&#8217;t regret it.</p>
<p>A final note: as you can tell, I don&#8217;t always get around to blogging about cool stuff I&#8217;m working on right away (if at all), so if you&#8217;d like to get updates as soon as possible I suggest following me on Twitter (<a href="http://twitter.com/iamseanmurphy" onclick="javascript:pageTracker._trackPageview ('/outbound/twitter.com');">iamseanmurphy</a>) and/or identi.ca (<a href="http://identi.ca/seanmurphy" onclick="javascript:pageTracker._trackPageview ('/outbound/identi.ca');">seanmurphy</a>). 140 characters just seems so much more digestible to me.</p>


<p>Related posts:<ol><li><a href='http://iamseanmurphy.com/2008/10/10/longurl-integration-for-your-website/' rel='bookmark' title='Permanent Link: LongURL Integration For Your Website'>LongURL Integration For Your Website</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2008/08/28/longurlrestoring-order-to-the-universe/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>MySQL SELECT Entries Before NOW()</title>
		<link>http://iamseanmurphy.com/2008/02/19/mysql-select-entries-before-now/</link>
		<comments>http://iamseanmurphy.com/2008/02/19/mysql-select-entries-before-now/#comments</comments>
		<pubDate>Tue, 19 Feb 2008 22:57:22 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[now]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[query cache]]></category>
		<category><![CDATA[rounded time]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2008/02/19/mysql-select-entries-before-now/</guid>
		<description><![CDATA[I’m in the business of making things faster. Using NOW() in a SQL query is something I’m going to complain about. Here’s a familiar scenario from the online publishing industry where future dating articles is a commonality:
You have a news site. You need to display only articles that have been published, and one of the [...]


Related posts:<ol><li><a href='http://iamseanmurphy.com/2007/08/20/natural-order-numerical-sorting/' rel='bookmark' title='Permanent Link: Natural Order Numerical Sorting'>Natural Order Numerical Sorting</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I’m in the business of making things faster. Using NOW() in a SQL query is something I’m going to complain about. Here’s a familiar scenario from the online publishing industry where future dating articles is a commonality:</p>
<p>You have a news site. You need to display only articles that have been published, and one of the criteria is that they need to have a publish_date before now. Easy, peasy, lemon squeezy.</p>
<p><span id="more-3"></span>
<pre name="code" class="sql">SELECT author, title, body FROM articles WHERE publish_date &lt;= NOW();</pre>
<p>That works, right? Yeeeeah, it works, but it isn’t <em>optimal</em>. The problem is that MySQL can’t use the query cache on any query that has NOW() in it (or CURRENT_TIME() or any of <a href="http://dev.mysql.com/doc/refman/5.0/en/query-cache-how.html" title="How MySQL Query Cache Works" onclick="javascript:pageTracker._trackPageview ('/outbound/dev.mysql.com');">these other functions</a> for that matter).  The solution I like to use is have PHP generate the timestamp. Even better is to have PHP round the timestamp, like so:</p>
<pre name="code" class="php">// Calculate time to nearest 15 minutes
$roundness = 60 * 15;
$rounded_now = (round(time() / $roundness) * $roundness);
$sql = "SELECT author, title, body FROM articles WHERE publish_date &lt;= $rounded_now";</pre>
<p>Of course, depending on how time sensitive your application is, you may need to change the code from rounding to 15 minutes to something like 5 minutes, or 1 minute. Hey, even rounding to 30 seconds would be better than using NOW() because you can use query cache!</p>


<p>Related posts:<ol><li><a href='http://iamseanmurphy.com/2007/08/20/natural-order-numerical-sorting/' rel='bookmark' title='Permanent Link: Natural Order Numerical Sorting'>Natural Order Numerical Sorting</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2008/02/19/mysql-select-entries-before-now/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The New SPEEDtv.com</title>
		<link>http://iamseanmurphy.com/2008/02/10/the-new-speedtvcom/</link>
		<comments>http://iamseanmurphy.com/2008/02/10/the-new-speedtvcom/#comments</comments>
		<pubDate>Sun, 10 Feb 2008 13:10:21 +0000</pubDate>
		<dc:creator>Sean Murphy</dc:creator>
				<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://iamseanmurphy.com/2008/02/10/the-new-speedtvcom/</guid>
		<description><![CDATA[February 6th has come, and it has gone. After much toil and many, many long days, the largest development project MindComet has ever undertaken launched on time. That statement alone is worth celebrating.
Whether the project ends up being a glorious success to the end users or not, as a developer I can make it something [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>February 6th has come, and it has gone. After much toil and many, many long days, the largest development project <a href="http://mindcomet.com" title="Interactive Marketing Agency" onclick="javascript:pageTracker._trackPageview ('/outbound/mindcomet.com');">MindComet</a> has ever undertaken launched on time. That statement alone is worth celebrating.</p>
<p>Whether the project ends up being a glorious success to the end users or not, as a developer I can make it something to be proud of in the lessons I take away from it. For example, here&#8217;s one thing I discovered about myself: I like BIG. I like the challenge&#8230;the complexity&#8230;the impact. Big forces you to approach problems in a different, often better, way. Big challenges your development processes and methodologies when you may otherwise be content. Big requires skills, tools, and architectures you don&#8217;t normally get to use with small. Big magnifies your weaknesses, and exposes your flaws&#8211;refining those who learn from it. And in the end, if you can make it to the finish; if you can reach your goal&#8211;you&#8217;re a cut above the rest. Here&#8217;s to big. Here&#8217;s to the <a href="http://speedtv.com" title="The leader in online motorsports news." onclick="javascript:pageTracker._trackPageview ('/outbound/speedtv.com');">SPEEDtv</a> development team.</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://iamseanmurphy.com/2008/02/10/the-new-speedtvcom/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
