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.

Comments