2009-08-27 19 views
10

Escribí mi propio middleware para proporcionar un punto final API a nuestra aplicación. El middleware carga clases que proporcionan los métodos API y enruta la solicitud a la clase/método apropiado. Las clases se cargan dinámicamente a través de String#constantize.La recarga de clase se detiene después de la excepción no detectada en el middleware personalizado

Mientras se ejecuta en modo de desarrollo, las clases se vuelven a cargar automáticamente. Sin embargo, si hay una excepción no detectada, que posteriormente es manejada por el middleware Failsafe, la recarga automática deja de funcionar. constantize todavía se está llamando, pero parece devolver la clase anterior.

Parece que hay algo más que descarga clases, y una excepción no detectada lo rompe. ¿Qué podría ser esto?

Ejecutando Ruby 1.8.7, Rails 2.3.3 y Thin 1.2.2.

+0

También tengo este problema. –

Respuesta

0

Rails almacena en caché muchas clases y las descarga y las vuelve a cargar en modo de desarrollo o cuando config.cache_classes se establece en verdadero. Aquí hay algunas ideas sobre el tema que también explican cómo funciona. http://www.spacevatican.org/2008/9/28/required-or-not/

No es para decirte que lo estás haciendo mal, pero la sobrecarga de String # constantize parece una manera estrafalaria de volver a cargar tu código. ¿Consideras usar algo como watchr para ejecutar tu servidor de aplicaciones en desarrollo y reiniciarlo cuando guardas archivos en tu subárbol de API? https://github.com/mynyml/watchr/

Además, para algunas ideas al azar sobre la forma de promover depuración, echa un vistazo a esta respuesta: https://stackoverflow.com/a/7907289/632022

1

Creo que este efecto proviene de la forma ActionController::Reloader está escrito. Aquí es ActionController::Reloader#call de 2.3.3, tenga en cuenta el comentario:

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 no quita constantes de auto-cargado, Dispatcher.cleanup_application hace. BodyWrapper#close se escribe con posibles excepciones en cuenta:

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

Sin embargo, esto no resuelve el problema, porque si @app.call en ActionController::Reloader#call se produce una excepción, BodyWrapper no recibe instanciado y Dispatcher.cleanup_application no se consiga llamar.

imaginar el siguiente escenario:

  • hago cambios en uno de mis archivos que afecta llamada a la API
  • golpeo llamada a la API y ver el error, en este momento todos los archivos, incluyendo el que tiene un error aren 't descargado
  • mía es codefix y golpeó la misma llamada API para comprobar si funcionaba
  • llamada se enruta la misma forma que antes, a las viejas clases/objetos/modules. Esto arroja el mismo error y deja de nuevo las constantes cargadas en la memoria

Esto no ocurre cuando los controladores tradicionales generan errores porque son manejados por ActionController::Rescue. Tales excepciones no llegan al ActionController::Reloader.

solución más simple sería poner la cláusula de reserva de rescate en la API de middleware de enrutamiento, alguna variación de esto:

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

Tenga en cuenta que esta es mi respuesta a la pregunta de 3 años y yo seguía pila de llamadas de 2.3.3 . Las versiones más nuevas de los rieles pueden manejar las cosas de manera diferente.

Cuestiones relacionadas