Repository: trpc/trpc
File: packages/client/src/links/httpSubscriptionLink.ts (TypeScript)

Code before:
                let recreateOnErrorOpts: RecreateOnErrorOpt = {
                  type: 'raw',
                  event: ev,
                };
                if ('status' in ev && typeof ev.status === 'number') {
                  recreateOnErrorOpts = {
                    type: 'http-error',
                    status: ev.status,
                    event: ev,
                  };
                }

                const shouldRestart = await opts.shouldRecreateOnError(
                  recreateOnErrorOpts,
                );
                if (!shouldRestart) {
                  return false;
                }

                if (typeof opts.eventSourceOptions !== 'function') {
                  // eslint-disable-next-line no-console
                  console.warn(
                    'shouldRecreateOnError has returned true but eventSourceOptions is not a function. This means eventSourceOptions will not be updated',
                  );
                }

                eventSource.restart(
                  url,
                  await resultOf(opts.eventSourceOptions),
                );

                return true;
              }

              return false;
            },
          });

          for await (const chunk of iterable) {
            if (!chunk.ok) {
              // TODO: handle in https://github.com/trpc/trpc/issues/5871
              continue;
            }
            const chunkData = chunk.data;

            // if the `tracked()`-helper is used, we always have an `id` field
            const data = 'id' in chunkData ? chunkData : chunkData.data;
            observer.next({
              result: {
                data,
              },

Review comment (bug):
Potential race condition here -

`shouldRestart` can be called twice before it gets a chance to restart

can you make the code in a way to avoid race conditions?

Code after:

              const recreateOnErrorOpts = createRecreateOnErrorOpts(ev);

              const shouldRestart = await opts.shouldRecreateOnError(
                recreateOnErrorOpts,
              );

              if (!shouldRestart) {
                return false;
              }

              eventSource.restart(
                getUrl({
                  transformer,
                  url: await urlWithConnectionParams(opts),
                  input,
                  path,
                  type,
                  signal: null,
                }),
                await resultOf(opts.eventSourceOptions),
              );

              return true;
            },
          });

          for await (const chunk of iterable) {
            if (!chunk.ok) {
              // TODO: handle in https://github.com/trpc/trpc/issues/5871
              continue;
            }
            const chunkData = chunk.data;

            // if the `tracked()`-helper is used, we always have an `id` field
            const data = 'id' in chunkData ? chunkData : chunkData.data;
            observer.next({
              result: {
                data,
              },
            });
          }

          observer.next({
            result: {
              type: 'stopped',
            },
          });
          observer.complete();
        }).catch((error) => {
          observer.error(TRPCClientError.from(error));