Replies: 11 comments
-
Hello, Thank you for this awesome project. I was wondering how we can help implementing the Websocket Transport? Is there anyway we can help achieving this? Also, would it be possible to implement it via NextJS API routes? It becomes really tricky in serverless environments like Vercel. Please let me know your thoughts. |
Beta Was this translation helpful? Give feedback.
-
Hey, thanks! There actually is experimental subscription implementation already that works on serverless...but it's a bad idea as long-running lambda fns are expensive and you'll likely choke the db with connections. However, if you want to play around with it, have a look at the chat in the examples! |
Beta Was this translation helpful? Give feedback.
-
I'm planning to do some videos where I walk through the internals of tRPC so that would've given you an idea where to look. Until then, here's the relevant files to dig in
-- Rough Idea how to add itIf we were to add WS transport this is the way I picture it Server
Client
Things I'm unsure about
|
Beta Was this translation helpful? Give feedback.
-
Hello! Thank you very much for all the info and I will look forward to the videos! All the ideas look great but as for some of the ideas, these might be some possible solutions and until we are sure of the implications, we can experimentally roll out some of them: Client:
split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === "OperationDefinition" &&
definition.operation === "subscription"
);
},
sseLink,
httpLink
) taking that in mind, we could implement it with something along the lines of: export function createTRPCClient<TRouter extends AnyRouter>(
opts: CreateTRPCClientOptions<TRouter>
) {
const httpClient = new TRPCClient<TRouter>(opts);
const wsClient = new TRPCWSClient<TWSRouter>();
return createMultiTransportClient([
{ name: "my-http-link", impl: httpClient, ssr: true },
{ name: "my-ws-link", impl: wsClient, ssr: false },
...opts?.transports // ---> Merging user created transports
]);
}
export type TRPCTransport = {
name: string; // ---> useful for debugging specific transport and error handling
ssr?: boolean; // ---> the actual env to run this client
impl: any; // ---> the Actual Implementation Link
};
export const createMultiTransportClient = (transports: TRPCTransport[]) => {
const isOnServer = typeof window === "undefined";
const envSpecificTransports = transports.filter(
(transport) => Boolean(transport.ssr) === isOnServer
);
return; //... handle wrappings, custom logic and conditionals
}; With this approach, we can accept custom links and custom rpcs merged in with existing ones and create an internal map of the transports (in case you'd like to support that).
Again, thank you for this awesome project and thank you for reading this and please let me know your thoughts and ideas, I'd like to hear them. ❤️ 👍 |
Beta Was this translation helpful? Give feedback.
-
Will have a proper think and prob respond to this tmrw! |
Beta Was this translation helpful? Give feedback.
-
I honestly don't think I would want to use WS for all operations even on the client, as a first version it could work that queries and mutations happens over http and subscriptions over WS. But let's talk about linksI do want to decouple the link from the client eventually anyway so we could enable things like #163 and potentially making things like #152 / #160 nicer. I've always thought the apollo links were confusing a/f but now that I'm reading into them they do make sense - just by reading the source code of a logger I understand how they work - https://github.com/blackxored/apollo-link-logger/blob/master/src/index.js Maybe something like this could be a nice DX: Standard setupexport const client = createTRPCClient<AppRouter>({
url: '/api/trpc',
}); With links, verboseconst websocketLink = new WebSocketLink({
uri: 'ws://localhost/trpc',
});
const httpLink = new HTTPLink({
uri: '/api/trpc',
});
const directionalLink = split(
({ type }) => type === 'subscription',
websocketLink,
httpLink,
);
export const client = createTRPCClient<AppRouter>({
link: directionalLink,
}); With loggerconst websocketLink = new WebSocketLink({
uri: 'ws://localhost/trpc',
});
const httpLink = new HTTPLink({
uri: '/api/trpc',
});
const directionalLink = split(
({ type }) => type === 'subscription',
websocketLink,
httpLink,
);
const loggerLink = new TRPCLink((procedure, next) => {
const startTime = new Date().getTime();
const {input, type, path} = procedure
console.log('OUT: ', procedure.type, procedure.input);
return next(procedure, (result) => {
const ellapsed = new Date().getTime() - startTime;
console.log(`RES: ${result.ok ? 'ok' : 'err'}`, {ellapsed, result})
return result;
});
});
export const client = createTRPCClient<AppRouter>({
link: [loggerLink, directionalLink],
}); SSR Clientexport const ssrClient = createTRPCClient<AppRouter>({
link: new SSRLink({router: appRouter }),
}); |
Beta Was this translation helpful? Give feedback.
-
I hacked around a bit and made this ugly implementation of a bidrectional middleware thing that we would need for the link stuff https://gist.github.com/KATT/35707bbe221f1740b9aaf2e8174b224d ... wouldn't work for retries though |
Beta Was this translation helpful? Give feedback.
-
Hello! That seems really cool and intuitive. I think WS reconnection is possible but I'll experiment with it tonight and will update the results here. |
Beta Was this translation helpful? Give feedback.
-
The link stuff is a bit more complicated than I first thought. One thing I missed in the sketches above is also that they need to be cancellable as well as retry-able 🙈 |
Beta Was this translation helpful? Give feedback.
-
If you wanna make an interim solution without the complexity of "links" I'm open to look at proposals as well |
Beta Was this translation helpful? Give feedback.
-
Hello! So, I've checked the code and although I'm still experimenting with the API, I believe retry-able and cancelable links could be possible via |
Beta Was this translation helpful? Give feedback.
-
Would be nice with a WebSocket transport. Subscriptions through long-polling are very 2010.
Beta Was this translation helpful? Give feedback.
All reactions