我正在尝试按照以下方式进行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()
或类似的东西。