2015-08-20 2 views
0

Когда пользователь пытается войти в наше приложение Rails, я обращаюсь к стороннему ICAM-серверу, который возвращает некоторую информацию о пользователе, если он существует на сервере ICAM. Я получаю хэш обратно с именем пользователя, электронной почтой и т. Д. (Наша среда настроена таким образом, что сервер ICAM может обнаружить идентификацию человека, который пытается выполнить вход, на основе их учетных данных рабочей станции).Почему код обмена Rails между сеансами пользователя?

Мы делаем все это в обычном драгоценном камне. Во время процесса входа в систему я пытаюсь кэшировать информацию, которую возвращает ICAM, поэтому мне больше не нужно разговаривать с сервером ICAM. Наивно, у меня был некоторый код, который в основном делал:

module Foo 
    def self.store_icam_data(data) 
    @icam_data = data 
    end 

    def self.icam_data 
    @icam_data || {} 
    end 
end 

Я только что обнаружил проблему, когда два пользователя вошли в систему. Когда пользователь А регистрируется, @icam_data задается с его информацией. Когда пользователь B входит в систему, @icam_data задает свою информацию. В следующий раз, когда Пользователь А сделает запрос, @icam_data имеет информацию пользователя пользователя B, а не пользователя А!

Я не ожидал, что переменная внутри этого модуля будет разделяться между потоками/сеансами, такими как. Это эффективно заставляет всех текущих пользователей системы становиться последним пользователем, который подписывает ... довольно грубую ошибку.

Может кто-нибудь объяснить, почему переменная @icam_data получает доступ к общим сеансам? Я ожидал, что данные/код будут более изолированными, чем кажется.

ответ

2

Есть только два способа обмена данными между запросами: ваша база данных (РСУБД, Redis и т. Д.) И объект session (внутри контроллеров). Любые другие данные, которые изменяют и выдерживают конец запроса, являются побочным эффектом, которого следует избегать.

Переменные вашего класса сохраняются в области памяти (ОЗУ), которые относятся к определенному процессу сервера приложений (например, рабочий процесс Unicorn). И один процесс, естественно, обслуживает множество запросов, потому что неэффективно убивать и перезапускать Rails по каждому запросу.

Так что это не «код обмена Rails», а сервер веб-приложений разделяет область памяти среди всех запросов, которые он обслуживает.

Если вы хотите связать небольшое количество данных для текущего пользователя, используйте сессию:

# save 
session[:icam_data] = MyICAMModule.get_icam_data 

# retain 
MyICAMModule.set_icam_data(session[:icam_data]) 

Более подробную информацию о session доступна в Action Controller Overview.

Если у вас есть большой объем данных - используйте базу данных.

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