Andrew Stewart <[email protected]> wrote: > Hello, > > I have run into the following situation several times in the past few months: > > (My stack is Nginx -- Unicorn -- Rails 3.0.12) > > 1. Client clicks a delete link in my webapp. > 2. Rails starts processing the appropriate destroy action. This updates > various things in the database (but not in a single db transaction). > 3. Client terminates the connection. > 4. Rails stops executing the destroy action wherever it has got to, leaving > the latter part of the action unexecuted and my db inconsistent. > 5. Rails and Unicorn don't write anything to their logs; Nginx writes a 499. > > This question has been asked before[1] but regrettably I don't > entirely understand all the solutions proposed :) > > I plan to wrap all the changes made by my destroy action in a single > db transaction. I'm assuming this will ensure db consistency, even > when subject to awkward clients. Is that correct?
Yes (assuming all your DB actions in the transaction may be rolled-back). I'm no expert in DBs, but I recommend you always use transactions when data consistency is required. > (I'll probably also move the action's work onto a background process, > e.g. with delayed job.) This also works, too, and is likely better if your DB actions take a long time. > Now apologies if I'm barking up the wrong tree here...in general is it > possible to configure Unicorn to buffer the request and: > > - if the client terminates before the request is fully received, don't > pass it to Rails at all; > - else pass the complete request to Rails and let Rails execute it > fully, even if client terminates in the meantime? Yes. Using the Unicorn::PrereadInput middleware (before Rails or any other middleware/framework touches env["rack.input"]) should do everything you want. > The thread[1] also mentioned Nginx's proxy_ignore_client_abort. If > that's relevant, has anyone tried it? I haven't, perhaps Jesse can respond? > [1] > http://rubyforge.org/pipermail/mongrel-unicorn/2011-August/001096.html On a related note, Tom Burns has/had the same problem[2]. Unlike you, he wanted to avoid processing the request in as many cases as possible. The solution he came up with isn't 100% foolproof, either, but his primary goal was to reduce load on an overloaded system. I haven't heard back on results of our nasty/crazy solution, though. If you do combine Tom's solution with yours, you still need to ensure DB consistency in the app. [2] http://mid.gmane.org/cak4qkg32dggnbztzcb6noh5hu_drhmofafhk-6xvy-t86++...@mail.gmail.com _______________________________________________ Unicorn mailing list - [email protected] http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
