Skip to content

Conversation

@tolgaozen
Copy link
Member

@tolgaozen tolgaozen commented Nov 25, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Better detection of duplicate tenant creation and more robust error mapping.
    • Safer tenant deletion with existence checks, transactional batch cleanup across related data, and clearer success reporting.
  • Tests

    • Substantially expanded test coverage for tenant management and garbage collection, covering many edge cases (timeouts, empty/invalid inputs, multi-tenant mixes, commit/close/error paths, recreation scenarios).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 25, 2025

Walkthrough

Adds extensive PostgreSQL test coverage for garbage collection and tenant management; CreateTenant now detects pgconn PgError code 23505 for unique-constraint detection; DeleteTenant was refactored to use BeginTx with tx options, run an EXISTS pre-check, execute batched deletions across related tables within a transaction, and improve error mapping and logging.

Changes

Cohort / File(s) Summary
GC tests
internal/storage/postgres/gc/gc_test.go
Adds many GC test cases covering closed DB errors, multi-tenant mixed outcomes, timeouts, tenants with/without data, expired-data cleanup, attribute/transaction cleanup; imports attribute package and adds extra post-write assertions.
TenantWriter implementation
internal/storage/postgres/tenant_writer.go
CreateTenant now inspects pgconn.PgError code 23505 to detect unique-constraint violations. DeleteTenant now uses BeginTx(w.txOptions), performs EXISTS pre-check, builds/executes batched deletions across related tables within a transaction, handles batch/close/commit errors consistently, and logs success on commit.
TenantWriter tests
internal/storage/postgres/tenant_writer_test.go
Expands CreateTenant and DeleteTenant tests (empty/special/Unicode names, timestamps, multi-tenant, long name, not-found, cascade deletes, recreate/delete-twice, empty ID); adds many error-path tests (batch exec/close/commit failures, query/connection errors) and uses SchemaWriter/DataWriter in scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant TenantWriter
    participant DB
    Note over TenantWriter,DB: CreateTenant (new handling)
    Client->>TenantWriter: CreateTenant(name)
    TenantWriter->>DB: INSERT INTO tenants (...)
    alt DB returns PgError(code=23505)
        DB-->>TenantWriter: PgError(code=23505)
        TenantWriter-->>Client: UniqueConstraint error
    else DB error (other)
        DB-->>TenantWriter: error
        TenantWriter-->>Client: mapped error
    else success
        DB-->>TenantWriter: row created
        TenantWriter-->>Client: success
    end
Loading
sequenceDiagram
    participant Client
    participant TenantWriter
    participant DB
    participant Batch
    Note over TenantWriter,DB: DeleteTenant (refactored batched delete)
    Client->>TenantWriter: DeleteTenant(id)
    TenantWriter->>DB: BeginTx(txOptions)
    TenantWriter->>DB: SELECT EXISTS(...) WHERE id=$1
    alt not exists
        DB-->>TenantWriter: false
        TenantWriter->>DB: Rollback
        TenantWriter-->>Client: NotFound error
    else exists
        TenantWriter->>Batch: prepare batched DELETEs (relations, attrs, data, tenant)
        Batch->>DB: execute batch
        alt batch success
            DB-->>TenantWriter: OK
            TenantWriter->>DB: Commit
            DB-->>TenantWriter: Commit OK
            TenantWriter-->>Client: success
        else batch error
            DB-->>TenantWriter: error
            TenantWriter->>Batch: Close
            TenantWriter->>DB: Rollback
            TenantWriter-->>Client: mapped error
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • internal/storage/postgres/tenant_writer.go: transaction lifecycle, batch construction/order, Rollback vs Commit edge paths, and mapping PgError 23505.
    • internal/storage/postgres/tenant_writer_test.go: many injected error-path tests that must reliably simulate DB failures and isolate state.
    • internal/storage/postgres/gc/gc_test.go: timing-sensitive GC scenarios and attribute interactions.

Possibly related PRs

Suggested reviewers

  • tolgaOzen

Poem

🐇 I hopped through rows and indexes bright,

I sniffed for code two-three-five-oh-five at night,
Batches queued and transactions tight,
Tenants cleaned and tests take flight,
A rabbit cheers for commits done right! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The PR title references garbage collector (gc) tests, but the majority of changes are in tenant_writer and tenant_writer_test files, with only a portion in gc_test. The title is partially accurate but emphasizes gc tests when tenant_writer changes represent significant modifications. Consider revising the title to reflect the broader scope: 'test: expand GC and tenant writer test coverage with error scenarios' to accurately represent all major changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/gc-error-handling-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 and usage tips.

Copy link

@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.

Actionable comments posted: 0

🧹 Nitpick comments (5)
internal/storage/postgres/gc/gc_test.go (3)

388-413: Test name doesn't match test behavior.

The test is named "should continue processing other tenants when one tenant fails" but it actually tests a scenario where both tenants are processed successfully - tenant1 has data and tenant2 has no data. Neither tenant "fails" in this test.

Consider renaming to better reflect the actual test behavior:

-		It("should continue processing other tenants when one tenant fails", func() {
-			// Create two tenants
-			tenant1 := "gc-error-tenant-1"
-			tenant2 := "gc-error-tenant-2"
+		It("should handle tenants with varying data states", func() {
+			// Create two tenants, one with data and one without
+			tenant1 := "gc-data-tenant-1"
+			tenant2 := "gc-nodata-tenant-2"

447-484: Test name doesn't match test behavior.

Similar to the earlier test, this is named "should handle multiple tenants with mixed success and failure" but all tenants are processed successfully. Tenant3 simply has no data, which is not a failure scenario.

Consider renaming:

-		It("should handle multiple tenants with mixed success and failure", func() {
+		It("should handle multiple tenants with varying data states", func() {

633-634: Consider a stricter assertion.

The assertion transactionCountAfter <= transactionCountBefore is weak because it would pass even if no transactions were deleted. Since this test specifically aims to verify that deleteTransactionsForTenant deletes old transactions, consider using a stricter assertion:

-			// After GC, old transactions should be deleted, so count should be less
-			Expect(transactionCountAfter).Should(BeNumerically("<=", transactionCountBefore))
+			// After GC, old transactions should be deleted, so count should be strictly less
+			Expect(transactionCountAfter).Should(BeNumerically("<", transactionCountBefore))

Alternatively, if there's a possibility that no transactions qualify for deletion in some runs, the current assertion is acceptable but the comment should reflect that.

internal/storage/postgres/tenant_writer_test.go (1)

271-385: Tests don't exercise distinct error paths.

All six error handling tests (lines 272-385) follow the same pattern: close the database, then call DeleteTenant. Since the database is closed, all tests will fail at the same point (transaction begin), meaning the specific error paths mentioned in test names (batch execution error, commit error, query row error, batch close error, final commit error) are not actually being exercised.

These tests provide basic coverage that errors are handled, but consider consolidating into a single test or documenting that these represent coverage for the general error handling path rather than specific error stages.

internal/storage/postgres/tenant_writer.go (1)

78-79: Comment is slightly misleading.

The comment says "Use parameterized query with constant table name for safety" but table names cannot be parameterized in SQL - they're concatenated. The $1 parameter is for the tenantID value. Consider clarifying:

-	// Use parameterized query with constant table name for safety
+	// Table name is a constant; tenant ID is parameterized to prevent SQL injection
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1951d73 and 086787b.

📒 Files selected for processing (3)
  • internal/storage/postgres/gc/gc_test.go (4 hunks)
  • internal/storage/postgres/tenant_writer.go (4 hunks)
  • internal/storage/postgres/tenant_writer_test.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
internal/storage/postgres/gc/gc_test.go (3)
internal/storage/postgres/gc/gc.go (1)
  • NewGC (31-45)
internal/storage/postgres/consts.go (1)
  • TransactionsTable (7-7)
pkg/testinstance/postgres.go (1)
  • PostgresDB (19-89)
internal/storage/postgres/tenant_writer_test.go (3)
internal/storage/postgres/schema_writer.go (1)
  • NewSchemaWriter (24-29)
pkg/database/postgres/postgres.go (1)
  • Postgres (22-52)
internal/storage/postgres/data_writer.go (1)
  • NewDataWriter (33-38)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Scan Container for Vulnerabilities
  • GitHub Check: Test with Coverage
  • GitHub Check: Analyze (go)
  • GitHub Check: Test with Coverage
🔇 Additional comments (15)
internal/storage/postgres/gc/gc_test.go (9)

18-18: LGTM!

Import added correctly for the new attribute-based test case.


370-386: LGTM!

Good test coverage for database connection errors. The updated comment clearly explains the various error stages being tested.


415-424: LGTM!

Good edge case coverage for tenants with no transactions.


426-445: LGTM!

Good test case verifying that recent data within the GC window is preserved.


486-502: LGTM!

Good test for timeout handling with an extremely short timeout to ensure consistent failure.


505-511: LGTM!

Good edge case test for GC behavior when no custom tenants exist.


513-546: LGTM!

Good test coverage for expired data cleanup, verifying that deleteRecordsForTenant is invoked for the RelationTuplesTable.


548-583: LGTM!

Good test coverage for attribute cleanup, verifying that deleteRecordsForTenant is called for the AttributesTable.


637-651: LGTM!

Good test for empty tenant list scenario with proper resource cleanup of the fresh database instance.

internal/storage/postgres/tenant_writer_test.go (3)

6-18: LGTM!

Imports added correctly to support the new test cases for time-based assertions, string operations, schema writing, tuple handling, and ID generation.


62-133: LGTM!

Excellent test coverage for CreateTenant:

  • Empty names
  • Special characters
  • Unicode characters (including emoji)
  • Timestamp validation with reasonable tolerance
  • Multiple distinct tenants
  • Long names

All edge cases are well-structured and assertions are appropriate.


149-246: LGTM!

Comprehensive test coverage for DeleteTenant:

  • Not found error handling
  • Cascade deletion with associated schema and tuple data
  • Tenant recreation after deletion
  • Double deletion prevention
  • Empty ID handling

Tests align well with the refactored DeleteTenant implementation that includes existence checks.

internal/storage/postgres/tenant_writer.go (3)

46-51: LGTM!

Good improvement using PostgreSQL error code 23505 instead of string-based error detection. This is more reliable and follows PostgreSQL best practices for error handling.


87-121: LGTM!

Good implementation of batch operations:

  • Efficient deletion across multiple related tables in a single batch
  • Proper error handling that closes the batch before returning
  • Transaction rollback is handled by defer on error paths

119-128: LGTM!

Clean implementation with proper error handling for batch close and commit, followed by success logging.

@codecov
Copy link

codecov bot commented Nov 25, 2025

Codecov Report

❌ Patch coverage is 33.33333% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.52%. Comparing base (1951d73) to head (ef3d09e).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
internal/storage/postgres/tenant_writer.go 33.33% 4 Missing and 4 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2652   +/-   ##
=======================================
  Coverage   82.51%   82.52%           
=======================================
  Files          74       74           
  Lines        8132     8125    -7     
=======================================
- Hits         6710     6705    -5     
+ Misses        906      904    -2     
  Partials      516      516           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@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.

Actionable comments posted: 0

🧹 Nitpick comments (3)
internal/storage/postgres/tenant_writer_test.go (3)

62-133: CreateTenant edge‑case coverage looks solid; minor timestamp assertion polish possible

The new tests around empty/special/unicode/long names and CreatedAt behavior provide good functional coverage and catch likely regressions. For the timestamp test, you could optionally simplify/readabilize the window check using Gomega’s temporal matchers (e.g. BeTemporally(">=", beforeCreate) / BeTemporally("<=", afterCreate)) instead of manual Add(±1 * time.Second), but the current approach is correct and reasonably robust.


150-246: DeleteTenant behavior tests are comprehensive; prefer enum constants over raw error strings

The new tests nicely exercise:

  • not‑found behavior (non‑existent ID and empty ID),
  • deletion with associated schema data and relation tuples,
  • recreation after deletion, and
  • double‑delete semantics.

One small consistency issue: the not‑found expectations use hard‑coded strings ("ERROR_CODE_NOT_FOUND"). Elsewhere in this file you assert against base.ErrorCode_... .String(). To keep things type‑safe and resilient to renames, consider switching to:

-Expect(err.Error()).Should(Equal("ERROR_CODE_NOT_FOUND"))
+Expect(err.Error()).Should(Equal(base.ErrorCode_ERROR_CODE_NOT_FOUND.String()))

for the not‑found cases (Lines 155, 237, 245).


291-471: Error‑handling tests are valuable; avoid hard‑coded PG version and minor redundancy

These error‑path tests (batch exec/close/commit/query‑row failures) add useful coverage by exercising DeleteTenant against closed DB instances. A couple of small improvements:

  1. Avoid hard‑coding "14" in separate DBs

All the separate DB setups use:

separateDB := testinstance.PostgresDB("14")

while BeforeEach honors POSTGRES_VERSION with a default. If CI or local runs change the target PG version, these tests will still pin to 14 and can diverge in behavior. Consider factoring a helper mirroring the existing logic and reusing it:

+func postgresVersion() string {
+    v := os.Getenv("POSTGRES_VERSION")
+    if v == "" {
+        v = "14"
+    }
+    return v
+}

and in the tests:

-separateDB := testinstance.PostgresDB("14")
+separateDB := testinstance.PostgresDB(postgresVersion())
  1. Remove redundant setup in the first batch‑exec test

In It("should handle batch execution error during table deletion", ...) you create a tenant via the main tenantWriter before creating and using the separate DB/tenant. That first creation on the primary db doesn’t influence the separate instance and can be safely removed to keep the test focused on the error path in the separate DB.

  1. Brittle line‑number references in comments

Comments like “(line 101)” / “(line 111)” in this file will drift as tenant_writer.go evolves. Consider rephrasing them in terms of behavior (“the batch Exec() in the table‑deletion loop”, “the tenant‑deletion Exec path”) rather than specific line numbers.

All of these are cleanups; the current tests are functionally correct and provide good error‑path coverage.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 086787b and fab7aa8.

📒 Files selected for processing (1)
  • internal/storage/postgres/tenant_writer_test.go (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Analyze (go)
  • GitHub Check: Scan Container for Vulnerabilities
  • GitHub Check: Test with Coverage
  • GitHub Check: Test with Coverage
🔇 Additional comments (1)
internal/storage/postgres/tenant_writer_test.go (1)

3-19: New imports are all exercised and scoped to tests

The additional imports introduced here are all used in the new test cases and are appropriately test-only concerns; no obvious dead dependencies or misplaced production imports.

Copy link

@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.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/storage/postgres/tenant_writer_test.go (1)

281-298: Closing the shared db instance may cause AfterEach to fail.

This test closes the shared db instance (line 286), but AfterEach (line 37-38) also attempts to close it, which could result in an error. The tests at lines 302-319, 381-398, and 400-417 have the same issue.

Consider using a separate database instance for these tests (like the pattern at lines 330, 357, etc.) to avoid double-close issues with the shared db.

 		Context("CreateTenant Error Handling", func() {
 			It("should handle execution error", func() {
 				ctx := context.Background()
 
-				// Create a tenantWriter with a closed database to trigger execution error
-				closedDB := db.(*PQDatabase.Postgres)
-				err := closedDB.Close()
+				// Create a separate database instance and close it to trigger execution error
+				separateDB := testinstance.PostgresDB("14")
+				err := separateDB.Close()
 				Expect(err).ShouldNot(HaveOccurred())
 
-				writerWithClosedDB := NewTenantWriter(closedDB)
+				writerWithClosedDB := NewTenantWriter(separateDB.(*PQDatabase.Postgres))
 
 				_, err = writerWithClosedDB.CreateTenant(ctx, "test_id", "test_name")
🧹 Nitpick comments (5)
internal/storage/postgres/tenant_writer_test.go (5)

104-123: Remove redundant distinctness assertions.

Lines 119-122 are redundant. Since lines 109, 113, and 117 already assert that each tenant ID equals its unique expected value ("multi_tenant_1", "multi_tenant_2", "multi_tenant_3"), their distinctness is already proven.

 			Expect(tenant3.Id).Should(Equal("multi_tenant_3"))
-
-			// Verify all tenants are distinct
-			Expect(tenant1.Id).ShouldNot(Equal(tenant2.Id))
-			Expect(tenant2.Id).ShouldNot(Equal(tenant3.Id))
-			Expect(tenant1.Id).ShouldNot(Equal(tenant3.Id))
 		})

91-102: Consider using Gomega's BeTemporally matcher for cleaner timestamp assertions.

The current approach works, but Gomega provides a more expressive matcher for time comparisons.

 			Expect(err).ShouldNot(HaveOccurred())
 			Expect(tenant.CreatedAt).ShouldNot(BeNil())
-			Expect(tenant.CreatedAt.AsTime().After(beforeCreate.Add(-1 * time.Second))).Should(BeTrue())
-			Expect(tenant.CreatedAt.AsTime().Before(afterCreate.Add(1 * time.Second))).Should(BeTrue())
+			Expect(tenant.CreatedAt.AsTime()).Should(BeTemporally(">=", beforeCreate.Add(-1*time.Second)))
+			Expect(tenant.CreatedAt.AsTime()).Should(BeTemporally("<=", afterCreate.Add(1*time.Second)))

158-178: Consider verifying associated data is actually deleted.

This test confirms that DeleteTenant succeeds when schema data exists, but doesn't verify that the schema data was actually removed. Consider adding a verification step (e.g., attempting to read the schema after deletion) to ensure the cascade delete works correctly.


321-351: Consider removing hard-coded line number references in comments.

Comments like "This will test the br.Exec() error path in the loop (line 101)" reference specific line numbers in tenant_writer.go that may become stale as the implementation evolves. Consider describing the error path by its logical purpose instead.

-				// Close the database to trigger batch execution error
-				// This will test the br.Exec() error path in the loop (line 101)
+				// Close the database to trigger batch execution error
+				// This tests the batch execution error path during table deletion loop

381-417: Tests "commit error after batch execution" and "query row error" appear to test the same error path.

Both tests close the shared db instance and then call DeleteTenant. Since the database is already closed, both will fail at the same point (transaction begin), not at their intended error paths (commit or query row). These tests are effectively duplicates.

Consider either:

  1. Removing one of these redundant tests, or
  2. Using different mechanisms (e.g., mocks, fault injection) to trigger distinct error conditions at the specific paths.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fab7aa8 and 64e9438.

📒 Files selected for processing (1)
  • internal/storage/postgres/tenant_writer_test.go (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/storage/postgres/tenant_writer_test.go (5)
internal/storage/postgres/schema_writer.go (1)
  • NewSchemaWriter (24-29)
internal/storage/postgres/data_writer.go (1)
  • NewDataWriter (33-38)
pkg/testinstance/postgres.go (1)
  • PostgresDB (19-89)
internal/storage/postgres/tenant_writer.go (1)
  • NewTenantWriter (29-34)
pkg/pb/base/v1/errors.pb.go (3)
  • ErrorCode_ERROR_CODE_EXECUTION (87-87)
  • ErrorCode_ERROR_CODE_SQL_BUILDER (85-85)
  • ErrorCode_ERROR_CODE_SCAN (88-88)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Scan Container for Vulnerabilities
  • GitHub Check: Analyze (go)
  • GitHub Check: Test with Coverage
  • GitHub Check: Test with Coverage
🔇 Additional comments (5)
internal/storage/postgres/tenant_writer_test.go (5)

1-19: LGTM!

Imports are well-organized and all newly added imports (strings, time, storage, tuple, xid) are utilized in the new test cases.


270-276: LGTM!

Documents the current behavior for empty ID handling. The ERROR_CODE_NOT_FOUND response is reasonable since an empty ID won't match any existing tenant.


201-228: Comprehensive data cleanup test is valuable.

This test verifies that DeleteTenant succeeds when multiple data types (schema, tuples) are associated with the tenant. The test coverage for the full batch operation flow is good.

As mentioned for the schema-only test, consider adding assertions to verify that the associated data (schema definitions, relation tuples) is actually removed after deletion, not just that the operation succeeds without error.


230-251: LGTM!

Good test for verifying tenant recreation after deletion. This confirms that deletion properly cleans up the unique constraint, allowing the same ID to be reused.


475-501: Test setup correctly uses separate DB instance.

This test properly creates an isolated database instance to test the commit error path, avoiding the double-close issue present in earlier error tests.

Copy link

@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.

Actionable comments posted: 0

🧹 Nitpick comments (4)
internal/storage/postgres/tenant_writer_test.go (4)

145-151: Prefer using the base error code constant instead of hard‑coded "ERROR_CODE_NOT_FOUND"

These tests currently assert on a raw string literal:

  • Line 150: non‑existent tenant
  • Line 270: second deletion
  • Line 278: empty ID

To keep tests aligned with the proto definition and avoid drift if the string ever changes, you can assert using the enum’s .String() like you do for the unique‑constraint case:

-			Expect(err.Error()).Should(Equal("ERROR_CODE_NOT_FOUND"))
+			Expect(err.Error()).Should(Equal(base.ErrorCode_ERROR_CODE_NOT_FOUND.String()))

Apply the same change to all three occurrences.

Also applies to: 256-271, 273-279


183-231: Consider asserting DB cleanup for tuples/all‑data cases, similar to the schema test

For the “associated relation tuples” and “all associated data types” tests you only assert that DeleteTenant returns no error. A regression where some tables aren’t fully cleaned up but still return nil would slip through.

You already directly check the schema table count in the schema test; mirroring that pattern for tuples and other data (using the appropriate table constants) would tighten these tests and validate the full batch‑deletion behavior.


324-354: Remove redundant tenant creation against the main tenantWriter

In It("should handle batch execution error during table deletion") you:

  • First create a tenant via the main tenantWriter (default DB).
  • Then create a separate DB and a separate tenant there.
  • Trigger the error path using writerWithClosedDB built from the separate DB.

The initial creation on the main DB isn’t used by this test and can be dropped to reduce noise and make it clearer which database you’re exercising:

-				// Create a tenant first
-				tenantID := "batch-exec-error-tenant"
-				_, err := tenantWriter.CreateTenant(ctx, tenantID, "Batch Exec Error Tenant")
-				Expect(err).ShouldNot(HaveOccurred())
-
-				// Create a separate database instance for this test
-				separateDB := testinstance.PostgresDB("14")
-				separateWriter := NewTenantWriter(separateDB.(*PQDatabase.Postgres))
-
-				// Create tenant in separate DB
-				_, err = separateWriter.CreateTenant(ctx, tenantID, "Batch Exec Error Tenant")
+				// Create a tenant only in the separate database whose deletion path we want to exercise
+				tenantID := "batch-exec-error-tenant"
+				separateDB := testinstance.PostgresDB("14")
+				separateWriter := NewTenantWriter(separateDB.(*PQDatabase.Postgres))
+
+				_, err := separateWriter.CreateTenant(ctx, tenantID, "Batch Exec Error Tenant")
 				Expect(err).ShouldNot(HaveOccurred())

287-301: Error‑handling tests are thorough; a couple of minor maintainability nits

The matrix of execution/tx/batch/connection/commit error paths is very well covered. Two small nits you might consider:

  1. Avoid line‑number references in comments

    The commit‑error test comment currently mentions a specific source line:

    // This will test the tx.Commit() error path (line 123)

    This will go stale quickly. You can keep the intent without tying it to a line number:

  •   		// This will test the tx.Commit() error path (line 123)
    
  •   		// This will exercise the tx.Commit() error path in DeleteTenant
    
    
    
  1. Reduce duplication in DB setup and error assertions (optional)

    • testinstance.PostgresDB("14") is repeated across many tests; if you ever change the default version logic, these can easily drift from the BeforeEach behavior. A small helper (e.g. newTestPostgresDB() that respects POSTGRES_VERSION with a default) would centralize that choice.
    • The Expect(err.Error()).Should(Or(Equal(...))) block is duplicated across all error‑handling tests; a helper like expectTenantWriterError(err) would make it easier to adjust the allowed codes in one place.

Given this is test code, these are purely cleanliness/DRY improvements, not correctness issues.

Also applies to: 308-322, 324-486

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64e9438 and ef3d09e.

📒 Files selected for processing (1)
  • internal/storage/postgres/tenant_writer_test.go (9 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test with Coverage
  • GitHub Check: Analyze (go)
  • GitHub Check: Test with Coverage
🔇 Additional comments (2)
internal/storage/postgres/tenant_writer_test.go (2)

6-19: New imports are all used correctly

strings, time, storage, tuple, and xid are all exercised in the new tests; the import block is consistent and there’s no dead import here.


62-128: CreateTenant edge‑case coverage looks solid

Nice breadth here: empty name, special chars, unicode, timestamp assertions, multi‑tenant creation, and long names give good confidence in the writer’s behavior. Assuming the underlying column length can accommodate longName, this all looks correct and non‑flaky for typical CI runtimes.

@tolgaozen tolgaozen merged commit 3eb57ec into master Nov 25, 2025
14 of 15 checks passed
@tolgaozen tolgaozen deleted the feature/gc-error-handling-tests branch November 25, 2025 12:36
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