Moving to geekin.gs
I'm moving my blog under a new domain http://geekin.gs
If you've subscribed the RSS feed please do subscribe the new site feed.
Thanks
Paolo
I'm moving my blog under a new domain http://geekin.gs
If you've subscribed the RSS feed please do subscribe the new site feed.
Thanks
Paolo
Posted by
hungryblank
at
12:29
0
comments
I wanted to play with CouchDB 0.9.0 on Ubuntu Jaunty, and to do this I had to compile it from sources, and to be in sync with CouchDBX I compiled as well erlang 13B.
This is the transcript of what I did.
sudo apt-get install build-essential m4 libssl-dev libncurses-dev
wget http://erlang.org/download/otp_src_R13B.tar.gz
tar zxf otp_src_R13B.tar.gz
cd otp_src_R13B
./configure
make
sudo make install
sudo apt-get install libcurl4-openssl-dev libicu-dev libmozjs-dev
wget http://apache.mirroring.de/couchdb/0.9.0/apache-couchdb-0.9.0.tar.gz
tar zxf apache-couchdb-0.9.0.tar.gz
cd apache-couchdb-0.9.0
./configure --sharedstatedir=/var/local --localstatedir=/var/local
make
sudo make install
sudo useradd -d /var/local/lib/couchdb couchdb
sudo chown couchdb. /var/local/lib/couchdb
sudo chmod 750 /var/local/lib/couchdb
[log]
file = /var/log/couchdb/couch.log
COUCHDB_USER=couchdb
COUCHDB_STDOUT_FILE=/dev/null
COUCHDB_STDERR_FILE=/dev/null
COUCHDB_PID_FILE=/var/run/couchdb.pid
COUCHDB_RESPAWN_TIMEOUT=5
COUCHDB_OPTIONS=
sudo cp -v /usr/local/etc/init.d/couchdb /etc/init.d/couchdb
if test -n "$COUCHDB_PID_FILE"; then
command="$command -p $COUCHDB_PID_FILE"
fi
if test -n "$COUCHDB_PID_FILE"; then
touch $COUCHDB_PID_FILE
chown $COUCHDB_USER. $COUCHDB_PID_FILE
command="$command -p $COUCHDB_PID_FILE"
fi
command="$COUCHDB -d"
command="$COUCHDB -d"
if test -n "$COUCHDB_PID_FILE"; then
command="$command -p $COUCHDB_PID_FILE"
fi
sudo mkdir /var/log/couchdb
sudo chown couchdb. /var/log/couchdb
/var/log/couchdb/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 couchdb adm
sharedscripts
postrotate
[ ! -f /var/run/couchdb.pid ] || kill -USR1 `cat /var/run/couchdb.pid`
endscript
}
/etc/init.d/couchdb start
curl 127.0.0.1:5984
curl 127.0.0.1:5984/test
curl -X PUT 127.0.0.1:5984/test
curl 127.0.0.1:5984/test
curl 127.0.0.1:5984/test/baz
curl -X PUT -d '{"foo":"bar"}' 127.0.0.1:5984/test/baz
curl 127.0.0.1:5984/test/baz
Posted by
hungryblank
at
02:52
2
comments
Labels: erlang couchdb ubuntu jaunty
Among the Amazon Web Services or AWS if you prefer acronyms, SimpleDB is one of the less popular.
I've been using this service it for a while in some personal projects using the aws-sdb, so far the only choice to deal with SimpleDB at a low level.
Since I wanted to overcome some of the limits of aws-sdb I wrote a new gem aws_sdb_bare.
Main feature of the gem are:
* Complete implementation of SimpleDB api
* XML parsing uses Hpricot or Nokogiri
And be free of chosing your HTTP connection library and strategy!
You can use Net::HTTP or curb or go concurrent using eventmachine or typhoeus to manage your connections with sdb
So just install it
sudo gem install hungryblank-aws_sdb_bare -s http://gems.github.com
RailsConf 2009 finished few days ago and after a long trip back and some time to chill out I was going through the material of the conference and trying to connect some dots among the different topics which were covered.
To give some background, I started my career as sysadmin (or linux geek, if you prefer) and because of that I like when custom software, whether it's a rails app or just a small script is seen in the context of an entire stack or as glue among heterogeneous systems.
Well, this year's RailsConf made me happy including quite a few talks which had this kind of point of view, I'll list them here for my and other's reference.
The Gilt Effect: Handling 1000 Shopping Cart Updates per second in Rails
This presentation was brilliant, the guys at Gilt have a very interesting business model which translates in a really interesting technological challenge.
They use a solutions which combines ruby, rails, java and postgres to manage extreme peaks of traffic, as a note they measure their peak traffic in fractions of the amazon.com ecommerce website traffic!
Since they run time limited sales they leverage very well the EC2 pay per use scheme reducing to the minimum the size of their cluster in quiet periods and expanding it when the sale is on and customer really fights to get hold of the items Gilt offers.
It was the same time I've seen the cloud architecture leveraged in a completely spike driven business.
It's a shame that the slides of thi presentation aren't available yet.
PWN Your Infrastructure: Behind Call of Duty: World at War
These guys run several communities dedicated to popular games, they've been successful and they had to manage to scale their apps, they deploy a single app on multiple servers and they tried some different deployment and monitoring tools, and what they've found out is... the simpler tools are the best for the job they use shell scripting when shell scripting is enough, they deploy with chef to manage their deployment process and monit monit for monitoring. They developed an internal app to keep all the configuration together and aggregate monitoring infos.
I really enjoyed the "use the simpler tool for the job" philosophy they embraced, very hard core linux geek stuff. By the way the only piece of architecture they're looking to change is nfs, used to keep in sync their ruby/rubygems stack across machines.
Slides are on the railscon website
Building a Mini-Google: High-Performance Computing in Ruby Interesting talk very CS oriented, the speaker went through the publicly available docs for google page rank algorithm and in the presentations shows the theory behind it and the ruby code to actually implement it, very high quality content for a 45 mins talk.
Slides are on the railscon website
Confessions of a PackRat
I've lost this one, can't find the slides on line.
Rube Goldberg Contraptions, Building Scalable Decoupled Web Apps and Infrastructure with Ruby Really interesting talk, presenting a bunch of interesting technologies and solutions at once: deployment with chef, computer cloud coordination and administration with nanite demoed live controlling all the notebooks in the room. Presentation on slideshare but go and check out nanite on github now!
Art of the Ruby Proxy for Scale, Performance, and Monitoring
Missed this one, but slides are available on the railsconf website and some excerpt can be found on the speaker's blog. Learn how to put small ruby proxies in front of your services to achieve better performances, adding load balancing, filtering and other really neat tricks using just ruby, EventMachine and other bits.
It's Not Always Sunny In the Clouds: Lessons Learned
Interesting talk about the problems of deploying your app on AWS infrastructure, really practical tips and tricks to run your app in the cloud, slides on
railsconf website
%w(map reduce).first - A Tale About Rabbits, Latency, and Slim Crontabs Ok this was my talk so I'll skip any comment slides are on slideshare.
This is the end of this post railsconf wrap up, I hope it's been interesting and please leave comment if you find around the missing slides
Posted by
hungryblank
at
02:08
0
comments
Lately I spent some time using eventmachine, my main interest so far has been in the deferrables and in writing clients to consume web services using them.
In the process I ended up writing event_utils a gem that makes (or at least should) more intuitive to write clients based on eventmachine deferrables.
Now let's start working at an example, first things first we need a web service to consume, our choice for this tutorial will be a dummy service named slowrand.
If you hit the url http://slowrand.elastastic.com/?delay=1 you'll be served a random number between 0 and 9, the random number will be served after a delay of at least one second.
So now that we have a web service to use, let's write a class that wraps the service.
Save the following as slow_rand.rb
class SlowRand
attr_accessor :value
include EM::Deferrable
def initialize(delay = 1)
client = EM::Protocols::HttpClient.request(
:host => "slowrand.elastastic.com",
:query_string => "delay=#{delay}")
@value = nil
client.callback do |response|
self.value = response[:content].to_i
puts "fetched value #{value} at #{Time.now}"
self.succeed
end
client.errback { self.fail }
end
def +(other)
self.value + other.value
end
def to_s
value.to_s
end
end
require 'rubygems'
require 'event_utils'
require 'slow_rand'
include EventUtils
in_deferred_loop do
puts "started at #{Time.now}"
a, b = SlowRand.new, SlowRand.new
waiting_for(a, b) do
sum = a + b
puts "sum executed at #{Time.now}, #{a} + #{b} = #{sum}"
end
end
sudo gem install eventmachine
sudo gem install hungryblank-event_utils -s http://gems.github.com
ruby client.rb
started at Mon Mar 16 21:53:13 +0000 2009
fetched value 1 at Mon Mar 16 21:53:14 +0000 2009
fetched value 6 at Mon Mar 16 21:53:14 +0000 2009
sum executed at Mon Mar 16 21:53:14 +0000 2009, 1 + 6 = 7
require 'rubygems'
require 'event_utils'
require 'slow_rand'
include EventUtils
in_deferred_loop do
puts "started at #{Time.now}"
a, b = SlowRand.new(3), SlowRand.new(3)
c, d = SlowRand.new(2), SlowRand.new(2)
e, f = SlowRand.new, SlowRand.new
waiting_for(a, b) do
sum = a + b
puts "== sum with delay 3 =="
puts "sum executed at #{Time.now}, #{a} + #{b} = #{sum}"
end
waiting_for(c, d) do
puts "== sum with delay 2 =="
sum = c + d
puts "sum executed at #{Time.now}, #{c} + #{d} = #{sum}"
end
waiting_for(e, f) do
puts "== sum with delay 1 =="
sum = e + f
puts "sum executed at #{Time.now}, #{e} + #{f} = #{sum}"
end
end
ruby client_multi.rb
started at Mon Mar 16 21:57:48 +0000 2009
fetched value 0 at Mon Mar 16 21:57:50 +0000 2009
fetched value 2 at Mon Mar 16 21:57:50 +0000 2009
== sum with delay 1 ==
sum executed at Mon Mar 16 21:57:50 +0000 2009, 0 + 2 = 2
fetched value 8 at Mon Mar 16 21:57:51 +0000 2009
fetched value 6 at Mon Mar 16 21:57:51 +0000 2009
== sum with delay 2 ==
sum executed at Mon Mar 16 21:57:51 +0000 2009, 8 + 6 = 14
fetched value 8 at Mon Mar 16 21:57:52 +0000 2009
fetched value 8 at Mon Mar 16 21:57:52 +0000 2009
== sum with delay 3 ==
sum executed at Mon Mar 16 21:57:52 +0000 2009, 8 + 8 = 16
Posted by
hungryblank
at
14:57
2
comments
Labels: client, event_utils, eventmachine, ruby, web services
The information in this post is outdated, if you want a better complete overview of the SimpleDB ruby libraries you should read this article
Out there you can already find more than one project that lets you access Amazon SimpleDB using ruby.
Since I wasn't really happy with any of them I started building my solution on top of aws-sdb.
Being really bad at naming projects I named my gem dead_simple_db.
To install the gem just type in your console
sudo gem install hungryblank-dead_simple_db -s http://gems.github.com
require 'rubygems'
require 'dead_simple_db'
#you need your Amazon AWS credentials defined in the environment
ENV['AMAZON_ACCESS_KEY_ID'] = 'your access key'
ENV['AMAZON_SECRET_ACCESS_KEY'] = 'your secret access key'
#Let's define a class that will use SimpleDb backend to store the instances
class Client < DeadSimpleDb::Base
#Let's define the SimpleDb domain where the class will be stored
domain 'test_domain'
#Add the definitions of the attributes we need to store
attr_sdb :first_name, 'String'
attr_sdb :last_name, 'String'
attr_sdb :budget, 'Integer', :digits => 9
attr_sdb :first_purchase, 'Time'
end
#and now is time to create the first object
c = Client.new
c.first_name = "Henry"
c.last_name = "Chinaski"
c.budget = 1000
c.first_purchase = Time.now
# that's how you save your first record on Amazon SimpleDB
c.save
# and that's how you fetch it
henry = Client.find(:first, "['first_name' = 'Henry']")
puts henry.first_name
henry.first_purchase
Ok, you were quite proud when on Rails 1.2.x you made your app restful.
Now in 2.0 REST has been improved cleaned reworked and... changed the naming of the nested Routes
Let's take a look at the differences in 1.2.x
the following code
map.resources :dinners do |dinner|
dinner.resources :dishes do |dish|
dish.resources :side_courses
end
dinner.resources :drinks
end
dinners_url
dinner_url
dishes_url
dish_url
side_courses_url
side_course_url
drinks_url
drink_url
dinners_url
dinner_url
dinner_dishes_url
dinner_dish_url
dinner_dish_side_courses_url
dinner_dish_side_course_url
dinner_drinks_url
dinner_drink_url
require 'route_migrator'
RouteMigrator.dump_current_route_methods
"side_courses_url" => "side_courses_url"
"side_courses_url" => "dinner_dish_side_courses_url"
rake routes
require 'route_migrator'
RouteMigrator.dump_named_routes
require 'route_migrator'
RouteMigrator.check_new_routes
require 'route_migrator'
RouteMigrator.upgrade_route_methods!
Posted by
hungryblank
at
03:09
6
comments
Yesterday was announced RMagick2.0.0 beta1 release.
Among others new features I've found interesting the "new methods to help control and monitor memory usage" I'm looking forward to playing with them when I'll be back from my holiday in late august.
RMagick has been quite often considered prone to memory leaks, but it seems that memory leaks are not the actual cause of the high memory consumption of RMagick it will be interesting to see what is now available to keep under control the memory used by this amazing library.
Posted by
hungryblank
at
02:01
0
comments
Labels: rmagick, ruby, rubyonrails

