Skip to content

Incorrect data is returned when using multiple clients #201

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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