不好意思问这么大的问题。我对Rails threads
和mutex
没有太多的经验。
我有一个如下的类,不同的控制器使用它来获取每个客户的许可证。
每小时添加和删除客户及其许可证。可以使用api获取所有客户及其许可证。
我计划创建一个rake任务调用update_set_customers_licenses
,通过cronjob
每小时运行一次。
我有以下问题:
1)即使是mutex
,目前也有潜在的问题,我的rake任务有可能在更新时发生。知道怎么解决这个问题吗?
2)我下面的设计将json
写出来到一个文件,这样做是为了安全,因为api不是那么可靠。可以看到,它没有回读文件,所以实际上文件写入是无用的。我试图实现一个文件读取,但与mutex
和rake task
一起,它真的很混乱。任何提示都会有帮助。
class Customer
@@customers_to_licenses_hash = nil
@@last_updated_at = nil
@@mutex = Mutex.new
CUSTOMERS_LICENSES_FILE = "#{Rails.root}/tmp/customers_licenses"
def self.cached_license_with_customer(customer)
Rails.cache.fetch('customer') {self.license_with_customer(customer)}
end
def self.license_with_customer(customer)
@@mutex.synchronize do
license = @@customers_to_licenses_hash[customer]
if license
return license
elsif(@@customers_to_licenses_hash.nil? || Time.now.utc - @@last_updated_at > 1.hours)
updated = self.update_set_customers_licenses
return @@customers_to_licenses_hash[customer] if updated
else
return nil
end
end
end
def self.update_set_customers_licenses
updated = nil
file_write = File.open(CUSTOMERS_LICENSES_FILE, 'w')
results = self.get_active_customers_licenses
if results
@@customers_to_licenses_hash = results
file_write.print(results.to_json)
@@last_updated_at = Time.now.utc
updated = true
end
file_write.close
updated
end
def self.get_active_customers_licenses
#http get thru api
#return hash of records
end
end
我觉得每次rails加载时,环境都是"新鲜的",并且在实例之间没有"状态"的概念。也就是说,一个ruby实例(对rails的一个请求)中的互斥锁对另一个ruby实例(对rails的另一个请求,或者在本例中是一个rake任务)没有影响。
如果你顺着数据往上走,你会发现每个实例的公共根都是数据库,可以用来同步它们。您可以使用事务性块,也可以在数据库中设置和取消手动标记。