Wednesday, September 28, 2011

Ruby error: uninitialized constant Qpid::Messaging::Tracker

My current task has me working on a non-blocking send queue for the Ruby bindings of our messaging toolkit. Long story short, I've developed a long-lived thread model that services a queue that contains message references that are popped off as the sender's outgoing capacity opens up enough to allow messages to go out without blocking the global interpreter.

The Problem

But in the process of doing that, I hit a very strange error:

/usr/lib/ruby/gems/1.8/gems/rake-0.9.2/lib/rake/ext/module.rb:36:in `const_missing': uninitialized constant Qpid::Messaging::Tracker (NameError)

The two classes in question are named SendQueue and Tracker. SendQueue uses Tracker to monitor the capacity so it will know when a slot opens up to send a message. In the constructor for SendQueue there's the line:

def initialize
  #Tracker is a singleton, so we grab the one instance
  @@tracker = Qpid::Messaging::Tracker.instance
end

The line fetching the instance resulted in the above mentioned error. If I explicitly required the tracker module:

require 'qpid/tracker'

the problem would go away. But that shouldn't be necessary, and other code in the library that uses sibling classes don't need to require those siblings. So I was stumped why this problem was happening.

The Solution

The problem was with the lib/qpid.rb file. When you use this library you would just need to:
require 'qpid'

which then evaluates the following module:
require 'qpid/errors'
require 'qpid/duration'
require 'qpid/address'
require 'qpid/encoding'
require 'qpid/message'
require 'qpid/send_queue'
require 'qpid/sender'
require 'qpid/receiver'
require 'qpid/session'
require 'qpid/connection'
require 'qpid/tracker'

The problem is that qpid/tracker wasn't evaluated until AFTER qpid/send_queue which meant that the SendQueue class is evaluated before Ruby knows that Tracker exists.

So to solve it, I had to break away from my OCD need to keep things sorted alphabetically and instead move qpid/tracker above qpid/send_queue:

require 'qpid/errors'
require 'qpid/duration'
require 'qpid/address'
require 'qpid/encoding'
require 'qpid/message'
require 'qpid/tracker'
require 'qpid/send_queue'
require 'qpid/sender'
require 'qpid/receiver'
require 'qpid/session'
require 'qpid/connection'


As you can see, simply moving the require line up in lib/qpid.rb solved the whole problem.

Thursday, September 1, 2011

Adding Git branch to your command prompt...

It's gotten a bit annoying having to type:

git branch

just to see where I am in my current git repo. So I added the current branch name to my prompt. And, additionally, if I'm not in a git repo then nothing is displayed.

Here's the code from my ~/.bashrc file:

# Setup for my prompt

COLOR1="\[\033[1;36m\]"
COLOR2="\[\033[0;32m\]"
COLOR3="\[\033[1;33m\]"
COLOR4="\[\033[1;37m\]"

PS1="$COLOR3\u@\h$COLOR2:$COLOR1\W $COLOR4\$(ruby -e \"print (%x{git branch 2> /dev/null}.grep(/^\*/).first || '').gsub(/^\* (.+)$/, '(\1) ')\") $COLOR1\\$ $COLOR4"

export PS1

The key here is the segment passed into ruby, run in a subprocess. It runs "git branch 2" to find the name of the current branch. If it gets a nil result then it knows we're not in a git repo and it returns an empty string. Otherwise, any result returned is placed within a pair of parantheses.

This give us a nice prompt such as:

mcpierce@mcpierce-laptop:cpp (master)  $

which is very nice. Now I know when I'm on the master branch, my upstream branch or some other branch. No more accidentally forcing a non-fast forwarding commit into the remote repo for me...

...hopefully.