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, :pool_size => 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:0x18aa010> (connection: #<Object:0x18aa4c0>)
Did not timeout! Yay fast database!
Measured select at 1.000166
Instantiating Query Object
Executing INSERT ... on #<Query:0x18a9a70> (connection: #<Object:0x18aa4c0>)
Did not timeout! Yay fast database!
Measured execute at 1.000148
Executing INSERT ... on #<Query:0x18a9a70> (connection: #<Object:0x18aa4c0>)
Did not timeout! Yay fast database!
Measured execute at 1.000085
Backward:
Instantiating Query Object
Selecting (reverse) SELECT ... FROM ... FOR UPDATE ... on #<Query:0x18a8f1c> (connection: #<Object:0x18a93cc>)
Measured select at 1.000116
Did not timeout! Yay fast database!
Instantiating Query Object
Executing (reverse) INSERT ... on #<Query:0x18a8990> (connection: #<Object:0x18a93cc>)
Measured execute at 1.00013
Did not timeout! Yay fast database!
Executing (reverse) INSERT ... on #<Query:0x18a8990> (connection: #<Object:0x18a93cc>)
Measured execute at 1.000094
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 wrap(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 construct_query(query_string, connection)
wrap :construct_query do
Query.new query_string, connection
end.call query_string, connection
end
def query(query_string, connection)
wrap :query do
construct_query(query_string, connection).query
end.call query_string
end
def execute(query_string, connection)
wrap :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 ||= ConnectionPool.new config[:pool_size]
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[[connection, 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