scalaz/scalaz-stream — pull request #250 by pchiusano (2014-10-01 22:02:35+00:00)
Title: New API for tcp based sockets

Review by @pchlupacek and @fthomas

Hi guys, I wasn't really happy with the existing API in `nio`, especially for code that needs to alternate between reading and writing to the socket in a particular sequence. This PR introduces a new type, `Connection`, and a `Process[Connection,A]` represents a stream that may read or write to a socket. See [`tcp.scala`](https://github.com/scalaz/scalaz-stream/blob/topic/socket/src/main/scala/scalaz/stream/tcp.scala#L113).

Here's the logic for an echo server:

```Scala
val echo: Process[Connection,Unit] =
tcp.writes_(tcp.reads(1024, allowPeerClosed = true)) ++
tcp.eof ++
Process.emit(())
```

To actually get a server for that logic, you do:

```Scala
val server: Process[Task, Throwable \/ Unit] =
tcp.server(addr, concurrentRequests = 1)(echo).run
```

Here's logic for a chat server (I think):

```Scala
val server = Process.suspend {
val topic = async.topic[String]()
val chat =
tcp.reads(1024).pipe(text.utf8Decode).to(topic.publish).wye {
tcp.writes(tcp.lift(topic.subscribe.pipe(text.utf8Encode)))
} (wye.mergeHaltBoth)
tcp.server(addr, concurrentRequests = 50)(chat).run
}
```

Check out [the tests](https://github.com/scalaz/scalaz-stream/blob/topic/socket/src/test/scala/scalaz/stream/TcpSpec.scala#L33). I'd like to get some feedback on this before merging. I anticipate deprecating and then removing the existing `nio` stuff in a future release, and then moving the `nio` specific stuff out of `tcp` and into `nio`, so I want to make sure the `tcp` API handles all the use cases of the existing API.

There seems to be a JDK issue on Mac with `AsynchronousSocketChannel` - it sometimes hangs on close when the socket is read / written concurrently. It does not happen often, but with scalacheck it happens every time. :) The travis build (which uses linux) is passing, though. @pchlupacek I am pretty sure this issue is also present in the existing `nio` implementation and I feel like I remember seeing random hangs on mac in some earlier version of the test suite. Does this sound familiar at all? It seems like the [netty devs may have encountered the same issue with `AsynchronousSocketChannel`](https://github.com/netty/netty/issues/852). I'd love to get to the bottom of it since I know a lot of people develop on Mac.