Open michalrus opened 6 years ago
@michalrus Yes, receiveData
blocks until data is received (just like most of the lower-level networking functions in Haskell). In order to send and receive, you can use forkIO
(or something like the async
) package to kick off a writer thread. Does that solve your problem?
Well, that receive
blocks is understandable.
What I want is a time-outing receive
.
So if you wrap it in http://hackage.haskell.org/package/base-4.12.0.0/docs/System-Timeout.html, the wrapped call returns with a Nothing
, but then sendTextData
called later on does… nothing.
System.Timeout.timeout
works by sending an async exception to the current thread.
Oh! I completely misunderstood the question, sorry. Yes, that makes sense to have.
I think we should implement this the nice way but that will be a breaking change. We basically want to be able to extend Stream
's interface with a Success | FatalError | Timeout
result type from read and pass in an optional timeout.
As for the API, do you think the timeout should be global (i.e. set on socket/stream creation) or local (i.e. a parameter to receive)?
I see…
IMO, local — see also #32. =)
I mean, these issues (+ the ones with ping timeout #174 #159) can certainly be worked around either like proposed by @rwbarton in #32, or some other way with Async
, but they would be nice to have natively — being explicit about the fact that networking is, in essence, unreliable. ¯\_(ツ)_/¯
Also not all programmers might be able to implement this correctly, so it’s a better task for the library.
Cf. fallacy 1. of https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing:
The network is reliable.
Software applications are written with little error-handling on networking errors. During a network outage, such applications may stall or infinitely wait for an answer packet, permanently consuming memory or other resources. When the failed network becomes available, those applications may also fail to retry any stalled operations or require a (manual) restart.
Also, similar to this, imagine:
finally
(forever $ receiveTextData conn >>= processMsgSomehow)
(sendTextData conn "bye bye")
If I throw an async exception to this simple code above, sendTextData
will throw a Network.WebSockets.ConnectionClosed
exception despite WAI thread clearly still being alive (the finally
hook happens in that WAI thread).
These API choices of WebSockets prevent writing slightly more, hmmm, refined(?) code, like the one above.
It’s not possible to implement something like:
… the client will never see the
"timeouted"
message.