Skip to content

Instantly share code, notes, and snippets.

@jbr
Forked from nkallen/MODULARITY_OLYMPICS.markdown
Created February 16, 2010 06:55
Show Gist options
  • Save jbr/305362 to your computer and use it in GitHub Desktop.
Save jbr/305362 to your computer and use it in GitHub Desktop.
require 'onion'
Onion.new Stats, Memoizer, TimesOut do
config :stats => true, :timeout => 1_000
connection_pool :whatever
puts "Forward:"
transaction do
query "SELECT ... FROM ... FOR UPDATE ..."
execute "INSERT ..."
execute "INSERT ..."
end
reverse!
puts
puts "Backward:"
transaction do
query "(reverse) SELECT ... FROM ... FOR UPDATE ..."
execute "(reverse) INSERT ..."
execute "(reverse) INSERT ..."
end
end
Forward:
Instantiating Query Object
Selecting SELECT ... FROM ... FOR UPDATE ... on #<Query:0x18ae890>
Did not timeout! Yay fast database!
Measured select at 1.00018
Instantiating Query Object
Executing INSERT ... on #<Query:0x18ae37c>
Did not timeout! Yay fast database!
Measured execute at 1.000167
Executing INSERT ... on #<Query:0x18ae37c>
Did not timeout! Yay fast database!
Measured execute at 1.000085
Backward:
Instantiating Query Object
Selecting (reverse) SELECT ... FROM ... FOR UPDATE ... on #<Query:0x18ad968>
Measured select at 1.000178
Did not timeout! Yay fast database!
Instantiating Query Object
Executing (reverse) INSERT ... on #<Query:0x18ad454>
Measured execute at 1.000127
Did not timeout! Yay fast database!
Executing (reverse) INSERT ... on #<Query:0x18ad454>
Measured execute at 1.000081
Did not timeout! Yay fast database!
Forward:
Instantiating Query Object
Selecting SELECT ... FROM ... FOR UPDATE ... on #<Object:0x11f6750>
Did not timeout! Yay fast database!
Measured select at 1.00 seconds
Instantiating Query Object
Executing INSERT ... on #<Object:0x11f6750>
Did not timeout! Yay fast database!
Measured select at 1.00 seconds
Executing INSERT ... on #<Object:0x11f6750>
Did not timeout! Yay fast database!
Measured select at 1.00 seconds
Backward:
Instantiating Query Object
Selecting SELECT ... FROM ... FOR UPDATE ... on #<Object:0x11f4ea0>
Measured select at 1.00 seconds
Did not timeout! Yay fast database!
Instantiating Query Object
Executing INSERT ... on #<Object:0x11f4ea0>
Measured select at 1.00 seconds
Did not timeout! Yay fast database!
Executing INSERT ... on #<Object:0x11f4ea0>
Measured select at 1.00 seconds
Did not timeout! Yay fast database!
require 'wrappable_methods'
class Onion < Array #so simple it makes me cry
include WrappableMethods
def initialize(*classes_or_objects, &blk)
@config = {}
super classes_or_objects.map {|q| q.new self rescue q.new rescue q}
instance_eval &blk
end
#target (see WrappableMethods::ClassMethods, something is wrong with bindings)
# wrappable_method(:construct_query) do |query_string|
# Query.new(query_string, connection_pool)
# end
def construct_query(query_string)
build_proc(:construct_query) do
Query.new(query_string, connection_pool)
end.call query_string
end
def query(query_string)
build_proc(:query) do
construct_query(query_string).query
end.call query_string
end
def execute(query_string)
build_proc(:execute) do
construct_query(query_string).execute
end.call query_string
end
def transaction() yield end
def connection_pool(pool = nil)
@pool = pool || @pool
end
def config(hash = nil)
hash ? @config.merge!(hash) : @config
end
end
class Query
def initialize(query_string, connection_pool)
@query_string, @connection_pool = query_string, connection_pool
puts "Instantiating Query Object"
end
def execute
sleep 1
puts "Executing #{@query_string} on #{self}"
[1,2,3]
end
def query
sleep 1
puts "Selecting #{@query_string} on #{self}"
1
end
end
class Memoizer
def initialize
@memos = {}
end
def construct_query(query_string)
@memos[query_string] ||= yield query_string
end
end
class Stats
def initialize(onion) @config = onion.config end
def respond_to?(method) @config[:stats] and super end
def returning(value) yield(value); value end
def query(query_string)
time = Time.now
returning yield(query_string) do
puts "Measured select at #{Time.now - time}"
end
end
def execute(query_string)
time = Time.now
returning yield(query_string) do
puts "Measured execute at #{Time.now - time}"
end
end
end
class TimesOut
def initialize(onion) @config = onion.config end
def query(query_string)
yield(query_string)
puts 'Did not timeout! Yay fast database!'
end
alias_method :execute, :query
end
module WrappableMethods
def self.included(klass) klass.extend ClassMethods end
def build_proc(method, &innermost)
reverse.inject(innermost) do |inner, item|
if item.respond_to?(method)
lambda {|*args| item.send method, *args, &inner}
else
inner
end
end
end
module ClassMethods
def wrappable_method(method_name, &blk)
define_method method_name do |*args|
build_proc(method_name, &blk).call *args
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment