feat(generic): validate generic mode and clarify config API (#3472) - #3500
feat(generic): validate generic mode and clarify config API (#3472)#3500NeverENG wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR tightens and clarifies the client-side generic-call configuration by validating generic mode early (at reference creation time) and improving API documentation to clearly separate generic mode (generalization format) from transport serialization (wire encoding).
Changes:
- Added
internal.ValidateGenericType+ tests to define and validate the accepted generic modes (including legacyprotobuf). - Wired generic-mode validation into
ReferenceOptions.initto fail fast on unknown values. - Added documentation clarifying defaults and the separation between generic mode and transport serialization, and introduced
WithGenericIncludeClass(bool).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| internal/config.go | Adds ValidateGenericType for generic-mode validation and clearer failure behavior. |
| internal/config_test.go | Adds table-driven tests covering valid/invalid generic modes and case-insensitivity. |
| client/options.go | Validates generic mode during reference initialization; adds WithGenericIncludeClass option and improves docs. |
| client/client.go | Documents NewGenericService defaults and clarifies generic mode vs transport serialization. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
lgtm |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #3500 +/- ##
===========================================
+ Coverage 46.76% 54.44% +7.67%
===========================================
Files 295 462 +167
Lines 17172 35616 +18444
===========================================
+ Hits 8031 19390 +11359
- Misses 8287 14687 +6400
- Partials 854 1539 +685 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
f314c38 to
634eecb
Compare
| // | ||
| // Whether the "class" field is kept in Map (generic=true) results is controlled by | ||
| // the global "generic.include.class" configuration (default true). It only affects | ||
| // the Map generalizer and currently has no per-reference override. |
There was a problem hiding this comment.
[P1] 当前实现与本 PR 勾选的 API 验收项不一致
这里明确写成 generic.include.class 仅支持全局配置、没有 per-reference override,当前 Head 也已经删除 WithGenericIncludeClass;但 PR 的 Changes 和 Acceptance criteria 仍声称已新增该 API,并将该验收项标记完成。#3472 可以选择不提供用户侧 API,但需要明确收缩 scope;否则按当前 PR 声明,这项需求仍未实现。请二选一:实现一条能实际传递到 MapGeneralizer 的 per-reference 配置链路并补行为测试,或同步修改 PR 描述/验收范围,明确本 PR 只保留全局配置。
There was a problem hiding this comment.
采用「收缩 scope」这一选项。WithGenericIncludeClass 已删除,generic.include.class 保持仅全局配置并在 client/client.go 文档中说明其范围(Map-only、无 per-reference override)。PR 描述的 Changes / Acceptance criteria 已同步更新:per-reference API 一项标记为 scoped out,不再声称已实现;同时新增了「Triple 识别 bean 并路由到 $invoke invoker」的验收项。本 PR 未在代码中实现 per-reference 链路,留待生成器读取该参数后再补。
293f908 to
634eecb
Compare
…edicate
ValidateGenericType accepted "bean" but protocol/triple/triple.go:isGenericCall
did not, so a Triple reference created with WithGenericType("bean") was routed to
NewDubbo3Invoker instead of the $invoke-capable NewTripleInvoker.
Extract the accepted generic-mode decision into a shared internal.IsGenericMode
predicate and have both ValidateGenericType and Triple's isGenericCall use it, so
the accepted-mode set stays in sync. Triple's previously accepted modes
(true/gson/protobuf/protobuf-json) are unchanged; only "bean" is added.
filter/generic/util.go:isGeneric is intentionally left untouched: it omits the
legacy "protobuf", and routing it through the shared predicate would silently
change filter behavior. That convergence is tracked as a follow-up.
Addresses review feedback on apache#3500 (part of apache#3472).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…edicate
ValidateGenericType accepted "bean" but protocol/triple/triple.go:isGenericCall
did not, so a Triple reference created with WithGenericType("bean") was routed to
NewDubbo3Invoker instead of the $invoke-capable NewTripleInvoker.
Extract the accepted generic-mode decision into a shared internal.IsGenericMode
predicate and have both ValidateGenericType and Triple's isGenericCall use it, so
the accepted-mode set stays in sync. Triple's previously accepted modes
(true/gson/protobuf/protobuf-json) are unchanged; only "bean" is added.
filter/generic/util.go:isGeneric is intentionally left untouched: it omits the
legacy "protobuf", and routing it through the shared predicate would silently
change filter behavior. That convergence is tracked as a follow-up.
Addresses review feedback on apache#3500 (part of apache#3472).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bd5543d to
e8ca1f7
Compare
…edicate
ValidateGenericType accepted "bean" but protocol/triple/triple.go:isGenericCall
did not, so a Triple reference created with WithGenericType("bean") was routed to
NewDubbo3Invoker instead of the $invoke-capable NewTripleInvoker.
Extract the accepted generic-mode decision into a shared internal.IsGenericMode
predicate and have both ValidateGenericType and Triple's isGenericCall use it, so
the accepted-mode set stays in sync. Triple's previously accepted modes
(true/gson/protobuf/protobuf-json) are unchanged; only "bean" is added.
filter/generic/util.go:isGeneric is intentionally left untouched: it omits the
legacy "protobuf", and routing it through the shared predicate would silently
change filter behavior. That convergence is tracked as a follow-up.
Addresses review feedback on apache#3500 (part of apache#3472).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
e8ca1f7 to
e97c376
Compare
Fail fast on an unknown generic mode when the reference is created, instead
of silently falling back to the Map generalizer at runtime, and keep the
accepted generic-mode set consistent between reference-creation validation
and Triple's invoker routing.
- add internal.IsGenericMode as the single source of truth for the accepted
generic modes (true/gson/protobuf-json/bean, plus legacy protobuf), and
build internal.ValidateGenericType on top of it, rejecting unknown values
- wire the validation into ReferenceOptions.init
- route protocol/triple/triple.go:isGenericCall through internal.IsGenericMode
so a reference created with WithGenericType("bean") is recognized as generic
and dispatched to the $invoke-capable NewTripleInvoker instead of
NewDubbo3Invoker
- clarify that generic mode and transport serialization are independent, and
document the scope of generic.include.class, in WithGenericType and
NewGenericService docs
- cover the validation and isGenericCall (including bean) with table-driven tests
Part of apache#3472
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: bang <3656828039@qq.com>
e97c376 to
cacd17c
Compare
|



What this PR does
Part of #3472 (泛化调用优化). This PR covers the
client+ config-validation slice: it makes an unknown generic mode fail fast at reference-creation time instead of silently falling back to the Map generalizer at runtime, and clarifies the generic-call configuration API. It also unifies the accepted generic-mode set between reference-creation validation and Triple's invoker routing so thatbeanis recognized consistently.Changes
internal/config.go: addValidateGenericType, acceptingtrue/gson/protobuf-json/bean(case-insensitive; empty = non-generic).protobufis currently kept as a legacy compatibility value. Unknown values return a clear error. Extract the accepted-mode decision into a sharedIsGenericModepredicate so validation and protocol-level routing share one source of truth.client/options.go: wire the validation intoReferenceOptions.init, soWithGenericType("bad-type")is rejected when the reference is created. RewriteWithGenericTypedocs to distinguish generic mode (generalization format) from transport serialization (on-the-wire encoding).client/client.go: documentNewGenericServicedefaults (generic modetrue/Map, transport serialization Hessian2), that the two settings are independent, and the scope ofgeneric.include.class(Map-only, global config, no per-reference override).protocol/triple/triple.go: routeisGenericCallthroughinternal.IsGenericModeso a Triple reference created withWithGenericType("bean")is recognized as generic and dispatched to the$invoke-capableNewTripleInvokerinstead ofNewDubbo3Invoker. The previously accepted modes (true/gson/protobuf/protobuf-json) are unchanged.internal/config_test.go/protocol/triple/triple_test.go: table-driven tests covering all valid modes, case-insensitivity, empty, and unknown values, plusbeancases forisGenericCall.Scope note (updated after review)
An earlier revision added
WithGenericIncludeClass(bool). It has been removed:generic.include.classis only read byMapGeneralizerfrom the global config (filter/generic/generalizer/map.go:getGenericIncludeClass) and does not consult reference/URL params, so the option was a no-op. Per #3472 §4 ("如果本次不新增 API,则……仅补充注释和文档"), this PR keepsgeneric.include.classas global-config only and documents its scope, rather than shipping a non-functional per-reference API. A real per-reference override can be added later once the generalizer reads it.Acceptance criteria (from #3472 §3/§4)
NewGenericService(..., WithGenericType("bad-type"))returns a clear error instead of falling back.generic.include.classscope documented (Map-only, global config).beanas a generic mode and routes it to the$invoke-capableNewTripleInvoker(shared with reference-creation validation viainternal.IsGenericMode).— intentionally scoped out (see Scope note).generic.include.classper-reference APIFollow-up: converge the last checker
The accepted-mode sets previously diverged across three checkers. This PR shares a single predicate (
internal.IsGenericMode) between reference-creation validation and Triple routing, so both now agree andbeanreaches the$invokepath:ValidateGenericType(this PR, viaIsGenericMode)protocol/triple/triple.go:isGenericCall(this PR, viaIsGenericMode)filter/generic/util.go:isGenericThe only remaining divergence is
filter/generic/util.go:isGeneric, which omits the legacyprotobuf. Routing it through the shared predicate would silently re-introduceprotobufinto the filter path — a behavior change in a separate slice/owner of #3472 — so it is intentionally left out here and tracked as a follow-up together with theprotobufdeprecation decision.Verification
go build ./...andgo test ./internal/ ./client/ ./protocol/triple/pass locally.🤖 Generated with Claude Code