-
Notifications
You must be signed in to change notification settings - Fork 68
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
Introduce method descriptor #594
Conversation
This type is desirable because there are many contexts where we - and users - only want to refer to a single RPC. The most prominent case is a query in connect-query, but we have other use cases in connect-es: 1. ConnectRouter
function routes(router: ConnectRouter) {
router.rpc(
ElizaService,
ElizaService.methods.say,
async (req) => new SayResponse({
sentence: `you said: ${req.sentence}`
})
);
} If we generate this new method type in But we can't support both types forever. More choices also means more complexity, ultimately making the API more difficult to use. So ideally, it should also be possible to use 2. Transport The interface Transport {
unary<I extends Message<I> = AnyMessage, O extends Message<O> = AnyMessage>(
service: ServiceType,
method: MethodInfo<I, O>,
// ...
): Promise<UnaryResponse<I, O>>;
/**
* Call a streaming RPC - a method that takes zero or more input messages,
* and responds with zero or more output messages.
*/
stream<I extends Message<I> = AnyMessage, O extends Message<O> = AnyMessage>(
service: ServiceType,
method: MethodInfo<I, O>,
// ...
): Promise<StreamResponse<I, O>>;
} Clearly, the new method type is the better fit in this case. The idea is to only generate the new method type for connect-query. Ultimately, 3. Universal handlers
4. Handler factory
In this project, we have Before we add new exports to this project, we need to fully consider these use cases (I am not sure the list above is exhaustive) to maintain good DX in the API. To get the ball rolling, I suggest that we do not export any new types, and instead accept an override in |
The diff between readonly name: string;
readonly I: MessageType<I>;
readonly O: MessageType<O>;
readonly idempotency?: MethodIdempotency;
+ readonly localName: string;
+ readonly service: Omit<ServiceType, "methods">;
Answering these two questions is IMO necessary to nail down what |
That makes sense to me. I'll close this PR and open one in connect-es instead so we can have a unified location to discuss the specifics. I'll provide more feedback over there on the other questions. |
Can we continue the conversation in this thread? It works for me to link here from a PR from connect-es, but I'd prefer that we don't fragment the discussion. |
I'm not 100% sure what you mean. The omitted field does allow us to assign a full ServiceType value to this, it just doesn't allow us to rely on it downstream.
From what I can see, it's not required. @srikrsna-buf was there a specific use case you were thinking of? |
I included it so that we can use the router, if we are changing the router then we don't need it. |
Alright, good to know. Since I think it does make sense to modify the router to allow the MethodType as a param, that will solve that problem. I'll remove |
@srikrsna-buf, can you elaborate? I'm not aware that |
I mean excess property checks. When we accept self-contained method types across the APIs, we will still have to handle the regular So interop becomes important. It must be possible to create const say = {...ElizaService.methods.say, service: ElizaService} I don't want us to find out that we have to make the property optional instead of omitting it down the line, for any of the use cases above, after we have shipped the type. |
That makes sense. I'll double check and write some tests around it if it's not the case. |
It seems like the inference used in rpc definitely ignores the excess properties. The only way I could get it to fail was like so: const methodDefinition: MethodType<Int32Value, StringValue> = {
...testService.methods.unary,
service: {
//...testService works fine
typeName: testservice.typeName,
methods: testService.methods,
}
}; And even this will work as long as you don't have the type declaration of |
Thanks for verifying! There is a long-standing feature request to expand excess property checks: microsoft/TypeScript#39998. But I don't think it would apply for Seems good to me to omit |
When we call |
True. Seems to be an acceptable limitation, though. We might even want to consider replacing |
This new type is to be used as a self describing entity of a service + method. Useful for enclosing all required information to implement a standalone method.