-
Notifications
You must be signed in to change notification settings - Fork 354
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
Improving ReactiveSocket
abstraction.
#129
Comments
The terminology is a little off here. It is used on the "requester" side of the relationship. Since this protocol is bi-directional, it can be used on either client or server. |
Well then that should be fixed. It used to be possible. A client had an overload that took a |
I don't understand that signature. You return the same type as is passed in. Is it the same one? A different one? It used to be very clear ... a server was created to accept connections, or a client connected to a server. |
There are two aspects to this change, let us discuss this one at a time. Remove
|
I really like this proposal for its elegance. Does this allow two interesting use cases, or if not, what would be different?
|
I think the usability from a server end will roughly be the same just with less concepts (no Both the usecases you mentioned I believe can be achieved today. |
I meant that today if I have a RequestHandler that implements my business logic, I can't use it anywhere that wants a ReactiveSocket without creating something like a Local Transport ReactiveSocket and going through serialization to frames etc. This is good and bad. Likewise currently if I have a ReactiveSocket, to expose it over another transport I need to make a RequestHandler to wrap it. |
@yschimke aah .. correct! I didn't think about that but it is a nice consequence of this change 👍 |
Talking more with @benjchristensen about it, a couple of points he brought up.
The cases I like can be pretty easily supported with adapters e.g. RequestHandler.fromOtherReactiveSocket(rs) and ReactiveSocket.buildLocal(requestHandler) |
This isn't too bad, its just the simpler helper methods of DefaultRequestSocket DefaultRequestSocket.fromClientConnection(DuplexConnection, ConnectionSetupPayload, RequestHandler, Consumer) I think real world usage will dictate whether we support 1-2 line connection building for both cases in each ReactiveSocketConnector impl, or you need to drop back to creating the DuplexConnection, passing it into fromClientConnection. |
Thanks for the input @benjchristensen @yschimke . Since @robertroeser and @stevegury are OOO I will wait for them to express their thoughts on this. |
I don't like this approach because it confuses the semantics of Requester and Responder. Just because they happen to have Publisher for both input and output, that does not mean Requester and Responder are semantically the same. They are asymmetric in a few ways: a) Developers will only ever implement the Responder interface, not the Requester, as the Requester APIs are always concretely provided by the reactivesocket-java library. b) The Requester APIs are exposed to be invoked by developers, but Responder APIs are enveloped inside the state machine and invoked by reactivesocket-java upon receiving frames. c) Practical usage of the interfaces resulted in the channel signature differing between Requester and Responder (not just name, but parameter signature) so that it provided an "initial payload". Without this it is difficult and costly to make routing decisions to which code a request should be handled with. Forcing Requester and Responder to be the same negatively affects usability. I strongly thing that Requester and Responder should be treated differently, have different names, and allow their signatures to diverge as necessary, despite being similar. They are similar because they are the duals of each other, but they are not the same. |
Both of these used to work and was quite elegant. Why not just revert to the prior design? What was the reason for moving away from it? |
That very clearly is not the reason for this change. The reason is that they both deal with same interactions (FnF, Request-Response, ....), one requests and another responds with same signature. To me separating out the first |
About separating out the first Payload for requestChannel, I would like to be able to access the Payload before subscribing. Clients may want to engage different channel behaviors, and should be able to specify it cleanly; I am running into this problem while writing the TCK. Right now, I have to define a handler that has to call request(n) and then decide what response to give based on the first payload received, which does not seem as elegant as it should. |
@xytosis I don't think I follow you completely. Are you referring to the stream of payloads returned from this method in Publisher<Payload> requestChannel(final Publisher<Payload> payloads); and you want |
@NiteshKant |
Ok so you are suggesting that this method in Publisher<Payload> requestChannel(final Publisher<Payload> payloads); can be changed to Publisher<Payload> requestChannel(final Payload first, final Publisher<Payload> payloads); It is interesting because a channel is symmetric and the need to peek to the first payload while sending a request may also apply to the received payload stream (returned I wonder if this can be achieved by providing a utility like: public static <T> void peekFirst(Publisher<T> source, BiConsumer<T, Publisher<T>> consumer) which basically removes the need of this peculiarity in the main interface. |
(I believe) That is inefficient as it requires either subscribing twice, or multicasting. |
But that's what this change looks to be pursuing, as I see no benefit of ever having the same interface shared for both. No developer is ever implementing the Requester side, only the Responder side. I am really struggling to see the real benefits of this change, only negatives. |
The current version of Protocol.md states this: > ReactiveSocket as specified here only allows for TCP, WebSocket, and Aeron as transport protocols. This is at https://github.com/ReactiveSocket/reactivesocket/blob/master/Protocol.md#transport-protocol Then in the next section, a couple paragraph away it mentions HTTP/2 as needing frame length. Link: https://github.com/ReactiveSocket/reactivesocket/blob/master/Protocol.md#framing-protocol-usage It is confusing to say the protocol only supports TCP, WebSocket, and Aeron, and then mention "HTTP/2" and "Other" in the framing section. In this change I propose a possible wording to resolve the confusion. But I'm not quite sure what was meant by this sentence, when the section itself is also permitting other transports. So what is trying to be said, and what can we do to make this clearer?
Today we have the following primary interfaces that application writers interact with:
ReactiveSocket
Primary abstraction for the multiplexed, full duplex connection following the protocol.
ConnectionSetupHandler
Used only at the server when a new connection is accepted.
RequestHandler
Used only at the server to handle various interaction models requested by the client.
Problem
There are a few issues/lack of feature with the above abstraction and current implementations:
ConnectionSetupHandler
andRequestHandler
for this purpose)RequestHandler
andReactiveSocket
have very similar methods (primarily around various request interaction models) and hence is confusing as to why they are two different contracts.Proposal
We can replace the 3 interfaces with two interfaces
ReactiveSocket
Keep the current interface but use it both as a way to request and respond to requests on a
ReactiveSocket
. This means for every connection there will be twoReactiveSocket
instances on each end.ReactiveSocketFactory
(May be a better name)On either end (client/server) there will be a factory which may look something like the below.
I am not yet sure, but this may look different at client than at the server due to the nature of replying to or sending a
ConnectionSetupFrame
. Anyways, this will be a replacement forConnectionSetupHandler
and either generify or provide for client side usecases.This change will simplify the API a bit and also provide symmetric APIs for both client and server.
The text was updated successfully, but these errors were encountered: