2016-08-19 1 views
0

Я использую Sequel с Sinatra на сервере Puma/Rack.Как настроить сеансовые подключения к базе данных с Sinatra, Sequel и Rack

Я хочу сохранить свой объект подключения Sequel DB с сеансом - не глобально - чтобы у меня мог быть отдельный пул соединений DB для каждого зарегистрированного пользователя. Цель состоит в том, чтобы иметь доступ к одному серверу базы данных для каждого входа в веб-сервер.

Я не могу решить, как это сделать, поскольку объект базы данных 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 
+0

Хм - просто интересно - это еще один способ спросить об этом - позволяет ли стойка разрешить сохранение состояния сеанса в памяти - или состояние для сеанса всегда необходимо сериализовать? –

+0

Ох - просто добавление объектов БД к глобальному хешу, похоже, делает это. Думаю, это сработает. –

ответ

2

Вы не можете сериализовать объект Sequel :: База данных. У вас есть несколько достойных вариантов:

  1. Использование рэк Связующее ПО, которое создает объект Sequel :: База данных для каждого запроса, используя объект только для запроса. В этом случае вы не будете присваивать результат Sequel.connect константе, вы должны передать блок и вызвать следующую переменную внутри этого блока.

  2. Создайте единый объект Sequel :: Database на верхнем уровне и сохраните его в константе DB. Расширения произвольного_сервера и server_block в объект Sequel :: Database. Затем используйте промежуточное программное обеспечение стойки, которое проверяет соединение с соответствующим сервером на время действия блока.

  3. Если у вас мало клиентов, вы можете просто использовать поддержку Shacking от Sequel и использовать только расширение server_block без произвольных_серверов. Одно из преимуществ этого заключается в том, что соединения могут быть кэшированы, поэтому вы не делаете отдельное соединение с базой данных для каждого запроса (что будет иметь место как для 1, так и для 2).

  4. Используйте глобальный хэш, как вы упомянули, с ключами, именами пользователей и значениями которых являются Sequel :: Объекты базы данных. Вы должны убедиться, что у вас достаточно памяти для хранения всех объектов, которые вы хотите отслеживать, если вы это сделаете.

+0

Спасибо Джереми. Вариант 2 звучит интересно. Мы поняли, что у нас есть аналогичная проблема с классами моделей, которые наследуют от 'Sequel :: Model', которые являются глобальными синглонами, которые включают соединение с базой данных. Вариант 2 также может решить эту проблему. –

Смежные вопросы