Skip to content

Instantly share code, notes, and snippets.

@myronmarston
Created February 24, 2012 19:07
Show Gist options
  • Select an option

  • Save myronmarston/1903020 to your computer and use it in GitHub Desktop.

Select an option

Save myronmarston/1903020 to your computer and use it in GitHub Desktop.
require 'sequel'
require 'delegate'
module DB
extend self
class NoCurrentShardError < StandardError; end
class Shard < ::Delegator
Spec = Struct.new(:host, :database) do
def connection_string
"mysql2://root@#{host}:3306/#{database}"
end
end
def spec=(spec)
Thread.current[:db_shard_spec] = spec
Thread.current[:db_shard] = nil
end
def spec
Thread.current[:db_shard_spec]
end
def __getobj__
Thread.current[:db_shard] ||= new_connection
end
# Ensure #send is proxied to the Sequel DB instance
undef send
private
def initialize
super(nil)
end
def new_connection
spec = Thread.current[:db_shard_spec]
raise NoCurrentShardError unless spec
::Sequel.connect(spec.connection_string)
end
def __setobj__(obj)
# no-op
end
end
def shard
@shard ||= Shard.new
end
def use_shard(*args)
orig_shard_spec = shard.spec
shard.spec = Shard::Spec.new(*args)
begin
yield
ensure
shard.spec = orig_shard_spec
end
end
end
# use the current sharded DB for our models by default
Sequel::Model.db = DB.shard
require 'sinatra'
class Widget < Sequel::Model
end
get '/:user_id/widgets' do
host, database = ShardMaster.host_and_db_for(params[:user_id])
DB.use_shard(host, database) do
Widget.all.to_json
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment