Ruby 如何使用Sinatra、Sequel和Rack设置基于会话的数据库连接

Ruby 如何使用Sinatra、Sequel和Rack设置基于会话的数据库连接,ruby,rack,sequel,puma,Ruby,Rack,Sequel,Puma,我正在Puma/Rack服务器中使用Sequel with Sinatra 我希望将我的Sequel DB connection对象存储在会话中,而不是全局存储,这样我就可以为每个登录的用户拥有一个单独的DB连接池。目的是让每个web服务器登录都有一个数据库服务器登录 由于Sequel数据库对象似乎是全局单例对象,因此我无法确定如何执行此操作。例如,如果我尝试序列化数据库对象并将其存储在会话中,我将收到一条错误消息:TypeError-无法转储匿名类:我不想在每次路由请求时都连接到数据库 我该怎

我正在Puma/Rack服务器中使用Sequel with Sinatra

我希望将我的Sequel DB connection对象存储在会话中,而不是全局存储,这样我就可以为每个登录的用户拥有一个单独的DB连接池。目的是让每个web服务器登录都有一个数据库服务器登录

由于Sequel数据库对象似乎是全局单例对象,因此我无法确定如何执行此操作。例如,如果我尝试序列化数据库对象并将其存储在会话中,我将收到一条错误消息:TypeError-无法转储匿名类:我不想在每次路由请求时都连接到数据库

我该怎么做?下面是一些示例代码,希望能说明我试图实现的目标:

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::数据库对象。您有几个不错的选择:

使用机架中间件,为每个请求创建Sequel::Database对象,仅为请求使用该对象。在这种情况下,您不会将Sequel.connect的结果赋给常量,而是传递一个块并调用该块中的下一个变量

在顶层创建一个Sequel::Database对象,并将其存储在DB常量中。将任意_服务器和服务器_块扩展添加到Sequel::Database对象中。然后使用机架中间件,在数据块期间检查与相应服务器的连接

如果您的客户很少,可以只使用Sequel的分片支持,只使用服务器块扩展,而不使用任意的服务器。这样做的一个优点是可以缓存连接,这样您就不会对每个请求进行单独的数据库连接,这对于1和2都是如此。和2

使用前面提到的全局哈希,键是用户名,值是Sequel::数据库对象。如果执行此操作,您需要确保有足够的内存来存储所有要跟踪的对象


无法序列化Sequel::数据库对象。您有几个不错的选择:

使用机架中间件,为每个请求创建Sequel::Database对象,仅为请求使用该对象。在这种情况下,您不会将Sequel.connect的结果赋给常量,而是传递一个块并调用该块中的下一个变量

在顶层创建一个Sequel::Database对象,并将其存储在DB常量中。将任意_服务器和服务器_块扩展添加到Sequel::Database对象中。然后使用机架中间件,在数据块期间检查与相应服务器的连接

如果您的客户很少,可以只使用Sequel的分片支持,只使用服务器块扩展,而不使用任意的服务器。这样做的一个优点是可以缓存连接,这样您就不会对每个请求进行单独的数据库连接,这对于1和2都是如此。和2

使用前面提到的全局哈希,键是用户名,值是Sequel::数据库对象。如果执行此操作,您需要确保有足够的内存来存储所有要跟踪的对象


嗯-只是想知道-是问这个的另一种方式-机架允许会话状态存储在内存中吗-或者会话的状态总是需要序列化吗?哦-仅仅将DB对象添加到全局哈希似乎就可以了。我想这是可行的。嗯,我只是想知道,这是另一种提问方式——机架是否允许会话状态存储在内存中——或者会话状态是否总是需要序列化?噢,只是将DB对象添加到全局哈希似乎就可以了。我想这会有用的。谢谢杰里米。选项2听起来很有趣。我们意识到,继承自Sequel::model的模型类也存在类似的问题,后者是包含数据库连接的全局单例。选项2也可以解决这个问题。谢谢Jeremy。选项2听起来很有趣。我们意识到,继承自Sequel::model的模型类也存在类似的问题,后者是包含数据库连接的全局单例。选择2也可以解决这个问题。