<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Wal McConnell - What! What?</title>
  <link href="http://wal.github.com/atom.xml" rel="self"/>
  <link href="http://wal.github.com/"/>
  <updated>2011-03-21T01:17:27-07:00</updated>
  <id>http://wal.github.com/</id>
  <author>
    <name>wal.github.com</name>
    <email>man@wal.github.com</email>
  </author>

  
  <entry>
    <title>Finding Data, Index and Free sizes for all the tables in your MySQL Database</title>
    <link href="http://wal.github.com/2010/09/16/MySQL-Database-Size"/>
    <updated>2010-09-16T00:00:00-07:00</updated>
    <id>http://wal.github.com/2010/09/16/MySQL-Database-Size</id>
    <content type="html">&lt;div&gt;
	
&lt;p&gt;'SHOW TABLE STATUS' is just pure ugly, so I have another simple command for showing the data, index and free sizes for the tables in my MySQL DB&lt;p&gt;
	
&lt;pre&gt;&lt;code&gt;SELECT concat(table_schema,'.',table_name),
	table_rows as 'rows',  
	concat(round(data_length/(1024*1024*1024),2),'Gb') Data_Size,  
	concat(round(data_free/(1024*1024*1024),2),'Gb') Free_Size,  
	concat(round(index_length/(1024*1024*1024),2),'Gb') Index_Size,  
	concat(round((data_length+index_length)/(1024*1024*1024),2),'Gb') Total_Size
FROM information_schema.TABLES   
ORDER BY data_length+index_length;
&lt;/pre&gt;&lt;/code&gt;
</content>
  </entry>
  
  <entry>
    <title>Building a simple, fast, scaleable API with sinatra, memcached, Amazon SQS, delayed_job, Exceptional and Heroku</title>
    <link href="http://wal.github.com/2010/08/16/Sinatra-API-Building"/>
    <updated>2010-08-16T00:00:00-07:00</updated>
    <id>http://wal.github.com/2010/08/16/Sinatra-API-Building</id>
    <content type="html">&lt;div&gt;
	&lt;i&gt;The following is a blog post I posed over at the &lt;a href=&quot;http://blog.getexceptional.com&quot;&gt;exceptional blog&lt;/a&gt;&lt;/i&gt;
	
&lt;p&gt;The recent fast growth in &lt;a href=&quot;http://getexceptional.com&quot;&gt;Exceptional&lt;/a&gt; has meant our publish API implementation needed to be updated. Below are some notes and decisions we made about its re-architecture.&lt;p&gt;
	
&lt;p&gt;I've put together a simple skeleton API app that demonstrates the use of the various libraries used below &lt;a href=&quot;http://github.com/wal/sinatra_api_example-&quot; target=&quot;_new&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Sinatra&lt;/h3&gt;
&lt;p&gt;The exceptional publish API is very simple, consisting of a single HTTP POST operation. The full rails stack is overkill for this, so we based our new API on &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Throttling&lt;/h3&gt;
&lt;p&gt;Every scaleable API requires throttling, so that overly 'aggressive' api clients (i.e apps throwing errors in our case) do not hog the limited API resources. We used &lt;a href=&quot;http://twitter.com/datagraph&quot;&gt;@datagraphs&lt;/a&gt; excellent &lt;a href=&quot;http://github.com/datagraph/rack-throttle&quot;&gt;rack_throttle&lt;/a&gt; rack middleware to handle request throttling for our app. rack_throttle allows you to set schemes for request limit counts on your interface, and makes it easy to set rules even for custom ways to identify clients (i.e by IP Address, API Key, path, cookie, header, etc).&lt;p&gt;                                                                                                                                              

&lt;p&gt;We hooked up rack_throttle with &lt;a href=&quot;http://memcached.org&quot;&gt;memcached&lt;/a&gt; to store the connection counts. On heroku a shared memcached instance is available to all dynos in an application, so this was a super handy (and fast) way to maintain connection counts across all dynos. We need a fair few dynos to handle the ~4k api requests per minute that the  exceptional API handles.&lt;/p&gt;
                                                     
&lt;h3&gt;Queueing&lt;/h3&gt;
&lt;p&gt;Exceptional uses &lt;a href=&quot;http://aws.amazon.com/sqs/&quot;&gt;Amazon SQS&lt;/a&gt; as its back end queueing infrastructure. This means that when requests are received by the API interface, they are queued for processing at a later stage on a cluster of processing servers (The status of which you can see &lt;a href=&quot;http://status.getexceptional.com&quot;&gt;here&lt;/a&gt;). This allows the processing server cluster an amount of elasticity during burst periods.&lt;/p&gt;
                                   

&lt;h3&gt;Delayed Job&lt;/h3&gt;
&lt;p&gt;The speed at which the API interface could return to the api request was of crucial importance to our API. Since Amazon SQS is a third party service with a network hop, we used delayed_job to decouple the Exceptional API interface from the publishing to Amazon SQS. Each API request is persisted immediately, and then delayed job workers pick up the API requests and enqeue them onto Amazon SQS. This gives us the fastest possible API response time, and also another level of infrastructural flexibility.&lt;/p&gt;
                                                                  

&lt;h3&gt;New Relic&lt;/h3&gt;
&lt;p&gt;Monitoring the runtime performance of the API is key, and New Relic RPM is simply fantastic for that. On Heroku with the New Relic Add-on enabled, configuring new relicwas as simple as

&lt;pre&gt;&lt;code&gt;configure :production do
  require 'newrelic_rpm'
end
&lt;/pre&gt;&lt;/code&gt;
&lt;/p&gt;

