Flashuni
Flashuni

Reputation: 41

Resque and redis wait for variable to be set

Currently I am running on rails 3.1 rc4 and using redis and resque for queueing creation of rackspace servers.

The rackspace gem that I am using, cloudservers, tells you when your server is done being setup with the status method.

What I am trying to do with the code below is execute the code in the elsif only after the server is active and ready to be used.

class ServerGenerator
  @queue = :servers_queue
  def self.perform(current_id)
    current_user = User.find(current_id)
    cs = CloudServers::Connection.new(:username => "***blocked for security***", :api_key => "***blocked for security***")
    image = cs.get_image(49) # Set the linux distro
    flavor = cs.get_flavor(1) # Use the 256 Mb of Ram instance
    newserver = cs.create_server(:name => "#{current_user.name}", :imageId => image.id, :flavorId => flavor.id)


  if newserver.status == "BUILD"
    newserver.refresh
  elsif newserver.status == "ACTIVE"
    # Do stuff here, I generated another server with a different, static name
    # so that I could see if it was working

    cs = CloudServers::Connection.new(:username => "***blocked for security***", :api_key => "***blocked for security***")
    image = cs.get_image(49)
    flavor = cs.get_flavor(1)
    newserver = cs.create_server(:name => "working", :imageId => image.id, :flavorId => flavor.id)
  end
 end
end

When I ran the above, it only generated the first server that uses the "current_user.name", as it's name. Would a loop help around the if statement? Also this seems like a poor way of queueing tasks. Should I enqueue a new task that just checks to see if the server is ready or not?

Thanks a bunch!

Upvotes: 0

Views: 657

Answers (1)

nirvdrum
nirvdrum

Reputation: 2319

Based upon what you've written, I'm assuming that cs.create_server is non-blocking. In this case, yes, you would need to wrap your check in a do ... loop or some similar construct. Otherwise you're checking the value precisely once and then exiting the perform method.

If you're going to loop in the method, you should add in sleep calls, otherwise you're going to burn a lot of CPU cycles doing nothing. Whether to loop or call a separate job is ultimately up to you and whether your workers are mostly idle. Put another way, if it takes 5 min. for your server to come up, and you just loop, that worker is not going to be able to process any other jobs for 5 min. If that's acceptable, it's certainly the easiest thing to do. If not acceptable, you'll probably want another job that accepts your server ID and makes an API call to see if it's available.

That process itself can be tricky though. If your server never comes online for whatever reason, you could find yourself creating jobs waiting for its status ad infinitum. So, you probably want to pass some sort of execution count around too, or keep track in redis, so you stop trying after X number of tries. I'd also check out resque-scheduler so you can exert control over when your job gets executed in this case.

Upvotes: 1

Related Questions