通过cats.effect.IO从flatMMapping请求超时



我正试图用IO monad中的Map转换封装在cats.effect.IO中的一些数据。我在blaze服务器上使用http4s,当我使用以下代码时,请求超时:

def getScoresByUserId(userId: Int): IO[Response[IO]] = {
implicit val formats = DefaultFormats + ShiftJsonSerializer() + RawShiftSerializer()
implicit val shiftJsonReader = new Reader[ShiftJson] {
def read(value: JValue): ShiftJson = value.extract[ShiftJson]
}
implicit val shiftJsonDec = jsonOf[IO, ShiftJson]
// get the shifts
var getDbShifts: IO[List[Shift]] = shiftModel.findByUserId(userId)
// use the userRoleId to get the RoleId then get the tasks for this role
val taskMap : IO[Map[String, Double]] = taskModel.findByUserId(userId).flatMap {
case tskLst: List[Task] => IO(tskLst.map((task: Task) => (task.name -> task.standard)).toMap)
}
val traversed: IO[List[Shift]] = for {
shifts <- getDbShifts
traversed <- shifts.traverse((shift: Shift) => {
val lstShiftJson: IO[List[ShiftJson]] = read[List[ShiftJson]](shift.roleTasks)
.map((sj: ShiftJson) =>
taskMap.flatMap((tm: Map[String, Double]) =>
IO(ShiftJson(sj.name, sj.taskType, sj.label, sj.value.toString.toDouble / tm.get(sj.name).get)))
).sequence
//TODO: this flatMap is bricking my request
lstShiftJson.flatMap((sjLst: List[ShiftJson]) => {
IO(Shift(shift.id, shift.shiftDate, shift.shiftStart, shift.shiftEnd,
shift.lunchDuration, shift.shiftDuration, shift.breakOffProd, shift.systemDownOffProd,
shift.meetingOffProd, shift.trainingOffProd, shift.projectOffProd, shift.miscOffProd,
write[List[ShiftJson]](sjLst), shift.userRoleId, shift.isApproved, shift.score, shift.comments
))
})
})
} yield traversed
traversed.flatMap((sLst: List[Shift]) => Ok(write[List[Shift]](sLst)))
}

正如您可以看到的TODO注释。我已经将此方法缩小到TODO注释下方的平面图。如果我移除那个flatMap并且仅仅返回";IO(移位(";对于遍历的变量,请求不超时;然而,这对我没有多大帮助,因为我需要使用lstShiftJson变量,该变量包含我转换后的json。

我的直觉告诉我正在滥用IO monad,但我不太确定是怎么回事。

感谢您花时间阅读本文!

因此,在Luis评论的指导下,我将代码重构为以下内容。我不认为它是最佳的(即结尾的平面图似乎不必要,但我不知道如何删除它。但这是我拥有的最好的。

def getScoresByUserId(userId: Int): IO[Response[IO]] = {
implicit val formats = DefaultFormats + ShiftJsonSerializer() + RawShiftSerializer()
implicit val shiftJsonReader = new Reader[ShiftJson] {
def read(value: JValue): ShiftJson = value.extract[ShiftJson]
}
implicit val shiftJsonDec = jsonOf[IO, ShiftJson]
// FOR EACH SHIFT
// - read the shift.roleTasks into a ShiftJson object
// - divide each task value by the task.standard where task.name = shiftJson.name
// - write the list of shiftJson back to a string
val traversed = for {
taskMap <- taskModel.findByUserId(userId).map((tList: List[Task]) => tList.map((task: Task) => (task.name -> task.standard)).toMap)
shifts <- shiftModel.findByUserId(userId)
traversed <- shifts.traverse((shift: Shift) => {
val lstShiftJson: List[ShiftJson] = read[List[ShiftJson]](shift.roleTasks)
.map((sj: ShiftJson) => ShiftJson(sj.name, sj.taskType, sj.label, sj.value.toString.toDouble / taskMap.get(sj.name).get ))
shift.roleTasks = write[List[ShiftJson]](lstShiftJson)
IO(shift)
})
} yield traversed
traversed.flatMap((t: List[Shift]) => Ok(write[List[Shift]](t)))
}
  1. Luis提到,将我的List[Shift]映射到Map[String,Double]是一个纯操作,所以我们想使用Map而不是flatMap
  2. 他提到,我正在IO中封装来自数据库的每一个操作,这会导致大量的重新计算。(包括DB交易(
  3. 为了解决这个问题,我在for循环中移动了所有的数据库操作,使用"&lt-&quot;operator to flatMap每个返回值都允许在IO monad中使用变量,从而防止以前经历的重新计算

我确实认为一定有更好的方法来返回我的返回值。flatMMapping;横越";回到IO monad内部的变量似乎是不必要的重新计算,所以请任何人纠正我。

相关内容

  • 没有找到相关文章

最新更新