Skip to content

refactor: Migrate Tenant API handler to WithTx#559

Merged
chet merged 2 commits into
NVIDIA:mainfrom
chet:with-tx-tenant
May 22, 2026
Merged

refactor: Migrate Tenant API handler to WithTx#559
chet merged 2 commits into
NVIDIA:mainfrom
chet:with-tx-tenant

Conversation

@chet
Copy link
Copy Markdown
Contributor

@chet chet commented May 21, 2026

Description

Continues the WithTx migration, this time covering the GetCurrentTenantHandler flow — the only BeginTx site in tenant.go.

Some callouts are:

  • Uses WithTxResult since each of the three branches (create-new, update-display-name, return-as-is) naturally returns the resulting tenant.
  • Pulled the tnDAO.GetAllByOrg pre-check inside the tx with an advisory lock on the org to close a TOCTOU race where concurrent requests could both pass the "no tenant exists" check and double-create.
  • The taDAO.GetAll inside updateTenantAccounts stays inside since its result drives in-tx writes.
  • Errors switched to NewAPIError.

Signed-off-by: Chet Nichols III chetn@nvidia.com

Type of Change

  • Feature - New feature or functionality (feat:)
  • Fix - Bug fixes (fix:)
  • Chore - Modification or removal of existing functionality (chore:)
  • Refactor - Refactoring of existing functionality (refactor:)
  • Docs - Changes in documentation or OpenAPI schema (docs:)
  • CI - Changes in GitHub workflows. Requires additional scrutiny (ci:)
  • Version - Issuing a new release version (version:)

Services Affected

  • API - API models or endpoints updated
  • Workflow - Workflow service updated
  • DB - DB DAOs or migrations updated
  • Site Manager - Site Manager updated
  • Cert Manager - Cert Manager updated
  • Site Agent - Site Agent updated
  • Flow - Flow service updated
  • Powershelf Manager - Powershelf Manager updated
  • NVSwitch Manager - NVSwitch Manager updated

Related Issues (Optional)

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)

Additional Notes

Continues the `WithTx` migration, this time covering the `GetCurrentTenantHandler` flow — the only `BeginTx` site in `tenant.go`.

Some callouts are:
- Uses `WithTxResult` since each of the three branches (create-new, update-display-name, return-as-is) naturally returns the resulting tenant.
- Pulled the `tnDAO.GetAllByOrg` pre-check inside the tx with an advisory lock on the org to close a TOCTOU race where concurrent requests could both pass the "no tenant exists" check and double-create.
- The `taDAO.GetAll` inside `updateTenantAccounts` stays inside since its result drives in-tx writes.
- Errors switched to `NewAPIError`.

Signed-off-by: Chet Nichols III <chetn@nvidia.com>
@chet chet requested a review from a team as a code owner May 21, 2026 19:50
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Review Change Stack

Summary by CodeRabbit

  • Bug Fixes

    • Fixed organization display name synchronization for tenant records to ensure accurate organization information.
  • Refactor

    • Improved transaction handling and concurrency management for tenant operations to enhance reliability.

Walkthrough

GetCurrentTenantHandler.Handle is refactored to adopt cdb.WithTxResult for transaction lifecycle management, removing direct database/sql dependencies. The handler now acquires an org-scoped advisory lock to serialize concurrent get-or-create operations, re-reads Tenant state under the lock, conditionally creates missing Tenant records with account updates, and syncs OrgDisplayName drift. Transaction errors are centralized through common.HandleTxError.

Changes

Tenant Handler Transaction Refactoring

Layer / File(s) Summary
Transaction pattern and advisory locking refactor
api/pkg/api/handler/tenant.go
Transitions from manual SQL transaction management to cdb.WithTxResult, eliminating database/sql imports. The refactored handler acquires org-scoped advisory locks inside transactions to serialize concurrent Tenant get-or-create semantics, re-reads Tenant rows under lock, conditionally creates Tenant records with account updates, and handles OrgDisplayName synchronization. Error handling is unified via common.HandleTxError.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: migrating the Tenant API handler from manual transaction management to the WithTx pattern.
Description check ✅ Passed The description is directly related to the changeset, detailing the WithTx migration strategy, race condition mitigation, and transaction management improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions
Copy link
Copy Markdown

🔐 TruffleHog Secret Scan

No secrets or credentials found!

Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉

🔗 View scan details

🕐 Last updated: 2026-05-21 19:51:58 UTC | Commit: c4fea2b

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
api/pkg/api/handler/tenant.go (1)

164-209: 🏗️ Heavy lift

Add a concurrent same-org regression test for this flow.

This refactor changes the transaction boundary and the get-or-create concurrency behavior. A test that drives two same-org GetCurrentTenantHandler.Handle requests concurrently and asserts a single tenant is created while both requests succeed would lock in the TOCTOU fix and catch lock-handling regressions.

🤖 Prompt for 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.

In `@api/pkg/api/handler/tenant.go` around lines 164 - 209, Add a concurrent
same-org regression test that exercises the new transactional get-or-create path
in GetCurrentTenantHandler.Handle: spawn two concurrent requests targeting the
same org and assert both return success while only one Tenant DB row is created;
the test should exercise the advisory lock path via
cdb.WithTxResult/TryAcquireAdvisoryLock and verify
tnDAO.GetAllByOrg/CreateFromParams/UpdateFromParams are exercised only once (or
result in a single created tenant), and also ensure updateTenantAccounts is
invoked exactly once when a create occurs to catch TOCTOU or lock-handling
regressions.
🤖 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.

Nitpick comments:
In `@api/pkg/api/handler/tenant.go`:
- Around line 164-209: Add a concurrent same-org regression test that exercises
the new transactional get-or-create path in GetCurrentTenantHandler.Handle:
spawn two concurrent requests targeting the same org and assert both return
success while only one Tenant DB row is created; the test should exercise the
advisory lock path via cdb.WithTxResult/TryAcquireAdvisoryLock and verify
tnDAO.GetAllByOrg/CreateFromParams/UpdateFromParams are exercised only once (or
result in a single created tenant), and also ensure updateTenantAccounts is
invoked exactly once when a create occurs to catch TOCTOU or lock-handling
regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f953ff03-69be-4d2d-a91a-b84c64fae0f2

📥 Commits

Reviewing files that changed from the base of the PR and between f813f8d and c4fea2b.

📒 Files selected for processing (1)
  • api/pkg/api/handler/tenant.go

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 21, 2026

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
nico-flow 66 4 34 18 2 8
nico-nsm 82 2 28 43 9 0
nico-psm 67 4 35 18 2 8
nico-rest-api 100 6 53 30 3 8
nico-rest-cert-manager 65 4 34 18 1 8
nico-rest-db 66 4 34 18 2 8
nico-rest-site-agent 65 4 34 18 1 8
nico-rest-site-manager 65 4 34 18 1 8
nico-rest-workflow 67 4 35 18 2 8
TOTAL 643 36 321 199 23 64

Per-CVE detail lives in the per-service grype-* artifacts (JSON + SARIF). Severity counts only — no CVE IDs published here.

Copy link
Copy Markdown
Contributor

@thossain-nv thossain-nv left a comment

Choose a reason for hiding this comment

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

Looks good, thank you @chet

@chet chet enabled auto-merge (squash) May 22, 2026 17:39
@chet chet merged commit 113f4f2 into NVIDIA:main May 22, 2026
50 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.

2 participants