Is a new instance of sinatra started on every request?
Asked Answered
D

4

9

When a new http request comes in, will a new instance of sinatra be started, e.g. has sinatra to be initialized, or is just the method of a previous instance (the corresponding get/post method/route) of sinatra be called? Thank you for any documentation links, i wasn't able to find any.

It would also be interesting if that behavior is dependent on the deployment type - WEBrick/Passenger etc

Dirac answered 26/11, 2011 at 21:12 Comment(4)
I've seen a lot of discussions about the ways to force Sinatra/Rack to reload the source files and applications, so my guess is that they are not getting reloaded by default, did I get your question right?Truncation
It would also be very interesting to know if that behavior is dependent on the deployment type - will WEBrick behave the same as Passenger for one?Truncation
@Oleg: "Reload a Ruby source file" and "Create a new instance" is different concepts. The former is done by require or load, The latter is TheClass.new.Leroy
@Oleg: I second miaout17, this question is totally not about reloading source files.Dirac
I
13

A new class is created for every request. However, this is not done by Rack. This is a feature of Sinatra. If you want to dig into the details: The instance is not actually created with Sinatra::Application.new but with Sinatra::Application.prototype.dup, see Sinatra::Base#call for the code.

Ingenuity answered 1/12, 2011 at 22:18 Comment(7)
So when no requests are being handled, Rack is just waiting for requests with one "empty" instance of Sinatra loaded. Then, when a request comes in, Rack tells this instance to duplicate and handle the request, did i got it right?Dirac
actually it would make sense to add this info to sinatra documentation siteTruncation
It actually is documented: sinatrarb.com/intro#Request/Instance%20ScopeIngenuity
then it would make sense to put the link to your answer :)Truncation
Konstantin, you are so helpful! But I have no idea how to get around this issue except for aborting Sinatra. If a new DB connection is opened each time, I'd rather run to another platform. I might just end up getting back to Rails with my tail between my legs.Groove
As I said in the other discussion: Simply don't use instance variables for storing DB connections. Use a setting, or whatever you feel like, Sinatra doesn't care. Note that Sinatra is not a framework, it simply solves HTTP for you.Ingenuity
Wow that relieves me of so much headache right now. Thank you!Assured
M
2

You should always assume that the entire app could be rebooted under you in-between requests. What if you are running 16 copies of your app - the request from user 'jane' for '/' could com e in on copy #2, then when she visits '/signup' the request will hit #12 (possibly booted for this event) app. So it does not matter what Sinatra does (although it looks like they do something similar), since your app could just appear anywhere, booted today, yesterday or a ms ago.

If you plan on growing - or deplying on Heroku, etc - your app needs to run fine using 'shotgun' - which restarts everything for each request. I guess if your app does something radically different than serve web pages, and hardly ever crashes or gets rebooted, you might get away with 'NO'

So my answer is 'YES' (but not always, and not even sometimes usually).

Nevertheless, it's handy to know how things work, so that you can perhaps only set up some complex calculated asset caching scheme once per app load - which is a performance opt. For example, if each call to your app with the url /calculate_pi?decimals=2000 always results in the same 2000 digit number, you could cache that on each instance.

Misteach answered 7/12, 2011 at 2:12 Comment(1)
thank you too for your practical answer. I for sure won't rely on having the same instance all the way. "it's handy to know how things work" - that's why I asked this question. "So my answer is 'YES' (but not always, and not even sometimes usually)." isn't that helpful to understand exactly how a "request cycle" works. Sorry for obviously wording my question badly.Dirac
L
0

A quick test shows that the same instance is running whatever the request (at least, by default).

require 'sinatra'

flag = false

get '/stuff' do
  puts "flag is #{flag ? 'set' : 'unset'}"
  flag = true
end

When this code is run and two requests are received, the server will prompt flag is unset and then flag is unset.

EDIT:

That shows the files are not reloaded. By using puts self.object_id, self.class (as pguardiario recommended), we actually see that a new instance of Sinatra::Application is created for each request.

Lamee answered 26/11, 2011 at 22:36 Comment(5)
Doesn't that show that it's a different instance? Maybe a better test would be: puts self.object_idAconcagua
Well, it shows that the file is not reloaded as @Oleg said and you're right : with self.object_id, we see that this is a different instance of Sinatra::Application for each request. I'll edit my answer right now.Lamee
Again - running under the ruby testfile2.rb gives flag unset on the first call, and flag set on all subsequent calls. With shotgun you get flag always unset. So relying on this kind of behaviour for a web server is bad news.Misteach
So there is a new Sinatra:Application instance on each call, but the 'flag' variable that is set is somehow kept when using a 'normal' server.Misteach
Things change when making the flag an @ variable - a class variable. In that case you always get @flag unset on each call, which makes sense.Misteach
S
0

Run this, you will know everything, but it dosen't mean the Rack mechanical of running as the Sinatra.(Actually, the Rack will creates a new instance for every request)

require 'sinatra'

configure do
    set :number, 0
end

number = 0

get '/test1' do
    var = "The number is #{number}"
    number = number + 1
    var
end

get '/test2' do
    var = "The number is #{settings.number}"
    set :number, settings.number + 1
    var
end
Soursop answered 28/11, 2011 at 2:0 Comment(2)
running this as a file with 'ruby test file.rb' and hitting test1 in the browser results in "The number is 0", then "The number is 1" then "The number is 2" - then switch to hitting test2 and it starts out at 0 again, and climbs.Misteach
running this file with 'shotgun' results in 'The number is 0' - always, no matter what you do.Misteach

© 2022 - 2024 — McMap. All rights reserved.