<?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>Justin Carmony &#187; Programming</title>
	<atom:link href="http://www.justincarmony.com/blog/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.justincarmony.com/blog</link>
	<description>Web Designer &#38; Software Engineer</description>
	<lastBuildDate>Wed, 01 Feb 2012 04:30:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Making a Distributed Workforce Work</title>
		<link>http://www.justincarmony.com/blog/2012/01/31/making-a-distributed-workforce-work/</link>
		<comments>http://www.justincarmony.com/blog/2012/01/31/making-a-distributed-workforce-work/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 04:30:16 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[distributed workforce]]></category>
		<category><![CDATA[employees]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=1097</guid>
		<description><![CDATA[I&#8217;ve been mulling over this blog post in my mind for quite awhile. I&#8217;ve been working exclusively for distributed companies since 2008. Also know as telecommuting and virtual workforce, it basically is when you have employees working for you regardless of location. Whether it is home, a co-working space, or another office space they prefer, ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2010/02/04/the-skill-of-making-habits/' rel='bookmark' title='The Skill of Making Habits'>The Skill of Making Habits</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/07/03/mac-keyboard-quirks-making-mac-more-like-windows/' rel='bookmark' title='Mac Keyboard Quirks &#8211; Making Mac more like Windows'>Mac Keyboard Quirks &#8211; Making Mac more like Windows</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/06/29/lifehacker-making-your-mac-sing/' rel='bookmark' title='Lifehacker &#8211; Making your Mac sing!'>Lifehacker &#8211; Making your Mac sing!</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been mulling over this blog post in my mind for quite awhile. I&#8217;ve been working exclusively for distributed companies since 2008. Also know as telecommuting and virtual workforce, it basically is when you have employees working for you regardless of location. Whether it is home, a co-working space, or another office space they prefer, its when an employee can work for a company other then the office.</p>
<p>I&#8217;ve met and talked with several companies that have had a great success with this approach. Toni Schneider, CEO at <a href="http://automattic.com/">Automattic</a>, has written about the <a href="http://toni.org/2010/03/08/5-reasons-why-your-company-should-be-distributed/">5 reasons why your company should be distributed</a>. </p>
<p>But on the flip side, I&#8217;ve met a few developers, managers, and owners who have horror stories of how it &#8220;didn&#8217;t work out at all.&#8221; They talk about how these workers were too distant from their team, how they didn&#8217;t communicate well, and struggled to get them to produce. </p>
<p>These are legitimate concerns and challenges face businesses. However, I think there is one key thing businesses can do to help minimize these challenges and make their attempts to bring in a distributed workforce a reality. At to show how it can be done, we&#8217;ll use our fictional company, Muppets Software Inc:</p>
<h3>Our Example: The Muppets</h3>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/836_D_03870_R.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/836_D_03870_R-300x200.jpg" alt="" title="DISNEY THE MUPPETS" width="300" height="200" class="alignnone size-medium wp-image-1098" /></a></p>
<p>Muppets Software is a company that produces the finest websites. They have a small office out in California and are doing pretty well. Their team consists of:</p>
<p><strong>Kermit &#8211; The Manager</strong></p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Kermit-the-frog.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Kermit-the-frog-150x150.jpg" alt="" title="Kermit-the-frog" width="150" height="150" class="alignnone size-thumbnail wp-image-1101" /></a></p>
<p><strong>Fozzie &#8211; Lead Developer</strong></p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Fozzie2.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Fozzie2-150x150.jpg" alt="" title="Fozzie2" width="150" height="150" class="alignnone size-thumbnail wp-image-1102" /></a></p>
<p><strong>Rizzo &#8211; Junior Developer</strong></p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/RizzoTheRat.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/RizzoTheRat-150x150.jpg" alt="" title="RizzoTheRat" width="150" height="150" class="alignnone size-thumbnail wp-image-1103" /></a></p>
<p><strong>Gonzo &#8211; Lead Sys-Admin</strong></p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Gonzo2.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Gonzo2-150x150.jpg" alt="" title="Gonzo2" width="150" height="150" class="alignnone size-thumbnail wp-image-1104" /></a></p>
<p><strong>Miss Piggy &#8211; Sales</strong></p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Miss-piggy-the-muppets.png"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Miss-piggy-the-muppets-150x150.png" alt="" title="Miss-piggy---the-muppets" width="150" height="150" class="alignnone size-thumbnail wp-image-1105" /></a></p>
<p>Things are going very well, but they are getting too busy, and to expand they need to bring on another developer. After a great deal of searching, they find an excellent candidate: </p>
<p><strong>Beaker &#8211; Awesome Developer</strong></p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Beaker.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2012/01/Beaker-150x150.jpg" alt="" title="Beaker" width="150" height="150" class="alignnone size-thumbnail wp-image-1106" /></a></p>
<p>There is only one problem, he lives in New York and can&#8217;t move to California. But he seems perfect, so Kermit decides to try having him be a remote worker. Fozzie and Rizzo think he&#8217;ll be good, so they hire him. It starts off pretty well at first, and they assign Beaker to help Fozzie with the new Sesame Street website. They decide to use a ticket system to help better manage what they need to get done, and set off to work.</p>
<p>After a time it seems Beaker would drop the ball and not get something done. It would be 4 PM in California, and Fozzie couldn&#8217;t get ahold of Beaker, so he would just have Rizzo do it. The next day Fozzie talked to Beaker, to find out Beaker hadn&#8217;t been in the impromtu meeting where this change was requested and didn&#8217;t know about it. </p>
<p>As time goes on, Gonzo starts to get annoyed with Beaker. It seems he would always come into the office with a list of things asking to be done. Since company policy says only Gonzo can make changes on production servers, he is suppose to be the only one to do it. Fozzie and Rizzo both have access to the production servers, and they have an unspoken agreement that the developers can make small changes to production servers as long as they stick their head in Gonzo&#8217;s cube and run it by him first. Of course, Beaker is unaware of this fact, so he continues to write requests to Gonzo.</p>
<p>Its coming down to crunch time with the Sesame project, and Miss Piggy is worried that they&#8217;ll miss their deadline. She keeps asking for last minute changes to make the site better for the client, so several nights she buys pizza for the office and she stays up late with the Developers to work overtime. She even calls Beaker to have him help out, but he is always the one to leave early, and seems the least effective out of everyone.</p>
<p>After the Sesame project, Gonzo, Fozzie, Rizzo and Miss Piggy talk with Kermit about their concerns with Beaker. They say he is a nice guy, but its been hard working with him. They say there isn&#8217;t one big incident, but rather it is just an overall vibe. </p>
<p>Kermit calls up Beaker and has a nice chat with him. Beaker says he feels bad the others feel this way, and shares some of his frustrations as well. He has a hard time staying up so late with the team on these late-night pushes, and many times tickets aren&#8217;t updated with the information he needs. Kermit sees his point, but doesn&#8217;t really know what to do to solve the problems. They&#8217;ve talked many times about keeping the ticket system up-to-date, but when things get busy, its so easy for the in-house employees to forget.</p>
<p><strong>What to do?</strong></p>
<p>I&#8217;ve seen and heard these problems, and I&#8217;ve even been in Beaker&#8217;s shoes in the past with a short-term project. </p>
<p>The bottom line is that it boils down to a problem with communication. It is so hard for remote developers to keep up with everything when there is a lot of communication that is happening outside of his reach. He isn&#8217;t at lunch with the other co-workers, or around the water cooler. He listens mostly to the meetings since it is so hard to get a word in without being there.</p>
<p>So what would be my recommendation? <strong>Turn your entire company into a distributed company.</strong></p>
<p>Wait, what? I&#8217;m not suggesting a company immediately close it&#8217;s offices. But allow the rest of your employees telecommute as well. I&#8217;d say at least 3 out of the 5 days a week. </p>
<p>As a manager, this is a scary thing. But what this does is naturally change the communication channels. So instead of awkward channels of communication forced on the employees to use, these channels become the channels of communication that empower their own work. They get to enjoy the benefits of telecommuting, regardless of where they live, just like Beaker.</p>
<p>When everyone uses the same channels of communication, all of a sudden being 10 miles away or 1000 miles away does not matter. It will become a much more natural process to send emails, update tickets, and chat online. Even when people are in the office, these channels will tend to stay the primary methods of communication.</p>
<p>Almost all of the most successful distributed companies are 100% distributed, not just 10%. I really do think that is the key. Even with Dating DNA, where I lived in Utah and the rest of the team (all 3 of them) lived in San Diego, we were a very distributed team. Our iPhone Dev only met face-to-face with the owner/project manager of the company once or twice a year, even though they lived 15 minutes from each other. Even when we go to expand our team, I like knowing that if we found the perfect match for a new employee, we can hire them regardless of physical boundaries.</p>
<p>Now, this isn&#8217;t a silver bullet approach. There is a lot more to making a distributed workforce work. <strong>However,</strong> I think the <strong>key</strong> is for this paradigm shift in thought: we&#8217;re not just hiring a remote worker, we becoming a distributed company.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2010/02/04/the-skill-of-making-habits/' rel='bookmark' title='The Skill of Making Habits'>The Skill of Making Habits</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/07/03/mac-keyboard-quirks-making-mac-more-like-windows/' rel='bookmark' title='Mac Keyboard Quirks &#8211; Making Mac more like Windows'>Mac Keyboard Quirks &#8211; Making Mac more like Windows</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/06/29/lifehacker-making-your-mac-sing/' rel='bookmark' title='Lifehacker &#8211; Making your Mac sing!'>Lifehacker &#8211; Making your Mac sing!</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2012/01/31/making-a-distributed-workforce-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SMS Nagios Notifications with PHP &amp; Twilio</title>
		<link>http://www.justincarmony.com/blog/2012/01/30/sms-nagios-notifications-with-php-twilio/</link>
		<comments>http://www.justincarmony.com/blog/2012/01/30/sms-nagios-notifications-with-php-twilio/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 01:12:14 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Nagios]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[sms]]></category>
		<category><![CDATA[system administration]]></category>
		<category><![CDATA[twilio]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=1089</guid>
		<description><![CDATA[I&#8217;ve had a few requests to share my Nagios SMS notifications using Twilio. I&#8217;m almost embarrassed to share them, since they are so dead simple. There was another plugin out there to do the same, but it was a lot more advanced and more work to setup, so I wrote my own in PHP. In ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2010/05/04/setting-up-nagios-for-servers/' rel='bookmark' title='Setting up Nagios for Servers'>Setting up Nagios for Servers</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/10/11/presentation-real-life-scaling/' rel='bookmark' title='Presentation: Real Life Scaling'>Presentation: Real Life Scaling</a></li>
<li><a href='http://www.justincarmony.com/blog/2010/02/24/bestbuy-gives-me-8770-wait-just-87-00/' rel='bookmark' title='BestBuy Gives Me $8,770 &#8212; Wait, Just $87.00'>BestBuy Gives Me $8,770 &#8212; Wait, Just $87.00</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had a few requests to share my <a href="http://www.nagios.org/">Nagios</a> SMS notifications using <a href="http://www.twilio.com/">Twilio</a>. I&#8217;m almost embarrassed to share them, since they are so dead simple. There was another plugin out there to do the same, but it was a lot more advanced and more work to setup, so I wrote my own in PHP.</p>
<p>In the past I would just use my iPhone&#8217;s email-to-txt email address. However, when I received the txt message, it wasn&#8217;t formated very pretty, and it would have a different &#8220;From Number.&#8221; So if we had a crazy day, I would have 20-30 message threads in my iPhone all about Nagios. I&#8217;ve been lazy in the past, and didn&#8217;t clear them out until I had about 200 of them, and it was a lot of &#8220;swipe, delete, swipe, delete, swipe, delete&#8221; to get rid of them.</p>
<p>What I like out this setup is with Twilio, I can buy a phone number for $1 a month. So all my notifications come through the same number. I&#8217;m also planning a way to call/text the number and it will read/send the current status and list the hosts that are down.</p>
<p>First thing is to get your Twilio account setup. Its pretty easy, and when I signed up (a long time ago) I got $30 in credit, not sure if they are doing that still for new customers. Either way you can add a credit card and say how much credit you want to add when your account dips below a certain amount. </p>
<p>Now, you can buy a number and set it up. Even if you&#8217;re only sending text messages, Twilio wants you to have a &#8220;SMS Request URL&#8221; before you can send any text messages. So I just put in a URL to my site that does nothing (yet). You&#8217;ll need to grab your Account SID and Token.</p>
<p><strong>How it Works</strong></p>
<p>I threw <a href="https://github.com/JustinCarmonyDotCom/Nagios-SMS-Requests-with-PHP-Twilio">the code up on GitHub</a>. There are a few things you&#8217;ll need to do:</p>
<p>First in sendTextMsg.php change your configurations to match your phone number, account SID and token. Here is the entire sendTextMsg.php file:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

require('twilio-php/Services/Twilio.php');

/* Start Configs */

$sid = &quot;A123.....&quot;;
$token = &quot;29d6b9f.......&quot;;
$twilio_number = '4045550101';

/* End Configs */

# Get the Argvs
$phone  = $argv[1];
$msg    = $argv[2];
$msg    = str_replace('\n', &quot;\n&quot;, $msg);

$client = new Services_Twilio($sid, $token);
try
{
    $message = $client-&gt;account-&gt;sms_messages-&gt;create(
        $twilio_number, // From a valid Twilio number
        $phone, // Text this number
        $msg
    );
} catch (Exception $ex)
{
    var_dump($ex);
}
</pre>
<p>As you can see, it is super simple. All you need to do is put this script somewhere with the Twilio PHP libraries (or just use my github code with all of it in there). Then, in your Nagios configurations add the commands:</p>
<code class="code">define command{
    command_name    notify-host-by-txt
    command_line    /usr/bin/php /path/to/sendTxtMsg/sendTxtMsg.php &quot;$CONTACTPAGER$&quot; &quot;Nagios Alert\nType: $NOTIFICATIONTYPE$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nWhen: $LONGDATETIME$&quot;
}

define command{
    command_name    notify-service-by-txt
    command_line    /usr/bin/php /path/to/sendTxtMsg/sendTxtMsg.php &quot;$CONTACTPAGER$&quot; &quot;Nagios Alert\nType: $NOTIFICATIONTYPE$\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\nWhen: $LONGDATETIME$&quot;
}</code>
<p>Then you need to add it to your contacts:</p>
<code class="code">define contact {
        contact_name                    justin
        alias                           Justin Carmony
        service_notification_period     24x7
        host_notification_period        24x7
        service_notification_options    w,u,c,r
        host_notification_options       d,r
        
        # Add the new commands to your list
        service_notification_commands   notify-service-by-email,notify-service-by-txt
        host_notification_commands      notify-host-by-email,notify-host-by-txt
        email                           justin@example.com
        
        # Add a pager number, cause we rock it old school 
        # like that: http://static.howstuffworks.com/gif/restaurant-pager-motorola.jpg
        pager                           4045551234
}</code>
<p>Simple, easy, and works very well. You can test the script by simply executing the command:</p>
<code class="code">php /path/to/sendTxtMsg.php 4045551234 &quot;This is my test.\nI am awesome.\n&quot;</code>
<p>Enjoy!</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2010/05/04/setting-up-nagios-for-servers/' rel='bookmark' title='Setting up Nagios for Servers'>Setting up Nagios for Servers</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/10/11/presentation-real-life-scaling/' rel='bookmark' title='Presentation: Real Life Scaling'>Presentation: Real Life Scaling</a></li>
<li><a href='http://www.justincarmony.com/blog/2010/02/24/bestbuy-gives-me-8770-wait-just-87-00/' rel='bookmark' title='BestBuy Gives Me $8,770 &#8212; Wait, Just $87.00'>BestBuy Gives Me $8,770 &#8212; Wait, Just $87.00</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2012/01/30/sms-nagios-notifications-with-php-twilio/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Workers with Redis &amp; Solo</title>
		<link>http://www.justincarmony.com/blog/2012/01/10/php-workers-with-redis-solo/</link>
		<comments>http://www.justincarmony.com/blog/2012/01/10/php-workers-with-redis-solo/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 18:20:10 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[solo]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[workers]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=1072</guid>
		<description><![CDATA[I&#8217;ve come across an awesome combination of tools for managing PHP Workers, and thought I&#8217;d share. Why Workers? Sometimes there are situations when you want to parallel process things. Other times you might have a list of tasks to accomplish, and you don&#8217;t want to make the user wait after pressing a button. This is ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2011/05/23/mysql-redis-and-a-billion-rows-a-love-story/' rel='bookmark' title='MySQL, Redis, and a Billion Rows &#8211; A Love Story'>MySQL, Redis, and a Billion Rows &#8211; A Love Story</a></li>
<li><a href='http://www.justincarmony.com/blog/2011/01/07/creating-chatroom-walls-with-redis-and-php/' rel='bookmark' title='Creating Chatroom / Walls with Redis &amp; PHP'>Creating Chatroom / Walls with Redis &#038; PHP</a></li>
<li><a href='http://www.justincarmony.com/blog/2011/01/10/debugging-with-php-stack-traces-and-redis/' rel='bookmark' title='Debuging with PHP, Stack Traces, and Redis'>Debuging with PHP, Stack Traces, and Redis</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve come across an awesome combination of tools for managing PHP Workers, and thought I&#8217;d share.</p>
<h3>Why Workers?</h3>
<p>Sometimes there are situations when you want to parallel process things. Other times you might have a list of tasks to accomplish, and you don&#8217;t want to make the user wait after pressing a button. This is where &#8220;Workers&#8221; can come in. They are independent scripts that run along side of your application, performing tasks, or &#8220;jobs.&#8221; </p>
<p>An example is with Dating DNA and our score system. We generate scores between users to show how compatible they are with each other. When a user signs up, or makes a significant change to their profile questionnaire, we need to run a job to query our database, build a list of potential users, and generate scores. This takes 10-20 seconds, and while it is pretty fast, we don&#8217;t want to make the user wait for that. So we queue up a job for the user, divide up the work among several workers, and process the work.</p>
<h3>General Concept</h3>
<p>For this post, we&#8217;ll use the example of generating reports. Lets say on your internal website there is a button that you can click and it will email the user a report, and the report takes 2-3 minutes to generate. When the button is clicked, your code will insert the job into the queue. Meanwhile, workers are monitoring the queue. A worker script will pull the job off the queue, process the report, and send the email when its done.</p>
<p>For the queue management, we&#8217;ll use Redis. To let PHP read and write data to Redis, we&#8217;ll use the PHP Library <a href="https://github.com/nrk/predis">predis</a>. In our examples we&#8217;ll use PHP 5.3, however predis has a PHP 5.2 backport if you are not running 5.3.</p>
<h3>Adding Jobs</h3>
<p>To add jobs, we&#8217;ll need to connect to our Redis server:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Connecting to Redis
 */

const REDIS_HOST = '127.0.0.1';
const REDIS_PORT = 6379;

$predis = new Predis\Client(array(
    'scheme' =&gt; 'tcp',
    'host'   =&gt; REDIS_HOST,
    'port'   =&gt; REDIS_PORT,
));
</pre>
<p>We&#8217;ll assume in all of our examples that we&#8217;ve done the following above &#038; connected to Redis. <span id="more-1072"></span></p>
<p>Now, to manage our queues we&#8217;ll use the Redis Datatype LIST. Whats awesome about lists is that regardless of size, adding or removing at the start or end of a list is extremely fast. So if your queue has 10 items, or 10,000,000 items, Redis wil be able to push and pop entries quickly.</p>
<p>We&#8217;ll have three queues, one for each priority: high, normal, and low. For the Redis key names, we&#8217;ll use queue.priority.high, queue.priority.normal, etc. When interacting with lists, you work with the ends, one called right, the other called left. So we&#8217;ll add items on the right with the RPUSH (Right Push) command, and we&#8217;ll pull items off the left with the BLPOP (Blocking Left Pop) command. We won&#8217;t worry about the pulling items just yet.</p>
<p>You store strings as the values for the list. My personal preference is to store JSON objects so you can easily pass variables needed to perform the job.</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Adding items to the queue
 */

$job = new stdClass();
$job-&gt;id = 1;
$job-&gt;report = 'general';
$job-&gt;email = 'test@example.com';

// Add the job to the high priority queue
$predis-&gt;rpush('queue.priority.high', json_encode($job));

// Or, you could add it to the normal or low priority queue.
$predis-&gt;rpush('queue.priority.normal', json_encode($job));
$predis-&gt;rpush('queue.priority.low', json_encode($job));
</pre>
<p>Simple enough! Having different queue priorities is very beneficial in managing which jobs should get done first. For example, you might have an Executive&#8217;s request go into the high priority queue so they get the report quickly. You might also have a weekly cron that queues up reports to be sent automatically, so those can go in the low priority as to not disrupt people trying to get a manual report.</p>
<p>Now, on to the worker&#8217;s code.</p>
<h3>Processing Jobs</h3>
<p>For now, lets say we have a script running in the PHP CLI (Command Line Interface) that you started by running this command on the server:</p>
<code class="code">php /path/to/worker.php</code>
<p>First thing is we want this worker to work continuously, so we can do a while loop:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Simple Continuous While Loop
 */

// Always True
while(1)
{
	/* ... perform tasks here ...  */
}
</pre>
<p>We&#8217;ll worry about making them more intelligent later. Now, let&#8217;s have our worker check the queue. You can do so with the BLPOP command:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Checking the Queue
 */
$job = $predis-&gt;blpop('queue.priority.high'
						, 'queue.priority.normal'
						, 'queue.priority.low'
						, 10);
</pre>
<p>What we&#8217;re telling PHP to do is to check each queue in order of priority: high, normal, and then low. If it finds an item, it will immediately return an array with the name of the queue it came from, and the string of data that was pulled.</p>
<p>The B in BLPOP is &#8220;blocking.&#8221; What that means is that Redis will wait until either an item enters one of the queues, or the timeout is reached. In this case, the timeout is 10 seconds. So instead of polling (checking every few seconds in a loop), we check and wait, and after 10 seconds it will return null and we can check again.</p>
<p>What this gives us is near instantaneous queues. As soon as something is available, it is passed to the workers that are listening. You can also have multiple workers, and it will pass jobs to the first listening worker, and the next job to the next worker, so you don&#8217;t have to worry about multiple workers getting the same queued item.</p>
<p>After $predis->blpop() returns, if it has an array, it returned an item. If not, the timeout had been reached. We can check to see if a Job was returned, and if so to process the job:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Checking to see if a Job was returned
 */

if($job)
{
	// Index 0 of the array holds which queue was returned
	$queue_name = $job[0];
	// Index 1 of the array holds the string value of the job.
	// Since we are passing it JSON, we'll decode it:
	$details = json_decode($job[1]);

	/* ... do job work ... */
}
</pre>
<p>Now we can have multiple workers listening to the same queues and scale our workload. Redis is very fast &#038; efficient, and you could have hundreds or even thousands of workers listening to a single redis server.</p>
<h3>Continuously Running Workers</h3>
<p>There are a lot of options when it comes to deploying these workers. You can use a framework like Gearman, but for simple things, I like very simple solutions. I came across a <a href="http://josephscott.org/archives/2011/09/solo/">blog post by Joseph Scott</a> about a little 10 line perl script called <a href="http://timkay.com/solo/solo">solo</a>. What it does is it will run a command, and to ensure that no one else is running that same exact command, it will lock a configurable port. This is awesome because the you don&#8217;t have to work about lock files or filesystem tricks, the kernel handles it all. </p>
<p>So what you can do is create a cronjob using solo to execute your script. First copy solo somewhere, I put it in my /usr/local/bin on my linux server. Then add this to your cron job using the command &#8220;crontab -e -u (which user to use)&#8221;:</p>
<code class="code">* * * * * /usr/local/bin/solo -port=5001 php /path/to/worker.php</code>
<p>What this will do is try to run this command every minute. Solo will check to see if the port is already in use, and if it is, it will exit. Otherwise, it will lock the port and then execute the command. The port will stay locked as long as the command is executing. Once the command terminates, the port will unlock.</p>
<p>Now, PHP is a great language, but it has been known to have some memory leaks while running a long time in a single instance. So we can have our scripts exit periodically to be restarted by our cron job. So lets make our &#8220;while(1)&#8221; statement a little smarter:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * A Smarter While Statement
 */

// Set the time limit for php to 0 seconds
set_time_limit(0);

/*
 * We'll set our base time, which is one hour (in seconds).
 * Once we have our base time, we'll add anywhere between 0
 * to 10 minutes randomly, so all workers won't quick at the
 * same time.
 */
$time_limit = 60 * 60 * 1; // Minimum of 1 hour
$time_limit += rand(0, 60 * 10); // Adding additional time

// Set the start time
$start_time = time();

// Continue looping as long as we don't go past the time limit
while(time() &lt; $start_time + $time_limit)
{
	/* ... perorm BLPOP command ... */
	/* ... process jobs when received ... */
}

/* ... will quit once the time limit has been reached ... */
</pre>
<p>One key thing to note is randomly shifting the time limit for the script. I like to do this because you don&#8217;t want your workers all stopping and starting at the same time. So if I have 8 workers, one might, but the 7 will continue until the 8th starts back up again via the cron job.</p>
<h3>Bells &#038; Whistles</h3>
<p>After using workers for awhile, here are a couple of ideas to enhance your workers &#038; system managing them. First off, you can add some monitoring for your queues. Using Redis a HASH, you can use them to store the state of your workers. </p>
<pre class="brush: php; title: ; notranslate">
/*
 * Assigning Worker IDs &amp; Monitoring
 *
 * Usage: php worker.php 1
 */

// Gets the worker ID from the command line argument
$worker_id = $argv[1];

// Setting the Worker's Status
$predis-&gt;hset('worker.status', $worker_id, 'Started');

// Set the last time this worker checked in, use this to
// help determine when scripts die
$predis-&gt;hset('worker.status.last_time', $worker_id, time());
</pre>
<p>Another problem with workers that run for a long time (several hours) is when you make a change to their code, they won&#8217;t reload that change until they exit. What I&#8217;ve found to successfully restart them is having a &#8220;version&#8221; number set in Redis that is checked at the end of every loop:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Using Versions to Check for Reloads
 */

$version = $predis-&gt;get('worker.version'); // i.e. number: 6

while(time() &lt; $start_time + $time_limit)
{
	/* ... check for jobs and process them ... */

	/* ... then, at the very end of the while ... */
	if($predis-&gt;get('worker.version') != $version)
	{
		echo &quot;New Version Detected... \n&quot;;
		echo &quot;Reloading... \n&quot;;
		exit();
	}
}
</pre>
<p>You would simply INCR (increment) worker.version and after finishing their last job, the worker would exit, and solo would start it up again.</p>
<p>You can also kill specific threads by having them check for their value in a hash:</p>
<pre class="brush: php; title: ; notranslate">
/*
 * Using Kill Switches to Check for Reloads
 */

while(time() &lt; $start_time + $time_limit)
{
	/* ... check for jobs and process them ... */

	/* ... then, at the very end of the while ... */
	// Check to see if a kill has been set.
	if($predis-&gt;hget('worker.kill', $worker_id))
	{
		// Make sure to unset the kill request before exiting, or
		// your worker will just keep restarting.
		$predis-&gt;hdel('worker.kill', $worker_id);

		echo &quot;Kill Request Detected... \n&quot;;
		echo &quot;Reloading... \n&quot;;
		exit();
	}
}
</pre>
<h3>Tweak to Solo &#038; Logging </h3>
<p>I made one small tweak in my version of solo, and that was to help it enable logging. Lets say I had three workers in my crontab:</p>
<code class="code"># crontab for user to run workers
* * * * * /usr/local/bin/solo -port=5001 php /path/to/worker.php 1 &gt;&gt; /tmp/worker.log.1
* * * * * /usr/local/bin/solo -port=5002 php /path/to/worker.php 2 &gt;&gt; /tmp/worker.log.2
* * * * * /usr/local/bin/solo -port=5003 php /path/to/worker.php 3 &gt;&gt; /tmp/worker.log.3</code>
<p>The &#8220;>> /tmp/worker.log.1&#8243; tells solo I want to log it&#8217;s output to a tmp file that I can tail and monitor their progress. This is great for debugging problems. However, when I did this, solo would write to the tmp file, and not the output from my script. To overcome this I changed the last line of solo:</p>
<pre class="brush: perl; title: ; notranslate">
# old
exec @ARGV;
# new
exec &quot;@ARGV&quot;;
</pre>
<p>This would ensure my script wrote out to the tmp file, and not just solo.</p>
<h3>Examples</h3>
<p>I&#8217;ve created an <a href="https://github.com/JustinCarmony/PHP-Workers-with-Redis-Solo-Examples">example on GitHub</a> that you can clone on your own machine. All you will need is PHP 5.3 and Redis installed.</p>
<p>To install redis, simple run these commands on your unix based system:</p>
<code class="code">wget http://redis.googlecode.com/files/redis-2.4.5.tar.gz
tar -xzvf redis-2.4.5.tar.gz
cd redis-2.4.5
make
make install</code>
<p>It will copy the redis binaries to /usr/local/bin.</p>
<p>To get a copy of the code, you can <a href="https://github.com/JustinCarmony/PHP-Workers-with-Redis-Solo-Examples/zipball/master">download them here</a>. <strong>HOWEVER, it doesn&#8217;t include predis! You&#8217;ll have to download and copy predis inside there via this link.</strong> It is much easier to clone it as so:</p>
<code class="code">git clone git://github.com/JustinCarmony/PHP-Workers-with-Redis-Solo-Examples.git php_example/
cd php_example
git submodule init
git submodule update</code>
<p>Then, using different terminal windows (or using screen), you can run different worker.php instances, use creator.php to insert jobs, and monitor.php to watch the progress. This is all done from the command line.</p>
<p>If you&#8217;re using windows, I suggest installed a VM of Ubuntu and using that. If you really want to use Redis on windows, there are some Windows Binaries you can google and download. Good luck!</p>
<p>Here is a video where I demo the example:</p>
<p><iframe width="640" height="480" src="http://www.youtube.com/embed/jhgGhBgY14U?hd=1" frameborder="0" allowfullscreen></iframe></p>
<p>(sorry for the poor mic quality)</p>
<h3>Final Thoughts</h3>
<p>I&#8217;ll post here shortly about how to run Redis in production with the init.d scripts and configuration files. One caveat to using solo is if your server has an application that randomly selects ports to use (i.e. VoIP, FTP), it might select one of your worker&#8217;s ports. But on a production server, you should have a good feel for which ports are available for locking.</p>
<p>If you want to learn more about Redis, <a href="http://redis.io/">check out their website</a>.  </p>
<p>Hopefully this will be helpful for anyone looking to use PHP Workers in an easy, simple way.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2011/05/23/mysql-redis-and-a-billion-rows-a-love-story/' rel='bookmark' title='MySQL, Redis, and a Billion Rows &#8211; A Love Story'>MySQL, Redis, and a Billion Rows &#8211; A Love Story</a></li>
<li><a href='http://www.justincarmony.com/blog/2011/01/07/creating-chatroom-walls-with-redis-and-php/' rel='bookmark' title='Creating Chatroom / Walls with Redis &amp; PHP'>Creating Chatroom / Walls with Redis &#038; PHP</a></li>
<li><a href='http://www.justincarmony.com/blog/2011/01/10/debugging-with-php-stack-traces-and-redis/' rel='bookmark' title='Debuging with PHP, Stack Traces, and Redis'>Debuging with PHP, Stack Traces, and Redis</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2012/01/10/php-workers-with-redis-solo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Siege with User Authentication</title>
		<link>http://www.justincarmony.com/blog/2011/11/03/siege-with-user-login/</link>
		<comments>http://www.justincarmony.com/blog/2011/11/03/siege-with-user-login/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 16:33:02 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[siege]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=1043</guid>
		<description><![CDATA[If you want to stress test your application, the quickest and best way to do so is with siege. From the siege website: Siege is an http load testing and benchmarking utility. It was designed to let web developers measure their code under duress, to see how it will stand up to load on the ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2010/07/14/setting-up-ssh-key-authentication-between-servers/' rel='bookmark' title='Setting up SSH Key Authentication Between Servers'>Setting up SSH Key Authentication Between Servers</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/10/local-lamp-developement-user-content/' rel='bookmark' title='Local LAMP Developement &amp; User Content'>Local LAMP Developement &#038; User Content</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/11/27/my-php-user-group-experience/' rel='bookmark' title='My PHP User Group Experience'>My PHP User Group Experience</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>If you want to stress test your application, the quickest and best way to do so is with <a href="http://www.joedog.org/index/siege-home">siege</a>. From the siege website:</p>
<blockquote><p>Siege is an http load testing and benchmarking utility. It was designed to let web developers measure their code under duress, to see how it will stand up to load on the internet. Siege supports basic authentication, cookies, HTTP and HTTPS protocols. It lets its user hit a web server with a configurable number of simulated web browsers. Those browsers place the server &#8220;under siege.&#8221;</p></blockquote>
<p>On Linux, you can install it easily via yum or apt. On OS X, you can install it easily via <a href="http://mxcl.github.com/homebrew/">homebrew</a> or <a href="http://www.macports.org/">macports</a>. I personally prefer homebrew. In your terminal just type:</p>
<code class="code">brew install siege</code>
<p>Now you can stress test a given app by simply using the siege command:</p>
<code class="code">siege -c 10 -n 10 http://www.example.com/</code>
<p>You can read the <a href="http://www.joedog.org/index/siege-manual">documentation</a> and <a href="http://www.joedog.org/index/siege-faq">faq</a> on their site to learn more. However, there is one question I get a lot when talking about siege: &#8220;How can I use siege to test users who are logged in?&#8221;</p>
<p>I would always recommend that they send a session header in the config, but today I learned there is an even easier way (although undocumented), thanks to <a href="http://serverfault.com/questions/292679/stress-login-area-with-siege">this question in Server Fault</a>. In your siege&#8217;s configuration you can add the login-url directive:</p>
<code class="code"># Login URL. This is the first URL to be hit by every siege
# client. This feature was designed to allow you to login to 
# a server and establish a session. It will only be hit once
# so if you need to hit this URL more then once, make sure it
# also appears in your urls.txt file.
#
# ex: login-url = http://eos.haha.com/login.jsp POST name=jeff&amp;pass=foo
#
# login-url =</code>
<p>Awesome! Now each connection will authenticate before continuing their siege. A very handy tool, especially if your load is generated by user account pages and such.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2010/07/14/setting-up-ssh-key-authentication-between-servers/' rel='bookmark' title='Setting up SSH Key Authentication Between Servers'>Setting up SSH Key Authentication Between Servers</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/10/local-lamp-developement-user-content/' rel='bookmark' title='Local LAMP Developement &amp; User Content'>Local LAMP Developement &#038; User Content</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/11/27/my-php-user-group-experience/' rel='bookmark' title='My PHP User Group Experience'>My PHP User Group Experience</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/11/03/siege-with-user-login/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mac OS X Lion, /etc/hosts Bugs, and DNS Resolution</title>
		<link>http://www.justincarmony.com/blog/2011/07/27/mac-os-x-lion-etc-hosts-bugs-and-dns-resolution/</link>
		<comments>http://www.justincarmony.com/blog/2011/07/27/mac-os-x-lion-etc-hosts-bugs-and-dns-resolution/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 22:21:00 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[lion]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[OS X]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=976</guid>
		<description><![CDATA[Final Update: I&#8217;m working on a follow-up post, but thanks to all the comments, it seems that somehow during the Snow Leopard to Lion upgrade, the /etc/hosts file was encoded incorrectly (likely the type of newlines used), and that Lion would fail to read it properly. Please try to copy the contents of the /etc/hosts ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/07/27/iphone-sdk-21-another-nda/' rel='bookmark' title='iPhone SDK 2.1 &#8211; Another NDA'>iPhone SDK 2.1 &#8211; Another NDA</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/10/local-lamp-developement-user-content/' rel='bookmark' title='Local LAMP Developement &amp; User Content'>Local LAMP Developement &#038; User Content</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/15/is-apple-blinded-by-style/' rel='bookmark' title='Is Apple Blinded by Style?'>Is Apple Blinded by Style?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><em>Final Update: I&#8217;m working on a follow-up post, but thanks to all the comments, it seems that somehow during the Snow Leopard to Lion upgrade, the /etc/hosts file was encoded incorrectly (likely the type of newlines used), and that Lion would fail to read it properly. Please try to copy the contents of the /etc/hosts file, recreate the file, and paste to fix your problem.</em></p>
<p><em>Update: I was still having problems with using .local for my development sites. After some extensive debugging and research I&#8217;ve found out some interesting things. It appears that <a href="http://www.multicastdns.org/">Multicast DNS</a> (mDNS), which is used in Apple&#8217;s Bonjuor for network discovery without a tradition DNS Server, has the Top Level Domain <a href="http://files.multicastdns.org/draft-cheshire-dnsext-multicastdns.txt">.local reserved for special mDNS functionality</a>. Mac OS X will treat domains ending with .local differently! <span style="color:#ff0000;">Use another TLD, like .dev, and it will work correctly.</span></em></p>
<p><em>This article will still help you fix problems with /etc/hosts abnormalities with it not having the correct priority.</em></p>
<p><em><strong>Update 2: Thanks for all the comments! A few updates: First off, per the comments, if you declare both a IPv4 and IPv6 address for a .local domain like so:</strong></em></p>
<code class="code">27.0.0.1 domain.local
::1 domain.local</code>
<p><em><strong>Then it will work correctly. Second, I ended up doing a fresh install of Lion and this problem has gone away for me. So it appears that this issue would affect some people who upgraded from Snow Leopard. So as Chris suggested below, I don&#8217;t think it has to do with the resolve order. I haven&#8217;t been able to figure out the difference between Lion installs that work correctly, and those that don&#8217;t. So if you are have the following problems, the suggestions below will work to fix it.</strong></em></p>
<p>This morning I was up a few hours earlier than normal today, and was looking forward to getting in some solid programming hours earlier so I wouldn&#8217;t work late tonight. Instead, I spent about four hours fighting a new change (I&#8217;d call it a bug) in Mac OS X Lion.</p>
<h2>The /etc/hosts File</h2>
<p>Now, instead of running a full blown DNS server on my machine, which is overkill and more work to edit and maintain, I would make manual adjustments to my /etc/hosts file. For those not familiar with the /etc/hosts file, it allows you to add entries that traditionally your computer will look up first before trying your server DNS. This is where your computer would set &#8220;localhost&#8221; is the IP &#8220;127.0.0.1&#8243;. </p>
<p>I use this a <strong>lot</strong> with local development. For example, when I work on <a href="http://joind.in/">joind.in</a>, I use MAMP and create a VirtualHost for the code under the server name local.joind.in (i.e. http://local.joind.in/). I don&#8217;t have access to the joind.in DNS, so I create an entry in my /etc/hosts file. You have to have admin permissions to edit the file, so I normally run the command &#8220;sudo nano /etc/hosts&#8221; and make my changes and then save.</p>
<p>The /etc/hosts file looks something like this:<span id="more-976"></span></p>
<code class="code">##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1   localhost
255.255.255.255 broadcasthost
::1             localhost
fe80::1%lo0    localhost

127.0.0.1       local.joind.in
209.114.40.229  www.example.com</code>
<p>Now, my actual /etc/hosts file contains 83 entries. Some are just short cuts to machines I often connect to. Sometimes during a migration when I&#8217;m making DNS entries, I can make the change in my /etc/hosts file as well, so I don&#8217;t have to wait for the DNS changes to propagate to test. All in all, it is a very handle little file that I use a great deal. Even windows has their own hosts file that works well.</p>
<h2>Problem #1: Bugs with Multiple Domains per Line</h2>
<p> With the new Lion Update comes better support for IPv6, however this seems to have broken the /etc/hosts file from allowing multiple domains per line. Before you could do something like this, which is works in several other operating systems:</p>
<code class="code">127.0.0.1 local.joind.in local.example.com</code>
<p>However, this now seems to break and not work. You must keep each line to one ip and one domain. So your configuration should look like this:</p>
<code class="code">127.0.0.1 local.joind.in
127.0.0.1 local.example.com</code>
<p>There was also reports about the order of IPv4 and IPv6 entries (<a href="http://gargoyle.wpm.iawhq.co.uk/2011/06/16/mac-os-x-lion-etchosts-file/" target="_blank">blog post about it</a>). I personally did not have this problem, but others seem to have had it. The problem was that OS X Lion seemed to ignore IPv4 entries after a IPv6 entry was made.</p>
<h2>Problem #2: DNS Resolution Orders has DNS Servers <em>Before</em> the Hosts File</h2>
<p>This is the problem that really, really ticked me off and caused me to waste hours and hours trying to debug and find a work-around. I was working on my local copy of Clipish, and because we have different domains for it that work together, I replace .com with .local. So I would have something like this in my /etc/hosts file:</p>
<code class="code">127.0.0.1 staff.example.local
127.0.0.1 images.example.local
127.0.0.1 www.example.local</code>
<p>However, anytime I made a request in Chrome to any of those domains, it would take 5.01 seconds. At first I thought it might be a bug with the new version of MAMP for OS X Lion. But I found using Chrome&#8217;s &#038; FireFox&#8217;s developer tools that it was taking 5 seconds for the DNS lookup, and 0.01 seconds for the rest. So I would go into my terminal and ping the domain. It worked just fine without the delay.</p>
<p>Apparently, the terminal and some of the BSD Unix tools correctly use /etc/resolv.conf and the correct order of /etc/hosts first and then DNS servers. <strong>However, everything else on OS X Lion, including all of your Applications, do it backwards!</strong> This wasn&#8217;t the case in Tiger, Leopard, or Snow Leopard.</p>
<p>You can test this by running the command &#8220;scutil &#8211;dns&#8221;:</p>
<code class="code">Justin-Carmonys-MacBook-Pro-2:etc justin$ scutil --dns
DNS configuration

resolver #1
  nameserver[0] : 8.8.8.8
  nameserver[1] : 192.168.1.1

resolver #2
  domain   : local
  options  : mdns
  timeout  : 5
  order    : 300000

resolver #3
  domain   : 254.169.in-addr.arpa
  options  : mdns
  timeout  : 5
  order    : 300200

resolver #4
  domain   : 8.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  order    : 300400

resolver #5
  domain   : 9.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  order    : 300600

resolver #6
  domain   : a.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  order    : 300800

resolver #7
  domain   : b.e.f.ip6.arpa
  options  : mdns
  timeout  : 5
  order    : 301000

DNS configuration (for scoped queries)

resolver #1
  nameserver[0] : 127.0.0.1
  if_index : 5 (en1)
  flags    : Scoped</code>
<p>I spent hours and hours googling, finding a bunch of people with this same problem, but no solution on how to fix the ordering. I have my suspicions why Apple made this change, which I&#8217;ll address later on. But after I couldn&#8217;t figure out a way to change the resolve order myself, I had to find another alternative. (Of course, OS X removed /etc/nsswitch.conf so I can&#8217;t change it there, grrr!)</p>
<h2>Solution: DNSMasq</h2>
<p>The only solution we have, that I could find, is to use your own DNS Server locally on your own machine. I&#8217;ve heard of others <a href="http://geoffhankerson.com/node/108" target="_blank">setting up BIND on OS X.</a> Now, the problem with this solution is that it isn&#8217;t nearly as quick and easy to manage DNS entries.</p>
<p>Then, I found out about <a href="http://thekelleys.org.uk/dnsmasq/doc.html">DNSMasq</a>. It is a lightweight DNS server that is easy to configure. However, it had one key feature we needed: it will read the /etc/hosts file and serve it&#8217;s entries. This means we can have our OS check the DNSMasq instance first, which will check the /etc/hosts file, restoring the proper order.</p>
<h3>Installing DNSMasq</h3>
<p>After <a href="http://www.davesouth.org/stories/how-to-set-up-dnsmasq-on-snow-leopard-for-local-wildcard-domains">some Googling around</a>, I think installing dnsmasq using <a href="http://www.macports.org/">MacPorts</a> is the easiest. First, you&#8217;ll need to install Xcode so your machine can compile with the tools. It is free on the Mac App Store (warning, it is a kind of big download). Then, you&#8217;ll need to <a href="http://www.macports.org/install.php">download and install the MacPorts for Lion</a>. If you already have MacPorts installed, make sure it is the current version of Lion.</p>
<p>Once it is installed, open up the terminal and then execute these commands. First, run selfupdate to make sure your MacPorts repositories are up to date:</p>
<code class="code">sudo port selfupdate</code>
<p>Then, install dnsmasq:</p>
<code class="code">sudo port install dnsmasq</code>
<p>That should execute with no problems. Now, it is installed, but we need to have OS X run it:</p>
<code class="code">sudo port load dnsmasq</code>
<p>Now, if you want to make some changes to your dnsmasq configurations, you can do that in this file:</p>
<p>/opt/local/etc/dnsmasq.conf</p>
<p>One thing I like to do is control which DNS Server&#8217;s dnsmasq will use. By default it will use /etc/resolv.conf, but OS X will overwrite that file on reboot and anytime you change internet connections (like switching wifi hotspots). So I would copy /etc/resolv.conf to /etc/resolv.dnsmasq.conf. When dealing with files in /etc/ and /opt/ you&#8217;ll need to run these commands using sudo.</p>
<code class="code">sudo cp /etc/resolv.conf /etc/resolv.dnsmasq.conf
sudo nano /etc/resolv.dnsmasq.conf</code>
<p>Then I set dnsmasq to read my new resolve.dnsmasq.conf by setting &#8220;resolv-file=/etc/resolv.dnsmasq.conf&#8221; in /opt/local/etc/dnsmasq.conf. </p>
<p>Now, we need to configure OS X to add 127.0.0.1 to our DNS Servers. Go to <strong>System Preferences > Network > (Select Connection, i.e. Wi-Fi) > Advanced > DNS</strong>.</p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/07/Screen-Shot-2011-07-27-at-3.37.45-PM.png"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/07/Screen-Shot-2011-07-27-at-3.37.45-PM-300x260.png" alt="" title="Screen Shot 2011-07-27 at 3.37.45 PM" width="300" height="260" class="alignnone size-medium wp-image-977" /></a></p>
<p>You can have other DNS entries, like Google&#8217;s DNS Entries (8.8.8.8, 8.8.4.4). Just make sure 127.0.0.1 is on top.</p>
<p>One thing I haven&#8217;t been able to figure out is how to reboot dnsmasq, but if you kill the process in the Activity Monitor OS X will restart it:</p>
<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/07/Screen-Shot-2011-07-27-at-3.41.25-PM.png"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/07/Screen-Shot-2011-07-27-at-3.41.25-PM-300x204.png" alt="" title="Screen Shot 2011-07-27 at 3.41.25 PM" width="300" height="204" class="alignnone size-medium wp-image-978" /></a></p>
<p>This is a lot of work to setup (especially if you don&#8217;t have Xcode install). However, it will work, and give you a lot more control over your DNS. So in a way it is an improvement! Just wish it wasn&#8217;t necessary.</p>
<p>If you would like to do wildcard dns entries, something you couldn&#8217;t do in /etc/hosts, then you can add this to your dnsmasq config:</p>
<p>address=/.local/127.0.0.1</p>
<p>Now any domains ending in .local will route to 127.0.0.1</p>
<h2>Why is this necessary Apple?</h2>
<p>What I don&#8217;t get, is why this change Apple? No other operating system that I know if, including Windows for crying out loud, does it this way. This had to be a deliberate change by Apple. I can only see one of the following reasons:</p>
<ul>
<li><strong>Security</strong> &#8211; Maybe, just maybe, it was for security. Technically, a virus can overwrite the /etc/hosts file if it the virus can prompt the user for their password to run a command as root. So you could maybe have a user visit www.google.com when in reality it isn&#8217;t a google server. But even then, HTTPS wouldn&#8217;t work without ugly errors. So this might be a reason, but out of all the things that can go wrong with a virus, it is a poor excuse. The virus could just hack mDNSresponder to use /etc/hosts.</li>
<li><strong>Prevent User Hacks</strong> &#8211; Most likely, I think this is why Apple made this change. I know with jailbreaking iOS devices and getting hacked apps, iTunes will try to validate an App by &#8220;phoning home&#8221; to Apple. However, if you change the entries in your /etc/hosts file so iTunes can&#8217;t reach the correct Apple Servers. I know people who have circumvented other software activation systems do the same technique. I think this is why Apple made the change, though at the expensive of all the professionals who actually use /etc/hosts for work.</li>
<li><strong>An Honest Bug</strong> &#8211; It is possible this was a bug, but seeing as how you would have to deliberately change the resolve orders for the operating system, I doubt this is the case.</li>
</ul>
<p>If this was an intended change by Apple, it is a frustrating one. One of my favorite things is that underneath the OS X&#8217;s nice UI and Applications is a BSD Unix system. I love how I can compile and install so many things just like I would on Ubuntu. But if they continue to change that Unix underbelly and make it less and less like it is everywhere else, then I think they&#8217;ll be frustrating many, many professionals.</p>
<p>Hopefully in the future I&#8217;ll find a way to change the resolve order in Mac OS X, but until this, this is how I worked around the problem.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/07/27/iphone-sdk-21-another-nda/' rel='bookmark' title='iPhone SDK 2.1 &#8211; Another NDA'>iPhone SDK 2.1 &#8211; Another NDA</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/10/local-lamp-developement-user-content/' rel='bookmark' title='Local LAMP Developement &amp; User Content'>Local LAMP Developement &#038; User Content</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/15/is-apple-blinded-by-style/' rel='bookmark' title='Is Apple Blinded by Style?'>Is Apple Blinded by Style?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/07/27/mac-os-x-lion-etc-hosts-bugs-and-dns-resolution/feed/</wfw:commentRss>
		<slash:comments>45</slash:comments>
		</item>
		<item>
		<title>Node.js, Evented I/O, and a Cup of Tea</title>
		<link>http://www.justincarmony.com/blog/2011/06/02/node-js-event-driven-development-and-tea/</link>
		<comments>http://www.justincarmony.com/blog/2011/06/02/node-js-event-driven-development-and-tea/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 16:30:42 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[event driven proramming]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=937</guid>
		<description><![CDATA[All Arthur Dent really wanted was a cup of tea. I was reading The Restaurant at the End of the Universe by Douglas Adams, and I found a humorous example of event driven programming. So I thought I would share. The Story Arthur Dent was one of the last surviving humans after Earth had been ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2011/04/29/node-js-lamp-and-the-future/' rel='bookmark' title='Node.JS, LAMP, and The Future'>Node.JS, LAMP, and The Future</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>All Arthur Dent really wanted was a cup of tea.</p>
<p>I was reading <a href="http://en.wikipedia.org/wiki/The_Restaurant_at_the_End_of_the_Universe">The Restaurant at the End of the Universe</a> by  Douglas Adams, and I found a humorous example of event driven programming. So I thought I would share.</p>
<h3>The Story</h3>
<p>Arthur Dent was one of the last surviving humans after Earth had been destroyed to make way for a new hyperspace bypass. He was living on a spaceship known as the &#8220;Heart of Gold,&#8221; which onboard had an amazing piece of equipment called the &#8220;Nutri-Matic Drinks Synthesizer&#8221; which &#8220;claimed to produce the widest possible range of drinks personally matched to the tastes and metabolism of whoever cared to use it.&#8221;</p>
<p>The problem was that &#8220;when put to the test, however, it invariably produced a plastic cup filled with a liquid that was almost, but nit quite, entirely unlike tea.&#8221; So Arthur tried to reason with the machine with no success. He would ask for tea, and the machine would respond with a cheerful &#8220;Share and enjoy&#8221; and produce the same sickly liquid. </p>
<p>Finally, after all reason and attempts failed, he tried one last time:</p>
<blockquote><p>&#8220;No,&#8221; he said, &#8220;look, it&#8217;s very, very simple &#8230; all I want &#8230; is a cup of tea. You are going to make one for me. Keep quiet and listen.&#8221;</p>
<p>And he sat. He told the Nutri-Matic about India, he told it about China, he told it about Ceylon. He told it about broad leaves drying in the sun. He told it about silver teapots. He told it about summer afternoons on the lawn. He told it about putting in the milk before the tea so it wouldn&#8217;t get scalded. He even told it (briefly) about the history of the East India Company.</p>
<p>&#8220;So that&#8217;s it, is it?&#8221; said the Nutri-Matic when he had finished.</p>
<p>&#8220;Yes,&#8221; said Arthur, &#8220;that is what I want.&#8221;</p>
<p>&#8220;You want the taste of dried leaves boiled in water?&#8221;</p>
<p>&#8220;Er, yes. With milk.&#8221;</p>
<p>&#8220;Squirted out of a cow?&#8221;</p>
<p>&#8220;Well, in a manner of speaking I suppose &#8230;&#8221;</p>
<p>&#8220;I&#8217;m going to need some help with this one,&#8221; said the machine tersely. All the cheerful burbling had dropped out of its voice and it now meant business.</p>
<p>&#8220;Well, anything I can do,&#8221; said Arthur.</p>
<p>&#8220;You&#8217;ve done quite enough,&#8221; the Nutri-Matic informed him.</p></blockquote>
<p>So everything was grand? Well, not quite. There were two problems.</p>
<p>First, the Nutri-Matic needed help processing all this information. So, it asked the spaceship&#8217;s computer to help:</p>
<blockquote><p>[The Nutri-Matic] summoned up the ship&#8217;s computer.</p>
<p>&#8220;Hi there!&#8221; said the ship&#8217;s computer.</p>
<p>The Nutri-Matic explained about tea to the ship&#8217;s computer. The computer boggled, linked logic circuits with the Nutri-Matic and together they lapsed into a grim silence.</p>
<p>Arthur watched and waited for a while, but nothing further happened.</p>
<p>He thumped it, but still nothing happened.</p>
<p>Eventually he gave up and wandered up to the bridge.</p></blockquote>
<p>Now, having the Heart of Gold&#8217;s entire computer system help calculate how to generate a cow and grow a tree to produce leaves so Arthur could have his tea isn&#8217;t a terrible issue, except the second problem:</p>
<p>A Vogon ship approached and began to attack.</p>
<p>So when the rest of the crew rushed to the bridge, they were perplexed that their entire computer was jammed, and all of their controls, navigation, and weapons were unresponsive. However, the reason was soon discovered:</p>
<blockquote><p>&#8220;What have you done to it, Monkeyman?&#8221; he breathed.</p>
<p>&#8220;Well,&#8221; said Arthur, &#8220;nothing in fact. It&#8217;s just that I think a short while ago it was trying to work out how to &#8230;&#8221;</p>
<p>&#8220;Yes?&#8221;</p>
<p>&#8220;Make me some tea.&#8221;</p>
<p>&#8220;That&#8217;s right guys,&#8221; the computer sang out suddenly, &#8220;just coping with that problem right now, and wow, it&#8217;s a biggy. Be with you in a while.&#8221; It lapsed back into a silence that was only matched for sheer intensity by the silence of the three people staring at Arthur Dent.</p>
<p>As if to relieve the tension, the Vogons chose that moment to start firing.</p></blockquote>
<p>Don&#8217;t worry, fortunately the occupants of the ship were able to hold a seance, summon the great grandfather of the captain, and have the great grandfather&#8217;s spirit save them. (I know, such an awesome book)</p>
<p>Anyway, that is a long example, but it show a point:</p>
<h3>Evented I/O</h3>
<p>Basically Evented I/O is when your program does some sort of I/O (like querying a database, reading a file, etc) and continues on executing, not waiting (or blocking) for the response. So in our example above, the ship can be seen like a PHP script:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

$ship = new HeartOfGold();
$nutrimatic = new NutriMatic();

$recipe = $ship-&gt;processQuery('How to make tea.');
$nutrimatic-&gt;makeDrink($recipe);

$enemies = $ship-&gt;detectEnemies();
if($enemies)
{
    $ship-&gt;evasiveManuvers();
}
</pre>
<p>The problem is the ship can&#8217;t detect enemies until it finishes processing Arther&#8217;s request on how to make tea. Now, in Node.js, you have functions that are callbacks. It is a way to say &#8220;Hey, when this request is done, do this afterwards.&#8221;</p>
<pre class="brush: jscript; title: ; notranslate">
var ship = new HeartOfGold();
var nutrimatic = new NutriMatic();

ship.processQuery('How to make tea.', function(recipe){
   nutrimatic.makeDrink(recipe);
});

var enemies = ship.detectEnemies();
if(enemies.length &gt; 0)
{
    ship.evasiveManuvers();
}
</pre>
<p>Now the function processQuery is non-blocking, meaning it will start the process of learning how to make tea and create a recipe, but continue execution. That way if it detects enemies, it can perform evasiveManuvers().</p>
<p>In a real life example, processQuery could be querying a database with a very slow query. In PHP, you can&#8217;t continue executing your code until that result is returned. However, in Node.js, if your SQL library takes advantage of Node.js&#8217;s evented abilities, you can send off a query and continue executing, and when the query returns you can do additional logic through your callback.</p>
<p>Hopefully that makes sense. I like finding programming analogies in books, especially with Douglas Adam&#8217;s series of Hitchhiker&#8217;s Guide to the Galaxy, since they are so fun to read.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2011/04/29/node-js-lamp-and-the-future/' rel='bookmark' title='Node.JS, LAMP, and The Future'>Node.JS, LAMP, and The Future</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/06/02/node-js-event-driven-development-and-tea/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Simple Trick: History Command</title>
		<link>http://www.justincarmony.com/blog/2011/05/31/simple-trick-history-command/</link>
		<comments>http://www.justincarmony.com/blog/2011/05/31/simple-trick-history-command/#comments</comments>
		<pubDate>Tue, 31 May 2011 21:05:08 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[Tips and Tricks]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=932</guid>
		<description><![CDATA[So today I quickly installed Redis on a server, and I wanted to keep a copy of all the commands I had used to do so. I knew there was a better way than hitting the up arrow each time to copy and paste each command in reverse order. So after some Googling, I found ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/06/30/soapui-a-simple-and-raw-java-soap-client/' rel='bookmark' title='SoapUI &#8211; a simple and raw Java SOAP Client'>SoapUI &#8211; a simple and raw Java SOAP Client</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/05/20/memcached-simple-effective-and-powerful/' rel='bookmark' title='Memcached: Simple, Effective, and Powerful'>Memcached: Simple, Effective, and Powerful</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/02/11/asp-net-ajax-straight-forward-and-simple-the-way-it-should-be/' rel='bookmark' title='ASP .NET Ajax &#8211; Straight forward and simple, the way it should be.'>ASP .NET Ajax &#8211; Straight forward and simple, the way it should be.</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>So today I quickly installed Redis on a server, and I wanted to keep a copy of all the commands I had used to do so. I knew there was a better way than hitting the up arrow each time to copy and paste each command in reverse order. So after some Googling, I found out about the history command. So I was able to type the command &#8220;history&#8221; and it showed me the last two thousand or so commands I had used. I was able to copy and paste that into a wiki, and was good to go. You could also search your history by piping the history command to grep. Cool stuff I don&#8217;t want to forget.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/06/30/soapui-a-simple-and-raw-java-soap-client/' rel='bookmark' title='SoapUI &#8211; a simple and raw Java SOAP Client'>SoapUI &#8211; a simple and raw Java SOAP Client</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/05/20/memcached-simple-effective-and-powerful/' rel='bookmark' title='Memcached: Simple, Effective, and Powerful'>Memcached: Simple, Effective, and Powerful</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/02/11/asp-net-ajax-straight-forward-and-simple-the-way-it-should-be/' rel='bookmark' title='ASP .NET Ajax &#8211; Straight forward and simple, the way it should be.'>ASP .NET Ajax &#8211; Straight forward and simple, the way it should be.</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/05/31/simple-trick-history-command/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mac OS X &amp; Wireshark &#8211; No Interfaces Found Fix</title>
		<link>http://www.justincarmony.com/blog/2011/05/12/mac-os-x-wireshark-no-interfaces-found-fix/</link>
		<comments>http://www.justincarmony.com/blog/2011/05/12/mac-os-x-wireshark-no-interfaces-found-fix/#comments</comments>
		<pubDate>Thu, 12 May 2011 18:58:57 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[wireshark]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=914</guid>
		<description><![CDATA[Alright, quick fix for a problem I always forget. When running Wireshark on OS X, when I go to select an interface to capture on, I get an error telling me there are no available interfaces to capture on. This is because Wireshark is running as a user that doesn&#8217;t have ownership on these interfaces. ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2009/02/14/xampp-for-mac-my-frustrations-solutions/' rel='bookmark' title='XAMPP for Mac &#8211; My Frustrations &amp; Solutions'>XAMPP for Mac &#8211; My Frustrations &#038; Solutions</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/10/ubuntu-desktop-terminal-su/' rel='bookmark' title='Ubuntu Desktop Terminal &#8211; Su'>Ubuntu Desktop Terminal &#8211; Su</a></li>
<li><a href='http://www.justincarmony.com/blog/2011/02/02/mysql-stored-procedure-name_const-and-character-sets/' rel='bookmark' title='MySQL Stored Procedure, NAME_CONST, and Character Sets'>MySQL Stored Procedure, NAME_CONST, and Character Sets</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/05/wireshark-logo.png"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/05/wireshark-logo-300x92.png" alt="" title="wireshark-logo" width="300" height="92" class="alignright size-medium wp-image-915" /></a>Alright, quick fix for a problem I always forget. When running Wireshark on OS X, when I go to select an interface to capture on, I get an error telling me there are no available interfaces to capture on. This is because Wireshark is running as a user that doesn&#8217;t have ownership on these interfaces.</p>
<p>Solution, open up the terminal and run the command:</p>
<p><code>sudo chown &lt;username&gt; /dev/bpf*</code></p>
<p>After a reboot, these permissions get reset, so you need to do it after each reset (and hence why I need this every now and then but can never remember the command).</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2009/02/14/xampp-for-mac-my-frustrations-solutions/' rel='bookmark' title='XAMPP for Mac &#8211; My Frustrations &amp; Solutions'>XAMPP for Mac &#8211; My Frustrations &#038; Solutions</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/10/10/ubuntu-desktop-terminal-su/' rel='bookmark' title='Ubuntu Desktop Terminal &#8211; Su'>Ubuntu Desktop Terminal &#8211; Su</a></li>
<li><a href='http://www.justincarmony.com/blog/2011/02/02/mysql-stored-procedure-name_const-and-character-sets/' rel='bookmark' title='MySQL Stored Procedure, NAME_CONST, and Character Sets'>MySQL Stored Procedure, NAME_CONST, and Character Sets</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/05/12/mac-os-x-wireshark-no-interfaces-found-fix/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Node.JS, LAMP, and The Future</title>
		<link>http://www.justincarmony.com/blog/2011/04/29/node-js-lamp-and-the-future/</link>
		<comments>http://www.justincarmony.com/blog/2011/04/29/node-js-lamp-and-the-future/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 23:35:37 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=901</guid>
		<description><![CDATA[I just read an article about &#8220;Node.JS and the JavaScript Age.&#8221; It was from a very &#8220;enthusiastic&#8221; point of view. My guess is they had tinkered around with Node.JS and using with client-side JavaScript rebuilding their Dashboard. You can do some pretty cool stuff with it, and it has a lot of potential. It is ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/10/10/local-lamp-developement-user-content/' rel='bookmark' title='Local LAMP Developement &amp; User Content'>Local LAMP Developement &#038; User Content</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/01/21/list-of-50-php-tools/' rel='bookmark' title='List of 50 PHP Tools'>List of 50 PHP Tools</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/09/15/jquery-tip-better-toggle/' rel='bookmark' title='jQuery Tip: Better Toggle'>jQuery Tip: Better Toggle</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I just read an article about &#8220;<a href="http://metamarketsgroup.com/blog/node-js-and-the-javascript-age/">Node.JS and the JavaScript Age</a>.&#8221; It was from a very &#8220;enthusiastic&#8221; point of view. My guess is they had tinkered around with Node.JS and using with client-side JavaScript rebuilding their Dashboard. You can do some pretty cool stuff with it, and it has a lot of potential. It is very easy to install and get going, much like Redis. Here ia an excerpt from the article:</p>
<blockquote><p>This decision was driven by a realization: the LAMP stack is dead. In the two decades since its birth, there have been fundamental shifts in the web’s make-up of content, protocols, servers, and clients. Together, these mark three ages of the web:</p>
<p>I. 1991-1999: The HTML Age.</p>
<p>The HTML Age was about documents, true to Tim Berners-Lee’s original vision of a “big, virtual documentation system in the sky.” The web was dominated by static, hand-coded files, which web clients crudely formatted (with defaults that offend even the mildest of typographiles). Static documents were served to static clients.</p>
<p>II. 2000-2009: The LAMP Age.</p>
<p>The LAMP Age was about databases. Rather than documents, the dominant web stacks were LAMP or LAMP-like. Whether CGI, PHP, Ruby on Rails, or Django, the dominant pattern was populating an HTML template with database values. Content was dynamic server-side, but still static client-side.</p>
<p>III. 2010-??: The Javascript Age.</p>
<p>The Javascript age is about event streams. Modern web pages are not pages, they are event-driven applications through which information moves. The core content vessel of the web — the document object model — still exists, but not as HTML markup. The DOM is an in-memory, efficiently-encoded data structure generated by Javascript.</p>
<p>LAMP architectures are dead because few web applications want to ship full payloads of markup to the client in response to a small event; they want to update just a fragment of the DOM, using Javascript. AJAX achieved this, but when your server-side LAMP templates are 10% HTML and 90% Javascript, it’s clear that you’re doing it wrong.</p></blockquote>
<h3>Claiming LAMP is Dead is Reaching</h3>
<p>It goes on to explain how LAMP like architectures dead. I would think that is a very overzealous point of view, and to perhaps put it in some perspective:</p>
<p>During each of these &#8220;Ages&#8221;  new technology was developed to solve problems. HTML was created to create inter-linking information. As the demand grew and became more difficult to manage, LAMP like tools like PHP, Django, Ruby on Rails, and others were developed to help make delivering this information easier. It wasn&#8217;t so much replacing the previous technology, but adding on to it. Sometimes you will replace older technology with newer ones, but we&#8217;re still using HTML &#038; CSS, and augment it when needed.</p>
<p>But LAMP-like systems are deployed in production all over the place, powering some of the most visited websites on the net. While <a href="https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node">there are some people who are using Node.JS</a>, like Yammer, but Node.JS isn&#8217;t serving nearly the volume of content like PHP, Ruby, Python, or event .NET. </p>
<h3>What is Node.JS?</h3>
<p>Basically, it is a lightweight framework wrapped around <a href="http://code.google.com/p/v8/">Google&#8217;s V8 JavaScript Engine</a>. V8 is the JavaScript engine that powers Google Chrome, their open source Web Browser. Another part of Node.JS is that it is event based, which can make is very quick and efficient.</p>
<p>I&#8217;ve been tinkering with Node.JS for a couple of weeks, and it is very interesting and has a lot of potential. It&#8217;s unique scoping with JavaScript and event-based methodology makes certain things easy to accomplish that are more difficult in other traditional tools. There are some pretty cool libraries for Node.JS like <a href="http://socket.io/">Socket.IO</a>, a library to support multiple transports using feature detection. So if your browser supports WebSocket or Adobe Flash Socket, it will use that, or AJAX long polling and multipart streaming, or even the Forever Iframe technique. So your application will use which ever type of communication is most efficient. </p>
<h3>A Little Bit of a Reality Check</h3>
<p>But lets be honest for a moment, Node.JS was created in 2010. It is still very, very young. In the video on the front page of the Node.JS is a video of it&#8217;s creator presenting to a PHP Users Group about Node, and even cautions using it in production. It still has a long way to go to maturing as a tool. Granted, being based off the V8 Engine brings a lot of maturity to the project.</p>
<p>As for replacing technologies like PHP, Ruby, and Django, I&#8217;m extremely skeptical that they are &#8220;dead.&#8221; Instead, I see Node.JS augmenting our existing technologies.  Like how I&#8217;ve implemented Redis as a data store where MySQL was poorly suited, I see Node.JS functioning as a tool for real-time communication for the future of websites. </p>
<p>I hope to write more about Node.JS, and look forward to using it to solve new and unique problems. But I won&#8217;t be rewriting all my websites in Node.JS, it would be a nightmare. So like with NoSQL, and Cloud Computing, yes it is a new tool, but it won&#8217;t radically remove everything else up to this point. Like with Redis, I didn&#8217;t get rid of MySQL, I just use Redis when it is a better choice.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/10/10/local-lamp-developement-user-content/' rel='bookmark' title='Local LAMP Developement &amp; User Content'>Local LAMP Developement &#038; User Content</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/01/21/list-of-50-php-tools/' rel='bookmark' title='List of 50 PHP Tools'>List of 50 PHP Tools</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/09/15/jquery-tip-better-toggle/' rel='bookmark' title='jQuery Tip: Better Toggle'>jQuery Tip: Better Toggle</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/04/29/node-js-lamp-and-the-future/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>First PHP Project &#8211; Tournament Brackets</title>
		<link>http://www.justincarmony.com/blog/2011/04/12/first-php-project-tournament-brackets/</link>
		<comments>http://www.justincarmony.com/blog/2011/04/12/first-php-project-tournament-brackets/#comments</comments>
		<pubDate>Tue, 12 Apr 2011 20:47:01 +0000</pubDate>
		<dc:creator>Justin Carmony</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[cevo]]></category>
		<category><![CDATA[lessons]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[stories]]></category>

		<guid isPermaLink="false">http://www.justincarmony.com/blog/?p=881</guid>
		<description><![CDATA[I mentioned on my twitter account that my very first project in PHP is used in production today, and I had a few people ask me what it was. So I thought I would show some examples of it in action. While I had done other things in PHP, this was the first time I ...


Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/06/28/whysecurityorg-a-new-mini-project/' rel='bookmark' title='WhySecurity.org &#8211; A New Mini-Project'>WhySecurity.org &#8211; A New Mini-Project</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/08/29/project-management-and-entrepreneurship/' rel='bookmark' title='Project Management &amp; Entrepreneurship'>Project Management &#038; Entrepreneurship</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/07/15/web-development-10-years-ago-now/' rel='bookmark' title='Web Development 10-Years Ago &amp; Now'>Web Development 10-Years Ago &#038; Now</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I mentioned on my twitter account that my very first project in PHP is used in production today, and I had a few people ask me what it was. So I thought I would show some examples of it in action. While I had done other things in PHP, this was the first time I had sat down and built someone by myself instead of just modifying someone else&#8217;s code. I built it for the very first time back in 2005, and since then have had to update it a few times. But it is still used regularly to host CEVO&#8217;s tournaments. </p>
<p>It basically is a system of managing a tournament bracket. Here is an example:</p>
<div id="attachment_882" class="wp-caption aligncenter" style="width: 674px"><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/brackets-example.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/brackets-example-664x1024.jpg" alt="Example Tournament Brackets" title="brackets-example" width="664" height="1024" class="size-large wp-image-882" /></a>
<p class="wp-caption-text">Example Tournament Brackets</p>
</div>
<p>It basically is a PHP script that pulls from a database with key-value pairs. In a template file, in which you would create the bracket&#8217;s HTML, you would insert tags with an id. Then, depending on if you are viewing or editing it, it with either insert the value, or a input box used for changing the value.</p>
<p>There was a basic admin listing of the brackets that are active, as well as access to archived brackets:</p>
<div id="attachment_883" class="wp-caption aligncenter" style="width: 310px"><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/brackets-admin.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/brackets-admin-300x252.jpg" alt="Admin Panel" title="brackets-admin" width="300" height="252" class="size-medium wp-image-883" /></a>
<p class="wp-caption-text">Admin Panel</p>
</div>
<p>You could add a new Bracket and select a template to use. When you select a template, it will show a preview of the template below.</p>
<div id="attachment_884" class="wp-caption aligncenter" style="width: 310px"><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/bracket-admin2.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/bracket-admin2-300x198.jpg" alt="Create a Bracket" title="bracket-admin2" width="300" height="198" class="size-medium wp-image-884" /></a>
<p class="wp-caption-text">Create a Bracket</p>
</div>
<p>Once you create a bracket, you can edit it. It isn&#8217;t pretty, but it gets the job done:</p>
<div id="attachment_885" class="wp-caption aligncenter" style="width: 310px"><a href="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/brackets-admin3.jpg"><img src="http://c747925.r25.cf2.rackcdn.com/blog/wp-content/uploads/2011/04/brackets-admin3-300x240.jpg" alt="Editing a Bracket" title="brackets-admin3" width="300" height="240" class="size-medium wp-image-885" /></a>
<p class="wp-caption-text">Editing a Bracket</p>
</div>
<p>Here is an <a href="http://www.cevo.com/playoffs/bracket.php?id=1243" target="_blank">example</a> of the finished product that I just created. If you want a better example, here is the recent <a href="http://www.cevo.com/playoffs/bracket.php?id=1227" target="_blank">League of Legends tournament bracket</a>. While it isn&#8217;t pretty, it works. Some of the biggest problems with it is the editing and managing of the templates. You can only use some sort of WYSIWYG editor to be able to make sense of them, since they are a giant table. What that ends up leading to is template files with 2,000+ lines. It still amazes me this chunk of PHP code has been used over 1,000 times for different tournaments around the world.</p>
<p>One day we are going to rewrite the system to allow the end user to make their own templates, and more interaction &#038; connectivity between the bracket and CTE (CEVO Tournament Engine). But until, my first real PHP project can continue to chug along just fine.</p>


<p>Related posts:<ol><li><a href='http://www.justincarmony.com/blog/2008/06/28/whysecurityorg-a-new-mini-project/' rel='bookmark' title='WhySecurity.org &#8211; A New Mini-Project'>WhySecurity.org &#8211; A New Mini-Project</a></li>
<li><a href='http://www.justincarmony.com/blog/2009/08/29/project-management-and-entrepreneurship/' rel='bookmark' title='Project Management &amp; Entrepreneurship'>Project Management &#038; Entrepreneurship</a></li>
<li><a href='http://www.justincarmony.com/blog/2008/07/15/web-development-10-years-ago-now/' rel='bookmark' title='Web Development 10-Years Ago &amp; Now'>Web Development 10-Years Ago &#038; Now</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.justincarmony.com/blog/2011/04/12/first-php-project-tournament-brackets/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 37/132 queries in 0.058 seconds using memcached
Content Delivery Network via Rackspace Cloud Files: c747925.r25.cf2.rackcdn.com

Served from: www.justincarmony.com @ 2012-02-04 05:14:37 -->
