Skip to content

Puma backlog is not drained and requests slip through between tests. #2822

@mikz

Description

@mikz

I was debugging CSRF exceptions in our test suite when running on a resource starved machine with just 1 puma thread.

It turned out a combination of fetch calls in setTimeout and puma not processing requests fast enough lead to requests leaking in between tests and producing CSRF exceptions.

Not sure exactly why or how it slips through the middleware - maybe there is a successful check before puma accepts more requests from the backlog.

In my testing this pretty basic monkeypatch fixes the issue and drains all the requests in between tests.

module CapybaraWaitForPumaBacklog
  extend ActiveSupport::Concern

  prepended do
    class_attribute :wait_for_pending_puma_backlog, default: true
  end

  def pending_requests?
    super || puma_backlog_pending?
  end

  def puma_backlog_pending?
    wait_for_pending_puma_backlog && puma_backlog > 0
  end

  private

    def find_puma_server
      @_puma_server ||= ObjectSpace.each_object(::Puma::Server).find(&:running)
    end

    def puma_backlog
      server = find_puma_server
      server ? server.backlog : 0
    end
end

Capybara::Server::Middleware.prepend(CapybaraWaitForPumaBacklog)

I'd like to contribute to capybara not exactly this, but rather a Puma plugin that would produce the same result and extend Capybara::Server#pending_requests? to check the server plugin in addition to the middleware. I don't have the exact design worked out yet.

Is that something worth contributing? I think it could remove some flakiness for people.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions