Skip to content

feat: EF-core-oubox-support-for-Dapr - #1863

Open
Psingle20 wants to merge 5 commits into
dapr:masterfrom
Psingle20:feat/ef-core-outbox-support
Open

feat: EF-core-oubox-support-for-Dapr#1863
Psingle20 wants to merge 5 commits into
dapr:masterfrom
Psingle20:feat/ef-core-outbox-support

Conversation

@Psingle20

@Psingle20 Psingle20 commented Jul 1, 2026

Copy link
Copy Markdown

Description

Adds convenience APIs on Dapr.Client that make it easier to compose state transactions engaging the Dapr runtime's native transactional outbox feature (state store component configured with outboxPublishPubsub and related metadata).

Scope-trimmed from the original submission per reviewer feedback — the Dapr.EntityFrameworkCore.Outbox package I initially included will be published as a standalone community NuGet instead, since it's a userland alternative to the runtime outbox rather than an extension of it.

Changes

  • DaprOutboxMetadata — canonical metadata key constants used by the state store outbox (outbox.projection, outbox.pubsubname, outbox.topic, cloudevent.id, cloudevent.type, cloudevent.source, cloudevent.datacontenttype, cloudevent.subject, etc.). Callers reference constants instead of stringly-typed keys.
  • StateTransactionRequestExtensions — fluent helpers on StateTransactionRequest:
    • WithOutboxProjection(pubsubName, topic, payload?, contentType?) — attaches the outbox projection metadata to a state entry.
    • WithCloudEventMetadata(...) — sets cloudevent.* overrides on an entry.
  • OutboxTransactionBuilder — small composer that enforces the invariant that the state entry and its outbox projection share the same key, so a single ExecuteStateTransactionAsync call publishes the message atomically with the state write.

Testing

  • 22 new unit tests in test/Dapr.Client.Test/:
    • DaprOutboxMetadataTests — validates the key constants match Dapr's runtime contract.
    • StateTransactionRequestExtensionsTests — covers default content type, metadata merging, and null-argument guards.
    • OutboxTransactionBuilderTests — enforces the state-entry / projection key-match invariant, verifies the produced request shape, and rejects mismatched configurations.
  • Full Dapr.Client.Test suite is green: 283 / 283 passing on net10.0.

Issue reference

Refs #1494

Checklist

  • Code compiles correctly (net8.0 / net9.0 / net10.0)
  • Created/updated tests (22 new, 283 total green)
  • Extended the documentation (XML doc comments on all new public APIs)

@Psingle20
Psingle20 requested review from a team as code owners July 1, 2026 19:03
@Psingle20
Psingle20 marked this pull request as draft July 1, 2026 19:04
@Psingle20
Psingle20 marked this pull request as ready for review July 1, 2026 19:04
@Psingle20

Copy link
Copy Markdown
Author

Hi @WhitWaldo can you review this ?

@WhitWaldo

Copy link
Copy Markdown
Contributor

First of all, thank you for putting this together especially in response to a long-standing ask from the community.

I don't mind reviewing and likely approving the extensions to simplify setting up the state transaction requests from the DaprClient side. I think those are certainly worthwhile and improve the developer experience in the current approach.

But with regards to the Dapr.EntityFrameworkCore.Outbox package, I'm not inclined to accept it. The transactional outbox is an operation handled entirely by the runtime using the components registered with it. The whole of the SDK is to facilitate the means of engaging with the runtime, not to emulate or replace whole pieces of it to run locally. As yours is a standalone outbox implementation that takes no dependency on the Dapr runtime except to persist the state and instead shifts the entire output responsibility to the SDK, it simply does not belong in this repository.

That said, I can certainly imagine a scenario where it might be a useful feature. I would instead urge you to consider publishing the package to NuGet yourself. Reach out to @marcduiker on Discord and schedule some time to show off your work and promote it to the larger Dapr community - I'm sure there's someone that can use that.

With regards to this PR though, I regret that I cannot accept it as provided. If you can instead remove everything but the Dapr.Client changes and the corresponding tests, I'd be happy to review and get those merged for one of the future 1.18 patch releases.

Adds convenience APIs on Dapr.Client that make it easier to compose state
transactions that engage the Dapr runtime's native transactional outbox
feature via a state store component (outboxPublishPubsub metadata).

- DaprOutboxMetadata: canonical metadata key constants (outbox.projection,
  outbox.pubsubname, outbox.topic, cloudevent.* overrides).
- StateTransactionRequestExtensions: WithOutboxProjection(...) and
  WithCloudEventMetadata(...) fluent helpers.
- OutboxTransactionBuilder: composer that enforces the state entry and its
  outbox projection share the same key, so a single ExecuteStateTransactionAsync
  call publishes the message atomically with the state write.

Tests: 22 new unit tests in Dapr.Client.Test covering metadata keys,
extension defaults, and the key-match invariant. Full Dapr.Client.Test
suite is green (283 tests).

Refs dapr#1494

Signed-off-by: Psingle20 <ingleprachit91@gmail.com>
@Psingle20
Psingle20 force-pushed the feat/ef-core-outbox-support branch from 50786f3 to 2bf105e Compare July 4, 2026 10:55
@Psingle20

Copy link
Copy Markdown
Author

First of all, thank you for putting this together especially in response to a long-standing ask from the community.

I don't mind reviewing and likely approving the extensions to simplify setting up the state transaction requests from the DaprClient side. I think those are certainly worthwhile and improve the developer experience in the current approach.

But with regards to the Dapr.EntityFrameworkCore.Outbox package, I'm not inclined to accept it. The transactional outbox is an operation handled entirely by the runtime using the components registered with it. The whole of the SDK is to facilitate the means of engaging with the runtime, not to emulate or replace whole pieces of it to run locally. As yours is a standalone outbox implementation that takes no dependency on the Dapr runtime except to persist the state and instead shifts the entire output responsibility to the SDK, it simply does not belong in this repository.

That said, I can certainly imagine a scenario where it might be a useful feature. I would instead urge you to consider publishing the package to NuGet yourself. Reach out to @marcduiker on Discord and schedule some time to show off your work and promote it to the larger Dapr community - I'm sure there's someone that can use that.

With regards to this PR though, I regret that I cannot accept it as provided. If you can instead remove everything but the Dapr.Client changes and the corresponding tests, I'd be happy to review and get those merged for one of the future 1.18 patch releases.

Thanks for the thoughtful review and for drawing a clear line on where the SDK ends and userland begins. That reasoning makes sense: the runtime already owns the transactional outbox as a first-class capability via the state store components, and the EF Core package I put together is really an alternative for users whose aggregates live outside a Dapr state store, rather than an extension of the runtime feature. Different pattern, different home.

I've force-pushed the branch back to just the [Dapr.Client] and made the required changes.

I'll spin the EF Core work out to its own repo + NuGet and reach out to @marcduiker on Discord to see about promoting it through the community channel. Appreciate the pointer.

@marcduiker

Copy link
Copy Markdown
Contributor

Hey @Psingle20! Yeah, this is a great topic for a community call. my Discord handle is marcduiker.

@Psingle20

Copy link
Copy Markdown
Author

Hey @Psingle20! Yeah, this is a great topic for a community call. my Discord handle is marcduiker.

Hi @marcduiker, sorry for the late reply. I’ve been caught up with work and haven’t been keeping well. I’ll try to reach out around the weekend.

@Psingle20

Psingle20 commented Jul 12, 2026

Copy link
Copy Markdown
Author

Hi @marcduiker have sent you a friend request my discord handle is Prachpit . Let me know how i can get involved with community!

Copilot AI 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.

Pull request overview

This PR adds first-class helper APIs in Dapr.Client to make it easier and safer to compose state transactions that leverage Dapr’s native transactional outbox behavior via state-store metadata, along with unit tests validating the new helpers.

Changes:

  • Introduces DaprOutboxMetadata constants for well-known outbox / CloudEvent metadata keys.
  • Adds StateTransactionRequestExtensions to mark requests as outbox projections and to apply CloudEvent metadata overrides without mutating the source request.
  • Adds OutboxTransactionBuilder to compose ordered state/projection request pairs for ExecuteStateTransactionAsync, plus unit tests for all new APIs.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Dapr.Client/DaprOutboxMetadata.cs Adds public constants for outbox-related metadata keys.
src/Dapr.Client/StateTransactionRequestExtensions.cs Adds non-mutating helpers to merge projection + CloudEvent metadata into StateTransactionRequest.
src/Dapr.Client/OutboxTransactionBuilder.cs Adds a fluent builder that emits correctly ordered state + projection transaction requests.
test/Dapr.Client.Test/DaprOutboxMetadataTests.cs Adds tests that lock metadata constant values to the runtime wire contract.
test/Dapr.Client.Test/StateTransactionRequestExtensionsTests.cs Adds tests covering non-mutation, metadata merge behavior, and null-guarding.
test/Dapr.Client.Test/OutboxTransactionBuilderTests.cs Adds tests for builder ordering, pairing behavior, and argument validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Dapr.Client/OutboxTransactionBuilder.cs Outdated
Comment thread src/Dapr.Client/OutboxTransactionBuilder.cs
Comment thread src/Dapr.Client/DaprOutboxMetadata.cs
@Psingle20

Copy link
Copy Markdown
Author

Hi @WhitWaldo I think this is good to go let me know if anything else required

@Psingle20
Psingle20 force-pushed the feat/ef-core-outbox-support branch from 97b78b2 to 104a72d Compare July 26, 2026 07:38
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Signed-off-by: Prachit <112982404+Psingle20@users.noreply.github.com>
@Psingle20
Psingle20 force-pushed the feat/ef-core-outbox-support branch from 104a72d to e4c6ae9 Compare July 26, 2026 07:42

@WhitWaldo WhitWaldo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good - thank you for taking the time to build and contribute this!

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.

4 participants