2011-12-08 9 views
3

時々非常に長時間実行されるDBリクエストが必要なアプリケーションを作成しています。私はいくつかのコードを実行したいのですが、クライアントがDBリクエストを処理するためにページをリロードしたりクローズしたりする場合です。ユーザーが接続を中断したときに何かする(Sinatra + Thin)

私はRackがこのようなものにフックを持つことを望んでいましたが、明らかにこれがRackよりも深いレベルであることがわかりました。

これまでのところ、私は見つけることができる唯一のフックが猿パッチング薄いConnectionクラスでアンバインド機能をすることにより、薄い自体にある:

module Thin 
    class Connection < EventMachine::Connection 

    def unbind 

     # DO something here 

     @request.async_close.succeed if @request.async_close 
     @response.body.fail if @response.body.respond_to?(:fail) 
     @backend.connection_finished(self) 
    end 
    end 
end 

これはシンのアンバインド機能を無効にして、私は切断にフックすることができますEventMachineによって呼び出されます。

良い方法がありますか?

+2

長い実行要求を非同期にすることを検討する必要があります。よりクリーンなデザインとなり、現在の問題も解決します。 – randomuser

+0

私は実際に、EventMachine、em-syncrhony、およびsinatra-synchronyを使用して、要求を非同期的に実行しています。これでも問題は解決しません。要求が同期しているかどうかにかかわらず、ユーザーがDBからの結果を気にかけなくなったときを知りたいです。 – Ben

+0

私が理解するところでは、sinatra-synchronyは同時に要求を実行するだけです。したがって、私はまだ@ガンジャンアドバイスが適用されると思います。 –

答えて

1

掘り下げた後、「バックエンド」を置き換えるメカニズム、またはサーバーがクライアントに接続する方法をThinが提供することがわかりました。

class Backend < Thin::Backends::TcpServer 

    def initialize(host, port, options={}) 
    super(host, port) 
    end 

    def connection_finished(connection) 
    super(connection) 

    if connection.request.env["query_killer"] 
     connection.request.env["query_killer"].kill 
    end 

    end 

end 

これは、コマンドライン引数を経て薄いに含めることができます:私は、クエリかどうかを殺すために必要がある場合、私は特定の要求インスタンスに対処し、知っているラックのenvの値と組み合わせることを、使用しています:

thin start -r 'my_module/backend' --backend MyModule::Backend 
関連する問題