Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream -> Response #246

Open
smaldini opened this issue Dec 18, 2017 · 4 comments
Open

Stream -> Response #246

smaldini opened this issue Dec 18, 2017 · 4 comments

Comments

@smaldini
Copy link
Member

Would it make sense to support a finite stream that produces a single response in the spec ? We already have Req/Res and Fire'n'forget, but what if an application wants a fully formed response for a given finite stream

I'm thinking about fragmented uploads, or requests that eventually produce a final result, which could include how many elements were processed & others statistics, application-related acknowledgement recipe etc.

@mostroverkhov
Copy link
Member

mostroverkhov commented Dec 28, 2017

Indeed, this would nicely complement Request-Stream. But I am wandering whether Request-Channel handles this effectively already - and protocol implementation can add it on top of this existing interaction. Request/Response & Fire-and-Forget make protocol less chatty and allow implementations to maintain less state - but can Stream-Response improve over Channel?

@yschimke
Copy link
Member

I'm not sold on this specific feature. Is there an concept in reactor-core you are trying to epress but can't?

n.b. I think there are two close equivalents for this

  1. A fragmented response for a request/response operation with metadata along the way.
  2. A request stream operation, which the client knows to block on complete and merge.

We already previously merged two operations that were confusingly similar

| __REQUEST_STREAM__             | 0x0006 | __Request Stream__: Request a completable stream. |
| __REQUEST_SUB__                | 0x0007 | __Request Subscription__: Request an infinite stream. | 

@benjchristensen
Copy link
Contributor

As @yschimke mentioned, we actually did try to be more specific earlier in this project with different specialized interactions and found it confused people. At this time I think the only reason for further specializations in the protocol are when we can demonstrate significant performance benefits for common use cases.

The stream->response case can be exposed in a client API and transferred using RSocket channel without any performance hits, so I don't see a reason to bake it into the protocol itself.

@benjchristensen
Copy link
Contributor

  1. Fire-and-forget

Far less state machine logic than channel as it doesn't need cancel or flow control, and has no response

  1. Request/Response

Could be done with channel over the wire as long as APIs exist on client and server to ensure that a single message is sent in both directions instead of splitting 'next' and 'complete' into two frames.

Due to it being such a common use case though, and to ensure the right APIs are exposed, it exists as a specialization to force having a performant implementation rather than some implementations only exposing channel.

  1. Request-Stream

Could be done with channel over the wire as long as APIs exist on client and server to ensure that a single message is sent in for the request instead of splitting 'next' and 'complete' into two frames, and that no request-n messages are sent from requester.

Due to it being such a common use case though for subscription style use cases (like Reactive Streams, Rx, etc), and to ensure the right APIs are exposed, it exists as a specialization to force having a performant implementation rather than some implementations only exposing channel.

This is a weaker argument than request/response for not just using channel, but has so far not been argued out of the spec in favor of just channel.

  1. Channel

Everything can be implemented on this. But the default API of a message stream in both directions is more complicated for most people to reason about. And the default behavior of using an async stream in both directions results in 2 frames (next + complete), and request-n in both directions.


Following are specializations that could exist but have been left to being done on channel:

  1. Subscription

Exactly the same as Request-Stream, except infinite, never receiving an onComplete.

This existed in the spec at some point to allow the state machine to enforce the infinite behavior, but it confused people as to why it existed, and just meant more code for implementations to write and maintain. It was removed.

  1. Stream->Response

Less common than Request->Stream which does have a specialization. Can be done directly using Channel, or specialized client APIs can be created on top of the channel APIs for ease-of-use to achieve this behavior (without needing specialized APIs on both ends).

Possible downside is that the responder could accidentally send two frames, instead of just one with the COMPLETE flag set.

  1. Stream-and-forget

Very uncommon that a stream is sent without wanting an ack or error. If the response is truly not needed, the server just doesn't need to send one, and the requester ends the stream and walks away. So channel is fine for this as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants