Skip to content

v1.0.33 - #89

Merged
yilmaztayfun merged 3 commits into
release-v1.0from
master
Jul 22, 2026
Merged

v1.0.33#89
yilmaztayfun merged 3 commits into
release-v1.0from
master

Conversation

@yilmaztayfun

@yilmaztayfun yilmaztayfun commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Consolidate PostgreSQL multi-schema support around qualified-name schema targeting, remove search_path-based switching modes and interceptor, and adjust the Unit of Work to allow non-transactional flows to use EF Core-owned pooled connections instead of a shared connection.

Enhancements:

  • Refine CompositeUnitOfWork so transactional roots open a shared connection/transaction lazily while non-transactional roots never hold a physical connection, relying on EF Core-owned pooled connections per operation.
  • Introduce QualifiedNamesCommandInterceptor to rewrite EF model placeholders and raw SQL {{schema}} tokens to fully qualified schema names without touching search_path, and wire it through the Npgsql provider.
  • Extend IAetherDatabaseProvider and IAetherDbContextConfigurator with owned-connection options to support non-transactional contexts that don't enlist on a shared connection.
  • Simplify SchemaSwitchingMode to a single QualifiedNames option and make NpgsqlAetherProvider parameterless, keeping AddAetherNpgsql's mode parameter only for signature compatibility.

Documentation:

  • Update multi-schema and unit-of-work documentation to reflect qualified-names as the sole schema targeting strategy and remove references to TransactionLocal and SessionSearchPath modes.
  • Clarify transactional vs non-transactional Unit of Work behavior, connection usage, and pooling guarantees in both English and Turkish guides.
  • Revise PgBouncer documentation and diagrams to describe schema safety without search_path manipulation.

Tests:

  • Update and expand PostgreSQL and infrastructure tests to validate qualified-name schema isolation, non-transactional connection behavior, pooling safety, and schema non-leakage across units of work.
  • Adjust schema setup in tests to rewrite generated EF Core DDL scripts using the qualified schema name, and align test expectations with the new interceptor and connection management model.
  • Remove tests specific to TransactionLocal and SessionSearchPath behaviors such as search_path leakage and mode-based token rejection.

claude and others added 3 commits July 22, 2026 14:44
…; reduce SchemaSwitchingMode to QualifiedNames

Non-transactional CompositeUnitOfWork roots no longer create/open a shared
DbConnection. Contexts are built via the new BuildOwnedOptions/ApplyOwned
path bound to the connection string, so EF Core rents a pooled connection
per operation and returns it immediately. This removes hold-for-request
connection pinning that inflated pool demand (Npgsql connect timeouts under
long-polling load). Transactional roots keep the shared connection +
transaction semantics unchanged.

SchemaSwitchingMode now has a single member, QualifiedNames; the
TransactionLocal and SessionSearchPath modes and all search_path
manipulation are removed. SearchPathCommandInterceptor is replaced by
QualifiedNamesCommandInterceptor(schema, currentSchema). NpgsqlAetherProvider
is parameterless; AddAetherNpgsql keeps the optional mode parameter for
signature compatibility and defaults to QualifiedNames.

Tests updated for the new topology (owned connections, qualified-names DDL
placeholder rewriting) and multi-schema/unit-of-work docs rewritten
accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKsqFuUQTnEJaJKygkEh2c
…out-mgzobn

Remove TransactionLocal and SessionSearchPath modes; use QualifiedNames only
@yilmaztayfun yilmaztayfun self-assigned this Jul 22, 2026
@yilmaztayfun
yilmaztayfun requested review from a team July 22, 2026 20:40
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0048deb1-d65d-4b58-b93e-b9f20e9eddf5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch master

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.

@sourcery-ai

sourcery-ai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Reviewer's Guide

Consolidates PostgreSQL multi-schema support onto a single QualifiedNames strategy, updates the Unit of Work to distinguish transactional (shared connection) vs non-transactional (EF-owned) connection lifecycles, removes all search_path-based modes and interceptors, and refreshes docs and tests to match the new behavior and APIs.

File-Level Changes

Change Details Files
UnitOfWork now differentiates transactional vs non-transactional connection lifecycles and supports schema-bound contexts without holding a shared connection in non-transactional flows.
  • Updated CompositeUnitOfWork docs and GetDbContextAsync to open a shared DbConnection/DbTransaction only when IsTransactional is true.
  • Introduced use of IAetherDbContextConfigurator.BuildOwnedOptions for non-transactional units of work so EF Core manages pooled connections per operation.
  • Commented out the MaxDbContextCount enforcement block (likely temporary) and clarified DisposeAsync cleanup semantics for providers that might write session-level state.
framework/src/BBT.Aether.Infrastructure/BBT/Aether/Uow/CompositeUnitOfWork.cs
PostgreSQL provider is simplified to a single QualifiedNames-based schema targeting strategy and extended with owned-connection configuration for non-transactional UoWs.
  • Replaced SearchPathCommandInterceptor with a new QualifiedNamesCommandInterceptor that rewrites model placeholders and raw {{schema}} tokens to a quoted schema and validates current schema, without touching search_path.
  • Refactored NpgsqlAetherProvider to drop mode configuration, always use QualifiedNames, and add ApplyOwned for connection-string-bound contexts.
  • Updated AetherNpgsqlServiceCollectionExtensions to default SchemaSwitchingMode to QualifiedNames and construct a parameterless NpgsqlAetherProvider.
  • Extended IAetherDatabaseProvider and IAetherDbContextConfigurator with ApplyOwned/BuildOwnedOptions, plus implementations for Npgsql and in-memory test providers.
framework/src/BBT.Aether.Npgsql/NpgsqlAetherProvider.cs
framework/src/BBT.Aether.Npgsql/QualifiedNamesCommandInterceptor.cs
framework/src/BBT.Aether.Npgsql/Microsoft/Extensions/DependencyInjection/AetherNpgsqlServiceCollectionExtensions.cs
framework/src/BBT.Aether.Infrastructure/BBT/Aether/Uow/EntityFrameworkCore/IAetherDatabaseProvider.cs
framework/src/BBT.Aether.Infrastructure/BBT/Aether/Uow/EntityFrameworkCore/AetherDbContextConfigurator.cs
framework/src/BBT.Aether.Infrastructure/BBT/Aether/Uow/EntityFrameworkCore/IAetherDbContextConfigurator.cs
SchemaSwitchingMode enum and related behaviors are collapsed to a single QualifiedNames member and all TransactionLocal/SessionSearchPath-specific behavior and tests are removed or refactored.
  • Simplified SchemaSwitchingMode to only QualifiedNames and updated its XML docs to describe its semantics as the sole strategy.
  • Removed SearchPathCommandInterceptor and all references to search_path-based modes, including transaction-enforcement behavior and RESET search_path cleanup.
  • Adjusted tests to stop parameterizing over modes, assume QualifiedNames-only behavior, and update naming and expectations (e.g., non-transactional connection behavior, schema-leakage tests, PgBouncer tests).
framework/src/BBT.Aether.Npgsql/BBT/Aether/Uow/EntityFrameworkCore/SchemaSwitchingMode.cs
framework/src/BBT.Aether.Npgsql/SearchPathCommandInterceptor.cs
framework/test/BBT.Aether.Postgres.Tests/QualifiedNamesTests.cs
framework/test/BBT.Aether.Postgres.Tests/UnitOfWorkDisposalTests.cs
framework/test/BBT.Aether.Postgres.Tests/MultiSchemaUnitOfWorkTests.cs
framework/test/BBT.Aether.Postgres.Tests/PgBouncerSearchPathTests.cs
framework/test/BBT.Aether.Postgres.Tests/NpgsqlLeaseStoreTests.cs
framework/test/BBT.Aether.Postgres.Tests/UnitOfWorkMiddlewareTests.cs
framework/test/BBT.Aether.Postgres.Tests/NonTransactionalOutboxDispatchTests.cs
DDL-generation paths in tests now rewrite the model’s schema placeholder to concrete schemas without relying on search_path, matching the QualifiedNames strategy.
  • Post-processing of Database.GenerateCreateScript() in multiple test fixtures to replace aether_schema placeholders with the concrete test schema and to make CREATE SCHEMA idempotent.
  • Ensured background job, outbox, inbox, and job store tests all use the rewritten DDL instead of search_path tricks for schema placement.
framework/test/BBT.Aether.Postgres.Tests/OutboxWithinSharedTransactionTests.cs
framework/test/BBT.Aether.Postgres.Tests/NonTransactionalOutboxDispatchTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/ArmingProcessorTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/DaprBridgeTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/EndToEndJobLifecycleTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/EnqueueAtomicityTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/JobDispatcherTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/JobStoreCasTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/JobStoreClaimReaperTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/ReaperTests.cs
Docs for multi-schema, unit of work, and adoption are rewritten to describe QualifiedNames-only schema targeting and the new transactional vs non-transactional connection model.
  • Updated multi-schema README, IMPLEMENTATION_NOTES, and ADOPTION-GUIDE to remove TransactionLocal/SessionSearchPath sections, describe QualifiedNames as the only mode, and explain that non-transactional UoWs hold no connection while EF Core manages pooled connections.
  • Refreshed unit-of-work README to show the new Npgsql registration pattern, QualifiedNames-only behavior, and connection lifecycle semantics.
  • Aligned test and diagram documentation around QualifiedNamesCommandInterceptor, context-schema binding checks, and PgBouncer-safe behavior without search_path.
framework/docs/multi-schema/README.md
framework/docs/multi-schema/IMPLEMENTATION_NOTES.md
framework/docs/multi-schema/ADOPTION-GUIDE.md
framework/docs/unit-of-work/README.md
Infrastructure, tests, and helpers are adjusted to work with the new configuration surface and QualifiedNames-only behavior.
  • Tweaked DomainEventFailureTests’ in-memory IAetherDbContextConfigurator to implement the new BuildOwnedOptions method.
  • Updated DbContextConfiguratorTests and other tests to match the interceptor and transaction behaviors of the new QualifiedNames-only provider.
  • Renamed tests and assertions for clarity around transactional vs non-transactional behavior and schema isolation mechanics.
framework/test/BBT.Aether.Infrastructure.Tests/BBT/Aether/Uow/DomainEventFailureTests.cs
framework/test/BBT.Aether.Postgres.Tests/DbContextConfiguratorTests.cs
framework/test/BBT.Aether.Postgres.Tests/OutboxWithinSharedTransactionTests.cs
framework/test/BBT.Aether.Postgres.Tests/BackgroundJob/*.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@yilmaztayfun
yilmaztayfun merged commit 51e4ff7 into release-v1.0 Jul 22, 2026
3 of 6 checks passed
@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 1 critical

Alerts:
⚠ 1 issue (≤ 0 issues of at least minor severity)

Results:
1 new issue

Category Results
Security 1 critical

View in Codacy

🟢 Metrics 8 complexity · 1 duplication

Metric Results
Complexity 8
Duplication 1

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

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

Hey - I've found 1 security issue, 1 other issue, and left some high level feedback:

Security issues:

  • Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements instead. You can obtain a PreparedStatement using 'SqlCommand' and 'SqlParameter'. (link)

Fixed security issues:

  • Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements instead. You can obtain a PreparedStatement using 'SqlCommand' and 'SqlParameter'. (link)

General comments:

  • In CompositeUnitOfWork.GetDbContextAsync the MaxDbContextCount guard is commented out rather than removed or replaced; if the limit is intentionally being dropped, consider deleting the dead code and updating any related configuration/docs instead of leaving it commented, or re-enable it with a clear rationale.
  • QualifiedNamesCommandInterceptor runs both RewriteModelPlaceholder and Rewrite on every command; if command frequency is high, it may be worth considering a small optimization (e.g., early-exit when the placeholder/token is absent, or combining the passes) to reduce repeated string processing on hot paths.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In CompositeUnitOfWork.GetDbContextAsync the MaxDbContextCount guard is commented out rather than removed or replaced; if the limit is intentionally being dropped, consider deleting the dead code and updating any related configuration/docs instead of leaving it commented, or re-enable it with a clear rationale.
- QualifiedNamesCommandInterceptor runs both RewriteModelPlaceholder and Rewrite on every command; if command frequency is high, it may be worth considering a small optimization (e.g., early-exit when the placeholder/token is absent, or combining the passes) to reduce repeated string processing on hot paths.

## Individual Comments

### Comment 1
<location path="framework/docs/multi-schema/IMPLEMENTATION_NOTES.md" line_range="86" />
<code_context>
-6. **PgBouncer-safe choices.** `TransactionLocal` never leaks because PostgreSQL reverts
-   `SET LOCAL` with the transaction. `QualifiedNames` has no connection schema state at all.
-   `SessionSearchPath` remains limited to a session-pinned/native connection.
+6. **Safe under any pooling.** Qualified names has no connection schema state at all — nothing
+   is ever written to session or transaction state — so it is safe under PgBouncer transaction
+   or session pooling as well as the native Npgsql pool. Non-transactional UoWs additionally
</code_context>
<issue_to_address>
**issue (typo):** Fix subject–verb agreement in the phrase "Qualified names has".

Change the sentence to: "Qualified names have no connection schema state at all" to ensure correct subject–verb agreement and consistency with other references to qualified names.

```suggestion
6. **Safe under any pooling.** Qualified names have no connection schema state at all — nothing
```
</issue_to_address>

### Comment 2
<location path="framework/src/BBT.Aether.Npgsql/QualifiedNamesCommandInterceptor.cs" line_range="86-88" />
<code_context>
        command.CommandText = PostgreSqlRawSchemaTokenRewriter
            .Rewrite(modelRewritten, _quotedSchema)
            .CommandText;
</code_context>
<issue_to_address>
**security (csharp.lang.security.sqli.csharp-sqli):** Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements instead. You can obtain a PreparedStatement using 'SqlCommand' and 'SqlParameter'.

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

6. **PgBouncer-safe choices.** `TransactionLocal` never leaks because PostgreSQL reverts
`SET LOCAL` with the transaction. `QualifiedNames` has no connection schema state at all.
`SessionSearchPath` remains limited to a session-pinned/native connection.
6. **Safe under any pooling.** Qualified names has no connection schema state at all — nothing

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (typo): Fix subject–verb agreement in the phrase "Qualified names has".

Change the sentence to: "Qualified names have no connection schema state at all" to ensure correct subject–verb agreement and consistency with other references to qualified names.

Suggested change
6. **Safe under any pooling.** Qualified names has no connection schema state at all — nothing
6. **Safe under any pooling.** Qualified names have no connection schema state at all — nothing

Comment on lines +86 to +88
command.CommandText = PostgreSqlRawSchemaTokenRewriter
.Rewrite(modelRewritten, _quotedSchema)
.CommandText;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security (csharp.lang.security.sqli.csharp-sqli): Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the SQL statement are not properly sanitized. Use a prepared statements instead. You can obtain a PreparedStatement using 'SqlCommand' and 'SqlParameter'.

Source: opengrep

@sonarqubecloud

Copy link
Copy Markdown

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