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 ConnectionPool.new(20)
puts "Forward:"
transaction do
query "SELECT ... FROM ... FOR UPDATE ..."
execute "INSERT ..."
execute "INSERT ..."
end
reverse!
puts "\nBackward:"
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:0x18ae8f4> (connection: #<Object:0x18aed7c>)
Did not timeout! Yay fast database!
Measured select at 1.000089
Instantiating Query Object
Executing INSERT ... on #<Query:0x18ae37c> (connection: #<Object:0x18aed7c>)
Did not timeout! Yay fast database!
Measured execute at 1.000109
Executing INSERT ... on #<Query:0x18ae37c> (connection: #<Object:0x18aed7c>)
Did not timeout! Yay fast database!
Measured execute at 1.000064
Backward:
Instantiating Query Object
Selecting (reverse) SELECT ... FROM ... FOR UPDATE ... on #<Query:0x18ad864> (connection: #<Object:0x18adcec>)
Measured select at 1.000085
Did not timeout! Yay fast database!
Instantiating Query Object
Executing (reverse) INSERT ... on #<Query:0x18ad300> (connection: #<Object:0x18adcec>)
Measured execute at 1.000108
Did not timeout! Yay fast database!
Executing (reverse) INSERT ... on #<Query:0x18ad300> (connection: #<Object:0x18adcec>)
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!
class Onion < Array
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
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
# def self.wrappable_method(method_name, &blk)
# define_method method_name do |*args|
# build_proc(method_name, &blk).call *args
# end
# 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, connection)
build_proc(:construct_query) do
Query.new query_string, connection
end.call query_string, connection
end
def query(query_string, connection)
build_proc(:query) do
construct_query(query_string, connection).query
end.call query_string
end
def execute(query_string, connection)
build_proc(:execute) do
construct_query(query_string, connection).execute
end.call query_string
end
def transaction(&blk)
ConnectionContext.new self, connection_pool, &blk
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)
@query_string, @connection = query_string, connection
puts "Instantiating Query Object"
end
def execute
sleep 1
puts "Executing #{@query_string} on #{self}"
[1,2,3]
end
def to_s() super + " (connection: #{@connection})" 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, connection)
@memos[query_string] ||= yield query_string, connection
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
class ConnectionPool
def initialize(num) end
def allocate_connection() Object.new end
end
class ConnectionContext
def initialize(callee, connection_pool, &blk)
@callee = callee
@connection = connection_pool.allocate_connection
instance_eval &blk
end
def query(string) @callee.query(string, @connection) end
def execute(string) @callee.execute(string, @connection) end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment