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

Oleg Mikheev
  • 17,186
  • 14
  • 73
  • 95
user562529
  • 931
  • 1
  • 11
  • 19
  • 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? – Oleg Mikheev Nov 26 '11 at 21:20
  • 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? – Oleg Mikheev Nov 28 '11 at 14:20
  • @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`. – miaout17 Nov 28 '11 at 14:36
  • @Oleg: I second miaout17, this question is totally not about reloading source files. – user562529 Dec 08 '11 at 15:55

4 Answers4

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.

Konstantin Haase
  • 25,687
  • 2
  • 57
  • 59
  • 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? – user562529 Dec 02 '11 at 18:54
  • actually it would make sense to add this info to sinatra documentation site – Oleg Mikheev Dec 03 '11 at 15:11
  • 5
    It actually is documented: http://www.sinatrarb.com/intro#Request/Instance%20Scope – Konstantin Haase Dec 13 '11 at 19:20
  • 2
    then it would make sense to put the link to your answer :) – Oleg Mikheev Dec 16 '11 at 14:53
  • 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. – mjnissim Jun 09 '12 at 08:48
  • 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. – Konstantin Haase Jun 19 '12 at 16:44
  • Wow that relieves me of so much headache right now. Thank you! – nex Aug 08 '13 at 08:09
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.

Tom Andersen
  • 7,132
  • 3
  • 38
  • 55
  • 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. – user562529 Dec 08 '11 at 15:51
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.

tomferon
  • 4,993
  • 1
  • 23
  • 44
  • 1
    Doesn't that show that it's a different instance? Maybe a better test would be: puts self.object_id – pguardiario Nov 27 '11 at 00:52
  • 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. – tomferon Nov 27 '11 at 10:26
  • 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. – Tom Andersen Dec 07 '11 at 02:16
  • 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. – Tom Andersen Dec 07 '11 at 02:19
  • 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. – Tom Andersen Dec 07 '11 at 02:22
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
coolesting
  • 1,451
  • 5
  • 18
  • 22
  • 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. – Tom Andersen Dec 07 '11 at 02:01
  • running this file with 'shotgun' results in 'The number is 0' - always, no matter what you do. – Tom Andersen Dec 07 '11 at 02:04