我的应用正在使用OAuth资源,并且有时必须使用其刷新令牌刷新访问令牌。为此,我正在做类似的事情:
record = MyClientModel.find(...)
client = OAuthClient.new(record.access_token)
begin
tries ||= 2
client.do_something
rescue ExpiredOAuthToken => e
new_access_token, new_refresh_token =
client.refresh_token(record.refresh_token)
client.access_token = new_access_token
record.access_token = new_access_token
record.refresh_token = new_refresh_token
record.save
retry unless (tries -= 1).zero?
raise e
end
此代码旨在在Web请求和工作进程中同时运行,但显然,它不是线程安全的,例如:
record.access_token
到期ExpiredOAuthToken
#refresh_token
ExpiredOAuthToken
#refresh_token
但由于record.refresh_token
现在无效我之前从未真正考虑过线程安全问题,因此我正在寻找有关如何改进此代码的建议。
答案 0 :(得分:0)
我最近遇到了这个问题-就我而言,我将访问令牌存储在ActiveRecord模型中,因此可以使用ActiveRecord fi<-list.files("C:/Users/Desktop/DL/Test",full.names=T)
dat<-lapply(fi, read.csv, row.names = NULL)
lapply(seq_along(dat), function(i) {
write.csv(dat[i], paste0('address/to/file', i,'.csv'))
})
方法(与MySQL / PostgreSQL一起使用)。
with_lock
当我的线程遇到过期的令牌时,它们都将调用# ...inside Authorization model instance methods
def refresh
# do not allow more than one refresh to occur simultaneously
with_lock do
# if the token was just refreshed, return (there may be threads waiting on this token)
return oauth_token if updated_at > 5.seconds.ago
oauth = OmniAuth::Strategies::Custom.new(nil)
token =
OAuth2::AccessToken.new(
oauth.client,
oauth_token,
refresh_token: oauth_refresh_token
)
new_token = token.refresh!
return unless new_token
update!(
oauth_token: new_token.token,
oauth_refresh_token: new_token.refresh_token,
oauth_expires_at: Time.at(new_token.expires_at)
) && new_token.token
end
end
,但是仅执行第一个refresh
,其他线程等待,并在更新时立即获得新令牌。