A Simple Python Nanny for Typo

It seems like the typo instance that supports mult.ifario.us goes down at random times, since I stop by every so often and find the blog down. If I were really a good guy, I'd look at it to figure out why, but the logs don't have any useful information. It's easier to just assign a lightweight nanny to look after it; my choice is python (three guesses as to why not ruby, but read the script first):

#!/usr/local/bin/python
import os
import time

def kill_and_restart(procs):
  print time.asctime(time.localtime()) + " - Killing processes..."
  for proc in procs:
    os.kill(int(proc.split(None)[0]),9)
  if len(procs) != 0:
    time.sleep(10)
  print time.asctime(time.localtime()) + " - Restarting server..."
  os.spawnve(os.P_NOWAIT,"/usr/local/sbin/lighttpd", ["lighttpd","-f",
              "/home/pbrown/web/lighttpd/config/lighttpd.conf"],
             {"PATH" : "/sbin:/bin:/usr/sbin:/usr/bin:" +
               "/usr/local/sbin:/usr/local/bin"})
  return
  
procs = []
for line in os.popen("ps xw").read().splitlines():
  if line.find("lighttpd") != -1 or line.find("ruby") != -1:
    procs.append(line)
status = "".join([x.split(None)[2] for x in procs])
if len(procs) != 3 or "Z" in status or "T" in status:
  kill_and_restart(procs)

The bit with the dictionary in the spawnve is needed because cron is pretty dumb about the environment that it provides to the processes it starts, and ruby isn't on the path. To make sure that we're not being bad citizens:

pbrown@chilco$ time ~/bin/nanny.py
real    0m0.104s
user    0m0.015s
sys     0m0.015s

And then it goes in the crontab:

MAILTO=paulrbrown<at>gmail⋅com
@reboot /usr/local/sbin/lighttpd -f /home/pbrown/web/lighttpd/config/lighttpd.conf
*/10 * * * * /home/pbrown/bin/nanny.py 2>&1 >> /home/pbrown/logs/nanny.out

This ensures that I'll get an email if a kick is needed, and only running every ten minutes should ensure that the script never overlaps with itself except under truly extraordinary circumstances. This approach won't detect situations like internal deadlock or unresponsiveness, but neither would a nagging nannny. That has to be approached other ways.

Indexed Search Engine 0.1.3

IndexedSearch Engine for Rails Engines version 0.1.3 has been released.

IndexedSearch is a simple, pluggable engine for rails applications which can be used to enable full text indexed searches within an application. Searchable data is parsed, stemmed using the Porter stemmer, and added to a fully indexed table. This allows you to index things like “he runs fast” which will be returned from a search for “running” without using the LIKE clause in your SQL searches.

Changes to version 0.1.3 include:

  • Performance improvements, including the addition of 3 new indexes (if you are upgrading from a previous release, you need to run the command ‘rake engines_migrate’ to pick up these changes).
  • Addition of 2 new configuration options, allowing users to choose whether or not to use “live search”, and if so what the observation frequency of the live search field should be. (Thanks to Jim Elliott)
  • Improved context display on search results by using the rails “excerpt” method. (Thanks to Jim Elliott)
  • Improved error handling.

For more information check out the project page

Replacing methods

Let's say we want to replace a method instead of just throwing it away. But we want the new method to be able to call the old implementation.

The standard way of doing this is by aliasing the old method and making the new one call the aliased version:


class Foo
  def method
    ...
  end

...

class Foo
  alias :method :old_method

  def method
    ...
    old_method
  end
end



This solution works perfectly for most situations, but what if we want to remove all traces of the old method?

Here's a simple trick to do exactly that:


class Foo
   old_method = instance_method(:method)

   define_method(:method) { |*args|
       # do something here ...
       old_method.bind(self).call(*args)
   }
end


It shouldn't take much to understand how it works, but let's analyze it in more detail. The first line gets a hold of the old implementation of method. instance_method returns an UnboundMethod object that wraps it.

Next, we redefine method and pass it a block with the new implementation. One thing worth mentioning is that the old_method variable inside the block is bound to the variable assigned to outside of the block. The binding is maintained even after the execution reaches the end of the class definition. As a result, the new method has a direct reference to the old one... and nobody else does.

After doing whatever it has to do, the new method calls the old one after binding the UnboundMethod to the current object (i.e., the object on which method was invoked).

