In environment.rb file, I initialize a connection to some data vending servers, through TCP sockets.
The connection object is global and hence the code:#environment.rb
$generic_connection = ConnectionClass.instance (singleton class)
$generic_connection.connect( this call will make the connection)
The above approach is to make sure that, only one connection is made to the data vending servers.ConnectionClass is a library Class that, I have written to handle connections and to ensure exception handling and all that stuff.
Now, in our rails code, whenever we need some data from these data vending servers, we use this global variable to get the data.#in controllers
$generic_connection.get_data('<our internal protocol>')
Since, we switched to mongrel, we are facing a strange issue. Our protocol code, specify what kind of data we want from data vending servers.So, lets say we want, x informatio, then we specify xxx as protocol code and get the data. protocol code "yyy" would give completely different kind of data. Now..sometimes what happens is, an Ajax call requests xxx protocol code and in the response we get data of protocol code yyy. Data vending servers are threaded again, and for each connection it starts a new thread and each request is served on a new thread.
Data vending servers are again mostly written in ruby.
Now, I am wondering where is the problem?
As i know, mongrel serves requests on new threads, so what happens to this global variable that is shared among the threads.Is there a possiblity that, problem is here?
I mean, lets say a thread is using this global variable for fetching data for protocol code xxx and same time another thread requests for protocol code yyy. My connection class, which is basically a proxy to these data vending servers, may not be thread safe.If this is the problem, then can anybody suggest better approach of making single connection to data vending servers, without using shared global variables.
It could be a problem with our data vending servers also.But I am not so, sure about that.
For anyone interested here is the ConnectionClass code:
require 'socket'
require 'timeout'
require 'singleton'
require 'yaml'
class ConnectionClass
include Singleton
def connect
p = YAML.load(File.read("#{RAILS_ROOT}/config/parameters.yaml"))
@socket_file = p["socket_file"]
return connect_to_proxy
end
def connect_to_proxy
begin
@proxy_con = UNIXSocket.open(@socket_file.strip)
return @proxy_con
rescue Exception => e
return nil
end
end
def get_data(request_string)
req_array = request_string.split(':')
code = req_array[0].strip
msg = req_array[1].strip
symbol = req_array[2].strip
return get_data_from_proxy(code,symbol)
end
def get_data_from_proxy(code,symbol)
temp_string = code + '<' + symbol + '>'
ret_data = nil
begin
@proxy_con.puts(temp_string)
rescue Errno::EPIPE
unless connect_to_proxy.nil?
@proxy_con.puts(temp_string)
else
return nil
end
rescue Exception => e
return nil
end
begin
timeout(8) do
ret_data = @proxy_con.gets()
end
rescue Timeout::Error
return nil
rescue Exception => e
return nil
end
if ret_data =~ /^600*/
return nil
elsif ret_data =~ /^620*/
return nil
else
return ret_data
end
end
end
Evidently, when rails load(i.e mongrel starts), the only call made is, $generic_connection.connect(from environment.rb), and hence within this class, only @proxy_con should be shared among the threads IMHO.
So, what happens when subsequent calls to $generic_connection.get_data is made from controller(ie mongrel threads)? while one thread is waiting for @proxy_con.gets, another thread can call the same method, but the question is, both the threads will share local variables defined within get_data and get_data_from_proxy methods?
If i make, both the methods threaded, it should solve the problem? but i am wondering, how mongrel would handle it.
_______________________________________________ Mongrel-users mailing list Mongrel-users@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-users