F# codegen: EF Core slice — runnable sample + compile-gate (GH-2969)#2983
Merged
Conversation
…H-2969) First store-specific slice of the F# code-generation audit: a runnable F# Wolverine + EF Core app and a compile-gate proving its handler chain emits valid F# through Wolverine's static codegen path. EF Core frame F# emit: - EnrollDbContextInTransaction -> task { } body: enroll-in-outbox, conditional BeginTransactionAsync (let! _ = ...; isNull guard), try/with around Next. reraise() is illegal inside a CE try/with (FS0413), so the handler rolls back and rethrows via ExceptionDispatchInfo.Capture(ex).Throw() (preserves the stack trace, the semantics of C# `throw;`). - CommitEfCoreEnvelopeTransaction -> do! envelopeTransaction.CommitAsync(...). Runnable sample (src/Samples/WolverineFSharpSample): - F# Item/ItemsDbContext/CreateItemCommand/ItemCreated + a [<Transactional>] CreateItemHandler. Runs via dynamic codegen (references Wolverine.RuntimeCompilation + UseRuntimeCompilation, since core dropped the in-box compiler, GH-2876). - Postgres-backed: the EF Core outbox needs a durable message store, so the sample is not infra-free (the *static* F# story is the compile-gate's job). Compile-gate (src/Testing/Wolverine.EfCore.FSharp{Tests,Fixture}): - Renders the sample's real CreateItemCommand chain to F# via the no-host HandlerGraph/AssembleTypes/GenerateFSharpCode path and dotnet-builds the fixture. Wire-up: sample + gate added to wolverine_fsharp.slnx; fsharp.yml runs the EF gate as its own sequential step. Bumps JasperFx 2.2.5 -> 2.2.7 (the service-location frame surface the EF render needs: LazyServiceLocationFrame et al., #400). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced May 29, 2026
Merged
This was referenced Jun 1, 2026
Merged
This was referenced Jun 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the F# code-generation audit (#2969). After the foundation + Phase A/B/C work proved Wolverine's core/HTTP/saga frames emit F#, this is the first store-specific slice: EF Core — and the first runnable F# Wolverine sample, an explicit #2969 acceptance criterion.
EF Core frame F# emit
EnrollDbContextInTransaction→ atask { }body: enroll-in-outbox, a conditionalBeginTransactionAsync(if isNull … then let! _ = …; ()), and atry … withwrappingNext.reraise()is illegal inside a computation-expressiontry/with(FS0413), so the handler rolls back and rethrows viaExceptionDispatchInfo.Capture(ex).Throw()— preserving the original stack trace, the exact semantics of C#throw;.CommitEfCoreEnvelopeTransaction→do! envelopeTransaction.CommitAsync(cancellation).Generated F# (from the gate):
Runnable sample —
src/Samples/WolverineFSharpSampleA real F# Wolverine app: F#
Item/ItemsDbContext/CreateItemCommand/ItemCreated+ a[<Transactional>]CreateItemHandler. Runs via dynamic codegen (referencesWolverine.RuntimeCompilation+opts.UseRuntimeCompilation(), since core dropped the in-box compiler in #2876). Postgres-backed — Wolverine's EF Core outbox needs a durable message store, so the runnable sample is not infra-free (the static F# story is the compile-gate's job). Verified end-to-end against the docker-compose Postgres: printsCreated an Item through the F# Wolverine + EF Core handler.Compile-gate —
src/Testing/Wolverine.EfCore.FSharp{Tests,Fixture}Renders the sample's real
CreateItemCommandchain to F# via the no-hostHandlerGraph→AssembleTypes→GenerateFSharpCodepath, thendotnet builds the checked-in fixture (with the FS0193/lock retry). Mirrors the Core/Http gates.Wire-up
wolverine_fsharp.slnx.fsharp.ymlruns the EF Core gate as its own sequential step (concurrent nested fixture builds race onWolverine.dll).Dependency
Bumps JasperFx 2.2.5 → 2.2.7. 2.2.7 (#400) adds F# emit for the service-location frame surface the EF Core render needs —
LazyServiceLocationFrame(the one this slice hit) plus the rest of the previously-throwing frames.Verification
dotnet build wolverine.slnx -c Releaseclean (per CLAUDE.md the slim build isn't sufficient).🤖 Generated with Claude Code