feat(http): opt-in filter for HTTP endpoint discovery (CustomizeHttpEndpointDiscovery) - #1
Draft
uniquelau wants to merge 1 commit into
Draft
feat(http): opt-in filter for HTTP endpoint discovery (CustomizeHttpEndpointDiscovery)#1uniquelau wants to merge 1 commit into
uniquelau wants to merge 1 commit into
Conversation
Message handlers can be split across hosts via Discovery.CustomizeHandlerDiscovery(q => q.Excludes.InNamespace(...)), but HTTP endpoints could not: HttpGraph.DiscoverEndpoints built an HttpChainSource from the assembly list alone, and HttpChainSource's TypeQuery never consulted any user-supplied filter, so an endpoint in an excluded namespace of a scanned assembly still registered. [WolverineIgnore] on the type was the only lever. Add WolverineHttpOptions.CustomizeHttpEndpointDiscovery(Action<TypeQuery>), the HTTP counterpart to HandlerDiscovery.CustomizeHandlerDiscovery. HttpChainSource layers the supplied TypeQuery on top of the built-in endpoint convention: Excludes are subtractive (drop endpoint types, e.g. q.Excludes.InNamespace(...)), Includes are additive (broaden discovery; an included type still only contributes methods carrying a Wolverine HTTP verb attribute). When the method is never called the discovery predicate is byte-for-byte identical to prior behaviour. Test proves both directions against a scanned assembly: by default an endpoint in the excluded namespace is discovered; with the filter it is not, while its sibling namespace still resolves. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
uniquelau
force-pushed
the
feat/customize-http-endpoint-discovery
branch
from
July 20, 2026 08:49
fe69a74 to
c081709
Compare
uniquelau
pushed a commit
that referenced
this pull request
Aug 1, 2026
Profiled (full-suite TRX, local M-series): 60 classes, 931s of test time, largest class 167s — a 5.6x parallelism ceiling, so the suite halves even at the 2-worker clamp on hosted runners. What the shakeout run at 4 workers surfaced, all fixed here: - Servers.SqlServerDatabaseName joins PostgresDatabaseName: the catalog parsed from the effective connection string, for assertions that were hard-coding 'master'. - LaneDatabases.Name scopes the sibling databases some suites create beside the main catalog (multi-tenancy's db1/db2/db3, the NServiceBus dedicated-database names) to the lane's catalog, so lanes cannot collide on them. Against the default master catalog the names are unchanged. - static_multi_tenancy's store-description and durability-agent-URI assertions now build from the configured names (bug shape #1 from the Marten lane work — nine tests there, three here). - saga_storage_operations.concurrency_exception_when_version_does_not_match opened with a raw 'delete from lightweight_sagas...' that bypassed the schema API's ensure-storage — on any fresh catalog it failed with 'Invalid object name' unless a sibling test had auto-created the table first. Test-ordering luck; the cleanup was unnecessary (fresh Guid) and is gone. Also: CISqlServer launches the container before compiling and gates on readiness after (LaunchDockerServices/AwaitDockerServices split), so the boot rides the compile instead of following it. Verified: supervised run at 4 workers, 390/390, zero retries, 5m37s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013eR4GL278688VhyhrGcttJ
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.
Review copy on our fork — please review before I open this against JasperFx/wolverine. Natural neighbour to the merged JasperFx#3373 / the live JasperFxGH-3371 (
fix/api-description-provider-http-graph), which touches the sameHttpGraphdiscovery area.Problem
Message handlers can be split across hosts by namespace —
Discovery.CustomizeHandlerDiscovery(q => q.Excludes.InNamespace(...))— but HTTP endpoints cannot.An
…Endpoint/…Endpointstype (or any[WolverineHttpMethod]method) in an excluded namespace of a scanned assembly still registers its routes.[WolverineIgnore]per endpoint type is the only lever, and it doesn't scale to a module/namespace split.This is the missing half of the modular-monolith-deployed-as-multiple-hosts story Wolverine already supports for handlers (
MultipleHandlerBehavior.Separated).Change (additive, opt-in, default unchanged)
New method on
WolverineHttpOptions, a byte-for-byte mirror ofCustomizeHandlerDiscovery:WolverineHttpOptions.CustomizeHttpEndpointDiscovery(Action<JasperFx.Core.TypeScanning.TypeQuery>)— lazily creates an internalTypeQueryand hands the caller itsIncludes/Excludes.HttpGraph.DiscoverEndpointspasses it toHttpChainSource; the discovery predicate layers the user query onto the built-in convention (Excludes subtractive, Includes additive). When unset, the predicate reduces to the exact prior condition — default discovery is byte-for-byte unchanged.Action<TypeQuery>(the public JasperFx type the handler API already exposes), notAction<CompositeFilter<Type>>— mirrorsCustomizeHandlerDiscoveryexactly and avoids leaking Wolverine.Http's own internalCompositeFilter<T>.Test
http_endpoint_discovery_filter(Wolverine.Http.Tests): proves the excluded-namespace endpoint is discovered by default and absent under the filter, while its sibling still resolves. Passes 2/2; regression suites scanning the same test assembly (generate_openapi_without_database,openapi_shape_tests) pass 17/0.Wolverine.Http.csprojbuilds clean.Open points for your call before upstream
Action<TypeQuery>for exact handler-discovery symmetry (agreed?).Includessupport, or trim to excludes-only for minimalism (the strict ask was excludes-only).Value: closes a documented asymmetry (the HTTP
endpoints.mdguide can gain the same filter examplehandlers/discovery.mdalready shows), and benefits every multi-host-from-one-build split (public vs admin host, plugin assemblies), not just our use.