<?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>Fubaredness Is Contagious &#187; ruby</title>
	<atom:link href="http://somic.org/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://somic.org</link>
	<description>Dmitriy Samovskiy's Blog</description>
	<lastBuildDate>Wed, 01 Sep 2010 07:55:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Capistrano Auth Trick</title>
		<link>http://somic.org/2009/10/07/capistrano-auth-trick/</link>
		<comments>http://somic.org/2009/10/07/capistrano-auth-trick/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 21:40:17 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[infrastructure development]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://somic.org/?p=857</guid>
		<description><![CDATA[This past summer, we needed to automate testing of several failure scenarios for VPN-Cubed. Having asked the LazyWeb about any frameworks that could help us and having gotten no response, our dev team had a short chat in the office. We decided that ultimately we were going to have to roll out our own system [...]]]></description>
			<content:encoded><![CDATA[<p>This past summer, we needed to automate testing of several failure scenarios for VPN-Cubed. Having <a href="http://twitter.com/somic/status/2804598299">asked</a> the LazyWeb about any frameworks that could help us and having gotten no response, our dev team had a short chat in the office. We decided that ultimately we were going to have to roll out our own system based on SSH. <a href="http://www.capify.org/">Capistrano</a> was the obvious choice, because it&#8217;s essentially a higher-level wrapper around Net::SSH module (if you prefer python, you may take a look at <a href="http://fabfile.org/">fabric</a> or <a href="http://www.lag.net/paramiko/">paramiko</a>).</p>
<p>One obstacle was that because we were emulating various failures, at times our local capistrano process, which was driving the tests, had to lose SSH connectivity to its target servers. We quickly discovered that this resulted in exception and cap process would die.</p>
<p>To work around this, I added yet another level on top of cap which uses GNU make (one of my all time <a href="http://twitter.com/somic/status/3543470903">favorites</a>). In a nutshell, user controls the testing process via make, and make starts cap. In this case, it&#8217;s ok for cap process to occasionally exit.</p>
<p>But then &#8211; and we are finally getting to the point of this post &#8211; another issue came up: I didn&#8217;t want to keep typing password into cap each time it was started by make. Here is how I ended up implementing it to avoid re-typing password.</p>
<p><code style="font-size:11px"><br />
# in Makefile<br />
USER_PASS := $(shell read -s -p "[make] user's password: " P; echo $$P )<br />
export USER_PASS</code><br />
<code style="font-size:11px"><br />
all: set_password<br />
# do something here</code><br />
<code style="font-size:11px"><br />
set_password:<br />
 &nbsp; &nbsp; @test "$(USER_PASS)"</code></p>
<p></code></p>
<p><code style="font-size:11px"><br />
# in Capfile<br />
set :password, lambda { ENV['USER_PASS'] ||<br />
CLI.password_prompt("[cap] #{user}'s password: ") }<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2009/10/07/capistrano-auth-trick/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Why I Sometimes Prefer Shell To Ruby or Python</title>
		<link>http://somic.org/2009/06/11/why-i-sometimes-prefer-shell-to-ruby-or-python/</link>
		<comments>http://somic.org/2009/06/11/why-i-sometimes-prefer-shell-to-ruby-or-python/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 16:38:02 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://somic.org/?p=620</guid>
		<description><![CDATA[Shell was among the first things I got familiar with when I was introduced to Linux. It&#8217;s not a typical programming language, primarily due to lack of easy-to-use high-level data structures such as hashes and arrays (anticipating your objection to this &#8211; note I said &#8220;easy-to-use&#8221;). This may explain why I often get funny looks [...]]]></description>
			<content:encoded><![CDATA[<p>Shell was among the first things I got familiar with when I was introduced to Linux. It&#8217;s not a typical programming language, primarily due to lack of easy-to-use high-level data structures such as hashes and arrays (anticipating your objection to this &#8211; note I said &#8220;easy-to-use&#8221;). This may explain why I often get funny looks from folks when I mention that I use shell quite a bit, often in quite non-trivial systems.</p>
<p>And here are my reasons.</p>
<p><strong>Memory Management</strong></p>
<p>Shell scripts are excellent in managing their memory and one has to try real hard to cause a shell script to leak memory. This makes shell a very convenient tool for long running processes, supervisors in multiple-workers models, daemons and so on. There is an easy explanation for this. In shell, there are only a handful of built-in primitives &#8211; everything else is an external command, which gets started and then finishes before giving control back to your script. If there is a memory leak in that command, it won&#8217;t damage your calling script and will usually be insignificant because it will return quickly.</p>
<p><strong>No Exceptions</strong></p>
<p>This is a double edged sword, and you need to be careful how you exploit this &#8220;weakness.&#8221; This feature allows me to write compact code which is easy to understand without enclosing every single command in &#8220;try&#8230; except&#8221;. For naysayers, I would like to point out that a strict mode exists, where every error is treated as fatal and causes the script to exit (<em>set -e</em>).</p>
<p>In general, not all unforeseen error conditions warrant a crash, like you get in Python or Ruby when an unhandled exception gets propagated all the way to the top. If a problem is transient, it may be better to ignore it temporarily.</p>
<p>To assure a Ruby or Python script doesn&#8217;t crash on some unforeseen transient problem, many people often end up enclosing their entire program in a wildcard try&#8230; except block to catch any exception &#8211; but to me this approach is dangerous, even though I sometimes end up using it myself.</p>
<p>If you are writing a daemon process to perform some action in a loop, shell is often by far the most stable alternative.</p>
<p><strong>When Not To Use Shell</strong></p>
<p>My personal rule of thumb is don&#8217;t use shell when you expect to need high-level data structures like hashes or arrays beyond what <em>for</em> loop can give you, or when you can see potential for code reuse following <a href="http://en.wikipedia.org/wiki/Object-oriented_programming">OOP</a> patterns like inheritance, or when your program needs to participate in some orchestration schemes that go beyond creating and removing files on the filesystem.</p>
<p><strong>Conclusion</strong></p>
<p>I wouldn&#8217;t overlook shell if I were you.</p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2009/06/11/why-i-sometimes-prefer-shell-to-ruby-or-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adjustable Per-URI Backend Capacity in Rabbitbal</title>
		<link>http://somic.org/2009/03/11/adjustable-per-uri-backend-capacity-in-rabbitbal/</link>
		<comments>http://somic.org/2009/03/11/adjustable-per-uri-backend-capacity-in-rabbitbal/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 17:45:04 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[rabbitbal]]></category>

		<guid isPermaLink="false">http://somic.org/?p=296</guid>
		<description><![CDATA[I recently pushed a Rabbitbal update to Github &#8211; http://github.com/somic/rabbitbal.
The biggest enhancement (IMHO) is ability to increase or decrease the number of backend consumers based on any HTTP request headers. In &#8220;table&#8221; routing mode (see rabbitbal.yml), you can now specify array of tests against which incoming request headers will be matched. This will cause your [...]]]></description>
			<content:encoded><![CDATA[<p>I recently pushed a Rabbitbal update to Github &#8211; <a href="http://github.com/somic/rabbitbal">http://github.com/somic/rabbitbal</a>.</p>
<p>The biggest enhancement (IMHO) is ability to increase or decrease the number of backend consumers based on any HTTP request headers. In &#8220;table&#8221; routing mode (see rabbitbal.yml), you can now specify array of tests against which incoming request headers will be matched. This will cause your request to be published with a matching key (note :key). Your backend consumers use the same YAML file and can bind to all or only some queues, thus giving you flexibility in adjusting the capacity. Old functionality is available by using &#8220;topic&#8221; routing mode.</p>
<p>Note that I still use topic-based exchange, because I wanted to support a use case where you want to aggregate all incoming requests into separate queues (routing key would be something like &#8220;request.#&#8221;) for bot detection, access log aggregation, etc. In other words, each request ultimately must end up in a single queue where it will be picked up by backend servers, while at the same time it can also be duplicated into other queues for other purposes.</p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2009/03/11/adjustable-per-uri-backend-capacity-in-rabbitbal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RabbitMQ and Rails</title>
		<link>http://somic.org/2009/01/29/rabbitmq-and-rails/</link>
		<comments>http://somic.org/2009/01/29/rabbitmq-and-rails/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 23:43:37 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://somic.org/?p=367</guid>
		<description><![CDATA[A quick note. This blog is getting a lot of google referrals for people looking for &#8220;rabbitmq rails&#8221;. I just wanted to say that I do not have good up-to-date material on the subject. Instead, check out this thread on ruby-amqp mailing list and consider tmm1-amqp gem for your project.
]]></description>
			<content:encoded><![CDATA[<p>A quick note. This blog is getting a lot of google referrals for people looking for &#8220;rabbitmq rails&#8221;. I just wanted to say that I do not have good up-to-date material on the subject. Instead, check out this <a href="http://groups.google.com/group/ruby-amqp/browse_thread/thread/3b39343aac6a7db5">thread</a> on ruby-amqp mailing list and consider <a href="http://github.com/tmm1/amqp">tmm1-amqp</a> gem for your project.</p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2009/01/29/rabbitmq-and-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing Rabbitbal</title>
		<link>http://somic.org/2008/12/18/introducing-rabbitbal/</link>
		<comments>http://somic.org/2008/12/18/introducing-rabbitbal/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 14:47:39 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[amqp]]></category>
		<category><![CDATA[reverse proxy]]></category>

		<guid isPermaLink="false">http://somic.org/?p=253</guid>
		<description><![CDATA[Inspired by Nanite, a very interesting project by Ezra Zygmuntowicz of EngineYard that uses RabbitMQ and eventmachine-based ruby amqp library by Aman Gupta, I sat down and wrote Rabbitbal, a reverse proxy for Rails (as well as other web frameworks, not necessarily limited to Ruby) on top of RabbitMQ. It&#8217;s now available on github at [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by <a href="http://github.com/ezmobius/nanite/tree/master">Nanite</a>, a very interesting project by <a href="http://brainspl.at/articles/2008/10/11/merbcamp-keynote-and-introducing-nanite">Ezra Zygmuntowicz</a> of EngineYard that uses <a href="http://www.rabbitmq.com">RabbitMQ</a> and eventmachine-based <a href="http://github.com/tmm1/amqp">ruby amqp library</a> by Aman Gupta, I sat down and wrote Rabbitbal, a reverse proxy for Rails (as well as other web frameworks, not necessarily limited to Ruby) on top of RabbitMQ. It&#8217;s now available on github at <a href="http://github.com/somic/rabbitbal">http://github.com/somic/rabbitbal</a>. Rabbitbal code is based on Nanite.</p>
<p>Here are benefits of AMQP-based approach over traditional HTTP-based reverse proxies taken from rabbitbal README file (in no particular order) as I see them.</p>
<ol>
<li>Model where workers fetch work as fast as they can (each going at its own pace) in theory should provide more efficient load balancing than a model where proxy assigns work based on certain criteria; methods based on round robin, arbitrary weights or least connections become simply unnecessary.</li>
<li>RabbitMQ broker implements intelligent failover out of the box &#8211; if a web server disconnects before ack&#8217;ing, the request will be automagically requeued for another server; all in all, RabbitMQ is way smarter than a bunch of low level TCP connections.</li>
<li>Enhanced security of actual web servers &#8211; servers behind Rabbitbal do not need inbound connectivity, they only need to be able to establish an outgoing connection to RabbitMQ broker(s).</li>
<li>Rabbitbal does not need to know IPs or have direct connectivity into its web servers (use case: Amazon EC2 without Elastic IPs)</li>
<li>Using Duplication pattern of RabbitMQ (see Resources below), you could be reading requests and responses off of the same broker in real time (access log aggregation, double-entry book keeping, logging, bot detection)</li>
<li>You could relatively easily have one request go to more than 1 web server</li>
<li>Add capacity as often and as much as you like &#8211; rabbitbal won&#8217;t even know</li>
<li>By slightly readjusting mapping between queues and URIs, you could add or remove capacity per URI if needed</li>
<li>TCP overhead savings compared with HTTP proxies (AMQP uses persistent TCP connections)</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2008/12/18/introducing-rabbitbal/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Forking Supervisor Daemon in Ruby</title>
		<link>http://somic.org/2008/12/03/forking-supervisor-daemon-in-ruby/</link>
		<comments>http://somic.org/2008/12/03/forking-supervisor-daemon-in-ruby/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 18:00:09 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://somic.org/?p=201</guid>
		<description><![CDATA[Here is my implementation of a forking supervisor daemon in ruby.

pre { font-size:10px; }


]]></description>
			<content:encoded><![CDATA[<p>Here is my implementation of a <a href="http://gist.github.com/31628">forking supervisor daemon in ruby</a>.</p>
<style>
pre { font-size:10px; }
</style>
<p><script src="http://gist.github.com/31628.js"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2008/12/03/forking-supervisor-daemon-in-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails update_attribute vs update_attributes</title>
		<link>http://somic.org/2008/09/22/rails-update_attribute-vs-update_attributes/</link>
		<comments>http://somic.org/2008/09/22/rails-update_attribute-vs-update_attributes/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 19:42:20 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://somic.org/?p=116</guid>
		<description><![CDATA[In Rails, update_attribute method bypasses model validations, while update_attributes and update_attributes! will fail (return false or raise an exception, respectively) if a record you are trying to save is not valid.
This means that if at certain point during the project you adjust validations such that some records that used to be valid are now invalid, [...]]]></description>
			<content:encoded><![CDATA[<p>In Rails, <em>update_attribute</em> method bypasses model validations, while<em> update_attributes</em> and <em>update_attributes!</em> will fail (return false or raise an exception, respectively) if a record you are trying to save is not valid.</p>
<p>This means that if at certain point during the project you adjust validations such that some records that used to be valid are now invalid, expect your code to stop working without any obvious reasons. This will happen because <em>update_attributes</em> will no longer update old records properly, but unless you check its return value, you&#8217;ll never know that it&#8217;s failing.</p>
<p>I stumbled upon this problem at least twice in the last month, and decided to write it up to finally remember to do it right next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2008/09/22/rails-update_attribute-vs-update_attributes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Selecting &#8220;FIELD AS NAME&#8221; in ActiveRecord Always Returns String</title>
		<link>http://somic.org/2008/07/17/selecting-field-as-name-in-activerecord-always-returns-string/</link>
		<comments>http://somic.org/2008/07/17/selecting-field-as-name-in-activerecord-always-returns-string/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 18:26:15 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://somic-org.homelinux.org/blog/2008/07/17/selecting-field-as-name-in-activerecord-always-returns-string/</guid>
		<description><![CDATA[If I select &#8220;field as alt_field_name&#8221;, the value will always come out as String, not what the field actually is.

&#160;
&#62;&#62; User.find&#40;:first, :select =&#62; :created_at&#41;.created_at
=&#62; Wed Jan 24 00:04:59 UTC 2007
&#62;&#62; User.find&#40;:first, :select =&#62; &#34;created_at&#34;&#41;.created_at
=&#62; Wed Jan 24 00:04:59 UTC 2007
&#62;&#62; User.find&#40;:first, :select =&#62; &#34;created_at as created__at&#34;&#41;.created__at
=&#62; &#34;2007-01-24 00:04:59&#34;

]]></description>
			<content:encoded><![CDATA[<p>If I select &#8220;field as alt_field_name&#8221;, the value will always come out as String, not what the field actually is.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby">&nbsp;
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:select</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:created_at</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">created_at</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> Wed Jan <span style="color:#006666;">24</span> <span style="color:#006666;">00</span>:<span style="color:#006666;">04</span>:<span style="color:#006666;">59</span> UTC <span style="color:#006666;">2007</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:select</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;created_at&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">created_at</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> Wed Jan <span style="color:#006666;">24</span> <span style="color:#006666;">00</span>:<span style="color:#006666;">04</span>:<span style="color:#006666;">59</span> UTC <span style="color:#006666;">2007</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> User.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first</span>, <span style="color:#ff3333; font-weight:bold;">:select</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;created_at as created__at&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">created__at</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;2007-01-24 00:04:59&quot;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://somic.org/2008/07/17/selecting-field-as-name-in-activerecord-always-returns-string/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby + AMQP + RabbitMQ Example</title>
		<link>http://somic.org/2008/06/24/ruby-amqp-rabbitmq-example/</link>
		<comments>http://somic.org/2008/06/24/ruby-amqp-rabbitmq-example/#comments</comments>
		<pubDate>Tue, 24 Jun 2008 23:17:30 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[rabbitmq]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://somic-org.homelinux.org/blog/2008/06/24/ruby-amqp-rabbitmq-example/</guid>
		<description><![CDATA[In this post I would like to show how one can exchange messages using AMQP protocol from Ruby, using RabbitMQ as a broker. I posted the original version of this script to rabbitmq-discuss mailing list back in September 2007.
Prerequesites:

RabbitMQ broker configured, up and running on 127.0.0.1 (localhost) on port 5672 (standard AMQP port).
Apache QPid Ruby [...]]]></description>
			<content:encoded><![CDATA[<p>In this post I would like to show how one can exchange messages using AMQP protocol from Ruby, using RabbitMQ as a broker. I posted the original version of this script to <a href="http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss">rabbitmq-discuss</a> mailing list back in September 2007.</p>
<p>Prerequesites:</p>
<ul>
<li><a href="http://www.rabbitmq.com">RabbitMQ</a> broker configured, up and running on 127.0.0.1 (localhost) on port 5672 (standard AMQP port).</li>
<li><a href="http://cwiki.apache.org/qpid/">Apache QPid</a> Ruby library installed within RUBYPATH (svn co http://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/ruby)</li>
<li>AMQP specification <a href="http://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.xml">XML</a> form <a href="http://amqp.org">AMQP official site</a> saved as /etc/amqp0-8.xml</li>
</ul>
<p>You can also download this script from <a href="/d/disttailf.rb">here</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby"><span style="color:#008000; font-style:italic;">#!/usr/bin/ruby -I/usr/local/qpid-svn/qpid/ruby</span>
<span style="color:#008000; font-style:italic;">#</span>
<span style="color:#008000; font-style:italic;">#</span>
__doc__ = <span style="color:#006600; font-weight:bold;">%</span>q<span style="color:#006600; font-weight:bold;">&#40;</span>
&nbsp;
disttailf.<span style="color:#9900CC;">rb</span> <span style="color:#006600; font-weight:bold;">-</span> distributed <span style="color:#996600;">&quot;tail -f&quot;</span>
&nbsp;
Aggregates <span style="color:#996600;">&quot;tail -f&quot;</span> output from multiple machines <span style="color:#9966CC; font-weight:bold;">and</span> multiple files
into a single RabbitMQ pubsub queue <span style="color:#006600; font-weight:bold;">&#40;</span>kind of splunk<span style="color:#996600;">'s log consolidation
function)
&nbsp;
Usage:
Producer: disttailf.rb [-s broker_host] [-p broker_port] [-x spec_xml] file ...
Consumer: disttailf.rb [-s broker_host] [-p broker_port] [-x spec_xml] -c
&nbsp;
)
&nbsp;
require '</span>qpid<span style="color:#996600;">'
require '</span>socket<span style="color:#996600;">'
&nbsp;
def consumer(client, ch)
    myqueue = ch.queue_declare()
    ch.queue_bind(:queue=&gt;myqueue.queue, :exchange=&gt;'</span>amq.<span style="color:#9900CC;">topic</span><span style="color:#996600;">',
                    :routing_key=&gt;'</span>disttailf.<span style="color:#008000; font-style:italic;">#')</span>
    cons = ch.<span style="color:#9900CC;">basic_consume</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:queue</span><span style="color:#006600; font-weight:bold;">=&gt;</span>myqueue.<span style="color:#9900CC;">queue</span>, <span style="color:#ff3333; font-weight:bold;">:no_ack</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    ruby_queue = client.<span style="color:#9900CC;">queue</span><span style="color:#006600; font-weight:bold;">&#40;</span>cons.<span style="color:#9900CC;">consumer_tag</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0000FF; font-weight:bold;">true</span>
        <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;Rabbitmq broker disconnected&quot;</span> <span style="color:#9966CC; font-weight:bold;">if</span> client.<span style="color:#9900CC;">closed</span>?
        <span style="color:#9966CC; font-weight:bold;">begin</span>
          msg = ruby_queue.<span style="color:#9900CC;">pop</span><span style="color:#006600; font-weight:bold;">&#40;</span>non_block=<span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
          <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;== #{msg.content.headers[:headers]} &quot;</span> \
                <span style="color:#996600;">&quot;#{msg.routing_key.split('.')[-1]}&quot;</span>
          <span style="color:#CC0066; font-weight:bold;">puts</span> msg.<span style="color:#9900CC;">content</span>.<span style="color:#9900CC;">body</span>
        <span style="color:#9966CC; font-weight:bold;">rescue</span>
          <span style="color:#CC0066; font-weight:bold;">sleep</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0.5</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> producer<span style="color:#006600; font-weight:bold;">&#40;</span>client, ch, filenames<span style="color:#006600; font-weight:bold;">&#41;</span>
    rkey = <span style="color:#996600;">&quot;disttailf.&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> Socket.<span style="color:#9900CC;">gethostname</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'.'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">-1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    tail_f<span style="color:#006600; font-weight:bold;">&#40;</span>filenames<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>filename, line<span style="color:#006600; font-weight:bold;">|</span>
        h = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">'sent'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>.<span style="color:#9900CC;">to_i</span>, <span style="color:#996600;">'filename'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> filename <span style="color:#006600; font-weight:bold;">&#125;</span>
        c = <span style="color:#6666ff; font-weight:bold;">Qpid::Content</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span>:headers<span style="color:#006600; font-weight:bold;">=&gt;</span>h<span style="color:#006600; font-weight:bold;">&#125;</span>, line<span style="color:#006600; font-weight:bold;">&#41;</span>
        ch.<span style="color:#9900CC;">basic_publish</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:routing_key</span><span style="color:#006600; font-weight:bold;">=&gt;</span>rkey, <span style="color:#ff3333; font-weight:bold;">:content</span><span style="color:#006600; font-weight:bold;">=&gt;</span>c,
                            <span style="color:#ff3333; font-weight:bold;">:exchange</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#996600;">'amq.topic'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{filename}: #{line}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> tail_f<span style="color:#006600; font-weight:bold;">&#40;</span>filenames, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    filedict = <span style="color:#CC00FF; font-weight:bold;">Hash</span>.<span style="color:#9900CC;">new</span>
    filenames.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> filedict<span style="color:#006600; font-weight:bold;">&#91;</span>f<span style="color:#006600; font-weight:bold;">&#93;</span> = open_or_nil<span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    reopen_counter = <span style="color:#006666;">0</span>
    <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0000FF; font-weight:bold;">true</span>:
        <span style="color:#9966CC; font-weight:bold;">if</span> reopen_counter <span style="color:#006600; font-weight:bold;">&gt;</span> <span style="color:#006666;">120</span>
            reopen_counter = <span style="color:#006666;">0</span>
            filenames.<span style="color:#9900CC;">reject</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> filedict<span style="color:#006600; font-weight:bold;">&#91;</span>f<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span>
                <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> filedict<span style="color:#006600; font-weight:bold;">&#91;</span>f<span style="color:#006600; font-weight:bold;">&#93;</span> = open_or_nil<span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        filedict.<span style="color:#9900CC;">values</span>.<span style="color:#9900CC;">reject</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#9966CC; font-weight:bold;">not</span> f <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span>
            <span style="color:#9966CC; font-weight:bold;">begin</span>
                <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;trunc&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">stat</span><span style="color:#006600; font-weight:bold;">&#40;</span>f.<span style="color:#9900CC;">path</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">size</span> <span style="color:#006600; font-weight:bold;">&gt;</span>= f.<span style="color:#9900CC;">tell</span>
            <span style="color:#9966CC; font-weight:bold;">rescue</span>
                <span style="color:#ff6633; font-weight:bold;">$stderr</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#996600;">&quot;#{f.path}: removed or truncated<span style="color:#000099;">\n</span>&quot;</span>
                f.<span style="color:#9900CC;">close</span>
                filedict<span style="color:#006600; font-weight:bold;">&#91;</span>f.<span style="color:#9900CC;">path</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#0000FF; font-weight:bold;">nil</span>
                <span style="color:#9966CC; font-weight:bold;">next</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
            <span style="color:#9966CC; font-weight:bold;">begin</span>
              block.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>f.<span style="color:#9900CC;">path</span>,f.<span style="color:#CC0066; font-weight:bold;">readline</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#0000FF; font-weight:bold;">true</span>
            <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">EOFError</span>
              <span style="color:#0000FF; font-weight:bold;">true</span>
            <span style="color:#9966CC; font-weight:bold;">end</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
        reopen_counter <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span>
        <span style="color:#CC0066; font-weight:bold;">sleep</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0.5</span><span style="color:#006600; font-weight:bold;">&#41;</span>
   <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#008000; font-style:italic;"># while true</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> open_or_nil<span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
        <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">rescue</span>
        <span style="color:#0000FF; font-weight:bold;">nil</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0000FF; font-weight:bold;">__FILE__</span> == $<span style="color:#006666;">0</span>
    <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'getoptlong'</span>
&nbsp;
    server = <span style="color:#996600;">'127.0.0.1'</span>
    port = <span style="color:#006666;">5672</span>
    specxml = <span style="color:#996600;">'/etc/amqp0-8.xml'</span>
    acts_as_consumer = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
    opts = GetoptLong.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>
        <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'--server'</span>, <span style="color:#996600;">'-s'</span>, <span style="color:#6666ff; font-weight:bold;">GetoptLong::REQUIRED_ARGUMENT</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
        <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'--port'</span>, <span style="color:#996600;">'-p'</span>, <span style="color:#6666ff; font-weight:bold;">GetoptLong::REQUIRED_ARGUMENT</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
        <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'--specxml'</span>, <span style="color:#996600;">'-x'</span>, <span style="color:#6666ff; font-weight:bold;">GetoptLong::REQUIRED_ARGUMENT</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
        <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'--consume'</span>, <span style="color:#996600;">'-c'</span>, <span style="color:#6666ff; font-weight:bold;">GetoptLong::NO_ARGUMENT</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    opts.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>opt,arg<span style="color:#006600; font-weight:bold;">|</span>
      <span style="color:#9966CC; font-weight:bold;">case</span> opt
        <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#996600;">'--server'</span>
            server = arg
        <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#996600;">'--port'</span>
            port = arg.<span style="color:#9900CC;">to_i</span>
        <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#996600;">'--specxml'</span>
            specxml = arg
        <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#996600;">'--consume'</span>
            acts_as_consumer = <span style="color:#0000FF; font-weight:bold;">true</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#008000; font-style:italic;"># set up connection to rabbitmq broker</span>
    client = <span style="color:#6666ff; font-weight:bold;">Qpid::Client</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>server, port, spec=Spec.<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span>specxml<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    client.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">&quot;LOGIN&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;guest&quot;</span>, <span style="color:#996600;">&quot;PASSWORD&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;guest&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    ch = client.<span style="color:#9900CC;">channel</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    ch.<span style="color:#9900CC;">channel_open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> acts_as_consumer
        consumer<span style="color:#006600; font-weight:bold;">&#40;</span>client, ch<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
        <span style="color:#9966CC; font-weight:bold;">if</span> ARGV.<span style="color:#9900CC;">length</span> == <span style="color:#006666;">0</span>
            <span style="color:#CC0066; font-weight:bold;">puts</span> __doc__
            <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#996600;">&quot;List of file names is empty - nothing to do&quot;</span>
        <span style="color:#9966CC; font-weight:bold;">end</span>
        producer<span style="color:#006600; font-weight:bold;">&#40;</span>client, ch, ARGV<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://somic.org/2008/06/24/ruby-amqp-rabbitmq-example/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Now Boarding: Elastic Passengers</title>
		<link>http://somic.org/2008/04/23/now-boarding-elastic-passengers/</link>
		<comments>http://somic.org/2008/04/23/now-boarding-elastic-passengers/#comments</comments>
		<pubDate>Thu, 24 Apr 2008 02:14:41 +0000</pubDate>
		<dc:creator>Dmitriy</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[work]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://somic-org.homelinux.org/blog/2008/04/23/now-boarding-elastic-passengers/</guid>
		<description><![CDATA[Starting today, Elastic Server On Demand allows you to select Phusion Passenger (mod_rails for Apache) as a web container for your Rails 2 application. This  allows you to deploy a Rails app on Apache, the world&#8217;s most popular web server. Check it out at http://es.cohesiveft.com/site/rails2.
]]></description>
			<content:encoded><![CDATA[<p>Starting today, <a href="http://es.cohesiveft.com">Elastic Server On Demand</a> allows you to select <a href="http://phusion.nl">Phusion</a> <a href="http://www.modrails.com">Passenger (mod_rails for Apache)</a> as a web container for your Rails 2 application. This  allows you to deploy a Rails app on <a href="http://httpd.apache.org">Apache</a>, the world&#8217;s most popular web server. Check it out at <a href="http://es.cohesiveft.com/site/rails2">http://es.cohesiveft.com/site/rails2</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://somic.org/2008/04/23/now-boarding-elastic-passengers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
