我有一个简单的用例:将产品从远程系统同步到本地应用程序。 实施的构建块的摘录:
RemoteProductRepository 通过 REST 接口从远程系统获取 RemoteProduct。使用 OAuth 令牌(带有刷新令牌)进行身份验证。 Repo(详细来说是抽象服务/客户端)决定是否必须刷新令牌。如果是,它将使用刷新令牌刷新令牌,并将两者(新令牌和新刷新令牌)保存到数据库中。
流程将是这样的(以非常简化的表示):
SyncProductCommandHandler {
handle(productId) {
try {
con.beginTransaction();
remoteProduct = remoteProductRepository.get(productId); // this will maybe refresh the token and save it to the database too
someService.createOrUpdateLocalProduct(remoteProduct); // will throw an exception
con.commit();
} catch (Exception e) {
// this not only rollbacks the changes made to the local product
// it will also rollback updates (in the local db) to the token and refresh-token. but clearly not remotely.
con.rollback();
}
}
}
你可以想象问题是什么...回滚也会丢弃我的新 oAuth-Token 和刷新令牌,这意味着我无法再连接。
我认为问题基本存在,因为refreshToken没有回滚。
刷新令牌是
RemoteProductRepository
的技术细节,因为此存储库用于从远程服务检索产品的客户端必须处理令牌。无需为令牌更新创建单独的命令。
因此,
RemoteProductRepository
本身会在需要时更新令牌,并在自己的事务中将其保存到数据库中。刷新令牌不需要以任何方式与产品保持一致,因此不需要在同一事务中执行此操作。目前,您将令牌保存在与域数据相同的数据库中,但令牌存储将来可能会发生变化,例如分布式缓存。
如果您的软件在多线程环境中运行,您还应该记住,多个线程可以并行刷新令牌,并且可能需要同步。