如何设置与Sinatra,Sequel和Rack的基于会话的数据库连接
我在Puma/Rack服务器中使用了Sinatra的Sequel。如何设置与Sinatra,Sequel和Rack的基于会话的数据库连接
我希望将会话的续集数据库连接对象(不是全局的)存储起来,这样我就可以为每个登录用户拥有单独的数据库连接池。目的是为每个Web服务器登录都有一个数据库服务器登录。
因为Sequel数据库对象似乎是全局单例,所以我无法解决这个问题。例如,如果我尝试序列化数据库对象并将其存储在会话中,我将收到一条错误消息:TypeError - can't dump anonymous class:
我不想在每个路由请求上连接到数据库。
我该怎么做?以下是一些示例代码,希望可以指示我正在尝试实现的内容:
require 'sinatra/base'
require 'pp'
require 'sequel'
require 'json'
require 'java'
require 'sqljdbc4.jar'
require 'yaml'
class MyApp < Sinatra::Base
set :sessions, true
use Rack::Session::Cookie, :key => 'rack.session',
:expire_after => 2592000,
:secret => 'sydasx'
get '/' do
db = session[:db]
DB = YAML::Load(db)
response = ''
DB['select * from SEC_USER'].each do |row|
response += row.to_s
end
response.to_json
end
get '/login/:username' do
username = params['username']
puts "username: #{username}"
conn_str = "jdbc:sqlserver://localhost:1434;databaseName=#{username};integratedSecurity=true;"
DB = Sequel.connect(conn_str)
puts "DB: #{DB.pretty_inspect}"
db = YAML::dump(DB)
puts "db: #{db}"
session[:db] = db
"logged in"
end
end
您无法序列化Sequel :: Database对象。你有几个像样的选择:
使用创建每个请求的续集::数据库对象,使用该对象仅适用于要求机架中间件。在这种情况下,您不会将Sequel.connect的结果分配给常量,您可以传递一个块并调用该块内的下一个变量。
在顶层创建一个Sequel :: Database对象,并将其存储在数据库常量中。 Sequel :: Database对象中的arbitrary_servers和server_block扩展。然后使用机架中间件,在该块的持续时间内检查到适当服务器的连接。
如果您的客户很少,可以仅使用Sequel的分片支持,并且只使用server_block扩展名而不使用任意服务器。这样做的一个好处是可以缓存连接,因此您不会为每个请求创建单独的数据库连接(对于1.和2.而言都是如此)。
正如您所提到的那样使用全局散列,其中的键是用户名和值为Sequel :: Database对象。如果你这样做,你需要确保你有足够的内存来存储你想跟踪的所有对象。
谢谢杰里米。选项2听起来很有趣。我们意识到我们与从Sequel :: Model继承的模型类有一个类似的问题,它们是包含数据库连接的全局单例。选项2也可以解决这个问题。 –
嗯 - 只是想知道 - 是另一种问这个问题的方法 - 机架允许会话状态存储在内存中吗?还是会话状态总是需要序列化? –
哦 - 只是将数据库对象添加到全局哈希似乎这样做。我想这是行得通的。 –