Skip to content

feat: gc now with options, close #1618#1647

Merged
looplj merged 1 commit into
unstablefrom
dev-tmp
May 11, 2026
Merged

feat: gc now with options, close #1618#1647
looplj merged 1 commit into
unstablefrom
dev-tmp

Conversation

@looplj

@looplj looplj commented May 11, 2026

Copy link
Copy Markdown
Owner

No description provided.

@greptile-apps

greptile-apps Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds user-configurable options to the manual GC cleanup flow: the "Run Cleanup Now" dialog now lets users specify retention days per resource type and shows a live estimated-deletion preview before confirming. The backend gains a new previewGcCleanup query and TriggerGcCleanupInput that threads explicit day overrides into runCleanup, replacing the old zero-day "delete everything" semantics.

  • GC refactorrunCleanup now accepts a manualDays map that overrides policy values per resource type; runAutomaticCleanup passes nil, preserving the scheduled-run behaviour unchanged.
  • Preview APIPreviewCleanup counts records older than the given cutoff; however, it only counts Request rows for the "requests" type while the actual cleanup also deletes Thread and Trace records, so the shown estimate will be lower than the true deletion count.
  • Frontend – The alert dialog is replaced with an interactive form featuring debounced preview fetching and per-resource number inputs with 1–365 day bounds.

Confidence Score: 4/5

Safe to merge with one fix: the preview count shown to users before they confirm a cleanup is incomplete.

The manual cleanup logic itself is correct — runCleanup properly skips resource types not present in manualDays and applies user-supplied day overrides. The concern is in PreviewCleanup: it counts only Request records for the "requests" resource type, but the actual cleanup additionally removes Thread and Trace records for that same option. Users see an undercount in the confirmation dialog and cannot accurately assess the impact before proceeding.

internal/server/gc/gc.go — the PreviewCleanup function needs to count Thread and Trace records alongside Request records for the "requests" resource type.

Important Files Changed

Filename Overview
internal/server/gc/gc.go Adds PreviewCleanup and refactors runCleanup to accept manualDays overrides; preview only counts Request rows for the "requests" type while actual cleanup also deletes Thread and Trace records, understating the deletion scope shown to users.
frontend/src/features/system/components/storage-policy-settings.tsx Replaces the simple confirm dialog with a richer manual-cleanup dialog featuring per-resource day inputs and a live preview; debounce timer is not cleared on unmount.
frontend/src/features/system/data/system.ts Adds TriggerGcCleanupInput and GcCleanupPreviewItem interfaces and a new usePreviewGcCleanup hook.
internal/server/gql/system.resolvers.go Adds PreviewGcCleanup resolver with read:settings scope check and updates TriggerGcCleanup to accept input; logic is correct.
internal/server/gql/system.graphql Adds TriggerGcCleanupInput, GcCleanupPreviewItem type, and previewGcCleanup query.
internal/server/biz/system.go Adds server-side validation rejecting cleanup_days <= 0 before persisting storage policy.
internal/server/gc/gc_internal.go Renames runCleanupWithSystemContext to runAutomaticCleanup and passes nil manualDays; clean rename.
internal/server/gql/generated.go Auto-generated GraphQL execution layer; changes reflect schema additions correctly.
internal/server/gql/gqlgen.yml Maps new TriggerGcCleanupInput and GcCleanupPreviewItem to their Go types.
frontend/src/locales/en/system.json Adds new i18n keys for manual cleanup dialog.
frontend/src/locales/zh-CN/system.json Chinese translations for new manual cleanup dialog keys added.

Sequence Diagram

