Archives
Tags
- General (13)
- Food (1)
- Cooking (1)
- Ruby (6)
- Rails (2)
- Svn (2)
- Linux (8)
- Git (1)
- Firefox (7)
- Porn (1)
- Freyja (1)
- Witchhammer (4)
- Music (1)
- Merb (3)
- Poetry (0)
- Bolverk (3)
- Sinatra (1)
- Discogs (1)
- Centos (1)
- Python (1)
- Whinging (1)
- Travel (2)
- Scheme (4)
- Lisp (4)
- Sicp (1)
- Rot13 (1)
- Czech (1)
- Metal (1)
- Passenger (1)
Constant outages with Passenger 2.2.11
After pushing a large Rails app live recently, I was constantly struggling to keep Passenger live. Roughly, every 24 hours passenger would simply hang and stop handling requests. The machine (VPS running CentOS 5, 2gb RAM, 4 CPUs) had sufficient free resources and memory. Restarting Apache would instantly fix the issue and flush a bunch of "Broken pipe" errors to the error logs.
I found that killing the passenger process with a SIGABRT signal (6) would cause the process to write a stacktrace to Apaches error log. This was mildly useful.
As it turns out, I was able to solve the problem by finding and killing a couple of mysteriously dormant Ruby processes that passenger had left running. Why these were still running I am not sure. The Passenger team claim that the issue will be fixed in Passenger 3, but in the mean time, keeping an eye on Ruby processes may be beneficial. My (moderately heavy traffic) app has been online for about 7 days without a hitch now. Hopefully it will stay up indefinately now.
It's also worthwhile to make sure Apaches MaxClients setting is at an appropriate level (max_clients * average_process_size). My Passenger seemed to hang up as soon as this was hit. Be careful, though, as it turns out that Apache will keep spawning new clients even if you are out of memory -- I found this out the hard way.
Here are some useful discussions: http://code.google.com/p/phusion-passenger/issues/detail?id=318 and http://code.google.com/p/phusion-passenger/issues/detail?id=199.
A Ruby wrapper for the Discogs.com API
I recently noticed that Discogs.com, a huge discographies database, had released their API in the public domain. I think this is a really nice offering, especially considering effective use of the Ebay API can cost in excess of $50,000 per year...
Unfortunately, I couldn't really think of anything useful to do with the information. So instead I've spent the last few weeks writing a 100% Ruby wrapper for version 1.0 of the API. It abstracts all of the tedious work of handling requests/responses, parsing the XML, etc. This way, if someone else has a good idea (or I have one in the future), most of the work will already be done!
Anyway, enough of that. The specifics:
Support
The library currently supports everything in version 1.0 of the API as documented (sort of) on the Discogs website. Namely:
- Artists
- Releases
- Labels
- Searching (all of the above
Installation
I've setup the library as a gem so installation is as easy as:
$ gem sources -a http://gems.github.com $ sudo gem install buntine-discogs
Usage
Here is a small taste of what you can do:
require 'rubygems'
require 'discogs'
wrapper = Discogs::Wrapper.new("my_api_key")
artist = wrapper.get_artist("Master's Hammer")
release = wrapper.get_release("611973") # Supply an ID.
artist.name # => Master's Hammer
artist.releases[0].title # => Finished
artist.releases[1].year # => 1989
artist.releases[4].extraartists # => [ "Arakain", "Debustrol" ]
release.title # => "Ritual"
release.labels[0].name # => "Osmose Productions"
release.formats[0].descriptions[0] # => "LP"
release.styles # => [ "Black Metal", "Death Metal" ]
release.tracklist[1].title # => "Pad modly"Finding out more
I have setup the repository at github. Please let me know of any bugs/problems you find. I'm open to suggestions for improvement, also. Fork me!
On the wiki at github, I have setup a bunch of examples and some documentation for each resource.
REST-mapping anchor elements in Merb
One of the things I liked about the REST implementation in Rails was the ability to use an anchor to fire off a HTTP "PUT" or "DELETE" request (or, rather the illusion of such) using the link_to helper method. It basically generates a chunk of inline JavaScript in the anchors onclick event that constructs a POST form, adds a few hidden elements, and finally submits it.
I noticed the functionality was not implemented in Merb. This is not totally surprising to me. I mean, inline JavaScript is never pretty. It also means we are relying on Javascript for the link to work correctly.
Regardless of my initial inhibitions, I decided to implement the functionality into a Merb application I was working on. The main chunk came down to this mixin to Merb::AssetsMixin:
module Merb
module AssetsMixin
alias_method :orig_link_to, :link_to
def link_to(name, url='', opts={})
if opts.include?(:method)
method = opts.delete(:method)
if [ :put, :delete ].include? method
opts[:onclick] = "var f = document.createElement('form'); f.style.display = 'none'; " +
"this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; " +
"var m = document.createElement('input'); m.setAttribute('type', 'hidden'); " +
"m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); " +
"f.appendChild(m);f.submit(); return false;"
else
raise ArgumentError, "The :method option only accepts :put or :delete."
end
end
orig_link_to name, url, opts
end
end
endIt mimicks Rails behaviour. Therefore, I call it like this:
link_to "Delete", url(:post, 1), :method => :delete # OR link_to "Save changes", url(:post, 1), :method => :put
I also wrote a bunch of specs and threw it up on GitHub. Eventually, I plan to set it (and the rest of my hacks) up as proper Merb plugins. If anyone wants to give me a hand, feel free to fork the project(s) and do your thing...
Multiple before/after model filters with Merb
This evening I found myself in a position in which I wanted to execute several "before" methods hooks/filters on a DataMapper model in a Merb application. I had a look around in the source and API docs, but couldn't really find a nice way of doing it (even though having every hook on a seperate line is not such a bad thing in terms of readability, I suppose).
Anyway, I came up with the following mixin for Extlib (which houses DataMapper's before/after hook functionality):
module Extlib
module Hook
module ClassMethods
alias_method :singular_before, :before
alias_method :singular_after, :after
def before(target_methods, filter_methods = nil, &block)
insert_multiple_hooks "before", target_methods, filter_methods, &block
end
def after(target_methods, filter_methods = nil, &block)
insert_multiple_hooks "after", target_methods, filter_methods, &block
end
private
def insert_multiple_hooks(context, target_methods, filter_methods, &block)
targets = [target_methods].flatten
filters = [filter_methods].flatten
targets.each do |target|
filters.each do |filter|
send("singular_#{context}", target.to_sym, filter.to_sym, &block)
end
end
end
end
end
end Hopefully it is fairly straight-forward. Basically, it will allow you to pass an array to the before and after methods. For example, you can do this:
before [ :create, :update ], [ :set_filename, :set_filesize, :generate_thumbnail ]
Which is equivalent to:
before :create, :set_filename before :create, :set_filesize before :create, :generate_thumbnail before :update, :set_filename before :update, :set_filesize before :update, :generate_thumbnail
I got it loaded into my Merb app by creating an app/lib directory and requireing the contents of it from the config/init.rb file.
Loading your Rails App independently
Yesterday I found myself in a position where some horrendously ugly code just became too much for me to handle. To cut a long story short, I needed to decouple a custom library from ActiveRecord. How did it get there in the first place, you ask? Please don't. It's a tragic story...
I set up an experimentation environment (in seperation from my working app), but of course, I needed to temporarily have full access to my models, controllers, etc, etc. Now, I use version control (who doesn't?) and I could have simply branched off and started hacking. But for shits-and-giggles, I decided not to.
I played around for a while and, as it turns out, it's very easy to load your application into an otherwise independent Ruby script. All you need is:
ENV['RAILS_ENV'] = 'development' require '/path/to/your/rails/app/config/environment'
Easy!
As a final note, it's worth pointing out that this is something that you should basically never need to do. If you simply want to automate something or perform an application-specific task, I highly recommend you write a raketask instead.
Hackers Hummus
I like to cook. I am shithouse at it.
With that said, I must mention that my recipe for easy Hummus (a Middle Eastern dip) is a fantastic addition to a late night hack-fest.
You will need the following:
- A Large handful of Garbanzo beans (chickpeas)
- Three tablespoons of Tahini (the sesame seed equivalent of peanut butter)
- Dash of Lemon Juice
- Two crushed garlic cloves
- Salt (must be Sicilian volcanic salt, or you will die instantly)
The salt is optional. I generally don't use it, but feel free.
The method is very straight-forward. So easy infact that I am going to write it in Ruby (assuming my ingredients hash already exists):
ingredients[:garlic].crush! bowl = Bowl.new bowl.add(ingredients) bowl.mash_contents_with(:potato_masher) if ingredients.has_key?(:salt) and ingredients[:salt] != "Sicilian Volcanic" puts "You have 4 seconds to live" end bowl.serve!
Yep, that's it. You just take all of the ingredients into a bowl and mash them up, slightly adding more of a particular ingredient until you have it just right.
Serve Hummus with dipping bread.