Skip to content

Add AbortController to fetch calls in useEffect for proper request cancellation #1102

@MODSetter

Description

@MODSetter

Description

Several useEffect hooks call fetch/authenticatedFetch without passing an AbortController signal. Some use a cancelled boolean flag which prevents state updates after unmount but doesn't cancel the HTTP request itself — the request keeps running, consuming bandwidth and server resources. Others have no cancellation at all.

Files to change

1. surfsense_web/components/assistant-ui/connector-popup/connector-configs/components/circleback-config.tsx (lines 38-72)

No cancellation at all:

useEffect(() => {
  const fetchWebhookInfo = async () => {
    const response = await authenticatedFetch(url);
    // ...
  };
  fetchWebhookInfo();
}, [connector.search_space_id]);

Fix: Add AbortController and pass signal:

useEffect(() => {
  const controller = new AbortController();
  const fetchWebhookInfo = async () => {
    const response = await authenticatedFetch(url, { signal: controller.signal });
    // ...
  };
  fetchWebhookInfo().catch(() => {});
  return () => controller.abort();
}, [connector.search_space_id]);

2. surfsense_web/components/layout/ui/tabs/DocumentTabContent.tsx (lines 57-113)

Uses cancelled flag but no signal on fetch.

Fix: Replace cancelled flag with AbortController, wrap fetch with signal.

3. surfsense_web/components/editor-panel/editor-panel.tsx (lines ~72-120)

Same pattern: cancelled flag without signal.

What to do

For each file, follow this pattern:

useEffect(() => {
  const controller = new AbortController();
  const doFetch = async () => {
    try {
      const response = await authenticatedFetch(url, { signal: controller.signal });
      if (controller.signal.aborted) return;
      // ... process response
    } catch (err) {
      if (controller.signal.aborted) return;
      // ... handle error
    }
  };
  doFetch();
  return () => controller.abort();
}, [deps]);

Note: Check that authenticatedFetch passes the signal through to fetch(). If it doesn't, that's a separate fix in base-api.service.ts.

Acceptance criteria

  • Listed useEffect fetches use AbortController for proper HTTP cancellation
  • Navigation away from a page cancels in-flight requests
  • No errors when abort fires (AbortError is caught/ignored)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions