<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Tomas Varaneckas</title>
    <description>Deliver or die.</description>
    <link>http://varaneckas.com/blog/</link>
    <item>
      <title>Always check your new server IP addresses</title>
      <description type="html">&lt;p&gt;Me and my friend have joined forces to create a side project - &lt;a href="https://www.fitnessblip.com"&gt;fitnessblip.com&lt;/a&gt;. The biggest mistake was to get a $5 DigitalOcean droplet and use it for our production without checking the IP address first.&lt;/p&gt;

&lt;h2&gt;Blocked by Google SMTP&lt;/h2&gt;

&lt;p&gt;After setting up the website and running it in production for a while, I thought, hey, this $5 droplet is using barely no resources, why can’t I slap Postfix on it and make it send emails? And so I did, just to notice that test emails to my Google inbox have bounced with following error:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Action: failed
Status: 5.7.1
Remote-MTA: dns; gmail-smtp-in.l.google.com
Diagnostic-Code: smtp; 550-5.7.1 [&amp;lt;OUR IP ADDRESS HERE&amp;gt; 1] Our system has
detected an unusual rate of 550-5.7.1 unsolicited mail originating from
your IP address. To protect our 550-5.7.1 users from spam, mail sent from
your IP address has been blocked. 550-5.7.1 Please visit 550-5.7.1
https://support.google.com/mail/?p=UnsolicitedIPError to review our 550
5.7.1 Bulk Email Senders Guidelines. n84si23842177qkn.163 - gsmtp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Okay. That explains a lot (I was scratching my head why Pinterest keeps blocking us at that point). I wrote both Google and DigitalOcean about this. DigitalOcean support was amazing and fast, they offered to recreate the droplet on new IP, and so I did. It helped, Google was no longer blocking the emails from new IP. &lt;/p&gt;

&lt;p&gt;However, Pinterest was still blocking us, since they apparently blacklisted the domain name because it was once hosted on spammer IP.&lt;/p&gt;

&lt;h2&gt;Blocked by Pinterest&lt;/h2&gt;

&lt;p&gt;I was testing Pinterest integration and noticed that after few days of pinning our website got blocked completely. When trying to pin, it said “Sorry, we blocked this link because it may lead to inappropriate content”. What inappropriate content? I opened a ticket at &lt;a href="https://help.pinterest.com" rel="nofollow"&gt;help.pinterest.com&lt;/a&gt;, explaining that I did nothing wrong, and asking why our perfectly legit website could be blocked as “inappropriate content”. &lt;/p&gt;

&lt;p&gt;Then the fun started. My first ticket got closed without response. Just closed a couple of days after it was opened. I then received the standard Zendesk follow up email asking “How would you rate our customer support?”. I rated it bad, obviously, and opened another ticket.&lt;/p&gt;

&lt;p&gt;Two days later, my second ticket was closed, also with no response, with another “How do you rate our customer support?” email. At that point I already knew that we have hosted our website on IP address that previously belonged to spammers. Since then we have changed the IP and enabled CloudFlare, but Pinterest kept blocking the site. &lt;/p&gt;

&lt;p&gt;I gave it a week and tried contacting their support again. Again, got no response, again asking to rate the support. At that point I got so pissed that I registered &lt;code&gt;pinterestcustomersupport.com&lt;/code&gt; domain with hopes to put something funny in there, which I still did not do. I am willing to give the ownership of this domain to Pinterest for free, if they help me solve my ticket, how about that?&lt;/p&gt;

&lt;p&gt;I also started reaching out to Pinterest through social networks, since there seemed to be no way to contact them though help.pinterest.com. And that was my final mistake.&lt;/p&gt;

&lt;blockquote class="twitter-tweet" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;Dear &lt;a href="https://twitter.com/Pinterest"&gt;@pinterest&lt;/a&gt;, you need to fix your broken &lt;a href="https://twitter.com/hashtag/customersupport?src=hash"&gt;#customersupport&lt;/a&gt;. It&amp;#39;s impossible to get an answer, tickets get closed without reply.&lt;/p&gt;&amp;mdash; Fitness Blip (@FitnessBlip) &lt;a href="https://twitter.com/FitnessBlip/status/802021311405027328"&gt;November 25, 2016&lt;/a&gt;&lt;/blockquote&gt;

&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;

&lt;p&gt;Also, while researching ways to reach Pinterest, I found that their customer support is really, and I mean &lt;em&gt;really&lt;/em&gt; &lt;a href="http://www.customerservicescoreboard.com/Pinterest"&gt;horrible&lt;/a&gt;. How can such a successful company neglect customer support so much and get away with it? Who knows.&lt;/p&gt;

&lt;h2&gt;Banned by Facebook&lt;/h2&gt;

&lt;p&gt;I never used Facebook much aside from integration development tasks at work, and managing business websites of my side projects. Therefore I only had a dummy development account, which unfortunately didn’t have my real name on it, even though I used it for years. And I was naive enough to use that account to post comments under Pinterest’s Facebook posts asking for help and complaining about their broken customer support. &lt;/p&gt;

&lt;p&gt;Of course, people at Pinterest flagged my comments, and since I didn’t have much activity on my development Facebook account, Facebook has banned me on premise that my account was created for harassment. If I wanted to unblock my account, Facebook had an appeal process, which consists of giving them a copy of your documents that prove that blocked account is yours. Here I had a major problem. My account was named “Tom Warr”, which is just a shortened variant of my full name. The test account was also registered using an email address that no longer works, and it was not my main email address.&lt;/p&gt;

&lt;p&gt;I said myself, oh well, there is tough chance I’ll get my account back, so I’ll just register a new, real account under my main email address, which is my full name at gmail.com. So I did that, created an account, entered my full name, real birthday, and then they suggested me a bunch of friends that they somehow know I’m familiar with, all that.&lt;/p&gt;

&lt;p&gt;But then my newly created account got merged with my developer account and got blocked again. When I tried to log in with my main email address, it displays that I&amp;#39;m “Tom Warr” - the name from my blocked development account. &lt;/p&gt;

&lt;p&gt;So far I had a 12 emails long conversation with Facebook customer support (which is way better than Pinterest one, because they at least do respond, and do it reasonably fast), though things are going nowhere.&lt;/p&gt;

&lt;p&gt;It seems like I’m not welcome to use Facebook anymore, because even though I gave a copy of my passport, drivers license and personal identification card, my appeals to get the account back were refused, because “the data on identity documents do not match the name and birthday on blocked account”.&lt;/p&gt;

&lt;p&gt;This sad story ends here. An unfortunate event of starting a project on IP address which belonged to a spammer put both the project and myself in jeopardy. Trying to prove something to customer support of huge corporations is not a battle a nobody like myself can win. And I cannot register a Facebook account and use their developer tools either. I also lost access to all my Facebook Pages and Apps.&lt;/p&gt;

&lt;p&gt;I hope others can learn from my mistakes. Check every IP address before putting your project on it in production. Oh, and also, don&amp;#39;t keep your apps and business pages on Facebook account that has a different full name and birthday than your passport does.&lt;/p&gt;
</description>
      <pubDate>Tue, 29 Nov 2016 16:35:18 +0000</pubDate>
      <link>http://varaneckas.com/blog/check-your-ip/</link>
      <guid>http://varaneckas.com/blog/check-your-ip/</guid>
    </item>
    <item>
      <title>Overriding Unicorn worker process names</title>
      <description type="html">&lt;p&gt;In my previous post I covered &lt;a href="/blog/ruby-tracing-threads-unicorn/"&gt;troubleshooting unicorn processes&lt;/a&gt;. This time I&amp;#39;ll share one more technique that can make your devops life easier. &lt;/p&gt;

&lt;h3&gt;Default unicorn worker process names suck&lt;/h3&gt;

&lt;p&gt;When you look at server process list using &lt;code&gt;ps auxf&lt;/code&gt; or something similar, unicorn looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;... unicorn master -c /etc/app/config.rb -E production -D
...  \_ unicorn worker[0] -c /etc/app/config.rb -E production -D
...  \_ unicorn worker[1] -c /etc/app/config.rb -E production -D
...  \_ unicorn worker[2] -c /etc/app/config.rb -E production -D
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not very useful, and quite redundant - your workers inherit the argument line from &lt;code&gt;master&lt;/code&gt; process. There&amp;#39;s no way to tell what they&amp;#39;re doing at given moment.&lt;/p&gt;

&lt;h3&gt;Overriding unicorn worker process names in Ruby on Rails app&lt;/h3&gt;

&lt;p&gt;How about something like this?&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;... unicorn master -c /etc/app/config.rb -E production -D
...  \_ unicorn worker[0] 66.249.78.123: last status: 200. Waiting for req.
...  \_ unicorn worker[1] 91.9.93.234: GET /items/3134
...  \_ unicorn worker[2] 62.227.53.32: POST /auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It shows the IP of your user along with current request method and path. And in case worker is slacking, last user IP and response status. Now, let&amp;#39;s make ourselves a piece of &lt;a href="http://railscasts.com/episodes/151-rack-middleware"&gt;Rack Middleware&lt;/a&gt; that will do the above.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;/app/middlewares/set_unicorn_procline.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;class SetUnicornProcline
  def initialize(app)
    @app = app
  end

  def call(env)
    user_ip = env[&amp;#39;HTTP_X_FORWARDED_FOR&amp;#39;] || env[&amp;#39;REMOTE_ADDR&amp;#39;]
    request_info = &amp;quot;#{env[&amp;#39;REQUEST_METHOD&amp;#39;]} #{env[&amp;#39;REQUEST_PATH&amp;#39;]}&amp;quot;
    worker_line = $0.split(&amp;#39;]&amp;#39;)[0] + &amp;quot;] #{user_ip}&amp;quot;
    set_procline &amp;quot;#{worker_line}: #{request_info}&amp;quot;[0..200]
    status, headers, body = @app.call(env)
    set_procline &amp;quot;#{worker_line}: last status: #{status}. Waiting for req.&amp;quot;
    [status, headers, body]
  end

  def set_procline(value)
    $0 = sanitize_utf8(value)
  end

  def sanitize_utf8(string)
    return string.force_encoding(&amp;#39;utf-8&amp;#39;) if string.valid_encoding?
    string.chars.select(&amp;amp;:valid_encoding?).join.force_encoding(&amp;#39;utf-8&amp;#39;)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then enabled it in &lt;code&gt;config/application.rb&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;...
module &amp;lt;YourApp&amp;gt;
  class Application &amp;lt; Rails::Application
    ...
    require File.join(&amp;quot;#{Rails.root}/app/middlewares/set_unicorn_procline.rb&amp;quot;)
    config.middleware.use SetUnicornProcline
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It should work with Ruby &amp;gt;= 1.9.3 and Rails &amp;gt;= 3.2.x. The middleware also takes care of broken encoding that would otherwise cause &lt;code&gt;$0.split&lt;/code&gt; to crash on next request after malicious &lt;code&gt;REQUEST_PATH&lt;/code&gt; was provided.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;watch &amp;#39;ps auxf | grep unicorn&amp;#39;&lt;/code&gt; and enjoy the show.&lt;/p&gt;
</description>
      <pubDate>Sat, 08 Feb 2014 07:17:07 +0000</pubDate>
      <link>http://varaneckas.com/blog/unicorn-procline/</link>
      <guid>http://varaneckas.com/blog/unicorn-procline/</guid>
    </item>
    <item>
      <title>Ruby Threads, Unicorn, and You</title>
      <description type="html">&lt;p&gt;If you are working with highly intensive Unicorn deployments, you will be familiar with following problems.&lt;/p&gt;

&lt;h3&gt;How to find out what Ruby processes are doing?&lt;/h3&gt;

&lt;p&gt;Occasionally some Ruby processes are running pedal to the metal, possibly burning CPU like crazy, you know they shouldn&amp;#39;t be, and you just can&amp;#39;t tell what&amp;#39;s happening. They are getting stuck, but can&amp;#39;t tell where or why - it&amp;#39;s frustrating.&lt;/p&gt;

&lt;p&gt;Tracing sometimes works. Run &lt;code&gt;strace -s 999 -fp &amp;lt;pid&amp;gt;&lt;/code&gt; on a suspicious process, and you may see some useful output. It may end with something like this, without any movement: &lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;[pid  7990] select(18, [16 17], NULL, [7 8], {133, 947558} &amp;lt;unfinished ...&amp;gt;
[pid 17728] select(19, [14 18], NULL, [7 8], {22, 500000} &amp;lt;unfinished ...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#39;s &lt;a href="http://man7.org/linux/man-pages/man2/select.2.html"&gt;selecting&lt;/a&gt; something from file descriptor 19, and you can try to find out what it is:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;$ lsof -p 17728
COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF      NODE NAME
...
ruby    17728    ruby   19u  IPv4          808319634      0t0       TCP web1.infra.net:35682-&amp;gt;db3.infra.net:mysql (ESTABLISHED)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case it&amp;#39;s waiting for MySQL, so you can look at what&amp;#39;s happening over there. But sometimes you see that worker is hanging on select from a pipe or socket:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;$ lsof -p 17728
COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF      NODE NAME
...
ruby    58610    ruby   12r  FIFO        0,8        0t0 3435272094 pipe
ruby    58610    ruby   13u  sock        0,6        0t0 3435234779 can&amp;#39;t identify protocol
ruby    58610    ruby   14w  FIFO        0,8        0t0 3435270598 pipe
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If your FD shows a pipe or socket, it&amp;#39;s difficult to dig further. &lt;/p&gt;

&lt;p&gt;Another case is when Ruby process is endlessly spilling it&amp;#39;s guts into trace output, and you can see a pattern repeating, meaning that there is some sort of infinite loop going on, but it&amp;#39;s hard to tell where.&lt;/p&gt;

&lt;p&gt;There are more &lt;a href="http://blog.newrelic.com/2013/04/29/debugging-stuck-ruby-processes-what-to-do-before-you-kill-9/"&gt;advanced techniques&lt;/a&gt;, but they are pretty cumbersome, and you may get your process killed before you manage to find out anything useful.&lt;/p&gt;

&lt;h3&gt;What Ruby is doing at any given moment?&lt;/h3&gt;

&lt;p&gt;Wouldn&amp;#39;t it be nice if you could be able to find out what line of code your Ruby process is executing at any given moment? Good news is that you can. Combine &lt;a href="http://www.ruby-doc.org/core-2.0.0/Signal.html#method-c-trap"&gt;&lt;code&gt;Signal.trap&lt;/code&gt;&lt;/a&gt; with &lt;a href="http://www.ruby-doc.org/core-2.0.0/Thread.html#method-c-list"&gt;&lt;code&gt;Thread.list&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://www.ruby-doc.org/core-2.0.0/Thread.html#method-i-backtrace"&gt;&lt;code&gt;Thread#backtrace&lt;/code&gt;&lt;/a&gt;, and you&amp;#39;re set.&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;Signal.trap(&amp;#39;USR2&amp;#39;) do
  pid = Process.pid 
  puts &amp;quot;[#{pid}] Received USR2 at #{Time.now}. Dumping threads:&amp;quot;
  Thread.list.each do |t|
    trace = t.backtrace.join(&amp;quot;\n[#{pid}] &amp;quot;)
    puts &amp;quot;[#{pid}] #{trace}&amp;quot;
    puts &amp;quot;[#{pid}] ---&amp;quot;
  end
  puts &amp;quot;[#{pid}] -------------------&amp;quot;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Place this code in Unicorn&amp;#39;s &lt;a href="http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-after_fork"&gt;&lt;code&gt;after_fork&lt;/code&gt;&lt;/a&gt;, Resque &lt;a href="https://github.com/resque/resque/blob/master/docs/HOOKS.md#worker-hooks"&gt;&lt;code&gt;after_fork&lt;/code&gt;&lt;/a&gt;, beginning of Rake tasks, or wherever it fits. When something is stuck or otherwise suspicious, find the pid, and then do:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;$ kill -USR2 26749
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Take a look at unicorn log. It should show something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;[26749] Received USR2 at 2014-01-19 04:28:35 +0000. Dumping threads:
[26749] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:291:in `backtrace&amp;#39;
[26749] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:291:in `block (3 levels) in reload&amp;#39;
[26749] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:290:in `each&amp;#39;
[26749] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:290:in `block (2 levels) in reload&amp;#39;
[26749] /srv/app.intra.net/releases/20140118185816/app/controllers/welcome_controller.rb:8:in `call&amp;#39;
[26749] /srv/app.intra.net/releases/20140118185816/app/controllers/welcome_controller.rb:8:in `sleep&amp;#39;
[26749] /srv/app.intra.net/releases/20140118185816/app/controllers/welcome_controller.rb:8:in `index&amp;#39;
[26749] /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-3.2.16/lib/action_controller/metal/implicit_render.rb:4:in `send_action&amp;#39;
[26749] /usr/local/lib/ruby/gems/2.0.0/gems/actionpack-3.2.16/lib/abstract_controller/base.rb:167:in `process_action&amp;#39;
[26749] 
...
[26749] ---
[26749] -------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see that it&amp;#39;s hanging on &lt;code&gt;sleep&lt;/code&gt; in &lt;code&gt;welcome_controller.rb&lt;/code&gt;, line &lt;code&gt;8&lt;/code&gt;. Bullseye.&lt;/p&gt;

&lt;h3&gt;Dumping Ruby threads when killing lazy Unicorn workers&lt;/h3&gt;

&lt;p&gt;You can&amp;#39;t sit all day and watch those processes manually. Unicorn has a &lt;a href="http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-timeout"&gt;timeout configuration option&lt;/a&gt;, where it kills workers that run longer than given amount of seconds.&lt;/p&gt;

&lt;p&gt;Trouble is that Unicorn sends &lt;code&gt;SIGKILL&lt;/code&gt; when terminating stuck workers, and &lt;code&gt;SIGKILL&lt;/code&gt; cannot be trapped. Workers get killed, and all you get are these lousy messages:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;E, [2013-11-19T12:30:08.905908 #61893] ERROR -- : worker=75 PID:62991 timeout (46s &amp;gt; 45s), killing
E, [2013-11-19T12:30:08.939120 #61893] ERROR -- : reaped #&amp;lt;Process::Status: pid 62991 SIGKILL (signal 9)&amp;gt; worker=75
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#39;s not very helpful. It just tells us that something went wrong, and that the perpetrator got a bullet in the head.&lt;/p&gt;

&lt;p&gt;But we can patch things up by overriding &lt;a href="https://github.com/defunkt/unicorn/blob/6f6e4115b4bb03e5e7c55def91527799190566f2/lib/unicorn/http_server.rb#L476"&gt;&lt;code&gt;Unicorn::HttpServer#murder_lazy_workers&lt;/code&gt;&lt;/a&gt;. Here&amp;#39;s a monkey patch that will send &lt;code&gt;SIGTERM&lt;/code&gt; 2 seconds before sending &lt;code&gt;SIGKILL&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;class Unicorn::HttpServer
  # forcibly terminate all workers that haven&amp;#39;t checked in in timeout seconds.
  # The timeout is implemented using an unlinked File
  def murder_lazy_workers
    next_sleep = @timeout - 1
    now = Time.now.to_i
    WORKERS.dup.each_pair do |wpid, worker|
      tick = worker.tick
      0 == tick and next # skip workers that haven&amp;#39;t processed any clients
      diff = now - tick
      tmp = @timeout - diff

      # monkey patch begins here
      if tmp &amp;lt; 2
        logger.error &amp;quot;worker=#{worker.nr} PID:#{wpid} running too long &amp;quot; \
                     &amp;quot;(#{diff}s), sending TERM&amp;quot;
        kill_worker(:TERM, wpid)
      end
      # end of monkey patch

      if tmp &amp;gt;= 0
        next_sleep &amp;gt; tmp and next_sleep = tmp
        next
      end
      next_sleep = 0
      logger.error &amp;quot;worker=#{worker.nr} PID:#{wpid} timeout &amp;quot; \
                   &amp;quot;(#{diff}s &amp;gt; #{@timeout}s), killing&amp;quot;
      kill_worker(:KILL, wpid) # take no prisoners for timeout violations
    end
    next_sleep &amp;lt;= 0 ? 1 : next_sleep
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Place this code somewhere where it gets loaded on unicorn startup. It can be next to Unicorn&amp;#39;s &lt;code&gt;before_fork&lt;/code&gt;. You may want to adjust your &lt;code&gt;Signal.trap&lt;/code&gt; to be a little more universal:&lt;/p&gt;

&lt;pre&gt;&lt;code class="ruby"&gt;[&amp;#39;TERM&amp;#39;, &amp;#39;USR2&amp;#39;].each do |sig|
  Signal.trap(sig) do
    pid = Process.pid 
    puts &amp;quot;[#{pid}] Received #{sig} at #{Time.now}. Dumping threads:&amp;quot;
    Thread.list.each do |t|
      trace = t.backtrace.join(&amp;quot;\n[#{pid}] &amp;quot;)
      puts &amp;quot;[#{pid}] #{trace}&amp;quot;
      puts &amp;quot;[#{pid}] ---&amp;quot;
    end
    puts &amp;quot;[#{pid}] -------------------&amp;quot;
    exit unless sig == &amp;#39;USR2&amp;#39;
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Restart your unicorns (this change may require full stop and clean start) and wait for any worker to receive a timeout. When it does, read your logs and rejoice:&lt;/p&gt;

&lt;pre&gt;&lt;code class="no-highlight"&gt;E, [2014-01-19T04:17:19.340983 #26722] ERROR -- : worker=5 PID:27033 running too long (45s), sending TERM
[27033] Received USR2 at 2014-01-19 04:17:19 +0000. Dumping threads:
[27033] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:291:in `backtrace&amp;#39;
[27033] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:291:in `block (3 levels) in reload&amp;#39;
[27033] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:290:in `each&amp;#39;
[27033] /srv/app.intra.net/releases/shared/config/unicorn-config.rb:290:in `block (2 levels) in reload&amp;#39;
[27033] ... your code ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And you can still use &lt;code&gt;kill -USR2 &amp;lt;pid&amp;gt;&lt;/code&gt; on your unicorn workers (or any other Ruby process for that matter) to get the backtrace on demand. Just don&amp;#39;t send &lt;code&gt;USR2&lt;/code&gt; to unicorn master process expecting to get a thread dump, it will &lt;a href="http://unicorn.bogomips.org/SIGNALS.html"&gt;reload your application&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;Everything is so much simpler when you can pinpoint problems in your code.&lt;/p&gt;
</description>
      <pubDate>Sat, 18 Jan 2014 18:50:21 +0000</pubDate>
      <link>http://varaneckas.com/blog/ruby-tracing-threads-unicorn/</link>
      <guid>http://varaneckas.com/blog/ruby-tracing-threads-unicorn/</guid>
    </item>
    <item>
      <title>How to get Hubot on HipChat using Hubot Control on CentOS Linux</title>
      <description type="html">&lt;h3&gt;What is Hubot and why should I want it?&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://hubot.github.com/"&gt;Hubot&lt;/a&gt; is an awesome chat bot open sourced by GitHub. It&amp;#39;s &lt;a href="https://github.com/github/hubot-scripts#readme"&gt;easily extendable&lt;/a&gt; using CoffeeScript, and you can run it on pretty much every popular messaging service using a variety of &lt;a href="https://github.com/github/hubot/blob/master/docs/adapters.md"&gt;adapters&lt;/a&gt;. Hubot is primarily a company chat bot that can be incredibly useful in daily operations - take a look at &lt;a href="http://www.youtube.com/watch?v=NST3u-GjjFw"&gt;ChatOps at GitHub&lt;/a&gt; screencast to get the idea.&lt;/p&gt;

&lt;p&gt;However, Hubot can be quite tricky configure and operate, and that&amp;#39;s where &lt;a href="https://github.com/spajus/hubot-control"&gt;Hubot Control&lt;/a&gt; comes in - it allows you to configure and manage multiple Hubot instances using a web interface.&lt;/p&gt;

&lt;p&gt;This article will guide you through running Hubot on &lt;a href="https://www.hipchat.com/"&gt;HipChat&lt;/a&gt;, but it is pretty similar to use any other adapter in same fashion, with exception of Skype, that requires you to jump some additional hoops.&lt;/p&gt;

&lt;h3&gt;Create a HipChat account for your Hubot&lt;/h3&gt;

&lt;p&gt;Add &lt;a href="http://help.hipchat.com/knowledgebase/articles/64413-how-do-i-add-invite-new-users-"&gt;a new user&lt;/a&gt; from your existing HipChat account. Log in with this new user, enter desired chatrooms. Set your bot&amp;#39;s @mention name to &lt;code&gt;@hubot&lt;/code&gt; in account settings.&lt;/p&gt;

&lt;h3&gt;Prepare your system&lt;/h3&gt;

&lt;p&gt;We will be doing the setup on CentOS 6.4, but since there is nothing too CentOS specific in the steps, you can do the same using corresponding packages for your favorite Linux distribution. &lt;/p&gt;

&lt;p&gt;For CentOS, you should have &lt;a href="http://www.rackspace.com/knowledge_center/article/installing-rhel-epel-repo-on-centos-5x-or-6x"&gt;EPEL repo enabled&lt;/a&gt; to have access for all required packages.&lt;/p&gt;

&lt;h3&gt;Install system dependencies&lt;/h3&gt;

&lt;p&gt;You will need several things to get everything running. Let&amp;#39;s make sure you have everything.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Development libraries for compiling ruby and some gems 
$ yum install -y readline-devel zlib-devel libyaml-devel libffi-devel openssl-devel sqlite-devel

# Node and NPM
$ yum install npm --enablerepo=epel

# Required node packages
$ npm install -g coffee-script
$ npm install -g hubot
$ npm install -g hubot-hipchat
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Prepare Hubot Control source&lt;/h3&gt;

&lt;p&gt;Hubot Control is a plain and simple Ruby on Rails webapp, there is no native packaging available, so we will clone the source code to our &lt;code&gt;/opt&lt;/code&gt; directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /opt
$ git clone https://github.com/spajus/hubot-control.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You may also want to use &lt;a href="https://github.com/spajus/hubot-control/fork"&gt;your own fork&lt;/a&gt;  of Hubot Control.&lt;/p&gt;

&lt;h3&gt;Add &lt;q&gt;hubot&lt;/q&gt; user&lt;/h3&gt;

&lt;p&gt;Running things as &lt;code&gt;root&lt;/code&gt; is a very dangerous practice, so let&amp;#39;s set up a fresh user just for Hubot, pointing it&amp;#39;s home directory to &lt;code&gt;/opt/hubot-control&lt;/code&gt;, where we just checked out our rails app:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ useradd -d /opt/hubot-control hubot
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then make sure this new user has all the rights to &lt;code&gt;/opt/hubot-control&lt;/code&gt; dir:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chown -R hubot:hubot /opt/hubot-control
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Install RVM and Ruby 2.0.0&lt;/h3&gt;

&lt;p&gt;We will install &lt;a href="http://rvm.io/"&gt;RVM&lt;/a&gt; to get desired version of Ruby without messing up the system. As &lt;code&gt;hubot&lt;/code&gt;, run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ su - hubot

# Will install RVM and Ruby 2.0.0. This will take a while.
$ \curl -sSL https://get.rvm.io | bash -s stable --ruby=2.0.0

# Will load RVM for the first time.
$ source ~/.rvm/scripts/rvm 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Afterwards &lt;code&gt;ruby -v&lt;/code&gt; should show something like &lt;code&gt;ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]&lt;/code&gt;/&lt;/p&gt;

&lt;h3&gt;Configure the database&lt;/h3&gt;

&lt;p&gt;You can configure Hubot Control to use any database you want - refer to &lt;a href="http://guides.rubyonrails.org/configuring.html#configuring-a-database"&gt;Ruby on Rails configuration guide&lt;/a&gt; to do that. In this article we will be using &lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; in development mode, so it will work out of the box. However, to avoid installing PostgreSQL gem, which requires development libraries, we will remove &lt;code&gt;gem &amp;#39;pg&amp;#39;&lt;/code&gt; line from &lt;code&gt;/opt/hubot-control/Gemfile&lt;/code&gt;, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sed -i &amp;quot;/gem &amp;#39;pg&amp;#39;/d&amp;quot; /opt/hubot-control/Gemfile
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Install Ruby Gems&lt;/h3&gt;

&lt;p&gt;To be able to start Hubot Controll, you have to install the dependencies. We will do this as &lt;code&gt;hubot&lt;/code&gt; user:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ su - hubot
$ cd /opt/hubot-control
$ bundle install
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;What to do if some gem fails to install&lt;/h3&gt;

&lt;p&gt;If some gem will fail to install, you will most likely need to install a development library for a missing native ruby extension to compile properly. Then just try again. For example, if &lt;code&gt;sqlite&lt;/code&gt; gem fails and &lt;code&gt;sqlite-devel&lt;/code&gt; package is not installed, you will see this error:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;An error occurred while installing sqlite3 (1.3.8), and Bundler cannot continue.
Make sure that `gem install sqlite3 -v &amp;#39;1.3.8&amp;#39;` succeeds before bundling.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To fix it, simply run as root:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ yum install -y sqlite-devel
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It should succeed this time, and then run &lt;code&gt;bundle install&lt;/code&gt; again, to proceed with the rest of gem dependencies.&lt;/p&gt;

&lt;h3&gt;Prepare the database&lt;/h3&gt;

&lt;p&gt;A final step before starting Hubot Control for the first time is to create your database. If it&amp;#39;s properly configured, this will succeed, and you will be good to go:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ rake db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Run Hubot Control&lt;/h3&gt;

&lt;p&gt;Now it&amp;#39;s time to run Hubot Control for the first time. We will do it in a straightforward way, by running:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd /opt/hubot-control
$ rails server --port=3000
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rails will boot and you will see all the output right in your console. Now point your browser to &lt;code&gt;http://your-server-ip:3000/status&lt;/code&gt;, login with &lt;code&gt;admin@hubot-control.org&lt;/code&gt; / &lt;code&gt;hubot&lt;/code&gt;, and if you see a green heading saying &lt;q&gt;You can run Hubot&lt;/q&gt; - you&amp;#39;re almost there. If something is missing, you will see the cause along with instructions what to do.&lt;/p&gt;

&lt;p&gt;When you will get everything running, you can start Hubot Control as a daemon using:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ unicorn_rails -p &amp;lt;port&amp;gt; -D
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Create a Hubot&lt;/h3&gt;

&lt;p&gt;To create a new Hubot, click &lt;q&gt;Add Hubot&lt;/q&gt; and fill out the form. Set Title and Name to &lt;code&gt;hubot&lt;/code&gt;, Adapter to &lt;code&gt;hipchat&lt;/code&gt; and click &lt;q&gt;Create&lt;/q&gt;. Now wait patiently for a while until you see a congratulatory screen with log output. You have just created a vanilla hubot instance. Click &lt;q&gt;Control hubot&lt;/q&gt; button to proceed with further configuration.&lt;/p&gt;

&lt;h3&gt;Configure your Hubot&lt;/h3&gt;

&lt;p&gt;There are some final steps to take before your Hubot can connect to HipChat. &lt;/p&gt;

&lt;h4&gt;Variables&lt;/h4&gt;

&lt;p&gt;Click &lt;q&gt;Configure&lt;/q&gt; button and go to &lt;q&gt;Variables&lt;/q&gt; tab. This is where you have to add some configuration variables for the &lt;a href="https://github.com/hipchat/hubot-hipchat"&gt;HipChat adapter&lt;/a&gt;. It should look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;quot;HUBOT_HIPCHAT_JID&amp;quot;: &amp;quot;12345_123456@chat.hipchat.com&amp;quot;,
  &amp;quot;HUBOT_HIPCHAT_PASSWORD&amp;quot;: &amp;quot;MySuperSecretPassword&amp;quot;,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Set the JID to the &lt;q&gt;Jabber ID&lt;/q&gt; shown on your bot&amp;#39;s &lt;a href="https://www.hipchat.com/account/xmpp"&gt;XMPP/Jabber account settings&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;package.json&lt;/h4&gt;

&lt;p&gt;In &lt;q&gt;package.json&lt;/q&gt; tab you have to add &lt;code&gt;hubot-hipchat&lt;/code&gt; dependency to &lt;code&gt;dependencies&lt;/code&gt; block. You can find the exact version of the package in &lt;a href="https://npmjs.org/package/hubot-hipchat"&gt;https://npmjs.org/package/hubot-hipchat&lt;/a&gt;. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  ...    
  &amp;quot;dependencies&amp;quot;: {
    &amp;quot;hubot&amp;quot;:         &amp;quot;&amp;gt;= 2.6.0 &amp;lt; 3.0.0&amp;quot;,
    &amp;quot;hubot-scripts&amp;quot;: &amp;quot;&amp;gt;= 2.5.0 &amp;lt; 3.0.0&amp;quot;,
    &amp;quot;hubot-hipchat&amp;quot;: &amp;quot;&amp;gt;= 2.6.4 &amp;lt; 3.0.0&amp;quot;
  },
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now hit &lt;q&gt;Save all changes&lt;/q&gt; and you are ready to start.&lt;/p&gt;

&lt;h3&gt;Starting Hubot&lt;/h3&gt;

&lt;p&gt;Click &lt;q&gt;hubot&lt;/q&gt; in the left sidebar and then click &lt;q&gt;Start&lt;/q&gt; to start it. Be patient, since it&amp;#39;s the first run, all dependencies will be installed, and Hubot Control will simply remain unresponsive. Go to your terminal where you started Hubot Control to check the output. When everything is installed, your Hubot should be running. &lt;/p&gt;

&lt;h3&gt;Testing Hubot on HipChat&lt;/h3&gt;

&lt;p&gt;Hubot will respond to @mention name - say &lt;code&gt;@hubot ping&lt;/code&gt; in the chatroom and &lt;code&gt;@hubot&lt;/code&gt; will respond with &lt;code&gt;PONG&lt;/code&gt;. Say &lt;code&gt;@hubot help&lt;/code&gt; to get the list of all commands. &lt;/p&gt;

&lt;p&gt;You can extend this list by enabling third party scripts or writing your own using Hubot Control.&lt;/p&gt;
</description>
      <pubDate>Thu, 26 Dec 2013 18:36:08 +0000</pubDate>
      <link>http://varaneckas.com/blog/hubot-hipchat-centos/</link>
      <guid>http://varaneckas.com/blog/hubot-hipchat-centos/</guid>
    </item>
    <item>
      <title>Surviving in Open Plan Office</title>
      <description type="html">&lt;p&gt;Many software development companies choose to have an open-plan office space and unfortunately I happen to &lt;a href="https://irs0.4sqi.net/img/general/width960/32812365_mVIebWLRQnYA38VLak47iPHwllUBRSuiJTuSPGlwu5o.jpg"&gt;work at
one&lt;/a&gt;.
Now, one thing makes me wonder. Why would any software development company want to use open plan
office? It looks nice on pictures and you can throw great parties in it, but how does it affect the
most important thing why people gather there in the first place - getting shit done?&lt;/p&gt;

&lt;p&gt;Just think about this - if a guy has chosen computer science as his way of life, would he rather be
more happy and productive hacking on code in a small, quiet, distraction free room, or in a big open space
full of noise and loud conversations? Would the guy enjoy people walking behind his back and constantly pulling him out of his sweet matrix of code by asking work related questions that could
be asked in chat or by email?&lt;/p&gt;

&lt;p&gt;Funny thing, &lt;a href="https://www.google.com/search?hl=en&amp;amp;q=open+plan+office"&gt;google for &lt;q&gt;open plan office&lt;/q&gt;&lt;/a&gt; and see the results on first page. You will find so many negative headlines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.news.com.au/business/openplan-offices-are-cold-noisy-and-lack-privacy/story-e6frfm1i-1226722920450"&gt;Open-plan offices are cold, noisy and lack privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stuff.co.nz/business/better-business/9181113/Workers-unhappiest-in-open-plan-offices"&gt;Workers unhappiest in open plan offices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.businessweek.com/articles/2013-07-01/ending-the-tyranny-of-the-open-plan-office"&gt;Ending the Tyranny of the Open-Plan Office - Businessweek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://associationsnow.com/2013/09/study-workers-dont-like-open-plan-offices/"&gt;Study: Workers Don&amp;#39;t Like Open Plan Offices: Associations Now&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.telegraph.co.uk/news/worldnews/australiaandthepacific/australia/10315165/Workers-less-satisfied-in-open-plan-offices.html"&gt;Workers &amp;#39;less satisfied in open plan offices&amp;#39; - Telegraph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.huffingtonpost.com/2013/08/24/open-plan-office-study_n_3810538.html"&gt;Open-Plan Offices Detrimental To Worker Productivity, Study Finds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actually, there was not a single headline saying &lt;q&gt;open plan office is great&lt;/q&gt; or anything alike, but for some strange reason those who make critical decisions have different beliefs. Let&amp;#39;s dig down to the arguments open-plan office fans may put on the table. Those fans obviously don&amp;#39;t write code at work, they are courageous business people who like to face their problems head-on, like James Bond:&lt;/p&gt;

&lt;h4&gt;&lt;q&gt;Offices with walls are dull, boring and old school - we don't want that in our company&lt;/q&gt;&lt;/h4&gt;

&lt;p&gt;Software development is dull and boring for most people, and it&amp;#39;s done best in dull and boring rooms where you don&amp;#39;t get distracted by all the fun around you. Quoting &lt;a href="http://en.wikipedia.org/wiki/Open_plan"&gt;Wikipedia&lt;/a&gt; - &lt;q&gt;Neither open or closed plan offices are perfect for any one situation or individual. The right balance is required. any office design is likely to involve trade-offs for the workers, with some positives and negatives.&lt;/q&gt; &lt;/p&gt;

&lt;p&gt;When you force developers to work in open space, you are making a trade-off for their productivity and happiness.&lt;/p&gt;

&lt;h4&gt;&lt;q&gt;Open plan office is more social&lt;/q&gt;&lt;/h4&gt;

&lt;p&gt;Computer science, software development, coding, math, concentration. Social doesn&amp;#39;t belong next to
these words. GitHub says it&amp;#39;s &lt;q&gt;Social Coding&lt;/q&gt;, but it&amp;#39;s easy to get the meaning wrong. GitHub is awesome, because you can get &lt;q&gt;social&lt;/q&gt; when
coding in your calm, quiet room, alone with 4 walls, no sunlight, just computer screens glaring
gently in your face. That&amp;#39;s the &lt;q&gt;social&lt;/q&gt; that gets shit done, not a crowd moving in front of your
face while you&amp;#39;re trying to concentrate on the code.&lt;/p&gt;

&lt;p&gt;Developers are introverts who prefer to socialize in digital form, where it&amp;#39;s easy to respond by
picking your words carefully, by doing a research on the subject, by choosing a right time to get
involved in a conversation. They don&amp;#39;t want to be social all day long, but they are forced to, against their will. If you&amp;#39;re their boss, they probably won&amp;#39;t say it in your face, since it could get them fired for bad attitude, but that&amp;#39;s the hard truth. Software developers would have chosen to become salespeople if they wanted to be social.&lt;/p&gt;

&lt;h4&gt;&lt;q&gt;You cannot hide from work in an open office&lt;/q&gt;&lt;/h4&gt;

&lt;p&gt;If you want to hide from work, you can find numerous ways to look busy with any office plan, and if you
have employees who want to hide from work, you have a much bigger problem. Those who want to get work
done, will do it anyway, question is, will they be happy doing it in the conditions they&amp;#39;re given?&lt;/p&gt;

&lt;p&gt;And those who would want to pretend they&amp;#39;re working hard would most likely make the loudest noise, so everyone would see how involved they are, right? Talking about work does not get shit done. Talking about work next to those who are trying to do it slows them down. Loud mouths should be banned from open space offices.&lt;/p&gt;

&lt;h4&gt;&lt;q&gt;It enhances communication among employees&lt;/q&gt;&lt;/h4&gt;

&lt;p&gt;Sure, people communicate around developers all the time. Walk across the office in the usual, noisy moment. Most developers will be wearing their headphones, hiding from communication. Sadly, good headphones are an absolute requirement to get any work done in an open-plan office.&lt;/p&gt;

&lt;p&gt;Communication in the middle of the office raises the noise level, which raises stress and blood pressure levels of everyone who is
trying to concentrate on getting their work done. You&amp;#39;re literally killing your developers.&lt;/p&gt;

&lt;p&gt;There may be more arguments, why someone would say open-plan is superior to other options, but none
of them would be valid when it comes to delivering results of labor that requires high levels of
concentration.&lt;/p&gt;

&lt;h4&gt;Surviving in open plan office&lt;/h4&gt;

&lt;p&gt;If you are trapped in such an office, there are ways to survive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Come to work as early as possible. Noise and distractions start around 9-10 AM. If you get to
your office as early as 7AM, you could get more work done in 3 hours than in rest of the day.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do work from home. If your company frowns upon remote work, you can still do it without telling
anyone, before or after normal office hours, while coming in a little late or getting out a
little earlier. Just be in the office at day time, when the noise is the loudest. This way
everyone will think you are getting work done right in the office, while being social and shit.
Or do long calm work sessions on Saturdays and Sundays. These are the best, but I have a feeling
that no one will be a big fan of that. You can burn yourself out after doing that for a while.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get some serious noise canceling headphones. Not hipster beats by rapper crap, not anything from
Apple store. Look for &lt;q&gt;Studio monitor headphones&lt;/q&gt; or DJ oriented products. The price tag will be
steep, but you will get what you pay for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get a curtain wall. Open-plan fans will want to keep it open, but you can close it again and
again. We have one in our office, and it&amp;#39;s &lt;a href="/blog-images/open-space-curtains.png"&gt;always closed shut&lt;/a&gt;. We need more of those, but I still
need to convince people. Hopefully this rant will do it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hide in meeting rooms and lounges. It will take a while for those who want to distract you to
find you in a secluded meeting room. And often they wouldn&amp;#39;t bother to look for you further than
your desk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce chaos by improving company processes to require less direct interactions. Implement Scrum properly, and you will get much more peace and quiet even in open-plan office, since there
will be significantly less clueless people trying to find out what to do next, less poking about
task statuses, less work given to developers directly out of thin air.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convince people that remote work is healthy now and then. I used to work in a company where one
day a week could be spent working remotely from home, and those were the most productive days -
no hard task could resist a one day cracking in a peaceful atmosphere of your choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When someone interrupts you, say you are working on something at the moment and ask them to send you
an email about it. Promise to respond as soon as you&amp;#39;ll be available. I know one person who used
to do it, and it worked as a charm. When you reject someone with direct request several times,
they start writing emails and come in person only when it&amp;#39;s really necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convince your company to adopt &lt;q&gt;Library rules&lt;/q&gt;, &lt;a href="http://37signals.com/svn/posts/3357-an-office-with-ldquolibrary-rulesrdquo"&gt;like in 37 Signals&lt;/a&gt;. All conversations should be
either in whisper, or in remote meeting rooms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is sad that remote work is not a part of software development culture in most companies.
Management almost always relates remote work with slacking or failing at communication, but that&amp;#39;s
far from being true. There are plenty of high profile companies (i.e.: &lt;a href="http://blogs.hbr.org/2013/03/how-wordpress-thrives-with-a-1/"&gt;Automattic&lt;/a&gt;), that are
wildly successful with remote workers. A well organized team doesn&amp;#39;t have to talk face to face to get work done. &lt;/p&gt;

&lt;p&gt;Make walls, not noise.&lt;/p&gt;
</description>
      <pubDate>Tue, 24 Sep 2013 04:04:42 +0000</pubDate>
      <link>http://varaneckas.com/blog/surviving-in-open-plan-office/</link>
      <guid>http://varaneckas.com/blog/surviving-in-open-plan-office/</guid>
    </item>
    <item>
      <title>The Law of Startup Lottery</title>
      <description type="html">&lt;p&gt;I&amp;#39;ve been willing to write about this for quite a while, but didn&amp;#39;t do it because some people will
want to throw stones at me for trying to break their spirit. You don&amp;#39;t have to take my word for it
if you don&amp;#39;t like what I&amp;#39;m saying. I don&amp;#39;t claim that my point of view is absolutely correct, so
don&amp;#39;t blame me for having one.&lt;/p&gt;

&lt;p&gt;I love people who love startups. Who work hard and believe that they can change the world. Who are
fearless and choose a different path than most of those who are playing it safe. There is something
about them that triggers a sense of respect.&lt;/p&gt;

&lt;p&gt;I consider myself a startup minded person too. I&amp;#39;ve been trying to spin off my own business for at
least 10 years. I&amp;#39;ve built software services, created products with optimistic hope that
people will find them useful and it will somehow evolve into something I could do for living. I&amp;#39;ve
been getting up at 5AM every day to find the time to code things of my own while having a full
time job. I&amp;#39;ve took breaks from job to create something of my own. But I was always dragged back by
the cruel reality. I still read NH nearly every day, stories about new successful software startups
always makes my heart beat faster and my pupils dilate.&lt;/p&gt;

&lt;p&gt;Like most of things in life, only a small fraction of everything that
people create is actually ingenious. Take music, for instance. Everyone can learn to play or compose
it, but it takes more than time, stubbornness, dedication and hard work to produce a true
masterpiece. And usually one doesn&amp;#39;t make it twice. Same goes with technology. Most software
products and services that startups produce are just worthless or only a little useful. But
&lt;q&gt;good enough&lt;/q&gt; doesn&amp;#39;t cut it - you have to be the best to succeed.&lt;/p&gt;

&lt;p&gt;More bad news for those who are dying to create a hit - you will never create one on purpose. I
don&amp;#39;t know if there&amp;#39;s a law for that, and if it&amp;#39;s not, I&amp;#39;m coining it as The Law of Startup
Lottery: chances of creating a really successful startup are roughly equal to winning the grand
prize of national lottery. And if you took some classes of statistics or have a common sense,
you will know that it&amp;#39;s not worth the try.&lt;/p&gt;

&lt;p&gt;Another interesting observation is that the most relatively successful things I&amp;#39;ve built were not
built with any intention of becoming a success whatsoever. For instance, my most successful part
time project was a mirror of JAD Java Decompiler, it&amp;#39;s homepage once disappeared from the internet
and I had pretty hard time finding a copy, so I decided to put out a mirror for other people to
save their time and to keep that great piece of free software alive. It took me 2 hours to do that,
and now I&amp;#39;m getting increasingly growing traffic from Wikipedia, StackOverflow, Eclipse Wiki, etc.
It&amp;#39;s not a huge traffic, since potential audience is just a small fraction of curious Java
developers and random hackers, but it&amp;#39;s way bigger than anything I&amp;#39;ve had with my other pet projects. And it was so
easy to set up. Brilliant things doesn&amp;#39;t have to take much time or strategical planning, you
just have to be at the right place at the right time. It&amp;#39;s much easier when you do it first.&lt;/p&gt;

&lt;p&gt;Read the stories of the greatest startups ever built. How many of them involve accidental luck, and
how many were built by intention to become a success?&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve been trying hard enough, spending endless hours of my spare time planning, writing code,
contemplating on various ideas, reading books and blogs about startups, trying to apply the learned
techniques. It was definitely and rewarding and fun, I&amp;#39;ve learned a heap of new things that I would
otherwise never learn. That was the best part.&lt;/p&gt;

&lt;p&gt;But then, ask yourself, why do you do it? It feels bad when you pour your heart into something no
one ever wants to use. Over and over again. It&amp;#39;s fun to learn, but you can&amp;#39;t do it just for the
sake of learning, can you?&lt;/p&gt;

&lt;p&gt;This is where I put down my hat, at least for a while. I will no longer try to create anything just
because it&amp;#39;s fun and it may become something more. I&amp;#39;ll rather do what I love for those who have
won the startup lottery. And if the day comes, I&amp;#39;ll create something useful unwillingly, but
chances are just one in a billion.&lt;/p&gt;

&lt;p&gt;If you&amp;#39;re trying hard to become a success, you&amp;#39;re doing it wrong. It does not work that way.&lt;/p&gt;
</description>
      <pubDate>Fri, 22 Feb 2013 05:01:39 +0000</pubDate>
      <link>http://varaneckas.com/blog/law-of-startup-lottery/</link>
      <guid>http://varaneckas.com/blog/law-of-startup-lottery/</guid>
    </item>
    <item>
      <title>Information Diet</title>
      <description type="html">&lt;p&gt;There are plenty of lifehacks for keeping up with the information flow. Organizing it, having &lt;q&gt;read later&lt;/q&gt; lists, processing it once a day, etc. I&amp;#39;ve tried many of them, but none of them worked in the long run. When you have a torrent of news coming at you from all directions, it&amp;#39;s impossible to keep up. &lt;/p&gt;

&lt;p&gt;There are social news sites like Reddit or HN that are supposed to give you handpicked trendy stuff. It&amp;#39;s a step forward, but you only get what ticks for the masses, and if it&amp;#39;s good, you&amp;#39;ll get it more than once - popular content is usually reposted and relinked multiple times - everyone wants to be the one to spread the important news. Next time, before posting a link from HN top page to your Twitter or Google+ account, think again. Internet is redundant enough. Stop sharing same things over and over.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve taken a few steps to reduce my own digital footprint in this bloated era of useless information. I&amp;#39;ve stopped using following services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Facebook: No value whatsoever. Sadly I couldn&amp;#39;t just deactivate my account because I&amp;#39;m a developer and have some apps I want to keep alive, so I just locked myself out by changing my password to something random. &lt;/li&gt;
&lt;li&gt;Google+: Never understood the need for it.&lt;/li&gt;
&lt;li&gt;LinkedIn &amp;amp; all other online career tools: I usually got my jobs as a result of direct recommendation by someone I know in real life. Over ~10 years of use, LinkedIn gave me nothing but lots of recruiter spam. So long, annoying skill endorsements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to deactivate my Twitter account too, but kept it for authentication purposes. Sometimes it&amp;#39;s the only acceptable type of auth that some app offers. I promise to tweet less though.&lt;/p&gt;

&lt;p&gt;And for my own information diet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No social networks.&lt;/li&gt;
&lt;li&gt;No television - haven&amp;#39;t been watching it for ages anyway. And a while ago I disconnected the external antenna.&lt;/li&gt;
&lt;li&gt;No local news sites. There are some online gazettes that everyone in Lithuania feels obligated to read daily. Sorry, I&amp;#39;m not into politics, local scandals or people bitching about high costs of winter heating.&lt;/li&gt;
&lt;li&gt;As few RSS as possible. Nothing that reposts content from other places. Nothing that posts daily.&lt;/li&gt;
&lt;li&gt;No pointless random browsing to amuse myself. Although it&amp;#39;s a hard habit to get rid of, I&amp;#39;m doing my best.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reading a book is so much better than reading random crap on the internet.&lt;/p&gt;

&lt;p&gt;Life has just become much simpler. &lt;/p&gt;
</description>
      <pubDate>Tue, 15 Jan 2013 06:00:41 +0000</pubDate>
      <link>http://varaneckas.com/blog/information-diet/</link>
      <guid>http://varaneckas.com/blog/information-diet/</guid>
    </item>
    <item>
      <title>How to Work with Large Rails Codebase Effectively</title>
      <description type="html">&lt;h3&gt;Welcome to the Real World&lt;/h3&gt;

&lt;p&gt;A couple of weeks ago I&amp;#39;ve started working on a pretty big Rails app. After dealing with my lightweight pet projects, a few inconveniences occurred. If you&amp;#39;re lazy, just jump to the end to see the summary of the important things I&amp;#39;ve learned.&lt;/p&gt;

&lt;h4&gt;App, Y U No start?&lt;/h4&gt;

&lt;p&gt;An empty rails app starts in 1-2 seconds. My biggest pet project starts in 5 seconds. The big app starts in 25 seconds. That&amp;#39;s a guaranteed 25 second overhead for every operation that has to load Rails - console, runner, tests, server. Multiply this overhead by number of times you do those during the day and it can easily build up into a solid amount of time wasted.&lt;/p&gt;

&lt;h4&gt;Testing woes&lt;/h4&gt;

&lt;p&gt;All tests run a solid half-hour, and you only see failures in the end. Continuous integration server helps, but at least in the very beginning I&amp;#39;d rather make sure everything works on my machine before pushing my commits to origin. &lt;/p&gt;

&lt;p&gt;An when you run tests one by one, you get to wait those extra 25 seconds every time. That can give you cancer.&lt;/p&gt;

&lt;h4&gt;The Tricky Extras&lt;/h4&gt;

&lt;p&gt;There is a small zoo of additional stuff that has to be installed and running for the main app to work. That stuff may also run in several instances, one for each environment you want to use (development, test). And when you suddenly realize that something required is not running, you waste more precious time to find what&amp;#39;s wrong and to fox it. Basically it&amp;#39;s a never ending fight with the environment, until you gradually get used to it and everything starts to work, because just like an experienced puppet master you have an eye for things and grow to feel what strings should be pulled to get back on track.&lt;/p&gt;

&lt;p&gt;And of course, those extra dependencies have their own rituals, like you occasionally may have to rebuild the indexes for the full text search server.&lt;/p&gt;

&lt;h4&gt;The Code Base&lt;/h4&gt;

&lt;p&gt;Navigating around a huge codebase of a heavily dynamic language is quite tricky, especially in the very beginning.&lt;/p&gt;

&lt;p&gt;This is mostly it. The rest is just pure awesomeness!&lt;/p&gt;

&lt;h3&gt;Lessons Learned&lt;/h3&gt;

&lt;h4&gt;Speeding things up&lt;/h4&gt;

&lt;p&gt;I&amp;#39;ve tried profiling, looking for bottlenecks, cutting out routes, removing gems, but nothing gave a significant speed up for Rails boot time. When running individual tests, &lt;a href="https://github.com/sporkrb/spork"&gt;spork&lt;/a&gt; gave a pretty good performance gain, but then a &lt;a href="http://edvinas.bartkus.lt/"&gt;colleague&lt;/a&gt; pointed me to something better - &lt;a href="https://github.com/burke/zeus"&gt;zeus&lt;/a&gt;. It&amp;#39;s a nifty thing that pre-boots various parts of rails and allows rapid execution for all those tasks that used to make me wait for 25 seconds. Running an individual test now takes 5 seconds instead of 30. Great success! &lt;/p&gt;

&lt;h4&gt;Tame the Zoo with Bootstrap Script&lt;/h4&gt;

&lt;p&gt;I&amp;#39;ve found a &lt;a href="http://zachholman.com/talk/ruby-patterns"&gt;nice presentation&lt;/a&gt; by a GitHubber &lt;a href="http://zachholman.com/"&gt;Zach Holman&lt;/a&gt;, which suggested using a &lt;code&gt;script/bootstrap&lt;/code&gt; which would handle installing dependencies and more things that hurt newbies. Haven&amp;#39;t done it yet, but I&amp;#39;m eventually going to write one.&lt;/p&gt;

&lt;h4&gt;Use the Right Tools&lt;/h4&gt;

&lt;p&gt;I started out with &lt;a href="http://www.jetbrains.com/ruby/"&gt;RubyMine&lt;/a&gt; - thought it would help me get around the code easier. It has a couple of goodies in it&amp;#39;s pocket, but you can do nearly everything using good old Vim, proper &lt;a href="https://github.com/robbyrussell/oh-my-zsh"&gt;shell&lt;/a&gt; and &lt;a href="http://www.iterm2.com/"&gt;terminal&lt;/a&gt; - and you will have much more fun too. Use &lt;a href="http://ctags.sourceforge.net/"&gt;ctags&lt;/a&gt; to jump around the code like a boss. Lots of people are in love with &lt;a href="http://www.sublimetext.com/"&gt;Sublime&lt;/a&gt;, so it&amp;#39;s worth checking out.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ve also found some tools that are very helpful for getting to know the application. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/josevalim/rails-footnotes"&gt;Rails Footnotes&lt;/a&gt; appends every page with a footer that contains lots of debug information and links that open your text editor with current controller, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pryrepl.org/"&gt;Pry&lt;/a&gt; is great for debugging. You just add &lt;code&gt;binding.pry&lt;/code&gt; anywhere in your code and it stops with an interactive shell. Just like &lt;code&gt;ipdb.set_trace&lt;/code&gt; does in Python. You can use pdb, but &lt;a href="http://pypi.python.org/pypi/ipdb"&gt;ipdb&lt;/a&gt; is better, but let&amp;#39;s not get carried away. Also take a look at &lt;a href="https://github.com/nixme/pry-nav"&gt;pry-nav&lt;/a&gt;, because for some weird reason pry alone won&amp;#39;t give you the possibility to step around your code, and you should really want that. &lt;/p&gt;

&lt;h4&gt;Summary (last update: Oct 27, 2012)&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://github.com/burke/zeus"&gt;zeus&lt;/a&gt; to get super fast Rails boot time.&lt;/li&gt;
&lt;li&gt;Get some inspiration &lt;a href="http://zachholman.com/talk/ruby-patterns"&gt;here&lt;/a&gt; and write a script for installing/starting/managing your development environment.&lt;/li&gt;
&lt;li&gt;If you want to have more fun, don&amp;#39;t use a heavy IDE. Use &lt;a href="http://www.sublimetext.com/"&gt;Sublime&lt;/a&gt; or &lt;a href="http://vim.org"&gt;vim&lt;/a&gt;. Here&amp;#39;s my &lt;a href="https://github.com/spajus/dotvim"&gt;vim config&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Use &lt;a href="http://ctags.sourceforge.net/"&gt;ctags&lt;/a&gt; with your text editor (it should support the integration).&lt;/li&gt;
&lt;li&gt;Use &lt;a href="http://pryrepl.org/"&gt;Pry&lt;/a&gt; and &lt;a href="https://github.com/nixme/pry-nav"&gt;pry-nav&lt;/a&gt; gem to debug.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Sat, 27 Oct 2012 13:58:34 +0000</pubDate>
      <link>http://varaneckas.com/blog/howto-effective-work-with-large-rails-codebase/</link>
      <guid>http://varaneckas.com/blog/howto-effective-work-with-large-rails-codebase/</guid>
    </item>
    <item>
      <title>Generating Static Website with Rails 3</title>
      <description type="html">&lt;h4&gt;Why Rails -&amp;gt; Static HTML is good&lt;/h4&gt;

&lt;p&gt;So you want to build a static website - a bunch of HTML files, some CSS, images - something you can host anywhere. Yet, you want to reuse your code, whenever you can - shared navigation, partial blocks, etc. It would also be nice to have some basic content management. You could build it with Rails and export a bunch of static html files. My website and this blog is built that way, and it&amp;#39;s pretty simple to do. You can also use this technique with other frameworks, like Django.&lt;/p&gt;

&lt;h4&gt;The Quick Formula&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Make HTML friendly routes&lt;/li&gt;
&lt;li&gt;Run in production mode on local machine&lt;/li&gt;
&lt;li&gt;Grab the static version using &lt;code&gt;wget&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Deploy HTML files to your hosting server&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;HTML Friendly Routes&lt;/h4&gt;

&lt;p&gt;There is only one rule - your routes must end with &lt;code&gt;.html&lt;/code&gt;, so your URLs will look like &lt;code&gt;blog.html&lt;/code&gt;. Here is an example route:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#in `routes.rb`:
get &amp;quot;blog.html&amp;quot; =&amp;gt; &amp;quot;posts#index&amp;quot;, :as =&amp;gt; :blog

#in views:
&amp;lt;%= link_to &amp;quot;Blog&amp;quot;, :blog_path %&amp;gt; &amp;lt;!-- will generate &amp;lt;a href=&amp;quot;/blog.html&amp;quot;&amp;gt;Blog&amp;lt;/a&amp;gt; --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you don&amp;#39;t want your URLs to have that &lt;code&gt;.html&lt;/code&gt; extension, you can do this folder trick:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#in `routes.rb`:
get &amp;quot;blog/&amp;quot; =&amp;gt; &amp;quot;posts#index&amp;quot;, :as =&amp;gt; :blog
get &amp;quot;blog/index.html&amp;quot; =&amp;gt; &amp;quot;posts#index&amp;quot;   

#in views:
&amp;lt;%= link_to &amp;quot;Blog&amp;quot;, :blog_path %&amp;gt; &amp;lt;!-- will generate &amp;lt;a href=&amp;quot;/blog/&amp;quot;&amp;gt;Blog&amp;lt;/a&amp;gt; --&amp;gt;

#in `application.rb`, for generating urls with trailing slash:
config.action_controller.default_url_options = { :trailing_slash =&amp;gt; true }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the example above, &lt;code&gt;wget&lt;/code&gt; will create a folder named &lt;code&gt;blog/&lt;/code&gt; and put &lt;code&gt;index.html&lt;/code&gt; inside, and &lt;code&gt;/blog/&lt;/code&gt; URL will be accessible.&lt;/p&gt;

&lt;h4&gt;Grabbing The Site&lt;/h4&gt;

&lt;p&gt;Make sure you are running Rails server in production mode before grabbing. Why production? In development mode Rails appends query strings with versions to static assets to avoid browser cacheing them, and &lt;code&gt;wget&lt;/code&gt; will be stupid enough to save files named &lt;code&gt;application.css?body=1&lt;/code&gt;. You will not be able to deploy these without renaming them. It&amp;#39;s much simpler to run Rails in production instead:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;rake assets:clean
rake assets:precompile
# Rails may want you to have a synced production database. SQLite works great.
RAILS_ENV=production db:migrate
rails server -e production
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, go to someplace clean (i.e.: temp) and run this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;wget -m localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It will recursively download your whole site and put it into localhost:3000/ directory. You won&amp;#39;t be able to see it properly right from file system because of relative URLs, but try deploying that and it will work like a charm. For easier deployment tar the files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd &amp;quot;localhost:3000&amp;quot;
tar -cf website.tar *
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Place &lt;code&gt;website.tar&lt;/code&gt; in document root of your server and extract it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tar -xf website.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It should work. If you want to serve those files from subdirectory, i.e.: &lt;code&gt;example.com/subdir/&lt;/code&gt;, you will have to scope all your paths in &lt;code&gt;routes.rb&lt;/code&gt; and set &lt;code&gt;ENV[&amp;#39;RAILS_RELATIVE_URL_ROOT&amp;#39;] = &amp;quot;/subdir&amp;quot;&lt;/code&gt; in your &lt;code&gt;environment.rb&lt;/code&gt;. I haven&amp;#39;t tried it though.  &lt;/p&gt;

&lt;h4&gt;Bonus: Dead Simple Local Admin Mode&lt;/h4&gt;

&lt;p&gt;To manage my content, I found this simple trick to work amazingly well - generate scaffolds to manage your content and add this around links that lead to content manipulation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;% if params[:admin] %&amp;gt;
  ... links to &amp;quot;new&amp;quot;, &amp;quot;edit&amp;quot;, &amp;quot;delete&amp;quot; content ...
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then simply run Rails in production mode and manually add &lt;code&gt;?admin=1&lt;/code&gt; to URLs where you want admin features to appear. Since you&amp;#39;re exporting static HTML, there is no security to concern for. Just don&amp;#39;t forget to change this method if you ever decide to deploy your Rails app instead of exported static content.&lt;/p&gt;

&lt;h4&gt;Next steps&lt;/h4&gt;

&lt;p&gt;To make it even easier, automate your deployment with Capistrano. I found it useful to have a two step deployment - first generate and deploy a test version of the static site, see if everything is OK and then finish the deployment by wiping out production directory and moving test files there. And don&amp;#39;t forget to add your production database to source control, assuming you went with SQLite.&lt;/p&gt;
</description>
      <pubDate>Wed, 10 Oct 2012 12:05:09 +0000</pubDate>
      <link>http://varaneckas.com/blog/rails3-to-static-website/</link>
      <guid>http://varaneckas.com/blog/rails3-to-static-website/</guid>
    </item>
  </channel>
</rss>
