Skip to content

controller/orgunit: reconciler for hold-period expiry and hard-delete (#182)#188

Merged
Prabhjot-Sethi merged 2 commits into
go-core-stack:mainfrom
dev-arya23:dev-arya/182-reconciler-hard-delete
Jun 27, 2026
Merged

controller/orgunit: reconciler for hold-period expiry and hard-delete (#182)#188
Prabhjot-Sethi merged 2 commits into
go-core-stack:mainfrom
dev-arya23:dev-arya/182-reconciler-hard-delete

Conversation

@dev-arya23

@dev-arya23 dev-arya23 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements a reconciler controller using go-core-stack/core/reconciler to handle hold-period expiry and hard-delete of soft-deleted org-units (issue #182).

Changes:

  • pkg/controller/orgunit/reconciler.go: New OrgUnitCleanupController with orgUnitReconciler that:
    • Fetches the org-unit entry by key, skips if not found or not deleted
    • Computes holdExpiry = deleted + hold_deleted_ou
    • If holdExpiry > now: returns Result{RequeueAfter: remaining + 1s} for delayed re-enqueue
    • If holdExpiry <= now: hard-deletes the entry via DeleteKey, returns nil
    • Handles transient errors with 5s backoff requeue
  • pkg/table/org-unit.go: ReconcilerGetAllKeys() override on OrgUnitTable returns only keys where deleted > 0 — ensures the reconciler bootstraps only entries pending hard-delete (not all org-units)
  • main.go: Conditional startup — reconciler only registers when experimental.allow_ou_delete is true

Design:

  • Follows the established controller pattern (EmailVerificationCleanupController, tenant controllers)
  • Uses core/reconciler pipeline for dedup, error retry, and RequeueAfter-based delayed processing
  • On startup, ReconcilerGetAllKeys() bootstraps all existing soft-deleted entries — handles process restart recovery
  • NotifyCallback from MongoDB change stream picks up new soft-deletes automatically
  • No cascade cleanup of org-unit-users — that is a separate concern per the issue

Test plan

  • Verify reconciler starts only when allow_ou_delete: true in config
  • Verify soft-deleted OU is hard-deleted after hold_deleted_ou seconds
  • Verify OU within hold period is requeued (not deleted prematurely)
  • Verify process restart re-bootstraps pending deletions via ReconcilerGetAllKeys
  • Verify active OUs (deleted == 0) are not affected by the reconciler
  • Verify idempotent behavior when entry is already gone (NotFound)

Closes #182

Summary by CodeRabbit

  • New Features

    • Soft-deleted org units can now be fully removed after a configured retention period.
    • Org unit server behavior now follows experimental settings more closely, including optional cleanup handling.
  • Bug Fixes

    • Improved cleanup of deleted org units so stale entries no longer remain indefinitely.
    • Cleanup retries safely when a removal attempt fails temporarily.

…go-core-stack#182)

Implements a reconciler controller using core/reconciler to handle
hold-period expiry and hard-delete of soft-deleted org-units.

Changes:
- pkg/controller/orgunit/reconciler.go: OrgUnitReconciler that computes
  holdExpiry = deleted + hold_deleted_ou, requeues if not yet expired,
  hard-deletes via DeleteKey when hold period expires
- pkg/table/org-unit.go: ReconcilerGetAllKeys override returns only
  keys where deleted > 0 (soft-deleted entries pending hard-delete),
  adds Deleted field to OrgUnitEntry
- main.go: conditional startup — reconciler only registers when
  experimental.allow_ou_delete is true, threads ExperimentalConfig
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Walkthrough

Adds soft-delete support to OrgUnitEntry with a Deleted int64 field, implements ReconcilerGetAllKeys on OrgUnitTable to bootstrap from MongoDB, introduces OrgUnitCleanupController with a hold-period Reconcile loop that hard-deletes expired entries, and wires conditional startup in main behind AllowOUDelete.

Org-unit cleanup reconciler

Layer / File(s) Summary
OrgUnitEntry soft-delete field and ReconcilerGetAllKeys
pkg/table/org-unit.go
Adds Deleted int64 (bson deleted,omitempty) to OrgUnitEntry and implements ReconcilerGetAllKeys() which queries MongoDB for deleted > 0 entries and returns their keys for reconciler bootstrap.
OrgUnitCleanupController and Reconcile logic
pkg/controller/orgunit/reconciler.go
Defines OrgUnitCleanupController and orgUnitReconciler types, implements Reconcile to fetch the entry, skip non-deleted, requeue until hold expiry, then call tbl.DeleteKey for hard-delete; NewOrgUnitCleanupController constructs and registers the controller.
Conditional startup and server wiring
main.go
Imports the orgunit controller package, conditionally creates and starts OrgUnitCleanupController when AllowOUDelete is enabled, and passes conf.GetExperimental() to server.NewOrgUnitServer.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A soft delete sits, waiting its fate,
The reconciler hops by — "Not yet, must wait!"
Hold period ticks, the clock counts away,
Then poof — hard deleted, a clean burrow today.
AllowOUDelete? Then I'll start my loop!
No ghost org-units left in my hutch or coop. 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the org-unit reconciler and its hold-period hard-delete behavior, matching the main change.
Linked Issues check ✅ Passed The PR adds the org-unit cleanup reconciler, deleted-entry bootstrapping, requeue/hard-delete logic, and conditional startup, aligning with #182.
Out of Scope Changes check ✅ Passed The changes stay focused on org-unit cleanup and the related experimental startup wiring; no unrelated features are introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@main.go`:
- Line 589: The call to NewOrgUnitServer in main.go is out of sync with the
constructor signature in pkg/server/org-unit.go, so the build will fail. Update
NewOrgUnitServer and its implementation to accept the experimental config
argument consistently, and make sure any call sites, the serverCtx setup, and
the org-unit server constructor logic all use the same parameter list.

In `@pkg/controller/orgunit/reconciler.go`:
- Line 71: The OrgUnitCleanupController constructor is using an undefined
config.ExperimentalConfig type, so update NewOrgUnitCleanupController to accept
the actual exported experimental config type returned by conf.GetExperimental()
or change the config package to export the intended type. Make the signature and
any related references in orgunit/reconciler.go use the same concrete type so
golangci-lint and compilation succeed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55c16920-952d-46d8-be98-a1191a1e6d26

📥 Commits

Reviewing files that changed from the base of the PR and between 95ddf93 and e56b052.

📒 Files selected for processing (3)
  • main.go
  • pkg/controller/orgunit/reconciler.go
  • pkg/table/org-unit.go

Comment thread main.go
Comment thread pkg/controller/orgunit/reconciler.go
@Prabhjot-Sethi Prabhjot-Sethi merged commit 7bbd8c4 into go-core-stack:main Jun 27, 2026
1 of 2 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.

Reconciler: hold-period expiry and hard-delete

2 participants