Best Practices: Sessions
I've been writing rails apps for a few months now. The most painful lesson I've learned is to be careful how you use sessions…. If you don't handle your sessions properly you will become a very frustrated developer. Trust me
Here are a few best practices I've observed with regards to sessions:
1) keep them small. Sessions get reloaded from database (or file) for every single hit on the application. Don't put hundreds of objects in a session or you're going to slow things way down. Rethink your design if you start seeing a need to have more than a few objects in a session.
2) put only "primitive" types in sessions. I know Ruby doesn't have primitive types, but you know what I mean – Integers, Strings, Floats. So instead of putting a "User" model in the session, put the "user id" in the session and when you need the model do this instead: user = User.find(session[:user_id]). If you do this you won't have to worry about having serialization/deserialization issues every time you roll out new code. If you put models in your sessions, you not only have the overhead of the database hit to reload these models for every hit, but you have to deserialize the models to instantiate them. If the object schema of the model changes the application won't (probably) be able to re-instantiate these models and your user will be left with an error message. If you need to store models in the session for some reason, make sure you wipe all your sessions as part of your deployment process.
3) For development have a script to delete your sessions (I use file sessions for dev). When your dev environment starts acting strangely, just run the script and clean them up. It may not solve your problem, but at least it eliminates session funkiness as the cause. This is much more important if you put models in your sessiosns.
4) Schedule a batch process to expire your sessions. You want to "expire" sessions at some point (there will be a performance hit if the sessions table gets to big). Here's our rake task for cleaning the sessions table:
desc "Delete row from the session table that have not been updated in ENV['DAYS_OLD'] days, default is 1.
Set RAILS_ENV on command line to hit correct database."
task :clean_session_table => :environment do
days_ago = ENV['DAYS_OLD'] || 1
remove_if_older_than = Date.today – days_ago.to_i
old_sessions = CGI::Session::ActiveRecordStore::Session.find(:all, :conditions => ['updated_at <= ?', remove_if_older_than],
rder => 'updated_at' )
puts "Removing #{old_sessions.length } sessions that are older than #{remove_if_older_than} from the #{ENV['RAILS_ENV']} database" unless ENV['SILENT']
old_sessions.each{|old_session|
puts "Destroying old session from #{old_session.updated_at} #{old_session.destroy ? '– Sucess' : '– Failure'}" unless ENV['SILENT']
}
end
That's it for today…
phil
Posted by ciruby
Posted by twolters