<?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>Hungry Machine &#187; tips</title>
	<atom:link href="http://blog.hungrymachine.com/tag/tips/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hungrymachine.com</link>
	<description>The guys behind LivingSocial</description>
	<lastBuildDate>Sun, 25 Oct 2009 15:08:39 +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>Agressive Timeouts On External API Calls</title>
		<link>http://blog.hungrymachine.com/2008/03/31/agressive-timeouts-on-external-api-calls/</link>
		<comments>http://blog.hungrymachine.com/2008/03/31/agressive-timeouts-on-external-api-calls/#comments</comments>
		<pubDate>Mon, 31 Mar 2008 03:48:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2008/05/13/agressive-timeouts-on-external-api-calls</guid>
		<description><![CDATA[One of the challenges with writing a Facebook or Bebo application is staying within a limit it gives you to respond with data before it shows the Application Did Not Respond page to a user. Having a content reach application calling external APIs, like Amazon or YouTube, with response times beyond your control, forces you [...]]]></description>
			<content:encoded><![CDATA[<p>One of the challenges with writing a Facebook or Bebo application is staying within a limit it gives you to respond with data before it shows the <em>Application Did Not Respond</em> page to a user. Having a content reach application calling external APIs, like Amazon or YouTube, with response times beyond your control, forces you to keep such calls short to allow extra time for processing. We usually wrap them in aggressive timeouts with a retry. As an example is this code from the <a href="http://www.pluitsolutions.com/projects/amazon-ecs">Ruby Amazon E-Commerce <span class="caps">REST</span> Service <span class="caps">API</span></a> gem rewritten to limit a single call attempt to two seconds with one more retry.</p>
<p><strong>Original Code</strong></p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#080; font-weight:bold">module</span> <span style="color:#B06; font-weight:bold">Amazon</span>
  <span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">Ecs</span>

    <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.send_request(opts)
      request_url = prepare_url(opts)

      res = <span style="color:#036; font-weight:bold">Net</span>::<span style="color:#036; font-weight:bold">HTTP</span>.get_response(<span style="color:#036; font-weight:bold">URI</span>::parse(request_url))
      <span style="color:#080; font-weight:bold">unless</span> res.kind_of? <span style="color:#036; font-weight:bold">Net</span>::<span style="color:#036; font-weight:bold">HTTPSuccess</span>
        raise <span style="color:#036; font-weight:bold">Amazon</span>::<span style="color:#036; font-weight:bold">RequestError</span>, <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">HTTP Response: </span><span style="background-color:#fff0f0"><span style="color:#710">#{</span>res.code<span style="color:#710">}</span></span><span style="color:#D20"> </span><span style="background-color:#fff0f0"><span style="color:#710">#{</span>res.message<span style="color:#710">}</span></span><span style="color:#710">&quot;</span></span>
      <span style="color:#080; font-weight:bold">end</span>
      <span style="color:#036; font-weight:bold">Response</span>.new(res.body)
    <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">end</span>
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p><strong>Modified Code</strong></p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#080; font-weight:bold">module</span> <span style="color:#B06; font-weight:bold">Amazon</span>
  <span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">Ecs</span>

    <span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">EmptyResponse</span>
      <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">items</span>; []; <span style="color:#080; font-weight:bold">end</span>
      <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">total_pages</span>; <span style="color:#00D; font-weight:bold">0</span>; <span style="color:#080; font-weight:bold">end</span>
    <span style="color:#080; font-weight:bold">end</span>

    <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.send_request(opts)

      res = timed_try(request_url, <span style="color:#00D; font-weight:bold">2</span>) <span style="color:#080; font-weight:bold">do</span> |url|

        uri = <span style="color:#036; font-weight:bold">URI</span>::parse(url)
        req = <span style="color:#036; font-weight:bold">Net</span>::<span style="color:#036; font-weight:bold">HTTP</span>.new(uri.host, uri.port)

        <span style="color:#888"># Agressive timeouts</span>
        req.open_timeout = <span style="color:#00D; font-weight:bold">1</span>
        req.read_timeout = <span style="color:#00D; font-weight:bold">2</span>

        req.start { |http| http.request_get(url) }

      <span style="color:#080; font-weight:bold">end</span>

      res.kind_of?(<span style="color:#036; font-weight:bold">Net</span>::<span style="color:#036; font-weight:bold">HTTPSuccess</span>) ? <span style="color:#036; font-weight:bold">Response</span>.new(res.body) : <span style="color:#036; font-weight:bold">EmptyResponse</span>.new

    <span style="color:#080; font-weight:bold">end</span>

private

     <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">timed_try</span>(url, attempts, &amp;block)

       attempt = <span style="color:#00D; font-weight:bold">1</span>
       <span style="color:#080; font-weight:bold">begin</span>
         block.call(url)
       <span style="color:#080; font-weight:bold">rescue</span> <span style="color:#036; font-weight:bold">Timeout</span>::<span style="color:#036; font-weight:bold">Error</span>
         <span style="color:#080; font-weight:bold">if</span> attempt &gt;= attempts
           <span style="color:#036; font-weight:bold">RAILS_DEFAULT_LOGGER</span>.warn <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">[amazon_api] gave up after attempt #</span><span style="background-color:#fff0f0"><span style="color:#710">#{</span> attempt <span style="color:#710">}</span></span><span style="color:#D20"> to get data from </span><span style="background-color:#fff0f0"><span style="color:#710">#{</span> url <span style="color:#710">}</span></span><span style="color:#710">&quot;</span></span>
           <span style="color:#038; font-weight:bold">nil</span>
         <span style="color:#080; font-weight:bold">else</span>
           <span style="color:#036; font-weight:bold">RAILS_DEFAULT_LOGGER</span>.warn <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">[amazon_api] attempt #</span><span style="background-color:#fff0f0"><span style="color:#710">#{</span> attempt <span style="color:#710">}</span></span><span style="color:#D20"> timed out on getting data from </span><span style="background-color:#fff0f0"><span style="color:#710">#{</span> url <span style="color:#710">}</span></span><span style="color:#710">&quot;</span></span>
           attempt += <span style="color:#00D; font-weight:bold">1</span>
           <span style="color:#080; font-weight:bold">retry</span>
         <span style="color:#080; font-weight:bold">end</span>
       <span style="color:#080; font-weight:bold">end</span>

     <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">end</span>
<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2008/03/31/agressive-timeouts-on-external-api-calls/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Reconfiguring the whole rails stack via a central YAML file</title>
		<link>http://blog.hungrymachine.com/2007/08/20/reconfiguring-the-whole-rails-stack-via-a-central-yaml-file/</link>
		<comments>http://blog.hungrymachine.com/2007/08/20/reconfiguring-the-whole-rails-stack-via-a-central-yaml-file/#comments</comments>
		<pubDate>Mon, 20 Aug 2007 02:07:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Ops]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[yaml]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2007/08/23/reconfiguring-the-whole-rails-stack-via-a-central-yaml-file</guid>
		<description><![CDATA[The challenge with hosting of multiple Rails-based Facebook applications is that the amount of users grow quickly. To address this problem we are using EC2 nodes that we can expand/shrink as the demand grows. The price/performance ratio isn&#8217;t quite what we first expected, so we are moving toward having a few dedicated boxes instead. Another [...]]]></description>
			<content:encoded><![CDATA[<p>The challenge with hosting of multiple Rails-based Facebook applications is that the amount of users grow quickly. To address this problem we are using <span class="caps">EC2</span> nodes that we can expand/shrink as the demand grows. The price/performance ratio isn&#8217;t quite what we first expected, so we are moving toward having a few dedicated boxes instead. Another problem that we add at least a couple of applications a week. On each box that hosts them, we need to reconfigure monit, haproxy, nginx, logrotate and nagios.</p>
<p>To mitigate both issues on dedicated boxes, we resolved to have a central configuration definition in svn with individual box configurations keyed on localhost name. A ruby script regenerates all those aforementioned configuration files from <span class="caps">ERB</span>-processed templates when it is run on a box and bounces the services. A sample config looks like:</p>
<div class="CodeRay">
<div class="code">
<pre>dedicated<span style="color:#00D; font-weight:bold">-1</span>:

    description: <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">The dedicated box #1</span><span style="color:#710">&quot;</span></span>
    ip: <span style="color:#60E; font-weight:bold">64.233</span>.<span style="color:#60E; font-weight:bold">167.99</span>
    failover: dedicated<span style="color:#00D; font-weight:bold">-2</span>

    apps:

        bookshelf:
            port: <span style="color:#00D; font-weight:bold">5000</span>
            instances: <span style="color:#00D; font-weight:bold">20</span>
            response: <span style="color:#036; font-weight:bold">Book</span>

        ljconnect:
            port: <span style="color:#00D; font-weight:bold">6000</span>
            instances: <span style="color:#00D; font-weight:bold">7</span>
            virtual: ljconnect.hungrymachine.com
            response: <span style="color:#036; font-weight:bold">Journal</span>
                      </pre>
</div>
</div>
<p>That definition would generate a monit config with 20 instances of the <em>bookshelf</em> application and 7 instances of the <em>ljconnect</em> application plus all other configurations (including nagios health checks expecting the <em>response</em> value) . It is all possible because we adopt a fixed application deployment file structure and port numbering conventions (via offsets) for all servers.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2007/08/20/reconfiguring-the-whole-rails-stack-via-a-central-yaml-file/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Killing sneaky mongrels</title>
		<link>http://blog.hungrymachine.com/2007/08/16/killing-sneaky-mongrels/</link>
		<comments>http://blog.hungrymachine.com/2007/08/16/killing-sneaky-mongrels/#comments</comments>
		<pubDate>Thu, 16 Aug 2007 18:16:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Ops]]></category>
		<category><![CDATA[mongrel]]></category>
		<category><![CDATA[monit]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2007/08/29/killing-sneaky-mongrels</guid>
		<description><![CDATA[We found that sometimes monit fails to restart all mongrel instances after deployment and some of them end up running with the pid file gone. Since there is no pid, monit believes the instance is not running so it tries to start a new one on the same port and, of course, fails. Which leads [...]]]></description>
			<content:encoded><![CDATA[<p>We found that sometimes <a href="http://www.tildeslash.com/monit/">monit</a> fails to restart all mongrel instances after deployment and some of them end up running with the pid file gone. Since there is no pid, monit believes the instance is not running so it tries to start a new one on the same port and, of course, fails. Which leads to stale mongrel instances with old code. We&#8217;re investigating a long term solution but in the meantime have wrapped the mongrel_rails start script with a replacement which finds and kills the stale mongrel instances before starting a new one.</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#888">#!/usr/bin/env ruby</span>

<span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">MongrelController</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.run_mongrel(args)
    pid = extract_pid(args)
    kill_stale_process(pid) <span style="color:#080; font-weight:bold">if</span> pid
    system <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">/bin/mongrel_rails </span><span style="background-color:#fff0f0"><span style="color:#710">#{</span> args.join(<span style="background-color:#ffe0e0"><span style="color:#710">'</span><span style="color:#D20"> </span><span style="color:#710">'</span></span>) <span style="color:#710">}</span></span><span style="color:#710">&quot;</span></span>
  <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.extract_pid(args)
     (args[<span style="color:#00D; font-weight:bold">0</span>] == <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">start</span><span style="color:#710">'</span></span>) &amp;&amp; (i = args.index(<span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">-P</span><span style="color:#710">'</span></span>)) &amp;&amp; args[i + <span style="color:#00D; font-weight:bold">1</span>]
  <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.kill_stale_process(pid)
    mongrel_processes(pid).each { |p| process_running?(p) &amp;&amp; <span style="color:#036; font-weight:bold">Process</span>.kill(<span style="color:#00D; font-weight:bold">9</span>, p)  }
  <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.mongrel_processes(pid)
    <span style="background-color:#f0fff0"><span style="color:#161">`</span><span style="color:#2B2">ps axww -o 'pid command'</span><span style="color:#161">`</span></span>.split(<span style="background-color:#fff0ff"><span style="color:#404">/</span><span style="color:#04D">\n</span><span style="color:#404">/</span></span>).inject([]) <span style="color:#080; font-weight:bold">do</span> |mongrels, process|
      mongrels &lt;&lt; process[<span style="background-color:#fff0ff"><span style="color:#404">/</span><span style="color:#808">^</span><span style="color:#04D">\s</span><span style="color:#808">*(</span><span style="color:#04D">\d</span><span style="color:#808">+)</span><span style="color:#404">/</span></span>][<span style="color:#d70; font-weight:bold">$1</span>].to_i <span style="color:#080; font-weight:bold">if</span> process.match(<span style="background-color:#fff0ff"><span style="color:#404">%r{</span><span style="color:#808">/bin/mongrel_rails</span><span style="color:#04D">\s</span><span style="color:#808">.*</span><span style="color:#04D">\s</span><span style="color:#808">-P</span><span style="color:#04D">\s</span><span style="background-color:#fff0ff"><span style="color:#404">#{</span> pid <span style="color:#404">}</span></span><span style="color:#04D">\b</span><span style="color:#404">}</span></span>)
      mongrels
    <span style="color:#080; font-weight:bold">end</span>
  <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#038; font-weight:bold">self</span>.process_running?(pid)
    pid &amp;&amp; (<span style="background-color:#f0fff0"><span style="color:#161">`</span><span style="color:#2B2">ps -p </span><span style="background-color:#f0fff0"><span style="color:#161">#{</span> pid <span style="color:#161">}</span></span><span style="color:#161">`</span></span>.split(<span style="background-color:#fff0ff"><span style="color:#404">/</span><span style="color:#04D">\n</span><span style="color:#404">/</span></span>).size == <span style="color:#00D; font-weight:bold">2</span>)
  <span style="color:#080; font-weight:bold">end</span>

<span style="color:#080; font-weight:bold">end</span>

<span style="color:#036; font-weight:bold">MongrelController</span>.run_mongrel(<span style="color:#038; font-weight:bold">ARGV</span>)</pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2007/08/16/killing-sneaky-mongrels/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using mocks at the early stage of FB app development</title>
		<link>http://blog.hungrymachine.com/2007/08/15/using-mocks-at-the-early-stage-of-fb-app-development/</link>
		<comments>http://blog.hungrymachine.com/2007/08/15/using-mocks-at-the-early-stage-of-fb-app-development/#comments</comments>
		<pubDate>Wed, 15 Aug 2007 12:50:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[mock]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2007/08/23/using-mocks-at-the-early-stage-of-fb-app-development</guid>
		<description><![CDATA[Developing applications for Facebook is a pain. The tunnel approach helps a lot to ease that pain but even then I prefer to start a FB app as a regular application, polish the logic, and then convert it to the Facebook one by adding FBML and such. At the early stages of the development I [...]]]></description>
			<content:encoded><![CDATA[<p>Developing applications for Facebook is a pain. <a href="http://rfacebook.rubyforge.org/tunnel.html">The tunnel approach</a> helps a lot to ease that pain but even then I prefer to start a FB app as a regular application, polish the logic, and then convert it to the Facebook one by adding <span class="caps">FBML</span> and such. At the early stages of the development I have the <em>mocked</em> parameter in <em>config/facebook.yml</em> set to <strong>true</strong> and keep this code in <em>config/initializers/facebook.rb</em>:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#036; font-weight:bold">PERSON_PROFILE_URL</span> = <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">http://www.facebook.com/profile.php</span><span style="color:#710">&quot;</span></span>

<span style="color:#036; font-weight:bold">FACEBOOK_CONFIG</span> = <span style="color:#036; font-weight:bold">YAML</span>.load_file(<span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="background-color:#fff0f0"><span style="color:#710">#{</span><span style="color:#036; font-weight:bold">RAILS_ROOT</span><span style="color:#710">}</span></span><span style="color:#D20">/config/facebook.yml</span><span style="color:#710">&quot;</span></span>)[<span style="color:#036; font-weight:bold">RAILS_ENV</span>] || {}

<span style="color:#080; font-weight:bold">if</span> <span style="color:#036; font-weight:bold">FACEBOOK_CONFIG</span>[<span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">mocked</span><span style="color:#710">'</span></span>]

  <span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">Facebook::FBMLController</span>

    require <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">ostruct</span><span style="color:#710">'</span></span>
    <span style="color:#036; font-weight:bold">FB_SESSION</span> = <span style="color:#036; font-weight:bold">OpenStruct</span>.new(<span style="color:#A60">:session_user_id</span> =&gt; <span style="color:#00D; font-weight:bold">1</span>, <span style="color:#A60">:session_key</span> =&gt; <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#D20">12345</span><span style="color:#710">&quot;</span></span>, <span style="color:#A60">:is_valid?</span> =&gt; <span style="color:#038; font-weight:bold">true</span>)

    <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">fbsession</span>; <span style="color:#036; font-weight:bold">FB_SESSION</span>; <span style="color:#080; font-weight:bold">end</span>

    <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">require_facebook_install</span>; <span style="color:#038; font-weight:bold">true</span>; <span style="color:#080; font-weight:bold">end</span>

    <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">redirect_to</span>(url); <span style="color:#080; font-weight:bold">super</span>; <span style="color:#080; font-weight:bold">end</span>

    <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">url_for</span>(*params); <span style="color:#080; font-weight:bold">super</span>; <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">module</span> <span style="color:#B06; font-weight:bold">Facebook::Acts::FbUser</span>
    <span style="color:#080; font-weight:bold">module</span> <span style="color:#B06; font-weight:bold">InstanceMethods</span>
      <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">friends</span>
        (<span style="color:#038; font-weight:bold">self</span>.class.find(<span style="color:#A60">:all</span>) - [ <span style="color:#038; font-weight:bold">self</span> ]).collect(&amp;<span style="color:#A60">:uid</span>)
      <span style="color:#080; font-weight:bold">end</span>
    <span style="color:#080; font-weight:bold">end</span>
  <span style="color:#080; font-weight:bold">end</span>

<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p>It mocks out just enough of <a href="http://code.google.com/p/facebook-rails/">Facebook on Rails</a> functionality to use <em>FBMLController</em> and <em>acts_as_fb_user</em> from the beginning without Facebook backend.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2007/08/15/using-mocks-at-the-early-stage-of-fb-app-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Routing to the initial action after facebook application install</title>
		<link>http://blog.hungrymachine.com/2007/08/14/routing-to-the-initial-action-after-facebook-application-install/</link>
		<comments>http://blog.hungrymachine.com/2007/08/14/routing-to-the-initial-action-after-facebook-application-install/#comments</comments>
		<pubDate>Tue, 14 Aug 2007 23:17:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2007/08/17/routing-to-the-initial-action-after-facebook-application-install</guid>
		<description><![CDATA[Some facebook applications might have multiple entries. For example, a user might be adding an application (action &#8211; new) or replying to an invitation (action &#8211; reply, param &#8211; id). Since the UI for Facebook application configuration allows to provide only static Post-Add URL it might seem like there is no way to route users [...]]]></description>
			<content:encoded><![CDATA[<p>Some facebook applications might have multiple entries. For example, a user might be adding an application (action &#8211; <em>new</em>) or replying to an invitation (action &#8211; <em>reply</em>, param &#8211; <em>id</em>). Since the UI for Facebook application configuration allows to provide only static <em>Post-Add <span class="caps">URL</span></em> it might seem like there is no way to route users back to the original action if they tried to reach when the application has not been installed for them. Luckily, we have full control on the destination via the <em>next</em> paramater of the post install <span class="caps">URL</span>. All we need is to build a <span class="caps">URL</span> using the incoming call parameters with the exclusion of Facebook-specific ones.</p>
<p>This is an example for <a href="http://code.google.com/p/facebook-rails/">Facebook on Rails</a> based code that might go to the application controller:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#080; font-weight:bold">class</span> <span style="color:#B06; font-weight:bold">ApplicationController</span> &lt; <span style="color:#036; font-weight:bold">Facebook</span>::<span style="color:#036; font-weight:bold">FBMLController</span>

protected

  before_filter <span style="color:#A60">:require_facebook_install</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">require_facebook_install</span>
    <span style="color:#080; font-weight:bold">if</span> in_canvas? &amp;&amp; !fbsession.is_valid?
      redirect_to fbsession.get_install_url(<span style="color:#A60">:next</span> =&gt; url_for(post_install_params))
      <span style="color:#038; font-weight:bold">false</span>
    <span style="color:#080; font-weight:bold">end</span>
  <span style="color:#080; font-weight:bold">end</span>

  <span style="color:#080; font-weight:bold">def</span> <span style="color:#06B; font-weight:bold">post_install_params</span>
    params.merge(<span style="color:#A60">:init</span> =&gt; <span style="color:#038; font-weight:bold">true</span>).delete_if { |k, v| k.starts_with?(<span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">fb_sig</span><span style="color:#710">'</span></span>) }
  <span style="color:#080; font-weight:bold">end</span>

<span style="color:#080; font-weight:bold">end</span></pre>
</div>
</div>
<p>Notice that the code sets the <em>init</em> parameter so it <a href="indentifying-users-who-just-installed-your-facebook-apps">can be used to identify a post install call</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2007/08/14/routing-to-the-initial-action-after-facebook-application-install/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Indentifying users who just installed your facebook apps</title>
		<link>http://blog.hungrymachine.com/2007/08/14/indentifying-users-who-just-installed-your-facebook-apps/</link>
		<comments>http://blog.hungrymachine.com/2007/08/14/indentifying-users-who-just-installed-your-facebook-apps/#comments</comments>
		<pubDate>Tue, 14 Aug 2007 23:13:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2007/08/24/indentifying-users-who-just-installed-your-facebook-apps</guid>
		<description><![CDATA[Sometimes it is useful to do some action on a Facebook user right after your application has been installed by the user. For example, you might want to push some default FBML to user&#8217;s profile in case he does not complete the action you expect him to do after installation. Facebook application configuration allows to [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it is useful to do some action on a Facebook user right after your application has been installed by the user. For example, you might want to push some default <span class="caps">FBML</span> to user&#8217;s profile in case he does not complete the action you expect him to do after installation. Facebook application configuration allows to provide <em>Post-Add <span class="caps">URL</span></em> to route users to the destination url after the application install. It could be a dedicated <em>post_add</em> action or, in case of a default action where you have some code in the controller and since Facebook limits amount of redirects you can use, it could be a parameter to the url, like <code>&#38;init=true</code>, used to identify that it was a post-install action and execute on it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2007/08/14/indentifying-users-who-just-installed-your-facebook-apps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using a ruby-based AIM notifier in nagios</title>
		<link>http://blog.hungrymachine.com/2007/08/14/using-a-ruby-based-aim-notifier-in-nagios/</link>
		<comments>http://blog.hungrymachine.com/2007/08/14/using-a-ruby-based-aim-notifier-in-nagios/#comments</comments>
		<pubDate>Tue, 14 Aug 2007 22:36:00 +0000</pubDate>
		<dc:creator>val</dc:creator>
				<category><![CDATA[All]]></category>
		<category><![CDATA[Ops]]></category>
		<category><![CDATA[aim]]></category>
		<category><![CDATA[nagios]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">blog.hungrymachine.com/2007/08/17/using-a-ruby-based-aim-notifier-in-nagios</guid>
		<description><![CDATA[If you use nagios for monitoring of your rails instances, you might want to get notification not only via email or SMS-messages but to your AIM when you are online. The script (libexec/aim_notifier.rb) utilizes the Net::TOC gem for sending out notifications:


#!/usr/bin/env ruby

 require 'rubygems'
 require 'net/toc'

 user = 'your_bot_name'
 password = 'bot_password'

 msg = ARGV[0].to_s.gsub('\n', [...]]]></description>
			<content:encoded><![CDATA[<p>If you use <a href="http://www.nagios.org/">nagios</a> for monitoring of your rails instances, you might want to get notification not only via email or <a href="http://www.sms411.net/2006/07/how-to-send-email-to-phone.html"><span class="caps">SMS</span>-messages</a> but to your <span class="caps">AIM</span> when you are online. The script (<em>libexec/aim_notifier.rb</em>) utilizes the <a href="http://rubyforge.org/projects/net-toc/">Net::TOC</a> gem for sending out notifications:</p>
<div class="CodeRay">
<div class="code">
<pre><span style="color:#888">#!/usr/bin/env ruby</span>

 require <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">rubygems</span><span style="color:#710">'</span></span>
 require <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">net/toc</span><span style="color:#710">'</span></span>

 user = <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">your_bot_name</span><span style="color:#710">'</span></span>
 password = <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">bot_password</span><span style="color:#710">'</span></span>

 msg = <span style="color:#038; font-weight:bold">ARGV</span>[<span style="color:#00D; font-weight:bold">0</span>].to_s.gsub(<span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">\n</span><span style="color:#710">'</span></span>, <span style="background-color:#fff0f0"><span style="color:#710">&quot;</span><span style="color:#04D">\n</span><span style="color:#710">&quot;</span></span>)

 client = <span style="color:#036; font-weight:bold">Net</span>::<span style="color:#036; font-weight:bold">TOC</span>.new(user, password)

 client.connect

 sleep <span style="color:#00D; font-weight:bold">3</span>

 buddies = []

 client.buddy_list.each_group { |g, b| buddies = b <span style="color:#080; font-weight:bold">if</span> g == <span style="background-color:#fff0f0"><span style="color:#710">'</span><span style="color:#D20">Friends</span><span style="color:#710">'</span></span> }

 buddies.each <span style="color:#080; font-weight:bold">do</span> |b|
   b.send_im(msg) <span style="color:#080; font-weight:bold">if</span> b.available?
 <span style="color:#080; font-weight:bold">end</span>

 sleep <span style="color:#00D; font-weight:bold">3</span>

 client.disconnect</pre>
</div>
</div>
<p> You need to add any account you want to be notified to bot&#8217;s friends (either by logging to <span class="caps">AIM</span> using the bot account or using Net::TOC&#8217;s ability to add friends).</p>
<p> The last piece is to add a new notifier in <em>etc/objects/commands.cfg</em> as:</p>
<div class="CodeRay">
<div class="code">
<pre> define command{
         command_name    notify-service-by-aim
         command_line    $USER1$/aim_notifier.rb $ARG1$ $ARG2$ &quot;***** Nagios *****\n\nNotification Ty
 pe: $NOTIFICATIONTYPE$\n\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState:
 $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$&quot;
         }</pre>
</div>
</div>
<p> and to append it to the list of notifiers defined for a contact template in <em>etc/objects/commands.cfg</em>:</p>
<div class="CodeRay">
<div class="code">
<pre> service_notification_commands   notify-service-by-email,notify-service-by-aim</pre>
</div>
</div>
<p>Repeat the configuration if you want to use the <span class="caps">AIM</span> notification for hosts as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hungrymachine.com/2007/08/14/using-a-ruby-based-aim-notifier-in-nagios/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
