Ich bekomme immer wieder widersprüchliche Meinungen über die Praxis des Speicherns von Informationen im Thread.current
Hash (z. B. current_user, aktuelle Subdomain usw.). Die Technik wurde vorgeschlagen, um die spätere Verarbeitung innerhalb der Modellschicht (Abfrageumfang, Prüfung usw.) zu vereinfachen.
- Warum sind meine Thread-Variablen in Rails intermittierend?
- Alternative zur Verwendung von Thread.current im API-Wrapper für Rails
- Sind Thread.current [] -Werte und Attribute auf Klassenebene sicher in Rails zu verwenden?
Viele halten die Praxis für inakzeptabel, da sie das MVC-Muster bricht. Andere äußern Bedenken hinsichtlich der Zuverlässigkeit / Sicherheit des Ansatzes, und meine zweiteilige Frage konzentriert sich auf den letzteren Aspekt.
Ist der
Thread.current
Hash während seines gesamten Zyklus garantiert für eine und nur eine Antwort verfügbar und privat?Ich verstehe, dass ein Thread am Ende einer Antwort durchaus an andere eingehende Anfragen übergeben werden kann, wodurch alle darin gespeicherten Informationen verloren gehen
Thread.current
. Würde das Löschen solcher Informationen vor dem Ende der Antwort (z. B. durch AusführenThread.current[:user] = nil
von einem Controllerafter_filter
) ausreichen, um eine solche Sicherheitsverletzung zu verhindern?
Vielen Dank! Giuseppe
quelle
Antworten:
Es gibt keinen bestimmten Grund, sich von threadlokalen Variablen fernzuhalten. Die Hauptprobleme sind:
Die Verwendung ist zwar nicht völlig ausgeschlossen, aber der beste Ansatz besteht darin, sie nicht zu verwenden. Von Zeit zu Zeit stoßen Sie jedoch an eine Wand, an der ein lokaler Thread die einfachste Lösung darstellt, ohne viel Code und zu ändern Sie müssen Kompromisse eingehen, ein weniger als perfektes objektorientiertes Modell mit dem lokalen Thread haben oder eine Menge Code ändern, um dasselbe zu tun.
Es ist also meistens eine Frage des Denkens, welche die beste Lösung für Ihren Fall sein wird, und wenn Sie wirklich den thread-lokalen Pfad beschreiten, würde ich Ihnen sicherlich raten, dies mit Blöcken zu tun, die daran denken, danach aufzuräumen Sie werden wie folgt ausgeführt:
around_filter :do_with_current_user def do_with_current_user Thread.current[:current_user] = self.current_user begin yield ensure Thread.current[:current_user] = nil end end
Dadurch wird sichergestellt, dass die lokale Thread-Variable vor der Verwendung bereinigt wird, wenn dieser Thread recycelt wird.
quelle
ensure
Block und versucht nicht, die Ausnahme abzufangen.Dieses kleine Juwel stellt sicher, dass Ihre lokalen Thread- / Anforderungsvariablen nicht zwischen Anforderungen hängen bleiben: https://github.com/steveklabnik/request_store
quelle
Die akzeptierte Antwort deckt die Frage ab, aber da Rails 5 jetzt eine "abstrakte Superklasse " ActiveSupport :: CurrentAttributes bereitstellt, die Thread.current verwendet.
Ich dachte, ich würde einen Link dazu als mögliche ( unpopuläre ) Lösung bereitstellen .
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/current_attributes.rb
quelle
Die akzeptierte Antwort ist technisch korrekt, aber wie in der Antwort sanft und in http://m.onkey.org/thread-safety-for-your-rails nicht so sanft ausgeführt:
Verwenden
Thread.current
Sie keinen lokalen Thread-Speicher, wenn Sie dies nicht unbedingt müssenDas Juwel für
request_store
ist eine andere Lösung (besser), aber lesen Sie die Readme-Datei dort aus weiteren Gründen, um sich vom lokalen Thread-Speicher fernzuhalten.Es gibt fast immer einen besseren Weg.
quelle