Skip to content

Backport 2409 (db session cleanup) to 0.10.x release - #2403

Open
supreme-gg-gg wants to merge 3 commits into
kagent-dev:release/v0.10.xfrom
supreme-gg-gg:feat/db-cleanup-ttl
Open

Backport 2409 (db session cleanup) to 0.10.x release#2403
supreme-gg-gg wants to merge 3 commits into
kagent-dev:release/v0.10.xfrom
supreme-gg-gg:feat/db-cleanup-ttl

Conversation

@supreme-gg-gg

@supreme-gg-gg supreme-gg-gg commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

This targets the 0.10.x release. To use, e.g. set database.posetgres.sessionRetentionDays: 30

The following tables are eligible for cleanup: session, shares, events (ADK), push notifications (A2A), tasks (A2A), checkpoints (LangGraph), memory and flow states (CrewAI)

This shares the same cleanup runner as long term memory.

@supreme-gg-gg
supreme-gg-gg requested a review from a team as a code owner August 7, 2026 15:52
Copilot AI lite review requested due to automatic review settings August 7, 2026 15:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@supreme-gg-gg
supreme-gg-gg changed the base branch from main to release/v0.10.x August 7, 2026 15:52
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Aug 7, 2026
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Aug 7, 2026
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Comment thread go/core/pkg/app/app.go Outdated
if err := mgr.Add(httpserver.NewMemoryCleanupRunnable(dbClient, 0)); err != nil {
setupLog.Error(err, "unable to set up memory cleanup runnable")
// DB TTL cleanup (memory + sessions) runs only on the leader to avoid duplicate deletes.
if err := mgr.Add(httpserver.NewDbCleanupRunnable(dbClient, 1*time.Minute, cfg.Database.SessionRetentionDays)); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NewDbCleanupRunnable mentions the default is every 24 hours, but this runs every minute by default and is hardcoded that way. Should we make the frequency configurable?

@supreme-gg-gg supreme-gg-gg Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oops, I changed it to every minute for testing but forgot to change it back... I also thought about making this configurable. However, for now I don't find it too useful and once every day would be a reasonable choice for most users. We will need more complicated logic like check cleanup period < TTL, handle different time units (minutes, hours, days) etc and it doesn't bring much benefit.


-- DeleteExpiredSessionsBatch hard-deletes up to batch_size idle sessions whose
-- updated_at is older than retention_days, plus cascaded conversation state.
-- name: DeleteExpiredSessionsBatch :one

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There is a potential for a race condition with this. The expiry CTE snapshots updated_at, but the final delete only rechecks id/user_id. So you can have an event update the session, followed by cleanup deleting the session, leaving the new event orphaned.

@supreme-gg-gg supreme-gg-gg Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've changed the CTE to use a FOR UPDATE locking clause, it also skips sessions locked by other transactions to avoid waiting (since a session actively being updated will not expire), good catch, thanks!

err := c.withTx(ctx, func(q *dbgen.Queries) error {
var err error
n, err = q.DeleteExpiredSessionsBatch(ctx, dbgen.DeleteExpiredSessionsBatchParams{
RetentionDays: int32(retentionDays),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a reason to convert the int to an int32 here? Should we just take in an int32? Probably not a problem based on the expected value ranges, but an int could be truncated by this conversion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

flag.IntVar takes in an *int and sqlc generates int32 for integer type, so we will need this conversion somewhere unfortunately

Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
@supreme-gg-gg supreme-gg-gg changed the title feat: add TTL and cleanup for hard-deleting sessions and events Backport 2409 (db session cleanup) to 0.10.x release Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants