Skip to content

fix(task): scope user exit preparation to the requesting owner - #2741

Open
HandSonic wants to merge 1 commit into
OtterMind:mainfrom
HandSonic:fix/task-exit-owner-scope
Open

fix(task): scope user exit preparation to the requesting owner#2741
HandSonic wants to merge 1 commit into
OtterMind:mainfrom
HandSonic:fix/task-exit-owner-scope

Conversation

@HandSonic

@HandSonic HandSonic commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Related issue

N/A — server-contract defect found by reviewing the #2712 task-system rebuild; described below.

Summary

LocalTaskManager's preparingForExit flag was global: the user-scoped prepareForUserExit path (triggered today by the desktop close flow via /api/tasks/prepare-user-exit) set a flag that rejected EVERY owner's task submissions with "The application is preparing to exit". Today only the desktop client drives this flow (web never calls it), so the practical blast radius is the same user — but the endpoint is a server/web API, and any API client (or future web adoption) hitting it locks out all other owners with no timeout reset. The flag is now split correctly:

  • applicationExiting — set only by the owner==null application shutdown path (global semantics preserved)
  • Set exitingOwners keyed by the TaskOwner record — submit() rejects only the requesting owner's new tasks; abortUserExit(userId, organizationId) removes exactly that key

Everything stays under the existing lifecycleLock; terminateActiveTasks keeps the original guard semantics; the public TaskService/REST surface is unchanged.

Affected surfaces

  • Frontend / Web
  • Backend / API / Storage
  • Database plugin / Driver
  • JCEF / Desktop packaging
  • CI / Build / Release
  • Documentation only

Verification

  • mvn -pl chat2db-community-domain/chat2db-community-domain-core -am test -Dmaven.test.skip=false: 216/216 green, incl. 3 new LocalTaskManagerTest cases (ownerA blocked + ownerB allowed; abort unblocks only the requesting owner; application-level shutdown blocks all owners).
  • Verified the client flow: useApplicationExit is desktop-gated (isDesktop), cancel always pairs abortUserExit, and confirming the exit terminates the whole process — so no lingering-key scenario exists in the current client.
  • Fork CI green: fix(task): scope user exit preparation to the requesting owner HandSonic/Chat2DB#48.

Risk and compatibility

  • Public API or stored data: N/A.
  • Database or driver compatibility: N/A.
  • Network, privacy, or security: N/A.
  • Community / Local / Pro boundary: N/A.
  • Backward compatibility: single-user desktop behavior unchanged (one owner).

Reviewer map

  • Start here: LocalTaskManager fields + submit() + terminateActiveTasks().
  • Failure condition: an exiting-owner entry lingers until abort or restart (bounded by distinct owners, harmless).
  • Rollback or disable path: revert single commit restores the global flag.

Contributor declaration

  • I linked the Issue that defines this change.
  • I tested the affected behavior and reported the actual results above.
  • I did not include credentials, private data, or generated build output.
  • I disclosed substantial AI assistance below, or this PR contains no substantial AI-generated code.

AI assistance: substantial — fix and tests drafted with AI assistance, verified locally and by adversarial review (including a client-flow audit of who actually calls these endpoints).

A single global preparingForExit flag rejected task submissions from
every user once one user hit prepare-user-exit. Keep the global flag
for app-level shutdown (owner == null) and track per-owner exit keys in
a set so only the exiting owner is blocked; abort-user-exit now removes
that owner's key under the same lifecycle lock.
@HandSonic
HandSonic requested review from a team and openai0229 as code owners August 23, 2026 18:54
@openai0229 openai0229 moved this to In Review in Chat2DB Community Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

2 participants