<?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>Stut.net</title>
	<atom:link href="http://stut.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://stut.net</link>
	<description>Ramblings of a random software engineer</description>
	<lastBuildDate>Fri, 19 Feb 2010 00:14:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>TweetMeme Live Test Video from April 2009</title>
		<link>http://stut.net/2010/02/19/tweetmeme-live-test-video-from-april-2009/</link>
		<comments>http://stut.net/2010/02/19/tweetmeme-live-test-video-from-april-2009/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 00:14:10 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://stut.net/?p=457</guid>
		<description><![CDATA[
The other day I was continuing my long-term quest to sort through all the flotsam and jetsam of accumulated crap on my hard drive when I came across the following video (click through if you don&#8217;t see the video below). Recorded in April 2009, it shows the first version of the TweetMeme Live functionality without [...]]]></description>
			<content:encoded><![CDATA[
<p>The other day I was continuing my long-term quest to sort through all the flotsam and jetsam of accumulated crap on my hard drive when I came across the following video (click through if you don&#8217;t see the video below). Recorded in April 2009, it shows the first version of the <a href="http://www.tweetmeme.com/">TweetMeme</a> Live functionality without any rate or minimum retweet restrictions. As you can see it moved pretty quickly.</p>
<p><span id="more-457"></span>
<p style="text-align:center;"><center><object width="500" height="405"><param name="movie" value="http://www.youtube-nocookie.com/v/IdzvCoNncgY&#038;hl=en_US&#038;fs=1&#038;color1=0x3a3a3a&#038;color2=0x999999&#038;border=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube-nocookie.com/v/IdzvCoNncgY&#038;hl=en_US&#038;fs=1&#038;color1=0x3a3a3a&#038;color2=0x999999&#038;border=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="405"></embed></object></center></p>
<p>Bear in mind that these are unique URLs, not simply repeats of URLs already seen. Between seeing a URL in a tweet and it appearing on this page the system has followed any redirects, grabbed and parsed the contents of the page and stuffed it into a database, and it does it all in near-realtime. Pretty impressive stuff if you ask me.</p>
<p>The live functionality on <a href="http://www.tweetmeme.com/">TweetMeme.com</a> has now been removed, but it was great fun to develop and demonstrated the rate at which the site discovered and processed new URLs back in April 2009; you can bet the rate is far higher now given the explosion in the popularity of <a href="http://www.twitter.com/stut">Twitter</a> since then.</p>
<p>The implementation used long-polling requests connected to an nginx module which internally checked a queue for new items. While it didn&#8217;t get a huge number of concurrent viewers during the time it was up on the site it scaled incredibly well for such a simple solution.</p>
<p>It&#8217;s a shame that it&#8217;s not available on the site anymore; it would be interesting to see how much the rate has increased in the past ten months.</p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2009/01/25/alexei-arkhipovskiy-sharmanka/" rel="bookmark" class="crp_title">Alexei Arkhipovskiy &#8211; Sharmanka</a></li><li><a href="http://stut.net/2009/03/23/extreme-sheep-led-art/" rel="bookmark" class="crp_title">Extreme Sheep LED Art</a></li><li><a href="http://stut.net/2006/09/29/knex-roller-coaster/" rel="bookmark" class="crp_title">Knex Roller Coaster</a></li><li><a href="http://stut.net/2008/01/28/tweetmeme-launch/" rel="bookmark" class="crp_title">Tweetmeme Launch</a></li><li><a href="http://stut.net/2006/09/29/amazing-machines/" rel="bookmark" class="crp_title">Amazing Machines</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2010/02/19/tweetmeme-live-test-video-from-april-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Goals for 2010</title>
		<link>http://stut.net/2010/01/15/goals-for-2010/</link>
		<comments>http://stut.net/2010/01/15/goals-for-2010/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 19:14:24 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://stut.net/?p=433</guid>
		<description><![CDATA[
I&#8217;ve put a post up on my personal blog detailing my goals for 2010 and this post will expand on some of the ideas I&#8217;ve had for the work goal.
The core of the goal is to create more freedom. Freedom to do what I want to do. Freedom to work when and how I want [...]]]></description>
			<content:encoded><![CDATA[
<p>I&#8217;ve put a post up on my personal blog detailing <a href="http://stuartdallas.com/goals-for-2010">my goals for 2010</a> and this post will expand on some of the ideas I&#8217;ve had for the work goal.</p>
<p>The core of the goal is to create more freedom. Freedom to do what I want to do. Freedom to work when and how I want to. Freedom to experiment with new ways of earning a living.</p>
<p><span id="more-433"></span><br />
<h2>Teaching</h2>
<p>When I wonder what I&#8217;m passionate about I see a common thread&#8230; I love to teach people. Whether it&#8217;s teaching a class of kids, training a group of adults, mentoring an employee or answering questions in mailing lists, I love to share my knowledge and experience. I love seeing the &#8220;I get it!&#8221; moments and generally watching people develop new skills.</p>
<p>I have a couple of ideas when it comes to exploring this passion. I&#8217;m going to create a set of screencasts on at least one topic, possibly two. I haven&#8217;t decided what model to use for revenue yet, if any, but the first few episodes will definitely be free forever.</p>
<p>I want to look at what else I can do in this area because it&#8217;s a very important part of my personality and I know I have a lot to give.</p>
<h2>Photography</h2>
<div style="float: right; padding-left: 8px; padding-bottom: 4px;"><a title="View '' on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/3974560256"><img style="border: 1px solid #bebebe;" src="http://farm3.static.flickr.com/2603/3974560256_195892053d_m.jpg" border="0" alt="" width="240" height="160" /></a></div>
<p>I love photography, and this year I want to develop this passion and my existing skills. I have recently had my first exposure of on-location portrait photography and I found it extremely fulfilling. <a href="/2009/11/26/in-search-of-models/">I want to do more of it</a>.</p>
<p>I want to start building a stock portfolio. Over the years I&#8217;ve taken some excellent stock shots, but I&#8217;m yet to have one accepted by <a href="http://www.istockphoto.com/">iStockphoto</a>. The reasons given have been varied, but tend to be around the areas of resolution (old camera), sharpness (interpolation didn&#8217;t fool them) and subjects. I think I have a great eye for this type of shot but I&#8217;ve never taken photos specifically for that purpose. That will change this year.</p>
<h2>Travel</h2>
<p>Generally speaking I hate taking holidays, but I&#8217;ve realised that this is due to my attitude to the word. Travel is something else entirely. I really enjoy exploring new places. When combined with photography it&#8217;s completely different, so I want to do a lot more of it this year.</p>
<p>I haven&#8217;t worked out any details yet but I&#8217;m planning a number of trips both within the UK and beyond. Some will be day trips, others will be weekends and a couple will be longer, but the idea is to get out there and see the world, little by little <img src='http://stut.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>As soon as I post the form to get my passport renewed&#8230;&#8230;&#8230;.</p>
<h2>Consulting</h2>
<div style="float: right; padding-left: 8px; padding-bottom: 4px;"><a title="View 'Online 2' on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/481929512"><img style="border: 1px solid #bebebe;" src="http://farm1.static.flickr.com/172/481929512_f76fa4d5c9_m.jpg" border="0" alt="Online 2" width="240" height="149" /></a></div>
<p>I really love internet-based technologies. Design, development, languages, architecture, tools, strategies, SEO&#8230; everything about the internet excites me&#8230; except coding. These days I&#8217;m finding that spending my hours coding away, writing the same stuff I&#8217;ve always written is leaving me excessively deflated. Except when I have an interesting problem to solve.</p>
<p>There&#8217;s nothing I like more than when a new and interesting problem comes along that needs solving. I will happily spend 48 hours straight designing and coding a solution, because it has grabbed my attention. If coding&#8217;s what I&#8217;m going to be doing then that&#8217;s the sort of coding I need to find. If not then I want to be architecting solutions.</p>
<p>In an ideal world I would be consulting for a number of startup companies, bringing my broad range of expertise and experience to the table without the burden of a full-time employee. If you&#8217;d like to talk about how I can help you check out <a href="http://uk.linkedin.com/in/stuartdallas">my LinkedIn profile</a> and/or <a href="http://3ft9.com/contact/">contact me</a>.</p>
<h2>And more&#8230;</h2>
<p>That doesn&#8217;t cover everything I have planned but it&#8217;s the key points and all I&#8217;m willing to reveal publicly <img src='http://stut.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . I&#8217;m very excited about the next twelve months and the opportunities and experiences they&#8217;ll bring. If you want to be a part of it, let me know.</p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2009/11/26/in-search-of-models/" rel="bookmark" class="crp_title">In search of models</a></li><li><a href="http://stut.net/2008/11/11/holiday-2008-part-1-the-scottish-highlands/" rel="bookmark" class="crp_title">Holiday 2008 part 1: The Scottish Highlands</a></li><li><a href="http://stut.net/2009/01/23/automated-content-failure/" rel="bookmark" class="crp_title">Automated content failure</a></li><li><a href="http://stut.net/2007/05/06/canon-speedlite-580ex-flash/" rel="bookmark" class="crp_title">Canon Speedlite 580EX Flash</a></li><li><a href="http://stut.net/2009/01/24/oauth-and-twitter-realistic-expectations/" rel="bookmark" class="crp_title">OAuth and Twitter: Realistic expectations</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2010/01/15/goals-for-2010/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>In search of models</title>
		<link>http://stut.net/2009/11/26/in-search-of-models/</link>
		<comments>http://stut.net/2009/11/26/in-search-of-models/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 21:45:00 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Photography]]></category>

		<guid isPermaLink="false">http://stut.net/blog/?p=396</guid>
		<description><![CDATA[

I&#8217;m looking to develop my portrait photography skills so I&#8217;m throwing this out there to see if anyone&#8217;s interested in a free photo session. I take a lot of photos but aside from weddings I generally haven&#8217;t had a lot of experience taking pictures of people. I want to change that.
So here&#8217;s the deal. I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[
<div style="float: left; line-height: 0.7em; padding: 0; margin: 0 0.5em 0.25em 0; border: 2px solid #000;"><a style="margin: 0; padding: 0;" title="View on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/4004701674"><img style="padding: 0; margin: 2px; border: 1px solid #000;" src="http://farm4.static.flickr.com/3525/4004701674_4b09ac20d7_m.jpg" border="0" alt="" width="240" height="160" /></a></div>
<p>I&#8217;m looking to develop my portrait photography skills so I&#8217;m throwing this out there to see if anyone&#8217;s interested in a free photo session. I take a lot of photos but aside from weddings I generally haven&#8217;t had a lot of experience taking pictures of people. I want to change that.</p>
<p><span id="more-396"></span>So here&#8217;s the deal. I&#8217;m offering to do on-location photo shoots with you and anyone else you want to involve; just you, you and your partner, you and your friends, whatever. This will give me further experience of taking portraits and add to my portfolio. As such I will require that everyone involved signs a model release.</p>
<div style="float: right; line-height: 0.7em; padding: 0; margin: 0 0 0.25em 0.5em; border: 2px solid #000;"><a style="margin: 0; padding: 0;" title="View 'Jared with a very big lens' on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/3004433984"><img style="padding: 0; margin: 2px; border: 1px solid #000;" src="http://farm4.static.flickr.com/3291/3004433984_d23c4661be_m.jpg" border="0" alt="Jared with a very big lens" width="160" height="240" /></a></div>
<p>In return you&#8217;ll get a CD containing full size image files of the best shots from the shoot and you&#8217;re welcome to do anything non-commercial with them. If you want to use them commercially you&#8217;ll need to get my permission, but I don&#8217;t see that ever being a problem. I&#8217;m also more than happy to get them professionally printed and optionally mounted.</p>
<p>I&#8217;m based in Surrey but would be willing to travel a reasonable distance &#8211; at the moment I don&#8217;t really know how far that is so let me know where you are and I&#8217;ll decide whether it&#8217;s too far or not <img src='http://stut.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>The location is completely up to you, or if I know the area I&#8217;ll happily recommend places. It&#8217;s up to you to let me know what you want to get from it, in terms of the experience and the resulting photos. I don&#8217;t have a studio or any studio equipment but I&#8217;ve found the best shots come from a less formal environment.</p>
<p>If you&#8217;re interested or have any questions please don&#8217;t hesitate to <a href="/who#contact">contact me</a>. If you don&#8217;t ask I can&#8217;t say yes!<br />
<center><br />
<table style="border: 2px solid #000;" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding: 2px; line-height: 0.7em;"><a style="margin: 0; padding: 0;" title="View on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/4004703974"><img style="margin: 0; padding: 0; border: 2px solid #000; margin-right: 1px;" src="http://farm3.static.flickr.com/2423/4004703974_9be36aaab4_m.jpg" border="0" alt="" width="159" height="240" /></a></td>
<td style="padding: 2px; line-height: 0.7em;"><a style="margin: 0; padding: 0;" title="View 'GG' on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/3025781308"><img style="margin: 0; padding: 0; border: 1px solid #000;" src="http://farm4.static.flickr.com/3032/3025781308_81afafd5f7_m.jpg" border="0" alt="GG" width="168" height="240" /></a></td>
<td style="padding: 2px; line-height: 0.7em;"><a style="margin: 0; padding: 0;" title="View on Flickr.com" href="http://www.flickr.com/photos/7913872@N03/4003943833"><img style="margin: 0; padding: 0; border: 1px solid #000;" src="http://farm3.static.flickr.com/2495/4003943833_729e716a50_m.jpg" border="0" alt="" width="160" height="240" /></a></td>
</tr>
</tbody>
</table>
<p></center></p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2009/01/23/automated-content-failure/" rel="bookmark" class="crp_title">Automated content failure</a></li><li><a href="http://stut.net/2008/11/11/holiday-2008-part-1-the-scottish-highlands/" rel="bookmark" class="crp_title">Holiday 2008 part 1: The Scottish Highlands</a></li><li><a href="http://stut.net/2010/01/15/goals-for-2010/" rel="bookmark" class="crp_title">Goals for 2010</a></li><li><a href="http://stut.net/2007/07/07/the-windsor-wheel/" rel="bookmark" class="crp_title">The Windsor Wheel</a></li><li><a href="http://stut.net/2009/01/24/oauth-and-twitter-realistic-expectations/" rel="bookmark" class="crp_title">OAuth and Twitter: Realistic expectations</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/11/26/in-search-of-models/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What&#8217;s going on?</title>
		<link>http://stut.net/2009/11/02/whats-going-on/</link>
		<comments>http://stut.net/2009/11/02/whats-going-on/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 12:25:32 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://stut.net/blog/?p=388</guid>
		<description><![CDATA[
I know it&#8217;s been a while since posted anything on this blog, but I&#8217;ve had a lot going on and it hasn&#8217;t really been at the forefront of my mind. So, what&#8217;s been going on?
Firstly I&#8217;ve shut TwitApps.com down. I won&#8217;t go into the reasons because they&#8217;re well documented in the blog post announcing it. [...]]]></description>
			<content:encoded><![CDATA[
<p>I know it&#8217;s been a while since posted anything on this blog, but I&#8217;ve had a lot going on and it hasn&#8217;t really been at the forefront of my mind. So, what&#8217;s been going on?</p>
<p><span id="more-388"></span>Firstly <a href="http://twitapps.com/">I&#8217;ve shut TwitApps.com down</a>. I won&#8217;t go into the reasons because they&#8217;re well documented in <a href="http://3ft9.com/10-twitapps-shutting-down">the blog post announcing it</a>. I&#8217;ve also <a href="http://3ft9.com/17-twitapps-code-released">released the code</a> so anyone can make a clone if they feel so inspired. One big side effect of this is that I&#8217;m open to offers for that domain name and a bunch of others I don&#8217;t see myself using anymore. Please only contact me with serious offers.</p>
<p>Secondly I&#8217;ve been doing a lot of soul searching lately, and one of the results of that has been my <a href="http://stuartdallas.com/">new blog over at stuartdallas.com</a> where I&#8217;m writing for my benefit rather than as a service to others, which is how I view this site. Check it out and let me know what you think.</p>
<p>Finally I have been all over the place in terms of my career lately, which I&#8217;ve <a href="http://stuartdallas.com/my-new-plan">written about on my new blog</a> so I won&#8217;t repeat it here. Ultimately it means I&#8217;m on the lookout for interesting projects to get involved with. If you think I may be able to help you or your company please let me know.</p>
<p>Hopefully that explains where I&#8217;ve been. I plan to continue publishing tech and development posts on this site for the foreseeable future, but how often depends on how much my focus gets split in my new reality. I also plan to change the layout of this site &#8211; it&#8217;s starting to depress me because I never really finished it.</p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2008/12/05/new-company-site-for-3ft9/" rel="bookmark" class="crp_title">New company site for 3ft9</a></li><li><a href="http://stut.net/2009/01/31/twitter-unfollows-too-much-information/" rel="bookmark" class="crp_title">Twitter unfollows: too much information?</a></li><li><a href="http://stut.net/2007/11/19/that-other-bit-of-news/" rel="bookmark" class="crp_title">That other bit of news</a></li><li><a href="http://stut.net/2009/03/08/handling-email-notifications-from-twitter/" rel="bookmark" class="crp_title">Handling email notifications from Twitter</a></li><li><a href="http://stut.net/2007/05/05/switched-to-wordpress/" rel="bookmark" class="crp_title">Switched to Wordpress</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/11/02/whats-going-on/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Job Queue</title>
		<link>http://stut.net/2009/05/29/php-job-queue/</link>
		<comments>http://stut.net/2009/05/29/php-job-queue/#comments</comments>
		<pubDate>Fri, 29 May 2009 20:26:58 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://stut.net/blog/?p=380</guid>
		<description><![CDATA[
One of the pillars of a scalable website is ensuring that only activity which is required to build a page should be performed during the processing of a page request. Activities that fall under this category commonly include sending emails, recording statistics and general housekeeping such as removing temporary files.
Back when I started working on [...]]]></description>
			<content:encoded><![CDATA[
<p>One of the pillars of a scalable website is ensuring that only activity which is required to build a page should be performed during the processing of a page request. Activities that fall under this category commonly include sending emails, recording statistics and general housekeeping such as removing temporary files.</p>
<p>Back when I started working on sites big enough for these activities to cause a problem I went down the obvious route of making a PHP CLI script for each job that needed doing and getting it to run using cron. This worked for a while but as the sites I was working on got bigger and more complex it quickly became clear that this was becoming difficult to manage, so I started to consider alternatives.</p>
<p><span id="more-380"></span>At the time all this happened I was mainly working with a site that ran on <a href="http://www.zend.com/en/products/platform/" target="_blank">Zend Platform</a>. One of the recent additions at the time was a module called <a href="http://www.zend.com/en/products/platform/product-comparison/job-queues" target="_blank">Job Queue</a> which appeared to do exactly what I needed. Unfortunately after spending a fair amount of time developing the infrastructure required to make it run the jobs I discovered that it really wasn&#8217;t very well tested; it was far from production quality <a href="#fn1">[1]</a> and nowhere near reliable enough so I went back to the drawing board.</p>
<h2>Time passes&#8230;</h2>
<p>After thinking about what I needed from such a system and what I had available I came up with an arrangement I&#8217;ve been using ever since with great success.</p>
<p>The core of the system is a DB table and a PHP script. The table contains the definition of jobs that need running and the script, erm, runs them.</p>
<p>I won&#8217;t go into the details of the table because the only important parts as far as this system go are the run_at, processor_pid and schedule_* fields.</p>
<p>The <em>run_at</em> field is a timestamp that simply indicates the time when that job should be executed.</p>
<p>The <em>processor_pid</em> field is an unsigned integer that defaults to 0 and will indicate the process that&#8217;s running a job if any.</p>
<p>The <em>schedule_*</em> fields specify how often the job should be executed. There are a number of ways of organising these depending on what your requirements are, but they fall into two general categories.</p>
<div style="padding-left: 1.5em;">
	<strong>Periodic only</strong><br />
	If you only need to say &#8220;run again in <em>n</em> seconds&#8221; then this is the one for you. Use a single field called <em>schedule</em> and put <em>n</em> in there.</p>
<p>	<strong>Complex</strong><br />
	If you need something more flexible then you&#8217;ll need to use a number of fields (or a single field you can parse) to specify how to calculate the next run_at time. For example a period (daily, weekly, monthly or anually) and a day/time field allows you to configure any of the following&#8230;</p>
<ul>
<li>Every day at 10am</li>
<li>Every Monday at 1am</li>
<li>The 1st of every month at midnight</li>
<li>Every year on February 14th at 8pm</li>
<li>etc&#8230;</li>
</ul>
</div>
<p>Before I move on to the script I apparently need to cover something that I missed when I first wrote this. <strong>You need to specify what to run in this table!</strong> I though this was pretty obvious but based on initial feedback I was wrong.</p>
<p>This can take any number of forms and will depend greatly on your specific application. Over the years I&#8217;ve used a number of different methods including a PHP script name, a CLI command and a method in a static class. Whatever you use you&#8217;ll want to make sure you do sufficient checks to ensure it&#8217;s secure.</p>
<p>Ok, on to the script which is designed to be run by cron according to a schedule that allows it to keep up with the size of the job queue you anticipate.</p>
<p>The following is a list of the basic steps the script performs. For this example I&#8217;m continuing with the assumption that the job queue is a table in a database.</p>
<ol>
<li>
		Get the pid and put it in $pid.
	</li>
<li>
		Execute this SQL query&#8230;</p>
<div style="padding-left: 1.5em; font-family: monospace;">
			update `job_queue`<br />
			set `processor_pid` = &#8220;$pid&#8221;<br />
			where `run_at` <= unix_timestamp()<br />
			&nbsp;&nbsp;and `processor_pid` = 0<br />
			order by run_at asc<br />
			limit 1
		</div>
</li>
<li>
		Check mysql_affected_rows() and exit if 0.
	</li>
<li>
		Execute this SQL query&#8230;</p>
<div style="padding-left: 1.5em; font-family: monospace;">
			select * from `job_queue`<br />
			where `processor_pid` = &#8220;$pid&#8221;
		</div>
<p>		Note that these SQL statements (step 2 and this one) atomically grab a job and lock it. If you&#8217;re using a different storage system for your queue you&#8217;ll need to lock it while you select a job to run and then mark it as in progress.
	</li>
<li>
		Run the job. As mentioned already this can mean any number of things and will depend on your particular application. One of the useful things you can do here is to set up a clean, safe environment for the job to run in, along with ways to capture errors and other outputs so you can do something useful with them.
	</li>
<li>
		As soon as the job has finished executing we mark it as completed and record the success or failure status.
	</li>
<li>
		If the job has a schedule (i.e. it&#8217;s a recurring job) we create a new job by effectively cloning the job we&#8217;ve just run. We now calculate the time it should be run according to the schedule definition and save that in the run_at field of the new job. Finally we set the <em>processor_pid</em> of the new job to 0 so it&#8217;s then available to step 2 of this process.
	</li>
<li>
		Depending on the job configuration and status we now either remove the completed job from the queue or archive it complete with errors and output for later inspection.
	</li>
<li>
		If this processor has been running for > 60 minutes it exits, otherwise it goes back to step 2 and looks for another job to run.
	</li>
</ol>
<p>To get this to do something useful we configure it to run via cron every <em>n</em> minutes where <em>n</em> depends upon the anticipated size of your job queue. For example running it every minute will automatically scale it up to 60 concurrent jobs at any one time. Running it every 5 minutes will reduce this to 12, and so on. There&#8217;s also nothing stopping you putting more than one line into the crontab so it runs two processes every minute which increases concurrent processors to 120.</p>
<p>Assuming your job queue is network accessible this system also scales across multiple machines with minimal changes. In fact the only change that&#8217;s required it to incorporate a machine identified into the <em>processor_pid</em> field. This could be as simple as <em>&lt;machine&gt;_&lt;pid&gt;</em>; the key thing is that it&#8217;s guaranteed to be unique to a given process across your entire infrastructure.</p>
<h2>Crashed jobs</h2>
<p>One problem you may need to deal with is how to handle crashed jobs. This will happen, you can&#8217;t get away from it and you&#8217;ll need a way to detect and deal with it when it does. Luckily the job queue makes detection fairly straightforward.</p>
<p>On a single machine you can implement a script (either run via cron separately or indeed run by the job queue) that will check that for each job that has a <em>processor_pid</em> > 0 there is a PHP process running with that PID.</p>
<p>If and when you&#8217;ve scaled across multiple machines this script essentially remains the same except that you need to run it on every machine that runs the job queue and filter the PID&#8217;s you check.</p>
<p>As far as what to do when you find a crashed job that&#8217;s really something you need to consider on a case-by-case basis. At the very basic level the script could simply reset the <em>processor_pid</em> field to 0 so it gets run again. At the other end of the spectrum in a very flexible system you could have a way to run a job with a flag to indicate that it had previously crashed; each job can then deal with crashes in their own custom way.</p>
<h2>Potential additions</h2>
<p>The components described above is just the core of a job queue system; you can add a lot of useful stuff above and around it to make it easier to manage and provide better feedback from your periodic tasks.</p>
<ul>
<li>
		<strong>Performance metrics</strong><br />
		Since you&#8217;re running all your jobs from a central script adding code around the actual execution to record execution time, load and possibly memory usage too is pretty simple. You then have the ability to compare the time a job took to previous executions of that job to detect potential errors.
	</li>
<li>
		<strong>Management interface</strong><br />
		Since you have all the information regarding the jobs in the queue, what&#8217;s running right now and the status of jobs that have previously been executed it&#8217;s a pretty small leap to build a UI that will let you view and manage the whole thing. This can be especially useful for presenting error messages and performance metrics.
	</li>
</ul>
<h2>Final thoughts</h2>
<p>I hope that&#8217;s useful to someone, I&#8217;ve certainly found it applicable to most web applications I now deal with. As I mentioned a few times you can implement the various parts in a number of ways, in particular how jobs are specified and how the scheduling works.</p>
<p>As an example of this flexibility I&#8217;ll make a passing mention to one implementation I&#8217;ve done that only needed to be able to execute scripts daily, hourly or every 15 minutes. To accomplish this I simply created a folder for the scripts, and three folders named <em>15min</em>, <em>hourly</em> and <em>daily</em> within that. The processor script uses a custom locking system and CLI arguments to run each set of scripts according the the directories they&#8217;re in.</p>
<p>This system has proven to work very well and will continue to do everything that site needs until we need to execute something at a specific time; a requirement that has not yet surfaced.</p>
<p>One of the many side projects I&#8217;m working on is a reusable version of this system. At the moment it&#8217;s a fairly messy combination of scripts that doesn&#8217;t work very well so far, but as soon as I have something worth sharing I&#8217;ll definitely do so on this blog. Stay tuned.</p>
<p>If you have an questions or suggestions for improvement please don&#8217;t hesitate to leave a comment or <a href="/who#contact">contact me privately</a>.</p>
<p><a name="fn1"></a> [1] <small>This was a few years back and I&#8217;ve heard that the Job Queue module has received some attention since then so is now a lot better, but I no longer use Zend Platform so I&#8217;m not in a position to comment. If budget is not an issue for you I&#8217;d recommend checking it out.</small></p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2008/06/08/php-models-2/" rel="bookmark" class="crp_title">PHP Models</a></li><li><a href="http://stut.net/2005/06/11/pay-per-mile/" rel="bookmark" class="crp_title">Pay per mile</a></li><li><a href="http://stut.net/2005/02/05/rename-a-mysql-database/" rel="bookmark" class="crp_title">Rename a MySQL Database</a></li><li><a href="http://stut.net/2008/06/18/sending-email/" rel="bookmark" class="crp_title">Sending email</a></li><li><a href="http://stut.net/2007/11/10/web-hosting-a-mugs-game/" rel="bookmark" class="crp_title">Web hosting &#8211; a mugs game</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/05/29/php-job-queue/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Facebook gets something right</title>
		<link>http://stut.net/2009/04/29/facebook-gets-something-right/</link>
		<comments>http://stut.net/2009/04/29/facebook-gets-something-right/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 20:50:04 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://stut.net/blog/?p=376</guid>
		<description><![CDATA[
A new phishing attack against Facebook has surfaced recently using the domain fbaction.net. Whenever I see these things I always reset my browser and try signing in with fake details to see what happens. In this case I got a nice surprise. When I got redirected to Facebook I got this&#8230;

This is fantastic. Every site [...]]]></description>
			<content:encoded><![CDATA[
<p>A new phishing attack against <a href="http://www.facebook.com/">Facebook</a> has surfaced recently using the domain fbaction.net. Whenever I see these things I always reset my browser and try signing in with fake details to see what happens. In this case I got a nice surprise. When I got redirected to Facebook I got this&#8230;</p>
<div style="text-align:center;"><span id="more-376"></span><a title="Facebook gets something right by Stuart Dallas, on Flickr" href="http://www.flickr.com/photos/stuartdallas/3486344611/"><img src="http://farm4.static.flickr.com/3592/3486344611_f924e7c1d7_o.png" alt="Facebook gets something right" width="647" height="263" /></a></div>
<p>This is fantastic. Every site should do this. It&#8217;s a really simple check to do and immediately informs the user that they have probably been compromised complete with advice as to what they should do next.</p>
<p>Top marks to Facebook!</p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2007/11/04/personal-info-on-facebook/" rel="bookmark" class="crp_title">Personal info on Facebook</a></li><li><a href="http://stut.net/2007/10/10/extracting-the-map-from-social-networks/" rel="bookmark" class="crp_title">Extracting the map from social networks</a></li><li><a href="http://stut.net/2007/08/22/links-for-2007-08-21/" rel="bookmark" class="crp_title">links for 2007-08-21</a></li><li><a href="http://stut.net/2007/11/25/information-responsibility/" rel="bookmark" class="crp_title">Information Responsibility</a></li><li><a href="http://stut.net/2008/11/11/holiday-2008-part-1-the-scottish-highlands/" rel="bookmark" class="crp_title">Holiday 2008 part 1: The Scottish Highlands</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/04/29/facebook-gets-something-right/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spam poetry</title>
		<link>http://stut.net/2009/04/29/spam-poetry/</link>
		<comments>http://stut.net/2009/04/29/spam-poetry/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 15:07:31 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[Grr]]></category>

		<guid isPermaLink="false">http://stut.net/blog/2009/04/29/spam-poetry/</guid>
		<description><![CDATA[
I&#8217;ll take the position
assume the missionary part
you work by committee
you had me pegged from the start.
I&#8217;ll be pounce pony
phony maroney
pony before the cart.
I&#8217;ll be pounce pony.
this ceremony
only fills my heart.

who cast the final stone?
who threw the crushing blow?
someone has to take the fall
why not me?
a punch toy volunteer
a weakling on its knee.
is all you want [...]]]></description>
			<content:encoded><![CDATA[
<div>I&#8217;ll take the position</div>
<div>assume the missionary part<br />
you work by committee<br />
you had me pegged from the start.<br />
I&#8217;ll be pounce pony<br />
phony maroney<br />
pony before the cart.<br />
I&#8217;ll be pounce pony.<br />
this ceremony<br />
only fills my heart.</div>
<div>
<p>who cast the final stone?<br />
who threw the crushing blow?<br />
someone has to take the fall<br />
why not me?</p>
<p>a punch toy volunteer<br />
a weakling on its knee.<br />
is all you want to hear<br />
and all you want to see.<br />
romantically, you&#8217;d martyr me<br />
and miss this story&#8217;s point<br />
it is my strength, my destiny<br />
this is the role that I have chosen.</p>
<p><em>Clarification: I received about 12 copies of this to various email addresses. While annoying I thought it was pretty well done and worth preserving. I have no idea who (or what) wrote it.</em></div>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2007/06/21/recruitment-agents-an-example/" rel="bookmark" class="crp_title">Recruitment agents&#8230; an example</a></li><li><a href="http://stut.net/2007/06/17/recruitment-agencies-just-say-no/" rel="bookmark" class="crp_title">Recruitment Agencies &#8211; Just Say No!</a></li><li><a href="http://stut.net/2008/06/18/sending-email/" rel="bookmark" class="crp_title">Sending email</a></li><li><a href="http://stut.net/2007/02/16/recruiting-home-owners/" rel="bookmark" class="crp_title">Recruiting home owners</a></li><li><a href="http://stut.net/2008/10/13/requiring_unnecessary_information/" rel="bookmark" class="crp_title">Requiring unnecessary information</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/04/29/spam-poetry/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Regional Limitations</title>
		<link>http://stut.net/2009/04/13/regional-limitations/</link>
		<comments>http://stut.net/2009/04/13/regional-limitations/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 04:18:42 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Grr]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://stut.net/blog/?p=370</guid>
		<description><![CDATA[
It&#8217;s 5am and I can&#8217;t sleep. When this happens I usually fire up Boxee and find something to watch, so that&#8217;s what I did. I was happy to see that since the last time I used it Boxee appear to have added a bunch more internet sources, which is great. However, the following 15 minutes [...]]]></description>
			<content:encoded><![CDATA[
<p>It&#8217;s 5am and I can&#8217;t sleep. When this happens I usually <a href="http://boxee.tv/">fire up Boxee</a> and find something to watch, so that&#8217;s what I did. I was happy to see that since the last time I used it Boxee appear to have added a bunch more internet sources, which is great. However, the following 15 minutes were nearly the most frustrating of my life so far.</p>
<p><span id="more-370"></span>I understand regional restrictions. I don&#8217;t necessarily agree with the reason they&#8217;re there, but I understand why.</p>
<p>What I can&#8217;t understand is why they&#8217;re not shown up-front when browsing available content. On sites like <a href="http://joost.com/">Joost</a>, <a href="http://thulu.com/">Hulu</a> and others you have to actually start streaming content before you get told you can&#8217;t view it. They clearly know where you&#8217;re coming from but they still insist on not telling you what you can and can&#8217;t watch until you actually try.</p>
<p>Maybe there&#8217;s a technical reason why it works this way (I can&#8217;t think of one that couldn&#8217;t be easily worked around), or maybe there&#8217;s a licensing reason for it. Whatever the reason it makes attempting to use any of these sites more and more frustrating the more region-limited content they contain.</p>
<p>So here&#8217;s my plea&#8230; please will these sites make it clear from the highest level possible in the browsable structure whether content is viewable from my current location. That&#8217;s all I ask.</p>
<p>Boxee themselves don&#8217;t help out with this problem. Take <a href="http://thewb.com/">theWB</a> for example. You can&#8217;t access the website at all if you&#8217;re outside the US (see below), but you can if you use Boxee. Right down to the content level, but when you start streaming you then get a message telling you it&#8217;s restricted.</p>
<p style="text-align:center"><a title="theWB - US only by Stuart Dallas, on Flickr" href="http://www.flickr.com/photos/stuartdallas/3437209682/"><img src="http://farm4.static.flickr.com/3663/3437209682_c06993a424_o.png" alt="theWB - US only" width="490" height="313" /></a></p>
<p>So, Boxee and co&#8230; sort it out!!</p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2007/06/11/content-distribution/" rel="bookmark" class="crp_title">Content distribution</a></li><li><a href="http://stut.net/2008/02/15/new-stutnet-design/" rel="bookmark" class="crp_title">New Stut.net design</a></li><li><a href="http://stut.net/2009/01/31/twitter-unfollows-too-much-information/" rel="bookmark" class="crp_title">Twitter unfollows: too much information?</a></li><li><a href="http://stut.net/2008/05/23/has-that-website-gone-titsup/" rel="bookmark" class="crp_title">Has that website gone TitsUp?</a></li><li><a href="http://stut.net/2008/06/18/sending-email/" rel="bookmark" class="crp_title">Sending email</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/04/13/regional-limitations/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Extreme Sheep LED Art</title>
		<link>http://stut.net/2009/03/23/extreme-sheep-led-art/</link>
		<comments>http://stut.net/2009/03/23/extreme-sheep-led-art/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 11:21:57 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Misc]]></category>

		<guid isPermaLink="false">http://stut.net/blog/2009/03/23/extreme-sheep-led-art/</guid>
		<description><![CDATA[
Not sure if I believe this is real or not, but either way it&#8217;s a pretty cool idea.
    
If you liked this you might also like these:Alexei Arkhipovskiy &#8211; SharmankaBigDog &#8230; WOW!Amazing MachinesTweetMeme Live Test Video from April 2009Knex Roller Coaster
]]></description>
			<content:encoded><![CDATA[
<p>Not sure if I believe this is real or not, but either way it&#8217;s a pretty cool idea.</p>
<p>  <object height="295" width="480"><param name="movie" value="http://www.youtube-nocookie.com/v/D2FX9rviEhw&amp;hl=en&amp;fs=1&amp;rel=0" /><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><embed src="http://www.youtube-nocookie.com/v/D2FX9rviEhw&amp;hl=en&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" height="295" width="480"></embed></object>  </p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2009/01/25/alexei-arkhipovskiy-sharmanka/" rel="bookmark" class="crp_title">Alexei Arkhipovskiy &#8211; Sharmanka</a></li><li><a href="http://stut.net/2008/03/28/bigdog-wow/" rel="bookmark" class="crp_title">BigDog &#8230; WOW!</a></li><li><a href="http://stut.net/2006/09/29/amazing-machines/" rel="bookmark" class="crp_title">Amazing Machines</a></li><li><a href="http://stut.net/2010/02/19/tweetmeme-live-test-video-from-april-2009/" rel="bookmark" class="crp_title">TweetMeme Live Test Video from April 2009</a></li><li><a href="http://stut.net/2006/09/29/knex-roller-coaster/" rel="bookmark" class="crp_title">Knex Roller Coaster</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/03/23/extreme-sheep-led-art/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling email notifications from Twitter</title>
		<link>http://stut.net/2009/03/08/handling-email-notifications-from-twitter/</link>
		<comments>http://stut.net/2009/03/08/handling-email-notifications-from-twitter/#comments</comments>
		<pubDate>Sun, 08 Mar 2009 20:27:14 +0000</pubDate>
		<dc:creator>Stuart</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://stut.net/blog/?p=362</guid>
		<description><![CDATA[
I had a request recently to release some of the code from the TwitApps bots. The core of both bots is actually a shared email handler and I have no problem sharing it with the world.
Twitter-related stuff &#187; Handling email notifications
On the assumption that I&#8217;ll eventually get around to sharing some more Twitter-related stuff I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[
<p>I had a request recently to release some of the code from the TwitApps bots. The core of both bots is actually a shared email handler and I have no problem sharing it with the world.</p>
<p style="text-align:center;"><a href="/projects/twitter/">Twitter-related stuff</a> &raquo; <a href="/projects/twitter/email_notifications.html">Handling email notifications</a></p>
<p>On the assumption that I&#8217;ll eventually get around to sharing some more Twitter-related stuff I&#8217;ve created a new section in the projects area of this site. If there&#8217;s anything related to Twitter integration that you&#8217;d like to see me cover there please let me know and I&#8217;ll be happy to help.</p>
<div id="crp_related"><h3>If you liked this you might also like these:</h3><ul><li><a href="http://stut.net/2007/08/04/links-for-2007-08-04/" rel="bookmark" class="crp_title">links for 2007-08-04</a></li><li><a href="http://stut.net/2008/05/23/has-that-website-gone-titsup/" rel="bookmark" class="crp_title">Has that website gone TitsUp?</a></li><li><a href="http://stut.net/2008/04/04/twitter-public-timeline/" rel="bookmark" class="crp_title">Twitter public timeline</a></li><li><a href="http://stut.net/2009/01/31/twitter-unfollows-too-much-information/" rel="bookmark" class="crp_title">Twitter unfollows: too much information?</a></li><li><a href="http://stut.net/2008/01/28/tweetmeme-launch/" rel="bookmark" class="crp_title">Tweetmeme Launch</a></li></ul></div>
]]></content:encoded>
			<wfw:commentRss>http://stut.net/2009/03/08/handling-email-notifications-from-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