Since yesterday google analytics seems to be experiencing problems.
Some login problems were experienced and a delay in the processing was announced.
Now in the dashboard I can see funny things like the image above (47 visits and no pageviews, quite a mistery). In the specific case the correct data should be 0 visits since I know yesterday there was no activity on that specific regexp-filtered profile.
Statistics for july the 25th have stopped at 17 GMT for me.
sh*t happens, at google too.
-- update 30 july
Today for some accounts google analytics data are delayed again.
In my case data last update is 6.00 AM GMT july 29 so at the moment the delay is more than one day.
Posted by
hungryblank
at
04:36
0
comments
Labels: google analytics
A little annoyance I've found using ruby on rails is the following:
If in your model you have some strings that can be null, and the user doesn't fill the related fields in the web form, rails will end up storing an empty string "" instead of the good old NULL in the database.
Now, this is for sure not a big problem but it has some implications that might affect the model validations and it can be even worse if the rails app is not the only program writing in the database, in this last case you easily end up with a mix of empty string and NULL values in the column making trickier to write queries conditions that involve that column.
Now I was playing today to fix this problem and I came with a solution that uses SimpleDescriptor.
For any model that uses SimpleDescriptor as described in this post the following is a way to have NULL saved in the database instead of the empty string ''
first you need to define the clean_strings method
def clean_strings
self.class.described_as(:string).each do { |field| send("#{field}=", nil) if send(field) == '' }
end
before_validation :clean_strings
Posted by
hungryblank
at
15:23
2
comments
Labels: activerecord, rubyonrails, simple_descriptor
After 6 month I've released a new version of Simple Descriptor.
This gem makes possible to attach some extra informations to a generic ruby class, but its mission is now includes specific methods to allow more control and flexibility on ActiveRecord validations, in addition to this, Simple Descriptor may help you in building a consistent approach in areas where rails doesn't.
Let's start getting our hands dirty, first of all install the gem
sudo gem install simple_descriptor
require 'simple_descriptor'
class CreateEmployees < ActiveRecord::Migration
def self.up
create_table :employees do |t|
t.column :first_name, :string, :limit => 30, :null => false
t.column :middle_name, :string, :limit => 10, :null => true
t.column :last_name, :string, :limit => 30, :null => false
t.column :gross_wage, :integer, :null => false
t.column :personal_email, :string, :limit => 100, :null => false
end
end
def self.down
drop_table :employees
end
class Employee < ActiveRecord::Base
end
class Employee < ActiveRecord::Base
extend SimpleDescriptor::ClassDescriptor
validates_ar_descriptions
end
Employee.described_as :string
Employee.maxlegth(:first_name)
Employee.described_as :required
=> [:first_name, :gross_wage, :last_name, :personal_email]
Employee.describes? :first_name as => :required
=> true
Employee.descriptions
class Employee < ActiveRecord::Base
extend SimpleDescriptor::ClassDescriptor
validates_ar_descriptions
describe :gross_wage as => :sensible
end
Employee.describes? :gross_wage, :as => :sensible
=> true
Employee.describes? :first_name, :as => :sensible
=> false
Employee.described_as :sensible
=> [:gross_wage]
Posted by
hungryblank
at
11:06
0
comments
Labels: activerecord, rubyonrails, simple_descriptor
ActiveRecord is an important slice of the joy included in Ruby on Rails, writing a SQL database driven application without actually writing any SQL is really pleasurable.
But sometime, even in the joy you get some pain.
The pain for me arrived when I was working on some reporting feature that was pulling various data across a quite long chain of has_many relationships.
I experienced a quite high load in the DB at the moment of the query and after that seconds of CPU full load eaten by my ruby process.
I checked what was going on in my log/development.log and I noticed the query was extracting all the columns of every table even if I specified a :select option, this turned a query originally quite light into a heavy one.
I googled a bit and I found out that with ActiveRecord, if you specify :select and :include option you don't get anymore 100% joy but just 50%, your :select statement will be ignored.
Today I'm trying to put back some percent of the joy.
select_with_include gem is meant to move the joy level up to 80% (no, not 100% yet)
select_with_include will allow you to specify a limited :select statement like
"table1.column1, table1.column3, table2.column2"
"table1.*, table2.column3, table2.column4, talbe3.*"
sudo gem install select_with_include
require 'select_with_include'
tail -f log/development.log
Posted by
hungryblank
at
15:03
7
comments
Labels: activerecord, rubyonrails, select_with_include
I'm using attachment_fu on the project I'm currently working on, using it to process the images the users upload.
As backend I use Rmagick, since it was already used in the same app. At some point I felt curious about the size in kb of the thumbnails generated, to estimate the increase of bandwidth the new feature would add on the server.
I quickly spotted the size of the generated jpegs was unreasonable for the pixel size of them.
It turned out that attachment_fu + Rmagick on Ubuntu 6.0.6 and Ruby 1.4 aren't compressing jpegs.
To fix here's a one line patch on attachment_fu.
this patch sets the jpeg quality to 85%
[~]$ cat atch_fu/attachment_fu_rmagick_compression.patch
Index: lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
===================================================================
--- lib/technoweenie/attachment_fu/processors/rmagick_processor.rb (revision 2864)
+++ lib/technoweenie/attachment_fu/processors/rmagick_processor.rb (working copy)
@@ -45,9 +45,9 @@
else
img.change_geometry(size.to_s) { |cols, rows, image| image.resize!(cols, rows) }
end
- self.temp_path = write_to_temp_file(img.to_blob)
+ self.temp_path = write_to_temp_file(img.to_blob {self.quality = 85})
end
end
end
end
-end
\ No newline at end of file
+end
Posted by
hungryblank
at
02:44
0
comments
Labels: attachment_fu, rmagick, rubyonrails