并行后,akka流停止

时间:2017-08-01 13:04:19

标签: scala playframework akka-stream

我尝试使用akka-streams(以及对它的有限理解)和Apache的pdfbox构建一个小的PDF解析器。 我没有真正得到的一件事是,在给定的 mapAsync 给定数量的 parallelism 之后,流完全停止。 因此,如果PDF-doc有20页并且并行度设置为5,则前5页被处理,其余被忽略,如果设置为20,则一切都很好。谁知道我做错了什么?

  class PdfParser(ws: WSClient, conf: Configuration, parallelism: Int) {

  implicit val system = ActorSystem("image-parser")

  implicit val materializer = ActorMaterializer()

  def documentPages(doc: PDDocument, key: String): Iterator[Page] = {

    val pages: util.List[_] = doc.getDocumentCatalog.getAllPages
    val pageList = (for {
      i ← 0 until pages.size()
      page = pages.get(i)
    } yield Page(page, s"$key-$i.jpg")).toIterator
    pageList
  }

  val pageToImage: Flow[Page, Image, NotUsed] = Flow[Page].map { p ⇒
    val img = p.content.asInstanceOf[PDPage].convertToImage()
    Image(img, p.name)
  }

  val imageToS3: Flow[Image, String, NotUsed] = Flow[Image].mapAsync(parallelism) { i ⇒

    val s3 = S3.fromConfiguration(ws, conf)
    val bucket = s3.getBucket("elsa-essays")
    val baos = new ByteArrayOutputStream()
    ImageIO.write(i.content, "jpg", baos)
    val res = bucket add BucketFile(i.name, "image/jpeg", baos.toByteArray)
    res.map { _ ⇒
      "uploaded"
    }.recover {
      case e: S3Exception ⇒ e.message
    }
  }

  val sink: Sink[String, Future[String]] = Sink.head[String]

  def parse(path: Path, key: String): Future[String] = {

    val stream: InputStream = new FileInputStream(path.toString)
    val doc = PDDocument.load(stream)
    val source = Source.fromIterator(() ⇒ documentPages(doc, key))

    val runnable: RunnableGraph[Future[String]] = source.via(pageToImage).via(imageToS3).toMat(sink)(Keep.right)
    val res = runnable.run()

    res.map { s ⇒
      doc.close()
      stream.close()
      s
    }

  }

}

1 个答案:

答案 0 :(得分:0)

问题出在你的水槽里。 Sink.head将从物化Stream中返回一个元素。所以问题是,为什么在流实现中使用mapAsync(> 1)时会收到多个值?也许是因为它使用多个演员推动下游价值。

在任何情况下,将您的接收器更改为:

<?php
function get_title($url){
    $c = curl_init();
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($c, CURLOPT_USERAGENT, 'Linux / Firefox 29: Mozilla/5.0 (X11; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0');

    $str = curl_exec($c);
    if(strlen($str)>0){
        $str = trim(preg_replace('/\s+/', ' ', $str)); // supports line breaks inside <title>
        preg_match("/\<title\>(.*)\<\/title\>/i",$str,$title); // ignore case
        return $title[1];
    }
}
//Example:
echo get_title("https://webdesign.tutsplus.com/articles/the-complete-beginners-guide-to-chinese-fonts--cms-23444");

它会起作用。