-
-
Save rociiu/305187 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I want to turn this into a programming contest. Everyone should do this using their favorite technique and language. But, I want to add three more challenges (that admittedly stack the deck in my favor). | |
1. create a stats collecting query decorate that measures the time it takes to execute the query | |
(assume you have a stats object that responds to #measure and takes a block: stats.measure { sleep 1.second } | |
2. read "configuration" from a hash like: | |
{ :timeout => 1.second, :stats => true } | |
that adds the timeout and stats decorators to the factory if present in the hash, otherwise not. | |
3. at the end write a program that REVERSES the order of the decorators. So if you did Timeout(Stats(Query)) make it Stats(Timeout(Query)). Note that you must do this programmatically so write a generic decorator reversing function. You may expand the proxy interface to have a method called "underlying", "delegate" or some such. | |
The contest is: do this in your language in as "elegant" a way as you like. The goal is clarity and modularity. | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
query_factory = MemoizingQueryFactory.new(TimingOutQueryFactory.new(Query, 1.second)) | |
query_evaluator = QueryEvaluator.new(ConnectionPool.new(20), query_factory) | |
query_evaluator.transaction do |t| | |
t.select("SELECT ... FOR UPDATE FROM ...") | |
t.execute("INSERT ...") | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MemoizingQueryFactory | |
def initialize(query_factory) | |
@memo = Hash.new do |h, k| | |
h = query_factory.new(*k) | |
end | |
end | |
def new(connection, query_string, *args) | |
@memo[[connection, query_string, args]] | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class QueryEvaluator | |
def initialize(connection_pool, query_factory = Query) | |
@query_factory = query_factory | |
@connection_pool = connection_pool | |
end | |
def select(query_string, *args) | |
@connection_pool.with_connection do |connection| | |
@query_factory.new(connection, query_string, *args).select | |
end | |
end | |
def execute(query_string, *args) | |
@connection_pool.with_connection do |connection| | |
@query_factory.new(connection, query_string, *args).execute | |
end | |
end | |
def transaction | |
@connection_pool.with_connection do |connection| | |
yield TransactionalQueryEvaluator.new(connection, @query_factory) | |
end | |
end | |
end | |
class TransactionalQueryEvaluator | |
def initialize(connection, query_factory) | |
@connection = connection | |
@query_factory = query_factory | |
end | |
def select(query_string, *args) | |
@query_factory.new(@connection, query_string, *args).select | |
end | |
def execute(query_string, *args) | |
@query_factory.new(@connection, query_string, *args).select | |
end | |
def transaction | |
yield self | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TimingOutQueryProxyFactory | |
def initialize(query_factory, timeout) | |
@query_factory = query_factory | |
@timeout = timeout | |
end | |
def new(connection, query_string, *args) | |
@query_factory.new(connection, query_string, *args) | |
end | |
end | |
class TimingOutQueryProxy | |
def initialize(query, timeout) | |
@query = query | |
@timeout = timeout | |
end | |
def select | |
Timeout.timeout(@timeout) do | |
@query.select | |
end | |
end | |
# ... | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment