<?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; api</title>
	<atom:link href="http://blog.hungrymachine.com/tag/api/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>
	</channel>
</rss>
