unbridled-41 opened a new pull request, #4754:
URL: https://github.com/apache/rocketmq-dashboard/pull/4754
Fixes #4753.
## Problem
The AI conversation retention pass deletes the conversation, its runs and
its events, but never the conversation's agent workspace — while the on-request
delete does. The workspace is the child's `HOME`
(`home/.claude/projects/<cwd>/<session-id>.jsonl`), so "expired" conversations
keep their full agent transcript on disk under an id nothing refers to any more.
- `AiConversationService.java:509-515` — `deleteCascade` deletes events,
runs, conversations and nothing else; its only caller is
`deleteExpiredConversations` (`:480-497`), reached from the scheduled
`purgeExpired` (`:412-426`).
- `AiConversationService.java:290` — `delete(Long, String)` calls
`workspace.delete(conversationId)`.
- `RmqctlWorkspace.java:61-70` and `:212-216` — the layout documents `home/`
as "the child's HOME, per conversation and persistent" and the materialisation
as leaving it alone, so the transcript is exactly what survives.
- `AiConversationProperties.java:37` — `retentionDays = 90`;
`application.yml:119` — `workspace-dir:
${STUDIO_AI_CONVERSATION_WORKSPACE_DIR:/tmp/rocketmq-studio-ai}`, so on a
deployment that points it at a persistent volume the directories accumulate
without bound.
## Root cause
The retention cascade was written as a database cascade ("no FK constraints
here, so the cascade is this method") and the workspace, a filesystem side
effect owned by another class, was only remembered by the interactive delete
path.
## Fix
`deleteCascade` now removes the workspace of every purged conversation
**after** the rows are gone (4 lines), the order `delete(Long, String)` uses: a
crash in between leaves a directory that is still reachable, whereas removing
the transcript of a conversation that is still visible is not recoverable. The
class javadoc's "Retention cascades by hand" note now says the workspace goes
with the rows.
## Tests
Red before the fix:
```
$ cd server && mvn -B -ntp -o test -Dtest=AiConversationServiceTest
[ERROR] ...retentionShouldRemoveTheWorkspaceOfEveryPurgedConversationTest
<<< FAILURE!
Wanted but not invoked:
[ERROR] Tests run: 19, Failures: 1, Errors: 0, Skipped: 0 # BUILD
FAILURE
```
After the fix:
```
$ mvn -B -ntp -o test -Dtest=AiConversationServiceTest
[INFO] Tests run: 19, Failures: 0, Errors: 0, Skipped: 0 # BUILD
SUCCESS
$ mvn -B -ntp -o test -Dtest='org.apache.rocketmq.studio.ops.ai.**'
[INFO] Tests run: 904, Failures: 0, Errors: 0, Skipped: 0 # BUILD
SUCCESS
```
The new test uses an `InOrder` verification (`deleteByIds` before
`workspace.delete(1)`, `(2)`, `(3)`), so it fails both if the workspace is
never removed and if it is removed before the rows; the pre-existing
`deleteShouldCascadeChildrenFirstAndRemoveTheWorkspaceTest` keeps the
interactive path's ordering pinned.
## Duplicate check
Searched open PRs (205) and issues (214) for `workspace`, `retention`,
`purge`, `transcript`, `orphan`, `disk`, `cleanup`, plus the commit index: the
retention hits are #4647/#4648 (alert snapshot retention) and the AI hits
(#4685, #4693, #4696, #4707, #4715, #4631, #4665, #4738, #4740) are all about
the run/stream lifecycle or the CLI session. Nothing covers the workspace
lifecycle, and `git log -S "deleteCascade" -- AiConversationService.java` shows
the cascade has been DB-only since it was introduced.
## Base branch
Targets the development trunk `rocketmq-studio`. GitHub interprets closing
keywords only for pull requests that target the repository default branch, and
that is still `master`, so merging will not close #4753 automatically — it
needs to be closed by hand.
## Risk
Low: the same side effect the interactive delete already performs, on a path
where the conversation is already gone. `RmqctlWorkspace.delete` never throws
(its javadoc: "a stale directory on a deleted volume must not turn a successful
delete into a 500"), so a filesystem problem cannot fail the retention pass.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]