我已经和这头野兽搏斗了几天,需要一些指导。我的原始代码太大而且太麻烦,所以我试图在这里创建所有部分并且它(几乎)编译,我在下面编写的代码中遇到了一些错误。
我想要做的是让“失败”将链级联到我的 API 层。该域围绕连接到后端以通过 MAC 地址获取设备健康检查列表。一个账号有多个设备,一个设备有多个mac地址。只有主 mac 会从后端系统获得成功响应。
Update 1: By Failure here I mean connection issues to the backend client. an Unknown mac (i.e. a mac that's not found/resolved) is not considered a failure. It should be reported as a Success.
这是我迄今为止重新创建的内容,以供您模拟我的系统。可以切换第 18 行和第 19 行以查看不同的条件。
import scala.util._
trait EquipmentStatus { val mac: String }
case class Offline(mac: String) extends EquipmentStatus
case class Online(mac: String) extends EquipmentStatus
case class Unknown(mac: String) extends EquipmentStatus
case class EquipmentHealth(mac: String, status: EquipmentStatus)
case class Account(number: Int, equipments: List[Equipment])
case class Equipment(macs: List[String]) {
def primaryMacs = macs.filter(_.endsWith("00"))
}
object StatusChecker {
def checkBatchStatuses(macs: List[String]):
Try[List[EquipmentStatus]] =
//Success(macs.map(Online(_)))
Failure(new Exception("Connection Timed Out"))
}
object DeviceService {
def getMacsByAccount(macs: List[String], equipments: List[Equipment]): Try[List[EquipmentHealth]] = {
for {
mac <- macs
equipment <- equipments.filter(_.macs.contains(mac))
statuses <- StatusChecker.checkBatchStatuses(equipment.primaryMacs)
} yield resolveStatus(statuses, mac)// ######### HOW DO I CONVERT/COLLECT Try[EquipmentHealth] to Try[List[EquipmentHealth]] AND ALSO ALLOW Try[Exception()] TO PROPAGATE UP AS WELL?
}
def resolveStatus(statuses: List[EquipmentStatus], mac: String): Try[EquipmentHealth] = {
statuses.partition(_.mac == mac) match {
case (Nil, Nil) => Success(EquipmentHealth(mac, Unknown(mac)))
case (List(one), Nil) => Success(EquipmentHealth(mac, one))
case _ => Success(EquipmentHealth(mac, Unknown(mac)))
}
}
}
val equipments = List(Equipment(List("mac100", "mac222")), Equipment(List("mac333", "mac400")))
val exampleAcc = Account(1234, equipments)
DeviceService.getMacsByAccount(List("mac222"), exampleAcc.equipments)
在我的代码库中,Try 实际上是一个自定义的 Boxed (Either) 类型,包含成功和失败。我的理解能力欠缺。我想要的是从 Try[EquipmentHealth] 到 Try[List[EquipmentHealth]]。
我把这弄得太复杂了吗?有没有我没有看到的更简单的方法?
最佳答案
你不是只想拥有List[Try[EquipmentStatus]]
而不是 Try[List[EquipmentStatus]]
?前者不允许从单个故障中恢复。理解总是产生类似迭代的结果,你不能返回 Try[List[Something]]
从中。
为了给出更详细的答案,我需要您澄清预期的行为。你的DeviceService.resolveStatus
很奇怪只能导致成功,这主要是因为您没有保留有关哪些查询失败的任何信息,因此您无法在“此查找失败”和“此 MAC 地址未知”之间做出决定。我认为应该删除未知案例,我们总是假设如果没有成功返回,那么它就是失败。否则,您需要存储更多信息,例如 List[(String, Try[EquipmentStatus]]
其中元组的第一个元素是被查询的 MAC 地址(或者,为了更好的性能,使用一个键是地址的映射)。
关于Scala 类型系统帮助 : Let a failure cascade up the stack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53791743/