我应该如何通过DDD获得这个值到Akka HTTP中的异步代码

8ehkhllq  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(188)

我尝试使用域驱动设计编写Akka HTTP Web服务,但我很难将Web服务接收到的技术数据传递给Future(即客户端发送给Web服务的correlationId)内执行工作的代码。
我对DDD的理解是,作为一种实现选择,correlationId不应该出现在域中:

package domain
trait MyRepository {
  def startWork(): Future[Unit]
}

为了使它在不作为方法参数的情况下对实现代码可用,我考虑使用线程本地存储,如org.slf4j.MDCThreadLocal。但是,我不知道这是否可行,或者对Web服务的多个调用是否会由同一个线程处理并覆盖该值。
以下是实现:

package infra
class MyRepository(implicit executor: ExecutionContextExecutor) extends domain.MyRepository {
  override def startWork(): Future[Unit] = {
    Future {
      val correlationId = ??? // MDC.get("correlationId") ?
      log(s"The correlationId is $correlationId")
    }
  }
}

我的Web服务中的路由:

val repo = new infra.MyRepository()
val route = path("my" / "path") {
  post {
    parameter('correlationId) { correlationId =>
      ??? // MDC.put("correlationId", correlationId) ?
      onComplete(repo.startWork()) {
        complete(HttpResponse(StatusCodes.OK))
      }
    }
  }
}

我的问题有两个:

  • 我的总体设计是否合理,DDD是否良好?
  • 使用org.slf4j.MDCThreadLocal是否有效,或者是否有更好/更适合Akka的实现方式?
dvtswwa3

dvtswwa31#

线程局部变量(包括MDC,尽管Lightbend订阅包括将MDC与消息和future一起传播的工具)通常是一个糟糕的主意,因为通常不能保证给定的任务(在这种情况下是Future,或处理已发送消息的执行元)将在与请求该任务的线程相同的线程上执行(在特定的情况下,任务与外部服务/DB(通过使用Future {}暗示)执行[可能阻塞]交互,您非常不希望这种情况发生)。此外,即使任务最终在请求该任务的同一个线程上执行,不太可能没有其他可能改变MDC/thread-local的任务在此期间执行。
我本人并不认为将相关ID作为参数传递给startWork有什么问题:您已经通过HTTP端点有效地公开了它。

相关问题