Frivol Ruby on Beer talk, Sept 2010
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
827
On Slideshare
827
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
4
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Frivol - Frivolously simple temporary storage backed by Redis
    • Marc Heiligers (@marcheiligers)
  • 7. Why Frivol?
    • Why the name?
      • Every technology needs a cool name
      • 8. I searched Thesaurus.com
      • 9. Antonym of save or put aside , actually
    • Why the technology?
      • Already had Resque
      • 10. Uses Redis which is fast and persistent
      • 11. Allows expiry of aging data
      • 12. Great for caching
  • 13. Usage
    • Intended to be used with ActiveRecord
    • 14. Set Frivol::Config.redis_config= in environment.rb
    • 15. include Frivol or Frivol::Config.include_in
    • 16. Simply use store and retrieve methods
    • 17. Stored keys are merged, not overwritten
    • 18. expire_storage and delete_storage
    • 19. Override storage_key if not using ActiveRecord
  • 20. Usage – Example from Mad Mimi # environment.rb # Each environment has a REDIS_CONFIG, eg. development.rb: # REDIS_CONFIG = { :host => &quot;localhost&quot;, :port => 6379 } Frivol::Config.redis_config = REDIS_CONFIG # Frivol could be included in all AR models using: # Frivol::Config.include_in ActiveRecord::Base, 10.minutes # audience_list.rb class AudienceList < ActiveRecord::Base include Frivol storage_expires_in 1.day has_many :memberships, :dependent => :destroy has_many :audience_members, :through => :memberships # ... def list_size retrieve :list_size => :force_list_size_update end def force_list_size_update new_size = audience_members.size store :list_size => new_size new_size end # ... end
  • 21. Implementation
    • Frivol is a Module which is included
    • 22. Uses Module#included (class methods)
    • 23. Has helper methods separated (privacy)
      • instance_variable_defined? , instance_variable_get and instance_variable_set
    • Config module creates @@redis when given a Redis configuration (lifetime)
    • 24. Resolves symbols vs strings for keys
    • 25. Json storage (network latency)
  • 26. Implementation – Config & Included module Config def self.redis_config=(config) @@redis = Redis.new(config) end def self.redis @@redis end def self.include_in(host_class, storage_expires_in = nil) host_class.send(:include, Frivol) host_class.storage_expires_in storage_expires_in if storage_expires_in end end module ClassMethods def storage_expires_in(time) @frivol_storage_expiry = time end def storage_expiry @frivol_storage_expiry end end def self.included(host) host.extend(ClassMethods) end
  • 27. Implementation - Helpers module Helpers def self.store_hash(instance) hash = instance.instance_variable_get(:@frivol_hash) is_new = instance.instance_variable_get(:@frivol_is_new) key = instance.send(:storage_key) Frivol::Config.redis[key] = hash.to_json if is_new instance.expire_storage instance.class.storage_expiry instance.instance_variable_set :@frivol_is_new, false end end def self.retrieve_hash(instance) return instance.instance_variable_get(:@frivol_hash) => if instance.instance_variable_defined? :@frivol_hash key = instance.send(:storage_key) json = Frivol::Config.redis[key] instance.instance_variable_set :@frivol_is_new, json.nil? hash = json.nil? ? {} : JSON.parse(json) instance.instance_variable_set :@frivol_hash, hash hash end def self.delete_hash(instance) key = instance.send(:storage_key) Frivol::Config.redis.del key instance.instance_variable_set :@frivol_hash, {} end end
  • 28. Implementation – Instance Methods def store(keys_and_values) Frivol::Helpers.retrieve_hash self keys_and_values.each do |key, value| @frivol_hash[key.to_s] = value end Frivol::Helpers.store_hash self end def retrieve(keys_and_defaults) Frivol::Helpers.retrieve_hash self result = keys_and_defaults.map do |key, default| @frivol_hash[ key.to_s ] || ( default.is_a?(Symbol) && respond_to?(default) && => send(default) ) || default end return result.first if result.size == 1 result end def delete_storage Frivol::Helpers.delete_hash self end def expire_storage(time) return if time.nil? Frivol::Config.redis.expire storage_key, time end def storage_key @frivol_key ||= &quot;#{self.class.name}-#{id}&quot; end
  • 29. Problems
    • Ruby 1.8 hash key order not guaranteed
      • Problem destructuring assignment although that was the goal
    • Single ”bucket” of storage
      • All data for a class lumped together
      • 30. Single expiry time
    • Not thread safe
      • Not a concern in goal use case
  • 31. Future Development
    • Class methods for setting defaults
    • 32. retrieve with a splat, instead of hash
    • 33. Named storage buckets with own expiry
      • Use method_missing to retrieve and store buckets
      • 34. Or class methods to define buckets and defaults
    • retrieve_hash method because Chris wants one
    • 35. retrieve_default method to override class set default
  • 36. Lessons Learnt
    • You need good people to bounce your ideas off of and to pick apart your assumptions
    • 37. You only really discover problems when you start using something in a real project
      • When you write your first tests you will write them to test the way you expect your software to be used
      • 38. Your first user will find a bug almost immediately
    • Simple solutions are best and can often solve complex problems without becoming complex themselves
    • 39. OpenOffice is pretty aweful for creating presentations (but it works)
  • 40. Frivol - Frivolously simple temporary storage backed by Redis
    • Github
      • http://github.com/marcheiligers/frivol
    • RubyGems
      • http://rubygems.org/gems/frivol
    • Mentioned on Ruby5
      • http://ruby5.envylabs.com/episodes/108-episode-106-august-27-2010