If you have a keen eye, you'll notice that there's something special about self. At first glance, it looks like a standard variable that just happens to hold a reference to the current object. If that were true, it would follow that the reference to self inside the block would be bound to the self representing class Foo. That is not the case, though. The binding of self is established when the block gets called.

Removing methods from a module

How do we remove a method from one of Ruby's built-in modules (Kernel, etc)? It should be easy and obvious, right? The following snippet should be enough, right?


#remove system from module Kernel
Kernel.send :remove_method, :system


Well, not quite. While that prevents you from calling system() in the context of the current object, you can still invoke it like this:


Kernel::system('date')


What's going on?

It turns out that they way Kernel (and other built-in modules) are defined is analogous to doing the following:


module Kernel
  def system (...)
    ...
  end

  module_function :system
end


Thus, system() is a method that will be added to instances of classes that include the given module (in our case, instances of any object, since Kernel is included by Object), but it is also a method in Kernel's singleton class (bear with me for a moment), or a module_method as the PickAxe book calls them. In Java parlance, they are simply static methods.

Looking at Ruby's source code, we can see that all of Kernel's methods are defined by way of the rb_define_module_function function, whose definition is:


void
rb_define_module_function(module, name, func, argc)
  VALUE module;
  const char *name;
  VALUE (*func)();
  int argc;
{
  rb_define_private_method(module, name, func, argc);
  rb_define_singleton_method(module, name, func, argc);
}


So, what does it mean that "system" is a method of Kernel's singleton class? Let's recap what happens when we create a class and add a method to the singleton class of one of it's instances.


class A
end

V1 = A.new    # creates an instance of A and assign it to constant V1
V2 = A.new    # ... and V2

# now we add method x() to V1's singleton class
class << V1
   def x
     puts "hello"
   end
end

V1.x    # will print "hello"
V2.x    # will fail ... V2 does not have a method x()


Clear?

Ok, now, remember that all Ruby modules are instances of a class called Module? Say we replace A by Module, V1 by Kernel and x() by system(). What we get is the following:


Kernel = Module.new

class << Kernel
   def system
     ...
   end
end


And that's essentially what's going on behind the scenes.

Going back to the question that started this post, how do we remove a method from one of the built-in modules, anyway? The answer is easy, if not as obvious as we might have expected:


module Kernel
   remove_method :system
end

class << Kernel
   remove_method :system
end


Or, more concisely,


Kernel.send :remove_method, :system
class << Kernel; self; end.send :remove_method, :system

Lightbox JS Typo Filter

I’ve added support for Lokesh Dhakar’s Lightbox JS to my local typo installation. I can’t take much credit – all of the work is in the javascript. I just addd a plugin that integrates it into typo.

But now that means that you can type something as simple as this:

<typo:lightbox img="70504519" thumbsize="small" displaysize="medium"/>

Which is rendered as this:

<div style="" class="lightboxplugin">
  <a href="http://static.flickr.com/18/70504519_6ee2bd866a.jpg" rel="lightbox" title="The Lumberjack">
    <img src="http://static.flickr.com/18/70504519_6ee2bd866a_m.jpg" width="240" height="240" alt="The Lumberjack" title="The Lumberjack"/>
  </a>
  <p class="caption" style="width:240px">Charlie's a tough guy.</p>
</div>

And gives you something as cool as this (click the image):

The Lumberjack

Charlie's a tough guy.

I’ve submitted a patch to the typo maintainers – let’s see if it gets in.

Yes Ruby in the Browser, No it won’t take off?

Obie Fernandez wants No Ruby in the Browser, after Paul Hammant discussed it in Ruby vs. JavaScript for Web 3.0. I am actually a fan of JavaScript these days. It isn't as evil as you think. However, I would love to have Ruby integrated as well as JavaScript it. We could then have true libraries, and if we could version them all within the browser etc, we could share them between apps so we don't duplicate painful downloads (not that we can't add this to JS, but we could use rubygems). Having true packages and namespaces, and a full environment like ruby in which we can share code in both worlds would be great. No need for Ruby to JSON etc. Send Ruby on down. The reality is that it would be hard to get the ball rolling. JavaScript is part of the majority of browser suites, including the Flash VM, and getting groundswell around a Ruby plugin would be tough. But in another dimension Marc A put Ruby into Netscape and we are all happy.

The most exciting programming I’ve done in a while

Even though I don’t get to do this for my day job (all java all the time), I’m now hacking away at RoR apps at night. Check out http://langwell-ball.com/indexed-search.