2

私は 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 経由で stdout に送るだけであれば問題はありません (例で見たように、その場合は「スルー」が機能するようです)。ストリームを io.stdOutLines に送信し、引き続きストリームを使用してクライアントに応答します。

4

2 に答える 2

0

より短い解決策は

val log = stdOutLines contramap { (_: Any).toString }
requests map(parseRequest) observe log
于 2015-09-04T15:22:53.860 に答える
0

自力で解決しました(やっと)。「.toChannel」を使用して、次のことができました。

val cmdFormatter = process1.id[Command].map(_.toString)
val cmdPrinter = io.stdOutLines.pipeIn(cmdFormatter)

...

val cmds: Process[Connection, Command] = requests.map(parseRequest) through
    cmdPrinter.toChannel
于 2015-05-03T00:37:21.410 に答える