【问题标题】:FS2 Running streams in sequenceFS2 按顺序运行流
【发布时间】:2018-01-10 22:50:16
【问题描述】:

我有一个相当简单的用例。我有两个 Web 服务调用,一个获取产品,另一个获取关系。我想运行 fetchProducts() 首先从产品集中提取一个字段,然后将输出传递给 fetchRelationships(ids: Seq[String]) 以便我可以在产品上重新设置关系。代码如下:

def fetchProducts(): Stream[IO, Seq[Product]]= {
 //webservice call
}

def fetchRelationship(ids: Seq[Product]): Stream[IO, Seq[Relationship]] = {
 //webservice call
}

//Pseudocode. How can I do this with fs2 Streams?
def process = {
      val prods = fetchProducts() //run this first
      val prodIds = prods.flatMap(i => i.productId)
      val rels = fetchRelationships(prodIds) //run after all all products are fetched 
      prods.forEach(p => p.setRelation(rels.get(p.id))
    }
}

 case class Product(productId: Option[String],
                        name: Option[String],
                        description: Option[String],
                        brandName: Option[String])

我受外部 Api 的限制,无法批量获取结果。所以我不确定如何使用 fs2 来表达这一点,或者我是否应该使用它。

【问题讨论】:

    标签: scala scala-cats scalaz-stream http4s fs2


    【解决方案1】:

    不幸的是,您在问题中的代码与您的文本描述不匹配,并且遗漏了很多重要的部分(例如整个 Relationship 类)。也不清楚是什么

    我受限于外部Api,无法批量获取结果

    真正的意思。也不清楚为什么Product 中的所有字段包括productId 都是Option

    以下代码可以编译,可能是也可能不是您需要的:

    case class Product(productId: Option[String],
                       name: Option[String],
                       description: Option[String],
                       brandName: Option[String],
                       relationships: mutable.ListBuffer[Relationship]) {
    
    }
    
    case class Relationship(productId: String, someInfo: String)
    
    def fetchProducts(): Stream[IO, Seq[Product]] = {
      //webservice call
      ???
    }
    
    //    def fetchRelationships(ids: Seq[Product]): Stream[IO, Seq[Relationship]] = {
    def fetchRelationships(ids: Seq[String]): Stream[IO, Seq[Relationship]] = {
      //webservice call
      ???
    }
    
    def process():  = {
      val prods = fetchProducts() //run this first
      val prodsAndRels: Stream[IO, (Seq[Product], Seq[Relationship])] = prods.flatMap(ps => fetchRelationships(ps.map(p => p.productId.get)).map(rs => (ps, rs)))
    
      val prodsWithFilledRels: Stream[IO, immutable.Seq[Product]] = prodsAndRels.map({ case (ps, rs) => {
        val productsMap = ps.map(p => (p.productId.get, p)).toMap
        rs.foreach(rel => productsMap(rel.productId).relationships += rel)
        ps.toList
      }
      })
      prodsWithFilledRels
    }
    

    【讨论】:

    • 感谢您的回答,对不完整的代码表示抱歉。我想我像你这样的聪明开发者能够弄清楚:)
    • @JoseH.Martinez,从你的评论中我不确定我的答案是你想要的还是你需要别的东西?
    • 你准确地回答了我的问题@SergGr。关于批处理,我想知道是否有办法将响应分别强制处理为产品流和关系对象。由于完整的有效载荷为 Json。但我想这应该是一个单独的问题。
    • @JoseH.Martinez,如果您正在寻找某个答案,您应该将该答案标记为已接受。至于批处理,我不确定我是否理解此描述的含义。可能带有更详细描述的单独问题是正确的方法。
    • 嗨@SergGr。我想知道是否有更惯用的方法来实现该算法,也许使用 fs2 Pipes。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    相关资源
    最近更新 更多