我对 scalaz-stream 和特别是 scalaz.stream.tcp 都很陌生。我正在尝试为自己的教育目的做一个非常简单的服务器。我将请求解析为命令,执行它们以产生响应,然后将响应写回客户端。我遇到的问题是我想将每个收到的命令记录到标准输出。
这是我传递给 tcp.server 的内部进程:
def inner: Process[tcp.Connection, Unit] = {
val requests: Process[Connection, String] = tcp.reads(1024) pipe text.utf8Decode
val cmds: Process[Connection, Command] = requests.map(parseRequest)
val header: Process[Task, ByteVector] = Process("HEADER\n").pipe(text.utf8Encode)
val loggedCmds: Process[Connection, Command] = cmds.map { cmd =>
println(cmd.toString)
cmd
}
val results: Process[Connection, Process[Task, ByteVector]] = loggedCmds.map(_.execute)
val processedRequests: Process[Connection, Unit] = results.flatMap(result => tcp.writes(tcp.lift(header ++ result)))
processedRequests
}
(我没有在任何地方指定类型的习惯;我这样做只是为了尝试处理事情。我打算删除这些。)
上面的代码实际上可以正确编译和运行,但我觉得它不是很干净或惯用。具体来说,我对loggedCmds 部分不满意。我想通过 .observer 或使用 writer.logged/mapW/drainW 使用 io.stdOutLines,但无论我尝试什么,我似乎都无法正确排列类型。我总是遇到任务和连接之间的类型冲突。tcp.lift 似乎有助于输入流,但它似乎不适用于接收器。是否有更清洁/更好的方法来执行 loggedCmds 部分(FWIW:我愿意对上述任何代码进行更正或改进)。
我应该注意,如果我只是通过 io.stdOutLines 将结果发送到标准输出,我没有问题(“通过”在这种情况下似乎有效,我在示例中看到过),这只是当我想发送流到 io.stdOutLines并继续使用流响应客户端。