In a Sinatra App on Heroku, Session Is Not Shared Across Dynos
In my comment, I suggested using rack cookie based sessions, but looking into it, the Sinatra sessions are Rack cookie sessions anyway.
Looking further, I found this in the Sinatra docs:
To improve security, the session data in the cookie is signed with a session secret. A random secret is generate for you by Sinatra. However, since this secret will change with every start of your application, you might want to set the secret yourself, so all your application instances share it:
set :session_secret, 'super secret'
So it seems each Heroku dyno is generating a different key, and so can't read each others session cookies, and you need to specify a key so each dyno uses the same one.
Rather than add a secret key to your source code, you're probably better setting an environment variable:
$ heroku config:add SESSION_KEY=a_longish_secret_key
Then in your sinatra app:
enable :sessions
set :session_secret, ENV['SESSION_KEY']
Rack/Sinatra session breaking when deployed on heroku - E13
This was a Rack 1.4.0 bug concerning the way invalid session digests were handled. github.com/rack/rack/issues/299 problem was solved by upgrade to Rack 1.4.1
I lose user session with Ruby + Sinatra + puma + sequel only when worker process puma 1
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.
Errors after increasing dyno number on Heroku
The fact that the problem only crops when scaling beyond one dyno suggests that it might be a shared-state problem. I.e. user authenticates on dyno-1 and a session-id gets stored in-memory on dyno-1. Same user's next request is server by dyno-2 which has no knowledge of the session and blows up. This is pure conjecture, I've haven't inspected your code.
Alternatively, this Sinatra issue has a similar-looking error from New Relic and suggests that upgrading to a pre-release version of the New Relic problem can solve the problem.
My bundler command is failing to load in my Sinatra app deployed in Heroku and thus causes it to crash
Identified Problems
You have a number of issues, but the largest is that you're attempting to run SinatraApp
rather than run Sinatra::Application
. This is most likely what's causing the app to crash, and the correct invocation is in both the Heroku and Sinatra documentation.
Furthermore, the Sinatra README recommends using the thin web server. Heroku recommends using a Procfile that explicitly defines the web server invocation for most Ruby-based apps. Specifically, it says:
Regardless of the webserver you choose, production apps should always specify the webserver explicitly in the Procfile.
Below, I provide my own suggested configuration for Sinatra apps that's (very slightly) less minimalist than the one provided in the Heroku docs. Start there, then tune it to suit.
Use a Foreman Procfile to Start Sinatra on Heroku
First, make sure your application's Heroku stack includes the heroku/ruby
buildpack. Then, use a foreman Procfile to start your Sinatra app using the thin web server. For example:
# Gemfile
ruby '2.6.6'
source 'https://rubygems.org'
gem 'sinatra'
gem 'thin'
gem 'foreman'
# config.ru
require './hello_app'
run Sinatra::Application
# Procfile
dev: bundle exec rackup
web: APP_ENV=production bundle exec rackup -p "$PORT"
You can probably get it working with other configurations, including the minimalist one suggested by Heroku, but this setup works reliably for a broad number of Sinatra applications on Heroku. Your mileage (and number of errors) with other configurations may vary.
Related Topics
How to Test If All Items in an Array Are Identical
Actiondispatch::Http::Uploadedfile.Content_Type Not Being Initialized in Rspec Test
Ruby: Remove Whitespace Chars at the Beginning of a String
How to Determine Leap Year in Ruby
Does Multibyte Character Interfere with End-Line Character Within a Regex
Attempting to Install Libv8, "Failed to Build Gem Native Extension"
Rails 4 Update Nested Attributes
Rails Redirect_To :Back Not Working
How to Remove All Elements That Satisfy a Condition in Array in Ruby
How to Fix Undefined Method 'Split' for Nil:Nilclass Error
Rails Pass Params/Arguments to Activerecord Callback Function
How to Get a Remote-File's Mtime Before Downloading It in Ruby
Activeadmin Forbiddenattributeserror
Rails - Paperclip Validating Attachment Size When It Shouldn't Be