2009-08-27 17 views
10

में बेजोड़ अपवाद के बाद बंद हो जाता है मैंने अपने आवेदन के लिए एपीआई एंडपॉइंट प्रदान करने के लिए अपना खुद का मिडलवेयर लिखा है। मिडलवेयर कक्षाओं को लोड करता है जो एपीआई विधियों को प्रदान करते हैं, और उपयुक्त वर्ग/विधि के अनुरोध को रूट करते हैं। कक्षाएं String#constantize के माध्यम से गतिशील रूप से लोड की जाती हैं।कस्टम रीडलोडिंग कस्टम मिडलवेयर

विकास मोड में चलते समय, कक्षाएं स्वचालित रूप से पुनः लोड हो जाती हैं। हालांकि, अगर कोई अपवाद अपवाद नहीं है - जिसे बाद में फेल्सएफ़ मिडलवेयर द्वारा नियंत्रित किया जाता है - स्वचालित रीलोडिंग काम करना बंद कर देती है। constantize अभी भी बुलाया जा रहा है लेकिन ऐसा लगता है कि पुरानी कक्षा वापस आती है।

ऐसा लगता है कि कुछ और है जो वर्गों को उतारता है, और एक बेजोड़ अपवाद इसे तोड़ देता है। यह क्या हो सकता है?

रुबी 1.8.7, रेल 2.3.3 और पतला 1.2.2 चल रहा है।

+0

मुझे यह समस्या भी है। –

उत्तर

0

रेल कई वर्गों और अनलोडों को कैश करता है और उन्हें विकास मोड में या फिर config.cache_classes को सत्य पर सेट करता है। यहां विषय पर कुछ विचार दिए गए हैं जो यह भी बताते हैं कि यह कैसे काम करता है। http://www.spacevatican.org/2008/9/28/required-or-not/

आपको यह बताने के लिए नहीं कि आप इसे गलत कर रहे हैं, लेकिन स्ट्रिंग # निरंतरता को ओवरलोड करना आपके कोड को पुनः लोड करने के लिए एक हैकी तरीका जैसा लगता है। क्या आपने अपने ऐप सर्वर को विकास में चलाने के लिए वॉकर जैसे कुछ का उपयोग करने पर विचार किया है और जब आप अपने एपीआई सबट्री में फाइलों को सहेजते हैं तो इसे पुनरारंभ करें? https://github.com/mynyml/watchr/

इसके अलावा, कैसे डिबग आगे बढ़ाने के लिए, इस जवाब की जाँच पर कुछ यादृच्छिक विचारों के लिए: https://stackoverflow.com/a/7907289/632022

1

मुझे लगता है कि इस आशय रास्ता ActionController::Reloader लिखा है से आता है। यहाँ ActionController::Reloader#call 2.3.3 से है, टिप्पणी पर ध्यान दें:

def call(env) 
    Dispatcher.reload_application 
    status, headers, body = @app.call(env) 
    # We do not want to call 'cleanup_application' in an ensure block 
    # because the returned Rack response body may lazily generate its data. This 
    # is for example the case if one calls 
    # 
    # render :text => lambda { ... code here which refers to application models ... } 
    # 
    # in an ActionController. 
    # 
    # Instead, we will want to cleanup the application code after the request is 
    # completely finished. So we wrap the body in a BodyWrapper class so that 
    # when the Rack handler calls #close during the end of the request, we get to 
    # run our cleanup code. 
    [status, headers, BodyWrapper.new(body)] 
end 

Dispatcher.reload_application ऑटो लोड स्थिरांक को दूर नहीं करता, Dispatcher.cleanup_application करता है। BodyWrapper#close मन में संभव अपवादों के साथ लिखा है:

def close 
    @body.close if @body.respond_to?(:close) 
ensure 
    Dispatcher.cleanup_application 
end 

हालांकि इस मदद नहीं करता है, क्योंकि अगर ActionController::Reloader#call में @app.call एक अपवाद फेंकता है, BodyWrapper instantiated नहीं होता है, और Dispatcher.cleanup_application बुलाया प्राप्त करता है।

इस परिदृश्य की कल्पना कीजिए:

  • मैं अपने फ़ाइलों में से एक है जो API कॉल
  • मैं API कॉल एक बग के साथ एक सहित सभी फाइलों को मारा और त्रुटि देखते हैं इस बिंदु पर, को प्रभावित करता है में परिवर्तन करने के नहीं हैं 'टी उतार
  • मैं एक codefix बनाने के लिए और जांच करने के लिए एक ही API कॉल मारा अगर यह काम किया
  • कॉल उसी तरह से कराई हो जाता है के रूप में पहले वर्ष की कक्षाओं/वस्तुओं/मॉड्यूल के लिए। यह एक ही त्रुटि फेंकता है और फिर स्मृति

यह नहीं होता है जब पारंपरिक नियंत्रकों त्रुटियों बढ़ा क्योंकि उन ActionController::Rescue द्वारा नियंत्रित किया जाता है में भरी हुई स्थिरांक छोड़ देता है। ऐसे अपवाद ActionController::Reloader पर नहीं आते हैं।

आसान समाधान, इस के कुछ बदलाव एपीआई मार्ग मिडलवेयर में वापस आने बचाव खंड डाल करने के लिए होगा:

def call(env) 
    # route API call 
resuce Exception 
    Dispatcher.cleanup_application 
    raise 
end 

ध्यान दें कि यह 3 वर्ष पुराने सवाल का मेरा उत्तर है और मैं 2.3.3 के कॉल स्टैक पीछा । रेल के नए संस्करण चीजों को अलग-अलग संभाल सकते हैं।

संबंधित मुद्दे