Now Hosted on EC2
February 3rd, 2010
I’ve moved the hosting for this blog from my old VPS into Amazon EC2. My calculations indicate this should save me around $9-$10 a month when using a single reserved m1.small instance. This is a pretty good deal since an m1.small instance has over twice as much memory and about 60% more cpu horsepower. The EC2 setup isn’t very complicated, so I’ll give you an overview right here.
I’m running a single elastic ip attached to a single running m1.small instance. I started with the public Fedora Ruby on Rails Web Starter AMI (ami-22b0534b) and lightly customized it to fit my needs. That included installing a few rubygems and mucking about in init.d and chkconfig to get the services starting the way I wanted.
The most complicated part of the setup was separating out some parts of the machine to an EBS volume for persistent storage. In particular, the mysql database needs to be on persistent storage so it is safe if the instance goes down. Also, I wanted any rails apps to be on persistent storage so I don’t have to create a new ami for every single configure change, upgrade, or deployment. All this is achieved simply by putting symlinks to the normal places where these would live in the filesystem and pointing them to the mount point for the EBS volume.
With that done and working the only remaining issue was to ensure that the EBS volume gets attached and mounted. A bit of googling confirmed that creating an init.d script was the generally accepted approach for this, and I found a workable starting point here. That solution relied on the EC2 api tools, which in turn rely on Java which I didn’t relish the idea of installing. Instead I installed the very nice amazon-ec rubygem and rewrote the mountec2vol script on top of it. Voila! Now bringing up a new instance attaches the EBS, mounts it, and then starts any services that needed the volume once it is available.
If you’re interested in the init.d script, you can get it here. It’s limited currently by having the volume id specified in the script, so you have to rebuild the ami to change the volume id. I’ll probably extract that in the future, but it’s doing what I need for now. If you find it useful, let me know!
DynamicTeardown
July 8th, 2009
I ran into a situation while working on DeepTest recently where I wanted an object to start a temporary drb server in the middle of the test and have it be stopped automatically at the end of the test. Ideally, I wanted to encapsulate inside the class itself, which is a fake used for testing and so can be aware of the test framework. Here’s the snippet I ended up with:
module DynamicTeardown
class <<self
def dynamic_teardowns
@dynamic_teardowns ||= []
end
def on_teardown(&block)
dynamic_teardowns << block
end
def run_dynamic_teardowns
while td = dynamic_teardowns.shift
td.call rescue nil
end
end
end
end
module DRbTestHelp
def drb_server_for(server)
drb_server = DRb::DRbServer.new "druby://localhost:0", server
DynamicTeardown.on_teardown { drb_server.stop_service }
return DRbObject.new_with_uri(drb_server.uri)
end
end
class Test::Unit::TestCase
def teardown
DynamicTeardown.run_dynamic_teardowns
end
end
This nice little implementation allows the class to know that it needs to get some teardown done while allowing the test framework to determine when the teardowns are called. So far it’s working great for me.
DeepTest 2.0 in the works
June 24th, 2009
I’ve started on a significant overhaul of DeepTest which will be released as version 2.0 when it’s finished. I thought I’d share some of my plans for what 2.0 will include and some thoughts about what might come versions after. I don’t have a timetable for yet, but work so far is going fairly quickly.
Plans for DeepTest 2.0
- A revamped distributed DeepTest architecture that will help ease setup and maintenance.
- A new console user interface that will provide much more information about what is going on during the test run
- Much better error handling & reporting (no more “Maybe an error was printed above?”!)
- RSpec integration that doesn’t break with every new release of rspec.
- Automatic configuration for Rails projects
What comes after 2.0? The next big feature I’d like to implement is support for cloud testing with deep test on EC2. Other than that, the features coming after 2.0 will likely be driven be requests. Is there a feature you’d like to see in DeepTest? Comment here or message me (qxjit) on github and we’ll get it rolling!
30 Days of Tech: Day 30 - Haskell Decompose
June 30th, 2008
Some time ago Tom, a friend, presented a math programming challenge to a me and a few others. The challenge was to create a function that when given a positive number would return a set of all the sets of positive numbers whose sum was the original number. He wasn’t so much interested in the result itself as he was in what sort of techniques were used in the implementation—memoization of course being a choice candidate for this problem. I was toying a lot with Haskell at the time, and since this was fundamentally a math problem, Haskell seemed well suited to the problem too.
Read the rest of this entry30 Days of Tech: Day 29 - C, Ruby, & Threads, Oh My!
June 29th, 2008
When Philippe and I worked on SystemTimer together we went back and forth about how much to write in Ruby and how much to write in C. Writing purely at the C level gave us more control over what was happening in the Ruby process as we installed and cleared signal handlers and such, but working in Ruby produced far more readable code.
Read the rest of this entry30 Days of Tech: Day 28 - lambda args
June 28th, 2008
The Ruby documentation for the lambda method (a.k.a. proc) says “Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.” This is almost exactly right. There are, however, at least two cases where this turns out to be false.
30 Days of Tech: Day 27 - Short Circuited Timeout
June 27th, 2008
Ruby’s timeout method operates by raising a exception, Timeout::Error. Timeout::Error inherits from Interrupt, SignalException, and finally Exception. In particular, it doesn’t inherit from StandardError, which means it isn’t caught by a default rescue clause with no exception class specified. When I first encountered this, I was annoyed that I had to explicitly catch timeout errors anytime I wanted to recover from errors in general, whether they were timeout errors or not. I realized something the other day that changed my opinion on this however.
30 Days of Tech: Day 26 - Fixnum#object_id
June 26th, 2008
In Ruby every object has an object_id that uniquely identifies that object in that particular instance of the Ruby process. Ruby also treats integers as objects—they are instances of Fixnum. For efficiency reasons, though, Ruby implements integers internally as simple values. That is, it doesn’t allocate heap memory for every integer you use, it just passes the value around instead. So how does Ruby generate object ids for all these integers?
30 Days of Tech: Day 25 - Gem dependency version
June 25th, 2008
RubyGems and I had a fight. It was about what version of net-ssh we wanted to have installed on my machine. RubyGems wanted the latest (2.0.2) and I wanted a 1.x version (1.1.4). Apparently net-ssh 2 has an issue with sshing into Fedora Core 4, which I needed it to do. Specifically I needed to use capistrano 1.4.1 to deploy an app to Fedora Core 4
30 Days of Tech: Day 24 - drubyall
June 24th, 2008
When we first started trying to use distributed DeepTest, we quickly ran into an issue with DRb servers not binding to the correct addresses. DRb does provide a way to bind to 0.0.0.0 to listen to all addresses, but there’s a downside to the way it does it. The url you provide to DRb to accomplish this must omit the hostname (e.g. druby://:0/). DRb then determines what hostname to report to clients by calling getaddrinfo with the empty hostname. Unfortunately for us getaddrinfo didn’t provide a hostname that could be used by our developer machines to connect to the DeepTest servers. For a brief moment we thought we were stuck.
30 Days of Tech: Day 23 - DearSoul
June 23rd, 2008
class DearSoul
def self.new(first, last)
ObjectSpace.define_finalizer(allocate, proc {|id|
puts "Goodbye, #{first}. We'll miss you."
})
end
end
DearSoul.new("George", "Carlin")
30 Days of Tech: Day 22 - Class#to_proc
June 22nd, 2008
Here’s a little hack for Ruby classes that comes from a project.
class Class
def to_proc
method(:new).to_proc
end
end
If you’ve ever used map (a.k.a. collect) to create a bunch of objects you might be familiar with code that looks something like this.
value_list.map {|v| Something.new(v)}
With Class#to_proc this can be simplified to
value_list.map(&Something)
This works very well for map, but I haven’t seen Class#to_proc become useful in any other situation to date. Even changing map to collect changes my opinion of it’s expressiveness. I don’t know that Class#to_proc is pulls its weight in our situation, but I just like the map statement above too much to give it up.
30 Days of Tech: Day 21 - Object Literals
June 21st, 2008
You can do object oriented programming in both Ruby and Javascript. I think most people would agree that Ruby is “more” object oriented than Javascript, whatever subjective judgement they’re using. One thing that’s interesting to me, though, is that Javascript has a syntax for literal objects built in where as Ruby does not.
Read the rest of this entry30 Days of Tech: Day 20 - Unmixed Methods
June 20th, 2008
mixology is a Ruby extension implemented by some of the Something Nimble collaborators. In short, it allows you to add modules to Objects (much like Ruby’s extend), but in such a way that they can also be removed. Mixology refers to these operations as mixin and unmix. If you want to know more about Mixology and the people behind it, here is a good resource. For the purposes of our discussion, here’s a simple example:
irb(main):001:0> require 'rubygems'; require 'mixology'
=> true
irb(main):002:0> module A
irb(main):003:1> def foo; puts "bar"; end
irb(main):004:1> end
=> nil
irb(main):005:0> o = Object.new
=> #<Object:0x4f2b8>
irb(main):006:0> o.foo
NoMethodError: undefined method `foo' for #<Object:0x4f2b8>
from (irb):6
irb(main):007:0> o.mixin A
=> #<Object:0x4f2b8>
irb(main):008:0> o.foo
bar
=> nil
irb(main):009:0> o.unmix A
=> #<Object:0x4f2b8>
irb(main):010:0> o.foo
NoMethodError: undefined method `foo' for #<Object:0x4f2b8>
from (irb):10
We can see that after o.unmix A the foo method is no longer accessible on the object o. But is there any way we could end up executing the foo method anyhow? It turns out there is. Let’s look at this example:
irb(main):001:0> require 'rubygems'; require 'mixology'
=> true
irb(main):002:0> module A
irb(main):003:1> def foo; puts self.inspect; end
irb(main):004:1> end
=> nil
irb(main):005:0> o = Object.new
=> #<Object:0x4d1ac>
irb(main):006:0> o.mixin A
=> #<Object:0x4d1ac>
irb(main):007:0> o.foo
#<Object:0x4d1ac>
=> nil
irb(main):008:0> foo = o.method(:foo)
=> #<Method: Object(A)#foo>
irb(main):009:0> o.unmix(A)
=> #<Object:0x4d1ac>
irb(main):010:0> o.foo
NoMethodError: undefined method `foo' for #<Object:0x4d1ac>
from (irb):10
irb(main):011:0> foo.call
#<Object:0x4d1ac>
=> nil
In this second example we can see that even though foo can’t be invoked through the object (since module A is no longer mixed in), Ruby has no problem invoking the method using the Method object that was grabbed before unmixing A. So yes, we can access foo if we should absolutely need to. There is one gotcha with this technique, however—even though we are in foo, no other methods from A are available!
irb(main):001:0> require 'rubygems'; require 'mixology'
=> true
irb(main):002:0> module A
irb(main):003:1> def called_as_method_object
irb(main):004:2> puts "got in, executing method_no_longer_available"
irb(main):005:2> method_no_longer_available
irb(main):006:2> end
irb(main):007:1>
irb(main):008:1* def method_no_longer_available
irb(main):009:2> raise "Will never make it"
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> o = Object.new
=> #<Object:0x366dc>
irb(main):013:0> o.mixin A
=> #<Object:0x366dc>
irb(main):014:0> method = o.method(:called_as_method_object)
=> #<Method: Object(A)#called_as_method_object>
irb(main):015:0> o.unmix A
=> #<Object:0x366dc>
irb(main):016:0> method.call
got in, executing method_no_longer_available
NameError: undefined local variable or method `method_no_longer_available' for #<Object:0x366dc>
from (irb):5:in `called_as_method_object'
from (irb):16:in `call'
from (irb):16
from :0
The implication of this is significant. If the code in called_as_method_object becomes complicated, you can’t even perform extract method to refactor it! Given that this technique is obscure to begin with and has this major limitation, I recommend you not use it if at all possible. That being said, you may find yourself in a situation where it’s the best option available, at least for the moment. I mean, how else would I come up with this stuff?
30 Days of Tech: Day 19 - instance_eval & Method#to_proc
June 19th, 2008
Ruby has instance_eval that accepts a block and executes it with self set to the receiver of instance_eval. Ruby also has a method called method that returns a Method object representing a callable method on an object. Method objects, in turn, have a method called to_proc which allows them to be converted to blocks. These are all facts I knew when the day began, but never before had this question occurred to me: what happens when you pass the result of Method#to_proc into instance_eval? What is self? The answer surprised me actually…