&lt;h3&gt;Exceptional&lt;/h3&gt;
&lt;p&gt;Obviously Exceptional is absolutely essential for monitoring any errors that occur on our API service. The &lt;a href=&quot;http://docs.getexceptional.com/getting-started/sinatra/&quot;&gt;docs&lt;/a&gt;describe the few steps required to enable exceptional for your sinatra app&lt;/p&gt;

&lt;h3&gt;Heroku&lt;/h3&gt;
&lt;p&gt;Our API runs on, and the fantastic infrastructure provided by heroku.&lt;/p&gt;
                                                                                                                                                
&lt;h3&gt;Database&lt;/h3&gt;
&lt;p&gt;We use a MySQL cluster hosted on &lt;a href=&quot;http://aws.amazon.com/rds/&quot;&gt;Amazon RDS&lt;/a&gt; for all our databases.&lt;/p&gt;
                                       
&lt;p&gt;Scalability &amp; Performance&lt;/p&gt;
&lt;p&gt;The API is currently scaling to burst traffic of ~7k request per minute without any degradation in average response time (~30ms). We have further scaleability testing, and likely further scaleability improvements to do, but what we have will keep us through our next growth period.&lt;/p&gt; 

&lt;h3&gt;Futures&lt;/h3&gt;
&lt;p&gt;We have not implemented it in our API (yet!), but David Dollars &lt;a href=&quot;http://github.com/ddollar/heroku-autoscale&quot;&gt;Autoscale&lt;/a&gt; middleware looks very interesting!&lt;/p&gt;&lt;p&gt;Using &lt;a href=&quot;http://github.com/eventmachine/eventmachine&quot;&gt;eventmachine&lt;/a&gt; or &lt;a href=&quot;http://nodejs.org/&quot;&gt;node.js&lt;/a&gt; are likely other avenues if our API traffic continues to scale at the current rate.&lt;/p&gt;
&lt;/div&gt;</content>
  </entry>
  
  <entry>
    <title>Sinatra & Heroku & NewRelic</title>
    <link href="http://wal.github.com/2010/07/11/Sinatra-Heroku-NewRelic"/>
    <updated>2010-07-11T00:00:00-07:00</updated>
    <id>http://wal.github.com/2010/07/11/Sinatra-Heroku-NewRelic</id>
    <content type="html">&lt;p&gt;The docs for instrumenting your Sinatra app with New Relic on Heroku are either wrong or a bit sparse. Its actually very simple.&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;Add the newrelic_rpm gem to either your .gems or Gemfile&lt;/li&gt;
	&lt;li&gt;require the rpm library when in production
&lt;pre&gt;&lt;code&gt;configure :production do
	require 'newrelic_rpm'
end&lt;/pre&gt;&lt;/code&gt;                                          
	&lt;/li&gt;
	&lt;li&gt;add the heroku new_relic addon
&lt;pre&gt;&lt;code&gt;heroku addons:add newrelic:bronze&lt;/code&gt;&lt;/pre&gt;
	&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A full working example is &lt;a href=&quot;http://github.com/wal/sinatra_heroku_newrelic&quot;&gt;here!&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>RDS Database Stats</title>
    <link href="http://wal.github.com/2010/07/10/RDS-Stats-via-Cloudwatch"/>
    <updated>2010-07-10T00:00:00-07:00</updated>
    <id>http://wal.github.com/2010/07/10/RDS-Stats-via-Cloudwatch</id>
    <content type="html">&lt;p&gt;If you use Amazon RDS the following might be useful for pulling some simple Min, Max stats (FreeStorageSpace, CPU Utilisation and DB Connection Count) about your RDS instance&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone http://github.com/wal/RDS-DB-Stats.git
cd RDS-DB-Stats
ruby rds_db_stats.rb AWS_ACCESS_KEY AWS_SECRET_KEY RDS_ID TIME
&lt;/code&gt;&lt;/pre&gt;
                                                                    
&lt;pre&gt;&lt;code&gt;RDS_ID - your rds instance identifier&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;TIME - the number of minutes you want to calculate the stats for 
(i.e 60 = last hour)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Code is on &lt;a href=&quot;http://github.com/wal/RDS-DB-Stats&quot;&gt;Github&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Darragh and Myself and Scotland Ruby Conf 2010</title>
    <link href="http://wal.github.com/2010/07/01/Scotland-Ruby-Conf"/>
    <updated>2010-07-01T00:00:00-07:00</updated>
    <id>http://wal.github.com/2010/07/01/Scotland-Ruby-Conf</id>
    <content type="html">&lt;video controls='' poster='http://video2010.scottishrubyconference.com/images/video_still.png'&gt;
 &lt;source src='http://video.scottishrubyconference.com/Day_02LT_04-mp4_500mbs.mp4' type='video/mp4'&gt;  &lt;/source&gt;

 &lt;source src='http://video.scottishrubyconference.com/Day_02LT_04-mp4_500mbs.ogv' type='video/ogg'&gt;  &lt;/source&gt;
 &lt;object data='http://video.scottishrubyconference.com/Day_02LT_04-mp4_500mbs.mp4' type='video/quicktime'&gt;
   &lt;param name='src' value='http://video.scottishrubyconference.com/Day_02LT_04-mp4_500mbs.mp4' /&gt;
   &lt;param name='showlogo' value='false' /&gt;
   &lt;param name='autoplay' value='false' /&gt;
   &lt;img alt='__Title of video__' src='/images/video_still.png' title='No video playback capabilities, please download the video below' /&gt;
 &lt;/object&gt;
&lt;/video&gt;
</content>
  </entry>
  
</feed>
