怎么做Monadic递归?

时间:2017-12-02 23:37:20

标签: scala recursion scala-cats

我正在尝试按照以下方式进行monadic递归:

object KkConsumer {

  private val delegate = Executors.defaultThreadFactory()

  def create
  (consumer: KkConsumerCreator): IO[Consumer[String, String]] =
    IO {
      val c = new KafkaConsumer[String, String](properties(consumer))
      c.subscribe(consumer.topic.asJavaCollection)
      c
    }

  def build[A]
  (consumer: Consumer[String, String])(cb: Vector[KkConsumerRecord] => IO[A])
  : IO[Thread] =
    for {
      t <- IO {
        val thread = delegate.newThread(() => {
          pool(consumer)(cb)
        })
        thread.setDaemon(true)
        thread
      }
    } yield t

  def run(thread: Thread): IO[Thread] =
    IO {
      thread.run()
      thread
    }

  //@tailrec
  private def pool[A]
  (consumer: Consumer[String, String])(cb: Vector[KkConsumerRecord] => IO[A]): IO[Unit] = {
    val records: ConsumerRecords[String, String] = consumer.poll(Long.MaxValue)
    val converted = records.iterator().asScala.map(rec => {
      KkConsumerRecord(rec.key(), rec.value(), rec.offset(), rec.partition(), rec.topic())
    })

    val vec = converted.foldLeft(Vector.empty[KkConsumerRecord]) { (b, a) =>
      a +: b
    }

    cb(vec).flatMap(_ => pool(consumer)(cb))
  }

  private def properties
  (consumer: KkConsumerCreator): Properties =
    Foldable[List]
      .foldRight(consumer.props, Later(new Properties())) { (a, b) =>
        a match {
          case ClientId(value) => b.map { p =>
            p.put(ConsumerConfig.CLIENT_ID_CONFIG, value)
            p
          }

          case AutoOffsetResetConfig(value) => b.map { p =>
            p.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, value)
            p
          }
        }
      }.map { p =>
      p.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, consumer.host)
      p.put(ConsumerConfig.GROUP_ID_CONFIG, consumer.groupId)
      p.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
      p.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer")
      p
    }.value

}

功能

  private def pool[A]
  (consumer: Consumer[String, String])(cb: Vector[KkConsumerRecord] => IO[A]): IO[Unit] = {
    val records: ConsumerRecords[String, String] = consumer.poll(Long.MaxValue)
    val converted = records.iterator().asScala.map(rec => {
      KkConsumerRecord(rec.key(), rec.value(), rec.offset(), rec.partition(), rec.topic())
    })

    val vec = converted.foldLeft(Vector.empty[KkConsumerRecord]) { (b, a) =>
      a +: b
    }

    cb(vec).flatMap(_ => pool(consumer)(cb))
  }

这就是我对monadic递归的意思 我使用如下:

  def main(args: Array[String]) {

    sys.addShutdownHook {
      latch.countDown
      println("exiting")
    }

    try {

      val c = KkConsumerCreator("localhost:9092", "khinkali", List("TEST"), List(ClientId("KHINKALI-IO"), AutoOffsetResetConfig("latest")))

      (for {
        c <- KkConsumer.create(c)
        b <- KkConsumer.build(c)(observe)
        t <- KkConsumer.run(b)
      } yield t).unsafeRunSync()

      latch.await
    } catch {
      case e: Throwable =>
        System.exit(1)
    }

    System.exit(0)


  }

  def observe(rec: Vector[KkConsumerRecord]): IO[Unit] =
    IO {
      println("Hello")
      println("Hell2")
    }

}

回调observe根本没有被调用。它停在cb(vec).flatMap(_ => pool(consumer)(cb))函数的pool上。

我认为原因是,为什么回调没有被调用,因为它错过了unsafeRunSync()或类似的东西。

0 个答案:

没有答案