所以,我有两个线程,每个都已经在他们自己的hibernate事务中(由于一些魔法,我无法控制)。他们都希望获得oauth
连接,但令牌已过期,因此他们需要刷新并更新它。此特定提供程序在刷新时使旧访问令牌无效,因此所有线程必须最终使用最新的访问令牌。
我有一个分布式read-write locking mechanism
(因为有多个应用程序实例),确保只有一个线程刷新oauth
组件的标记,而其余的则等待获取更新的标记。 updateComponent
和getComponent
方法都在事务中创建自己的新事务,希望在write-lock
发布之前进行刷新。不幸的是,情况似乎并非如此。
这是我的OauthComponent
帮助
@Transactional(readOnly=false, rollbackFor=Throwable.class, propagation=Propagation.REQUIRES_NEW)
void updateToken(String connectionId, OauthComponentDto component);
@Transactional(readOnly=true, propagation=Propagation.REQUIRES_NEW)
<T extends OauthComponentDto> T getComponent(String connectionId);
这是我的oauth令牌刷新代码:
// FYI, already in a transaction here. Can't change that
final String connectionId = connection.getIdentifier();
final String lockKey = String.format("%s-refresh", connectionId);
try { // If write-lock can be acquired, refresh the token and save to db
getWriteLock(lockKey);
try {
Oauth2ComponentDto component = oauthComponentHelper.getOauthComponent(connectionId);
if (isExpiringSoon(component)) {
refreshToken(component, connection);
oauthComponentHelper.updateToken(connectionId, component); // updates in new transaction
}
return component;
} finally {
releaseWrite(lockKey);
}
} catch (LockNotAcquiredException e) {
try { // Write-lock was not acquired, so wait for read-lock to get new token from db
getReadLock(lockKey);
try {
Oauth2ComponentDto component = oauthComponentHelper.getOauthComponent(connectionId); // gets with new transaction
if (isExpiringSoon(component)) {
throw new ExpiredAuthorizationException();
}
return component;
} finally {
releaseRead(lockKey);
}
} catch (LockNotAcquiredException e2) {
throw new ExpiredAuthorizationException();
}
}
最终发生的事情是等待读锁的线程最终使用旧的访问令牌。我相信这是因为读取线程在刷新更新之前最终从db读取。有没有人有任何建议?