I'm working on a Sinatra-JRuby application and handling a situation where concurrent API calls are coming to the API layer and then subsequently handled by service and adapter layer. I'm having a GlobalService module to share the common information, so that I can access this common information from any other layer. This works just fine until concurrent calls come and reset the value of thw previous API. Though I've implemented Mutex to address this problem, but I've got a gut feeling that this is not the right approach to the problem. Here is what I've implemented:
require 'thread'
module GlobalService
@@mutex = Mutex.new
def self.set_header(auth_subject, transaction_id)
@@mutex.synchronize {
@auth_subject = auth_subject
@transaction_id = transaction_id
}
end
def self.get_header
@@mutex.synchronize {
return @auth_subject, @transaction_id
}
end
end
Please let me know of any alternative solution to address this problem.
Sharing memory will never really be thread safe, so you might do well to use a message passing strategy. My preference for this would be to create actors and have them communicate about state change. Check out Concurrent Ruby's actors http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html .
You could do something like
require 'concurrent'
class GlobalService < Concurrent::Actor::Context
def initialize(auth_subject, transaction_id)
@auth_subject = auth_subject
@transaction_id = transaction_id
end
def on_message(message)
#some logic
@auth_subject = message.auth_subject
@transaction_id = message.transaction_id
end
end
service = GlobalService.spawn(:first, "header...", id) etc...
I've used this strategy in the past and it has worked out fairly well. You may also want to ask for help over at https://gitter.im/ruby-concurrency/concurrent-ruby Pitrch is usually very helpful!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.