Search code examples
rubyherokusinatrapumasequel

I lose user session with Ruby + Sinatra + puma + sequel only when worker process puma> 1


My app in Heroku with Ruby + Sinatra + puma + sequel is ok while worker process = 1 when increasing worker process = 2 or if increasing dyno = 2 I start with problems of losing the user session randomly at different points in the system making it very difficult to locate the specific error through heroku logs.

The same app works fine with:

But you lose the value of session[: user] with:

My app rack sinatra class:

class Main <Sinatra :: Aplicación
    use Rack :: Session :: Pool
    set: protection ,: except =>: frame_options

    def usuarioLogueado?          
      if defined?( session[:usuario] )   
        if session[:usuario].nil?
          return false
        else
          return true
        end
      else
        return false
      end    
    end

    get "/" do  
       if usuarioLogueado?  
               redirect "/app"
               .....
       else
              redirect "/home"
       end
    end
end

My sequel connection:

pool_size  = 10
@ db = Sequel.connect (strConexion ,: max_connections => pool_size )
@ db.extension (: connection_validator)
@ db.pool.connection_validation_timeout = -1

My puma.rb: (20 connections max DB)

workers Integer (ENV ['WEB_CONCURRENCY'] || 1)
threads_count = Integer (ENV ['MAX_THREADS'] || 10)
threads threads_count, threads_count

preload_app!

rackup DefaultRackup
port ENV ['PORT'] || 3000

Solution

  • Rack::Session::Pool is a simple memory based session store. Each process has its own store and they are not shared between processes or hosts. When a request gets directed to a different dyno or different process on the same dyno, the session data will not be available.

    You could look at sticky sessions, but they won’t work in all situations (e.g. when dynos are created or destroyed) and won’t work at all if you have multiple processes on a single dyno.

    You should look at using cookie based sessions, or set up a shared server side store such as memcached with Dalli, so that it doesn’t matter which dyno or process each request is routed to.