CQRS 应用程序-命令和事务

问题描述 投票:0回答:1

我有一个简单的用例:将产品从远程系统同步到本地应用程序。 实施的构建块的摘录:

  • SyncProductCommand + 关联的 SyncProductCommandHandler (包装在事务中,因为它是由干净的架构建议的并且也有意义)
  • RemoteProductRepository接口(域)+RemoteProductRepository(基础设施)

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 和刷新令牌,这意味着我无法再连接。

  • 干净的架构建议每个应用程序命令都应该在一个事务中。这是完全有道理的。在这种情况下我应该违反这条“法律”吗?
  • 我是否应该借此机会刷新 RemoteProductRepository 中的令牌并创建专用命令 RefreshTokenCommand + 处理程序?对我来说看起来不太好,因为我为技术细节创建了一个用例......
  • 创建专用连接和事务仅用于存储令牌,以便回滚不会影响此?

我认为问题基本存在,因为refreshToken没有回滚。

cqrs clean-architecture
1个回答
0
投票

刷新令牌是

RemoteProductRepository
的技术细节,因为此存储库用于从远程服务检索产品的客户端必须处理令牌。无需为令牌更新创建单独的命令。

因此,

RemoteProductRepository
本身会在需要时更新令牌,并在自己的事务中将其保存到数据库中。刷新令牌不需要以任何方式与产品保持一致,因此不需要在同一事务中执行此操作。目前,您将令牌保存在与域数据相同的数据库中,但令牌存储将来可能会发生变化,例如分布式缓存。

如果您的软件在多线程环境中运行,您还应该记住,多个线程可以并行刷新令牌,并且可能需要同步。

© www.soinside.com 2019 - 2024. All rights reserved.