Skip to content

fix: make sure cancel actually aborts push#1831

Merged
charlesvien merged 1 commit intomainfrom
04-22-fix_make_sure_cancel_actually_aborts_push
Apr 23, 2026
Merged

fix: make sure cancel actually aborts push#1831
charlesvien merged 1 commit intomainfrom
04-22-fix_make_sure_cancel_actually_aborts_push

Conversation

@jonathanlab
Copy link
Copy Markdown
Contributor

@jonathanlab jonathanlab commented Apr 22, 2026

Now that we immediately push on push & commit we should let the user abort the push with the cancel button in the UI. HOWEVER we do not support canceling TRPC procedures via electron-trpc so we had to add that in as well.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 22, 2026

Comments Outside Diff (1)

  1. packages/electron-trpc/src/main/handleIPCMessage.ts, line 211-226 (link)

    P1 operations.delete incorrectly removes a legitimate operation on duplicate-ID error

    When the duplicate-ID check throws (line 65-70), operations.set has not been called for the current invocation — the existing first operation's controller is registered under internalId. The unconditional operations.delete(internalId) in the catch block then evicts the first operation's AbortController, leaving it permanently un-cancellable for the rest of its lifetime.

    Track whether set was called in this invocation and guard the delete accordingly:

      let registered = false;
      try {
        if (operations.has(internalId)) {
          throw new TRPCError({ message: `Duplicate id ${internalId}`, code: "BAD_REQUEST" });
        }
        operations.set(internalId, abortController);
        registered = true;
        // ...
      } catch (cause) {
        if (registered) {
          operations.delete(internalId);
        }
        // ...
      }
    
    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/electron-trpc/src/main/handleIPCMessage.ts
    Line: 211-226
    
    Comment:
    **`operations.delete` incorrectly removes a legitimate operation on duplicate-ID error**
    
    When the duplicate-ID check throws (line 65-70), `operations.set` has **not** been called for the current invocation — the existing first operation's controller is registered under `internalId`. The unconditional `operations.delete(internalId)` in the catch block then evicts the first operation's `AbortController`, leaving it permanently un-cancellable for the rest of its lifetime.
    
    Track whether `set` was called in this invocation and guard the delete accordingly:
    
    ```
      let registered = false;
      try {
        if (operations.has(internalId)) {
          throw new TRPCError({ message: `Duplicate id ${internalId}`, code: "BAD_REQUEST" });
        }
        operations.set(internalId, abortController);
        registered = true;
        // ...
      } catch (cause) {
        if (registered) {
          operations.delete(internalId);
        }
        // ...
      }
    ```
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/electron-trpc/src/main/handleIPCMessage.ts
Line: 211-226

Comment:
**`operations.delete` incorrectly removes a legitimate operation on duplicate-ID error**

When the duplicate-ID check throws (line 65-70), `operations.set` has **not** been called for the current invocation — the existing first operation's controller is registered under `internalId`. The unconditional `operations.delete(internalId)` in the catch block then evicts the first operation's `AbortController`, leaving it permanently un-cancellable for the rest of its lifetime.

Track whether `set` was called in this invocation and guard the delete accordingly:

```
  let registered = false;
  try {
    if (operations.has(internalId)) {
      throw new TRPCError({ message: `Duplicate id ${internalId}`, code: "BAD_REQUEST" });
    }
    operations.set(internalId, abortController);
    registered = true;
    // ...
  } catch (cause) {
    if (registered) {
      operations.delete(internalId);
    }
    // ...
  }
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/electron-trpc/src/renderer/ipcLink.ts
Line: 96-102

Comment:
**Aborted operation may wait forever if cancel races context creation**

`operations.set` only happens after `await createContext()` returns (line 52 → 71 in `handleIPCMessage.ts`). If the `AbortSignal` fires and `operation.cancel` is dispatched during that `await`, `operations.get(internalId)` returns `undefined` and the abort is silently dropped. The renderer then waits indefinitely for a response that will never arrive, because the procedure itself runs to completion uninterrupted.

A small hardening in `handleIPCMessage.ts` would close it: move `operations.set(internalId, abortController)` to immediately before `await createContext()`, or check `abortController.signal.aborted` right after `createContext` returns.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/code/src/renderer/features/git-interaction/hooks/useGitInteraction.ts
Line: 463-476

Comment:
**`trackGitAction` duplicated across both catch branches**

`trackGitAction(taskId, store.pushMode, false)` appears identically in both the aborted path and the error path. Per the OnceAndOnlyOnce principle, it can be hoisted before the branch:

```suggestion
    } catch (error) {
      trackGitAction(taskId, store.pushMode, false);
      if (controller.signal.aborted) {
        return;
      }
      log.error("Push failed", error);
      const message = error instanceof Error ? error.message : "Push failed.";
      modal.setPushError(message);
      modal.setPushState("error");
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: make sure cancel actually aborts pu..." | Re-trigger Greptile

Comment on lines +96 to +102
const onAbort = () => {
if (!this.#pendingRequests.has(scopedId)) return;
this.#electronTRPC.sendMessage({
id: scopedId,
method: "operation.cancel",
});
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Aborted operation may wait forever if cancel races context creation

operations.set only happens after await createContext() returns (line 52 → 71 in handleIPCMessage.ts). If the AbortSignal fires and operation.cancel is dispatched during that await, operations.get(internalId) returns undefined and the abort is silently dropped. The renderer then waits indefinitely for a response that will never arrive, because the procedure itself runs to completion uninterrupted.

A small hardening in handleIPCMessage.ts would close it: move operations.set(internalId, abortController) to immediately before await createContext(), or check abortController.signal.aborted right after createContext returns.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/electron-trpc/src/renderer/ipcLink.ts
Line: 96-102

Comment:
**Aborted operation may wait forever if cancel races context creation**

`operations.set` only happens after `await createContext()` returns (line 52 → 71 in `handleIPCMessage.ts`). If the `AbortSignal` fires and `operation.cancel` is dispatched during that `await`, `operations.get(internalId)` returns `undefined` and the abort is silently dropped. The renderer then waits indefinitely for a response that will never arrive, because the procedure itself runs to completion uninterrupted.

A small hardening in `handleIPCMessage.ts` would close it: move `operations.set(internalId, abortController)` to immediately before `await createContext()`, or check `abortController.signal.aborted` right after `createContext` returns.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 463 to +476

modal.setPushState("success");
} catch (error) {
if (controller.signal.aborted) {
trackGitAction(taskId, store.pushMode, false);
return;
}
log.error("Push failed", error);
const message = error instanceof Error ? error.message : "Push failed.";
trackGitAction(taskId, store.pushMode, false);
modal.setPushError(message);
modal.setPushState("error");
} finally {
if (pushAbortRef.current === controller) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 trackGitAction duplicated across both catch branches

trackGitAction(taskId, store.pushMode, false) appears identically in both the aborted path and the error path. Per the OnceAndOnlyOnce principle, it can be hoisted before the branch:

Suggested change
modal.setPushState("success");
} catch (error) {
if (controller.signal.aborted) {
trackGitAction(taskId, store.pushMode, false);
return;
}
log.error("Push failed", error);
const message = error instanceof Error ? error.message : "Push failed.";
trackGitAction(taskId, store.pushMode, false);
modal.setPushError(message);
modal.setPushState("error");
} finally {
if (pushAbortRef.current === controller) {
} catch (error) {
trackGitAction(taskId, store.pushMode, false);
if (controller.signal.aborted) {
return;
}
log.error("Push failed", error);
const message = error instanceof Error ? error.message : "Push failed.";
modal.setPushError(message);
modal.setPushState("error");
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/git-interaction/hooks/useGitInteraction.ts
Line: 463-476

Comment:
**`trackGitAction` duplicated across both catch branches**

`trackGitAction(taskId, store.pushMode, false)` appears identically in both the aborted path and the error path. Per the OnceAndOnlyOnce principle, it can be hoisted before the branch:

```suggestion
    } catch (error) {
      trackGitAction(taskId, store.pushMode, false);
      if (controller.signal.aborted) {
        return;
      }
      log.error("Push failed", error);
      const message = error instanceof Error ? error.message : "Push failed.";
      modal.setPushError(message);
      modal.setPushState("error");
```

How can I resolve this? If you propose a fix, please make it concise.

@jonathanlab jonathanlab force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch from f8c2d77 to c7b587f Compare April 22, 2026 13:36
@jonathanlab jonathanlab force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 61fd2b6 to 5bb6709 Compare April 22, 2026 13:36
@charlesvien charlesvien force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch from c7b587f to cb07e28 Compare April 22, 2026 15:38
@charlesvien charlesvien force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 5bb6709 to 3ddb134 Compare April 22, 2026 15:39
@charlesvien charlesvien force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch from cb07e28 to 172016f Compare April 22, 2026 22:56
@charlesvien charlesvien force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 3ddb134 to 3c8f815 Compare April 22, 2026 22:56
@jonathanlab jonathanlab force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch from 172016f to b5e3a2e Compare April 23, 2026 10:20
@jonathanlab jonathanlab force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 3c8f815 to 6749f51 Compare April 23, 2026 10:22
@jonathanlab jonathanlab force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch from b5e3a2e to 4691a08 Compare April 23, 2026 10:42
@jonathanlab jonathanlab force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 6749f51 to cbd0c88 Compare April 23, 2026 10:43
@charlesvien charlesvien force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch from 4691a08 to 34161ec Compare April 23, 2026 10:48
@charlesvien charlesvien force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from cbd0c88 to 22fdcea Compare April 23, 2026 10:49
@charlesvien charlesvien force-pushed the 04-22-fix_immediately_run_push_on_commit_push branch 2 times, most recently from cbac191 to d483201 Compare April 23, 2026 10:56
@charlesvien charlesvien force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 22fdcea to 7126725 Compare April 23, 2026 10:56
@charlesvien charlesvien changed the base branch from 04-22-fix_immediately_run_push_on_commit_push to graphite-base/1831 April 23, 2026 11:03
@charlesvien charlesvien force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from 7126725 to cd3953a Compare April 23, 2026 11:03
@graphite-app graphite-app Bot changed the base branch from graphite-base/1831 to main April 23, 2026 11:04
@charlesvien charlesvien force-pushed the 04-22-fix_make_sure_cancel_actually_aborts_push branch from cd3953a to 5412863 Compare April 23, 2026 11:04
@charlesvien charlesvien merged commit 1847867 into main Apr 23, 2026
16 checks passed
Copy link
Copy Markdown
Member

Merge activity

@charlesvien charlesvien deleted the 04-22-fix_make_sure_cancel_actually_aborts_push branch April 23, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants