Skip to content

feat: add transactional repository methods (InsertWithTx, CheckLimitsWithTx)#73

Merged
alexgarzao merged 23 commits intodevelopfrom
feat/idempotency-key-support--transactional-repository-methods
Mar 23, 2026
Merged

feat: add transactional repository methods (InsertWithTx, CheckLimitsWithTx)#73
alexgarzao merged 23 commits intodevelopfrom
feat/idempotency-key-support--transactional-repository-methods

Conversation

@alexgarzao
Copy link
Collaborator

Summary

Add WithTx variants alongside existing repository methods, enabling transactional usage without breaking existing non-transactional callers. This is the foundation for atomic deduplication in the next PR.

Changes

Repository Layer

  • InsertWithTx(ctx, db, entity): Inserts transaction validation using provided pgdb.DB parameter
  • insertInternal: Extracted shared logic between Insert and InsertWithTx (DRY)
  • Nil db validation: Returns error instead of panic when db is nil

Service Layer

  • CheckLimitsWithTx(ctx, db, input): Accepts pgdb.DB for API consistency (db param reserved for future transactional repo support)
  • checkLimitsInternal: Extracted shared logic between CheckLimits and CheckLimitsWithTx (DRY)

Interfaces

  • command.TransactionValidationRepository: Added InsertWithTx
  • query.LimitChecker: Added CheckLimitsWithTx
  • Mocks regenerated for both interfaces

Code Quality

Design Decisions

  • DD-6: Inline transaction -- tx passed as pgdb.DB parameter (no TxManager)
  • Both WithTx methods are additive -- existing methods unchanged, backward compatible
  • CheckLimitsWithTx accepts db for API consistency; underlying repos will use it when they support transactional operations

Backward Compatibility

  • Existing Insert and CheckLimits methods unchanged
  • All existing tests pass without modification

…WithTx)

Add WithTx variants alongside existing methods for transactional usage:
- InsertWithTx accepts pgdb.DB parameter for atomic operations
- CheckLimitsWithTx accepts pgdb.DB for API consistency
- Extract insertInternal/checkLimitsInternal to eliminate duplication
- Add nil db validation to InsertWithTx
- Add forbidden practice rule: no task/ticket IDs in code
- Regenerate mocks for updated interfaces
@alexgarzao alexgarzao requested a review from a team as a code owner March 20, 2026 00:17
@lerian-studio
Copy link

This PR is very large (27 files, 1359 lines changed). Consider breaking it into smaller PRs for easier review.

@lerian-studio
Copy link

Consider updating CHANGELOG.md to document this change. If this change doesn't need a changelog entry, add the skip-changelog label.

@lerian-studio
Copy link

Consider updating CHANGELOG.md to document this change. If this change doesn't need a changelog entry, add the skip-changelog label.

@lerian-studio
Copy link

This PR is very large (27 files, 1360 lines changed). Consider breaking it into smaller PRs for easier review.

@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds transactional entry points and shared internal helpers: InsertWithTx(ctx, db, validation) on the TransactionValidation repository and CheckLimitsWithTx(ctx, db, input) on the LimitChecker service. Centralizes insert/check logic into insertInternal and checkLimitsInternal helpers, consolidating span creation and error handling and parameterizing operation names. Updates mocks and unit tests for the new transactional methods. Also updates Swagger/OpenAPI description text, removes brief comments referencing section 4.1.1, adjusts defensive copying of nested LimitUsageDetail.Scopes, and updates CI/workflow and Dockerfile metadata.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Repo as TransactionValidationRepository
    participant DB
    participant Tracer

    Client->>Repo: InsertWithTx(ctx, db, validation)
    Repo->>Tracer: Start span "repository.transaction_validation.insert_with_tx"
    Repo->>Repo: insertInternal(ctx, db, validation, logger, span, operationName)
    Repo->>DB: ExecContext("INSERT INTO transaction_validations", args)
    DB-->>Repo: Exec result / error
    Repo->>Tracer: HandleSpanError(span, err)
    Repo-->>Client: return error | nil
Loading
sequenceDiagram
    participant Client
    participant Service as LimitCheckerService
    participant LimitRepo as LimitRepository
    participant UsageRepo as UsageCounterRepository
    participant DB
    participant Tracer

    Client->>Service: CheckLimitsWithTx(ctx, db, input)
    Service->>Tracer: Start span "service.limit_checker.check_limits_with_tx"
    Service->>Service: checkLimitsInternal(ctx, input, logger, span, operationName)
    Service->>LimitRepo: List(applicable limits)
    LimitRepo-->>Service: limits
    Service->>UsageRepo: UpsertAndIncrementAtomic(..., /* may use db */)
    UsageRepo-->>Service: updated usage / error
    Service->>Tracer: HandleSpanError(span, err)
    Service-->>Client: CheckLimitsOutput | error
Loading
🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description covers key aspects: summary of changes, repository and service layer modifications, interface updates, and design decisions. However, it does not follow the required template structure with explicit checklist items completion. Consider following the repository's PR template by explicitly marking checklist items as completed (e.g., testing, documentation, coding standards, security checks) to provide full transparency on review readiness.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: adding transactional repository methods (InsertWithTx, CheckLimitsWithTx) with appropriate feature prefix.

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


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

@alexgarzao alexgarzao changed the base branch from develop to feat/idempotency-key-support--foundation--schema-and-query-and-input-validation March 20, 2026 00:23
@github-actions
Copy link

github-actions bot commented Mar 20, 2026

🔒 Security Scan Results — tracer

Trivy

Filesystem Scan

✅ No vulnerabilities or secrets found.

Docker Image Scan

✅ No vulnerabilities found.


Docker Hub Health Score Compliance

✅ Policies — 4/4 met

Policy Status
Default non-root user ✅ Passed
No fixable critical/high CVEs ✅ Passed
No high-profile vulnerabilities ✅ Passed
No AGPL v3 licenses ✅ Passed

🔍 View full scan logs

@alexgarzao alexgarzao changed the base branch from feat/idempotency-key-support--foundation--schema-and-query-and-input-validation to develop March 20, 2026 14:11
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/build.yml:
- Line 10: Replace the mutable tag for the reusable workflow reference
"LerianStudio/github-actions-shared-workflows/.github/workflows/build.yml@v1.18.1"
with the immutable commit SHA "09f3e9acbe91c58bac6997b4f6f7f2584a6200c5" in both
places it appears (the current occurrences using `@v1.18.1`); update the string to
"LerianStudio/github-actions-shared-workflows/.github/workflows/build.yml@09f3e9acbe91c58bac6997b4f6f7f2584a6200c5"
so the workflow is pinned to the exact commit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: aa391465-582a-4ffd-b9b8-863f2e3d7dae

📥 Commits

Reviewing files that changed from the base of the PR and between fa47d4e and 0c8b7bc.

📒 Files selected for processing (2)
  • .github/workflows/build.yml
  • Dockerfile

- Add span trade-off documentation comment in InsertWithTx nil check
- Add span error annotation for FromEntity failure in insertInternal
- Add TODO(T-003) markers for future db parameter wiring in CheckLimitsWithTx
- Add TODO(T-003) markers in limit_checker_test.go for future expectations
…methods' of github.com:LerianStudio/tracer into feat/idempotency-key-support--transactional-repository-methods
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: 1

♻️ Duplicate comments (1)
internal/services/query/limit_checker.go (1)

80-92: ⚠️ Potential issue | 🔴 Critical

CheckLimitsWithTx still isn't transactional.

db is discarded and this method delegates into the same repository path as CheckLimits, so counter mutations can still commit even if the caller rolls back its surrounding transaction. The inline TODO documents the gap, but shipping a WithTx API before the repositories honor that handle is still unsafe. Please wire db through repository WithTx methods before exposing this entrypoint, or fail fast/remove it for now.

Also applies to: 143-164

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/services/query/limit_checker.go` around lines 80 - 92, The
CheckLimitsWithTx entrypoint is not actually transactional because it discards
the db parameter and delegates to the same repository path as CheckLimits;
either thread the provided db (pgdb.DB) through the underlying repositories
using their WithTx (or equivalent) methods so all counter mutations use the
caller's transaction, or remove/fail-fast this API until repositories accept the
transactional handle; update CheckLimitsWithTx to accept *model.CheckLimitsInput
and return *model.CheckLimitsOutput as before but call
repo.WithTx(db).<method>…</method> (use the repository names and WithTx methods
found in the same package) so that all calls that mutate counters use the
transactional repo handle instead of the non-transactional path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/services/query/limit_checker_test.go`:
- Around line 5304-5305: Replace any TODO comments that include task/ticket IDs
(e.g., "TODO(T-003)") with plain "TODO" so they comply with the new no
task/ticket IDs rule; specifically update the comment containing "TODO(T-003):
When repos support WithTx, add gomock.Eq(mockDB) expectations..." to remove
"(T-003)" and do the same for the other occurrence of "TODO(T-003)" around the
later comment (previously noted at the other location), leaving the rest of the
comment text unchanged.

---

Duplicate comments:
In `@internal/services/query/limit_checker.go`:
- Around line 80-92: The CheckLimitsWithTx entrypoint is not actually
transactional because it discards the db parameter and delegates to the same
repository path as CheckLimits; either thread the provided db (pgdb.DB) through
the underlying repositories using their WithTx (or equivalent) methods so all
counter mutations use the caller's transaction, or remove/fail-fast this API
until repositories accept the transactional handle; update CheckLimitsWithTx to
accept *model.CheckLimitsInput and return *model.CheckLimitsOutput as before but
call repo.WithTx(db).<method>…</method> (use the repository names and WithTx
methods found in the same package) so that all calls that mutate counters use
the transactional repo handle instead of the non-transactional path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: af93c69c-5958-409d-9825-ef43563eb596

📥 Commits

Reviewing files that changed from the base of the PR and between 0c8b7bc and c915e90.

📒 Files selected for processing (3)
  • internal/adapters/postgres/transaction_validation_repository.go
  • internal/services/query/limit_checker.go
  • internal/services/query/limit_checker_test.go

FNV-1a 32-bit hash converts UUID to int32 for use with
pg_advisory_xact_lock. Deterministic, fast, and well-distributed
across the int32 range.
- Add ValidateResult struct with Response and IsDuplicate fields
- Add transactionValidationQueryRepo dependency for FindByRequestID
- Check for existing record before processing (DD-3: Stripe model)
- Duplicate requests return cached response, skip rule/limit eval
- Add ErrNilTransactionValidationQueryRepo sentinel error
- Update constructor to accept and validate query repo dependency
- Handler uses ValidateResult.IsDuplicate to select status code
- HTTP 201 Created for new requests (DD-9)
- HTTP 200 OK for duplicate requests returning cached response
- Wire transactionValidationQueryRepo in bootstrap config
- TestValidate_DuplicateRequestID_ReturnsOriginal
- TestValidate_DuplicateRequestID_NoDoubleCount
- TestValidate_DuplicateRequestID_NoAudit
- TestValidate_DenyByRule_RetryTolerant
- TestValidate_DenyByLimit_RollbackAtomic
- TestValidate_Review_RollbackAtomic
- TestValidationHandler_Validate_ReturnsCorrectStatusCodes (201/200)
Adapt all existing validation service and handler tests to use the
new 6-parameter constructor and ValidateResult return type. Add
FindByRequestID mock expectations for non-duplicate flows.
Replace TODO(T-003) markers with NOTE comments per
PROJECT_RULES.md rule against task IDs in source code.
Move nil validation check to the top of Insert and InsertWithTx,
before GetDB() or span creation. Avoids unnecessary DB connection
and OpenTelemetry overhead for programming errors. The check in
insertInternal is kept as defense-in-depth.
@lerian-studio
Copy link

This PR is very large (35 files, 2333 lines changed). Consider breaking it into smaller PRs for easier review.

@blacksmith-sh
Copy link

blacksmith-sh bot commented Mar 23, 2026

No description provided.

The wrap-around is intentional: pg_advisory_xact_lock accepts int32,
and we need the full hash range including negative values.
@lerian-studio
Copy link

This PR is very large (35 files, 2333 lines changed). Consider breaking it into smaller PRs for easier review.

@alexgarzao alexgarzao merged commit 6a0dec9 into develop Mar 23, 2026
25 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants