jnthn / p6-io-socket-async-ssl

Asynchronous TLS sockets in Raku
11 stars 19 forks source link

Question: Why does .upgrade-server return a Supply #50

Closed zostay closed 4 years ago

zostay commented 4 years ago

I am somewhat confused by the way .upgrade-server works. I expected it to return a Promise that is kept with the connection following the SSL handshake or broken if that fails. Instead, it returns a Supply that emits the connection following the SSL handshake and quits if fails. Furthermore, the Supply never closes, so performing an await on it will block forever. I expected that to work even if it returned a Supply as I can't think what it would mean for the Supply to emit more than one value.

  1. It would be nice if that were more clearly documented in the README example. Especially, the description of what the Supply emits and what its behavior is.

  2. I was hoping for an explanation of why it works this way, if this is the intended behavior.

jnthn commented 4 years ago

It's a Supply to hint to the consumer that they should be using whenever, not await, because if they use await then they'll cause a deadlock. Given:

  1. A whenever block should run to completion before another message is processed (transactional semantics)
  2. A sender will not do another emit until the emit it was currently working on as been processed by downstream logic (back-pressure)

Then if you put an await inside the thing that handles a packet, then no further packets can be emitted, but the await depends on them in order for the handshake to be processed. A whenever allows sufficient concurrency to avoid this problem. I think you were part of the way to realizing this:

the Supply never closes, so performing an await on it will block forever

But the reason it never closes is really because it's impossible for it to complete anyway.

Please see the upgrade tests for a working example; I suspect when I debugged and fixed that, I may have forgotten to upgrade the documentation. There's a separate issue for that, so I'll close this one now that the question is answered.

zostay commented 4 years ago

That makes sense. Thank you for taking the time to explain it.

Basically, you are making use of whenever/tap semantics on a Supply to enforce the natural flow required for the plaintext part of the connection to quit, initiate the SSL handshake, and then and only then start the SSL part of the connection.

It's an interesting pattern. I'll have to think about it some more. I may have to blog about it. Thanks again.