I have a simple Sinatra app running on top of Apache via Phusion Passenger.
When the app starts, I initiate a Ruby thread that does a heavy computation once a minute, leav开发者_StackOverflow中文版ing the result in a global variable (which is then accessed else where).
The variable is updated and refreshed once a minute as expected when using rackup
, however when run under Passenger, it does not seem to do this.
# Seed the initial license data - on Sinatra starting - and
# set it on a global variable.
$license_data = generate_license_data(360)
# Start up a worker thread that will update the license data
# every 60 seconds. This thread will run until termination
# of the parent thread. Only this thread will modify the values
# of the global variable "license_data".
worker_thread = Thread.new do
while true
sleep 60
t = Time.now
print "Generating license data ..."
$license_data = generate_license_data(360)
print " OK (#{seconds_to_string(Time.now-t)})\n"
end
end
# Generate the actual HTML snippet we need for the license entry
# by accessing the global variable "license_data".
def generate_license_entry
# The license block.
@licensechart = {}
@licensechart[:values] = $license_data[:values_string]
# Generate the table entry.
haml :license
end
Any ideas? I'll also be happy to know of an alternate, better way of caching a computation, and how to update it once a minute.
Depending on how you have passenger configured, it may have more than one process running (so you'd be duplicating the calculation work in each process), or none (as it can shut down instances that have not served requests for some time).
Using another system to run background tasks (like Resque or delayed_job) would be much more reliable, and allow you to configure Passenger according to your web request needs independently of your worked thread requirements.
I'm not quite into Passenger, but I think it's spawning several processes for serving responses and therefore might not be able to update and or access the variable. Saving and accessing the data in a database should at least fix that problem. For that scenario I personally would go with Resque with Resque Scheduler, which is a library for creating and processing (recurring) background jobs, which is what you do right now with a thread.
And again, the Passenger statement is highly speculative and might be wrong.
Best regards
Tobias
精彩评论