sequenceDiagram
    participant UI as Frontend Dialog
    participant GQL as GraphQL API
    participant GC as gc.Worker

    UI->>GQL: previewGcCleanup(input) [query]
    GQL->>GC: PreviewCleanup(ctx, input)
    GC-->>GQL: []GcCleanupPreviewItem (requests + usage_logs counts)
    GQL-->>UI: preview items

    Note over UI: User reviews estimate and confirms

    UI->>GQL: triggerGcCleanup(input) [mutation]
    GQL->>GQL: spawn goroutine (system bypass ctx)
    GQL-->>UI: true (async acknowledged)
    GQL->>GC: RunCleanupNow(bgCtx, input)
    GC->>GC: "runCleanup(ctx, manual=true, manualDays)"
    Note over GC: Deletes Requests + Threads + Traces (Threads/Traces absent from preview)
    GC->>GC: cleanupUsageLogs
Loading

Reviews (2): Last reviewed commit: "feat: gc now with options, close #1618" | Re-trigger Greptile

Comment thread internal/server/biz/system.go Outdated
Comment thread internal/server/gc/gc.go
Comment thread frontend/src/features/system/components/storage-policy-settings.tsx

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces a manual garbage collection (GC) cleanup feature with a preview capability. Key changes include updating the frontend to allow users to specify retention days for request and usage logs, adding a preview of estimated deletions, and modifying the backend to support manual overrides and preview queries. Feedback focuses on refining the manual cleanup logic to prevent unintended deletions, ensuring proper cleanup of timers in the frontend to avoid memory leaks, and cleaning up unused variables in the backend validation logic.

Comment thread internal/server/gc/gc.go
Comment on lines +125 to +131
if option.Enabled || manual {
days := option.CleanupDays
if manual && manualDays != nil {
if d, ok := manualDays[option.ResourceType]; ok {
days = d
}
}

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.

high

When manual is true, the current logic triggers cleanup for all resource types defined in the policy, even those not specified in manualDays or those disabled in the policy. This behavior is unexpected for a manual cleanup with specific options, as it might trigger unwanted deletions for other resource types using their default policy days. It's better to only process resource types that are either enabled in the policy (for automatic runs) or explicitly provided in the manual override map.

		days, shouldRun := option.CleanupDays, option.Enabled
		if manual {
			days, shouldRun = manualDays[option.ResourceType]
		}

		if shouldRun {

const [manualUsageLogsDays, setManualUsageLogsDays] = useState(7);
const [previewItems, setPreviewItems] = useState<GcCleanupPreviewItem[]>([]);
const [isPreviewLoading, setIsPreviewLoading] = useState(false);
const previewTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

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.

medium

The previewTimerRef is used to manage a debounce timer for fetching previews. To prevent potential memory leaks or state updates on an unmounted component, it's a good practice to clear this timer when the component unmounts.

  const previewTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    return () => {
      if (previewTimerRef.current) {
        clearTimeout(previewTimerRef.current);
      }
    };
  }, []);

Comment thread internal/server/biz/system.go Outdated
Comment thread internal/server/gc/gc.go
Comment on lines +575 to +587
if input.RequestsCleanupDays > 0 {
cutoff := time.Now().AddDate(0, 0, -input.RequestsCleanupDays)
count, err := w.Ent.Request.Query().Where(request.CreatedAtLT(cutoff)).Count(ctx)
if err != nil {
return nil, fmt.Errorf("failed to count requests for preview: %w", err)
}
items = append(items, GcCleanupPreviewItem{
ResourceType: "requests",
EstimatedCount: count,
CutoffTime: cutoff,
RetentionDays: input.RequestsCleanupDays,
})
}

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.

P1 Preview count silently omits threads and traces

PreviewCleanup only counts Request records for the "requests" resource type, but runCleanup deletes three entity types for that same option: requests (via cleanupRequests), threads (via cleanupThreads), and traces (via cleanupTraces). A user who opens the dialog and sees "42 Request Logs records" will then confirm a cleanup that actually deletes far more rows — threads and traces are invisible to the preview entirely. To give an accurate estimate, the preview should sum counts from all three tables (or at least make clear that threads and traces are also included).

@looplj looplj merged commit 9773d7f into unstable May 11, 2026
4 checks passed
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.

1 participant