Reputation: 994
How can I run a ruby script in the background of the server while still being able to get the variables that the script uses to display the user when they load the page.
I need the server to continuously run processes in the background in an infinite while loop.
Example of background proccess:
while 0==0
if @variable!=nil
@variable+=1
else
@variable=0
end
end
How can I have this run in the background on my server and have sinatra get the value of @variable when it receives a get request: ex:
get 'variable' do
"This is the current value of the variable: #{@variable}"
end
Upvotes: 0
Views: 1439
Reputation: 8467
You're probably best off putting the output of your server-side process in a database, file, shared memory segment, or key-value store (e.g. Redis), and accessing the current value from Sinatra when the request is made. Although theoretically possible (with a forked process or background thread that kicks off before Sinatra racks up), you probably shouldn't attempt to commingle the two things into a single process.
Responding to your comment, it seems like you are just getting started with Ruby and possibly programming in general. You should take some time to learn about databases, SQL, and migrations (e.g. ActiveRecord migrations). It would be good knowledge for a lot of practical use cases.
Since it is probably beyond your scope today to install and configure MySQL, Redis, or something equivalent, we can use a simple SQLite database (and the sqlite3 gem) to solve your problem. SQLite is similar in some ways to a relational database in that it understands SQL statements, but instead of a full-fledged service it simply uses a file that lives on disk. Our server-side process (i.e. the loop) will be responsible for creating the database, the table to hold our value(s), and for updating the value(s). Our Sinatra process will open the database and retrieve the current value(s) as needed.
Before we get into the code, I want to stress that this is a very simplistic example, and it's merely one way to solve the problem. There are a lot of other techniques at your disposal. Maybe some other SO posters will be kind enough to post other suggestions. :-)
background.rb:
require 'sqlite3'
db = SQLite3::Database.new('/tmp/test.db')
# Initialize the table and zero count if not yet present.
db.execute <<-SQL
CREATE TABLE IF NOT EXISTS my_values (
id INTEGER PRIMARY KEY,
my_count INTEGER
);
INSERT OR IGNORE INTO my_values (id, my_count) VALUES (1, 0);
SQL
# Prepare a query to run every interval.
stmt = db.prepare <<-SQL
UPDATE my_values
SET my_count = my_count + 1
WHERE id = 1;
SQL
# Main processing loop.
loop do
stmt.execute
sleep 10
end
sinatra.rb:
require 'sinatra'
require 'sqlite3'
configure do
set :database, SQLite3::Database.new('/tmp/test.db', { :readonly => true })
end
get '/variable' do
count = settings.database.get_first_value <<-SQL
SELECT my_count FROM my_values WHERE id = 1;
SQL
"This is the current value of the variable: #{count}"
end
There are a lot of ways to improve the above as you continue to learn and grow as a Ruby programmer:
INSERT
, UPDATE
, and SELECT
SQL statements). CREATE TABLE
SQL statements).background.rb
to ensure that e.g. only one copy is running at a time.background.rb
so that it backgrounds (daemonizes) itself and writes out a log of its activities. sinatra.rb
(some ORMs provide this out of the box). You'll need to learn more about Rack and create a separate "rackup" script (e.g. config.ru
).Hope this helps.
Upvotes: 3
Reputation: 1984
You could just do it in a different thread, and make the variable global to access it, like:
require 'sinatra'
Thread.new do
loop do
if $variable!=nil
$variable+=1
else
$variable=0
end
end
end
get '\variable' do
"This is the current value of the variable: #{$variable}"
end
Source: http://blog.markwatson.com/2011/11/ruby-sinatra-web-apps-with-background.html?m=1
Upvotes: 1