Skip to content

Incorrect data is returned when using multiple clientsΒ #201

@BrendanC23

Description

@BrendanC23

There is a race condition that causes incorrect data to be returned if there are two different clients. I have two different TRPC clients. The first is a regular client.

function App() {
    const [queryClient] = useState(() => new QueryClient());
    const trpcClient = trpc.createClient({
        links: [loggerLink(), ipcLink()],
        transformer: superjson,
    });

    return (
        <trpc.Provider client={trpcClient} queryClient={queryClient}>
            <QueryClientProvider client={queryClient}>
            </QueryClientProvider>
        </trpc.Provider>
    );
}

The second is a proxy client.

export const trpc = createTRPCReact<AppRouter>();

export const trpcProxyClient = createTRPCProxyClient<AppRouter>({
    links: [loggerLink(), ipcLink()],
    transformer: superjson,
});

I can use the regular client in components, doing things like const result = trpc.path.getData.useQuery(). The proxy client is used in TanStack Router route loaders, as it can be awaited.

export const Route = createRootRouteWithContext<RouterContext>()({
    loader: async ({ context }) => {
        const data = await context.trpcProxyClient.path.getData.query();
        return data;
    },
    component: RootComponent,
});

This causes an issue because the two TRPC clients cause there to be two instances of onMessage.

this.#electronTRPC.onMessage((response: TRPCResponseMessage) => {
this.#handleResponse(response);
});

Each electron-trpc client will have a separate request Operation id.

https://github.com/trpc/trpc/blob/48de686d22ccbefe1cf97eaa7f205dabe7302d2a/packages/client/src/internals/TRPCUntypedClient.ts#L79-L88

Thus, it is possible for the wrong data to be returned in some circumstances. Consider the following:

  1. trpcClient (client 1) is created. It's requestId = 0. An onMessage handler is added.
  2. trpcProxyClient (client 2) is created. It's requestId = 0. An onMessage handler is added.
  3. trpcClient fetches data using requestId = 1.
  4. trpcProxyClient fetches data using requestId = 1.
  5. trpcClient's request completes. Both trpcClient and trpcProxyClient have their onMessage callback trigger with id = 1.
  6. trpcClient fullfils the request with the correct data.
  7. trpcProxyClient's onMessage was called with id = 1, and so it returns incorrect data back to the caller.
  8. trpcProxyClient's request finishes, but #handleResponse has already been run on incorrect data. The correct response is discarded.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions