2012-08-17 27 views
10

Bir Rails uygulaması yazmak zorundayım çünkü Rails işleminde bir Neo4j grafik veritabanını içeren Neo4j.rb'nin üzerinde çalışıyorum ve böylece aynı süreçten birden fazla istekte bulunmak zorundayım. Evet, SQL veritabanları gibi çalıştı bir Neo4j veritabanına bağlarsanız, ama olurdu, bu yüzden şikayet bırakacağım ve sadece kullanacağız.Thread-safe Denetleyici eylemlerini yönlendirir - örnek değişkenleri belirleme?

Eşzamanlı kod yazmanın etkileri konusunda oldukça endişeliyim (olması gerektiği gibi) ve ortak bir senaryoyu nasıl ele alacağımız konusunda biraz tavsiyeye ihtiyacım var - bir denetleyici bir örnek değişkenini veya oturum karma değişkenini bir değişken olarak ayarlar sonra bazı şeyler olur.

# THIS IS NOT REAL PRODUCTION CODE 
# I don't do this in real life, it is just to help me ask my question, I 
# know about one-way hashing, etc.! 

class SessionsController 
    def create 
    user = User.find_by_email_and_password(params[:email], params[:password]) 
    raise 'auth error' unless user 
    session[:current_user_id] = user.id 
    redirect_to :controller => 'current_user', :action => 'show' 
    end 
end 

class CurrentUserController 
    def show 
    @current_user = User.find(session[:current_user_id]) 
    render :action => :show # .html.erb file that uses @current_user 
    end 
end 

soru: Bu kodun herhangi yarış koşulları var mıdır ne demek istediğimi göstermek için aşağıdaki ham kodunu düşünün?

SessionsController'da session hash ve params hash thread-local? Aynı tarayıcı oturumunda, farklı kimlik bilgileriyle/session'larının oluşturulmasında (Rails route sözdizimini ödünç almak için) birden fazla istekte bulunulduğunu varsayalım, oturum açmış olan kullanıcı en son session[:current_user_id] = user.id numaralı satıra ulaşan istek olmalıdır. Yoksa denetleyici eyleminin etrafında bir mutex kilit mi sarmalıyım?

CurrentUserController'da, show eylemi farklı oturumlarda iki istekle eşzamanlı olarak vurulursa, aynı @current_user değişkeni her ikisi tarafından ayarlanacak mı? Yani .html.erb dosyasını işlerken ilk istek, @current_user örnek değişkenin aniden ikinci iş parçacığı tarafından değiştirildiğini görecek mi?

Teşekkür

cevap

10

Her istek bir new instance of your controller alır. Sonuç olarak denetleyici örneği değişkenleri iş parçacığı güvenlidir. params ve session da denetleyici örnek değişkenleri (veya istek nesnesinin kendisi) tarafından desteklenir ve bu nedenle de güvenlidir.

+0

Bu eski bir ileti dizisidir, üzgünüz. Ama ben bir takip yapıyorum. Bu çok mantıklı (ve neden insanlar denetleyici yöntemlerinde @ variables hakkında endişe etmiyorlar. Ancak bu doğruysa, bu adamın her birinin kendi sayacıyla ilgili sorunları olduğu konusunda kafam karıştı. Http://tenderlovemaking.com/2012/ 06/18/remove-config-threadsafe.html –

+1

@OliverShaw, bu post sayacı bir sınıf örneği değişkendir (çünkü "class << self' bloğundadır), bu nedenle tüm istekler aynı sayacı değiştirerek olurdu –

+0

Coming Ruby'ye geri dönelim: Sınıf değişkenlerini değil, sınıf değişkenlerini hatırladım.Çok teşekkürler! –

2

Konuyla paylaşılmayanlar arasında nelerin paylaşıldığını bilmek önemlidir.

Şimdi özel örneğinize dönün. İki istek aynı anda CurrentUserController#show numarasına çarptı, dolayısıyla iki eşzamanlı iş parçacığı tarafından işlenir. Buradaki anahtar, her bir iş parçacığının kendi örneğinin CurrentUserController olduğundan, bu nedenle, birbirine müdahale etmeyen iki @current_user değişken vardır. Yani @current_user civarında bir yarış durumu yok.

yarış şartı örneği bu olacaktır: Daha genel bir not

class ApplicationController < ActionController::Base 
    before_each :set_current_user 
    cattr_accessor :current_user 

    def set_current_user 
    self.class.current_user = User.find_by_id(session[:current_user_id]) 
    end 
end 

# model 
class LogMessage < ActiveRecord::Base 
    belongs_to :user 

    def self.log_action(attrs) 
    log_message = new(attrs) 
    log_message.user = ApplicationController.current_user 
    log_message.save 
    end 
end 

, çünkü GIL (Küresel Tercüman Kilidi) MRI Ruby konuları kullanmasını faydaları oldukça sınırlıdır. GIL'den (jruby) özgür olan uygulama var.

+0

Örnek için teşekkürler, ancak sınıf değişkenlerinin bir yarışa neden olacağını biliyorum. GIL meselesinde yanlış olduğunu düşünüyorum - Ruby 1.9 adet yerel, ve ben zaten JRuby kullanıyorum –

+1

Doğru yoldayım, MRI ruby ​​1 için geldiğine sevindim.9: Bu yerel konuları ve bu yerli konuları tarafından kullanılan global muteks olan GIL vardır. –

+0

Ah, anlıyorum. Söylediğim gibi minnetle JRuby kullanıyorum :) –

İlgili konular