Commit fc7f14f
feat(metadata): Clarify metadata report selection for multi-registry and multi-instance scenarios (#3369)
* fix(metadata): make GetMetadataReport() deterministic in multi-registry setup
* fix(metadata): Remove() fans out to all reports, consistent with Map()
* fix(metadata): thread registryId through GetMetadataFromMetadataReport call chain
* fix(metadata): scope revision calculation to per-registry services, thread registryId through createInstance
* fix(metadata): GetMetadataReportByRegistry returns nil for unknown registryId instead of silently falling back to wrong registry
When a caller provides a specific non-empty registryId that has no
registered report, the previous implementation silently fell back to
GetMetadataReport() and returned an arbitrary report from a different
registry. This undermined the per-registry scoping added in the earlier
commits: metadata for registry A could be fetched from registry B's
report without any indication.
Fix: return nil (with a Warnf log) when a specific registryId is not
found. The existing nil-guard in GetMetadataFromMetadataReport (client.go)
already surfaces this as an error to the caller, which is the correct
behaviour.
The empty-string path is unchanged: it still delegates to
GetMetadataReport() because callers that pass "" have no registry
context and should receive the stable default.
Also expose ClearMetadataReportInstances() to allow cross-package test
isolation of the package-level instances map.
* fix(metadata): ServiceNameMapping.Remove collects all errors instead of returning only the last one
The previous implementation used a lastErr variable that was overwritten
on each iteration. If the first report failed and the second succeeded,
the error was silently discarded and the caller saw no error despite a
partial failure — leaving a stale mapping in the first registry.
Fix: collect all errors with errors.Join so the caller receives the full
failure picture. The loop continues past individual failures (best-effort
fan-out) so a transient error in one registry does not prevent removal
from the others.
Add a comment explaining the intentional behavioural difference from
Map(), which is fail-fast: Map stops at the first report failure, while
Remove continues and collects all errors so every reachable registry gets
the removal attempt.
* test: expand coverage for per-registry metadata report selection
Three gaps identified in PR review, all addressed:
1. metadata/client_test.go — rewrite TestGetMetadataFromMetadataReport
- Add sub-test: specific registryId routes to its own report (not default)
- Add sub-test: unknown registryId returns error, not silent wrong-registry result
- Each sub-test now resets instances independently to prevent state leakage
2. registry/servicediscovery/customizer/service_revision_customizer_test.go
- Add TestExportedRevisionMissingRegistryIdYieldsZero: instance with no
RegistryIdKey gets revision "0" and does not borrow another registry's
service list
- Add TestSubscribedRevisionMissingRegistryIdYieldsZero: same for subscribed
- Add t.Cleanup(ClearMetadataReportInstances) + unique registry-id prefixes
to all four tests to prevent cross-test global map pollution
3. registry/servicediscovery/service_instances_changed_listener_impl_test.go
- Add TestListenerUsesRegistryIdToFetchRemoteMetadata: creates a listener
with registryId="remote-reg-test", registers a mock MetadataReport under
that id, triggers OnEvent with a RemoteMetadataStorageType instance, and
asserts via mock.AssertExpectations that the correct per-registry report
was called — end-to-end proof that registryId threads from
NewServiceInstancesChangedListener through to GetMetadataFromMetadataReport
* chore: translate Chinese comments to English, remove UTF-8 BOM
- metadata/report_instance_test.go: translate inline comments and
testify assertion messages in TestGetMetadataReportIsDeterministic
from Chinese to English, consistent with the rest of the file
- registry/servicediscovery/customizer/service_revision_customizer.go:
translate Customize doc-comments for both exported and subscribed
customizers from Chinese to English
- registry/servicediscovery/service_instances_changed_listener_impl_test.go:
strip the UTF-8 BOM (EF BB BF) that was introduced at line 1;
Go toolchain accepts BOMs but they are not idiomatic and cause
spurious diffs in some editors and CI tools
* style(metadata): fix import formatting
* fix(registry): upgrade missing-registryId log from Warn to Error with accurate consequence
The previous Warnf said 'revision will be empty', which is wrong on two
counts: the actual computed revision is "0" (not empty), and revision
"0" causes OnEvent to silently skip the instance entirely, making it
permanently invisible to all consumers.
Upgrade to Errorf and describe the actual outcome so operators can
diagnose misconfigurations immediately. Applies to both exported and
subscribed revision customizers.
* fix(registry): scope metaCache key to (registryId, revision) to prevent cross-registry metadata poisoning
The cache in GetMetadataInfo was keyed by revision string only. In a
multi-registry setup, if two registries happen to produce the same
revision value (e.g. identical service sets yielding the same CRC, or
test fixtures using literal revision strings), the second registry's
listener would get a cache hit and return MetadataInfo fetched via a
different registry's report — silently serving wrong endpoints with no
error surfaced.
Fix: use registryId+":"+revision as the cache key for both Get and Set,
so each registry's metadata is cached independently.
Update all test helpers and direct metaCache.Set/Delete calls to use
the same composite key (with constant.DefaultKey as the registryId for
all existing single-registry test listeners).
* docs(registry): restore TODO for multi-instance metadata service URL alignment
The previous commit removed the TODO without fixing the underlying issue.
GetMetadataService() still returns a global singleton, so all instances
across registries receive the same metadata service URL regardless of
which registry they belong to.
Restore the TODO with a more detailed explanation so the gap is visible
to future contributors. The fix requires per-registry MetadataService
support and is out of scope for this PR.
* Revert "docs(registry): restore TODO for multi-instance metadata service URL alignment"
This reverts commit 5d7bcc6.
* style(metadata): fix import formatting
* fix(debug) : fix review problems
* style(metadata): fix format issue && revert some changes
* fix(metadata): update tests and comment to match default fallback in GetMetadataReportByRegistry
GetMetadataReportByRegistry intentionally falls back to the 'default'
report when a specific registryId is not found. This supports standalone
metadata-report configs registered under 'default' being used by named
registries (e.g. nacos, zk). Update tests and doc comment to reflect
this behavior instead of the old 'return nil for unknown id' contract.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: address review comments on clarify-metadata-report-selection
- fix(registry): unify registryId default to constant.DefaultKey before
GetMetadataInfo lookup in RegisterService, eliminating empty-string
fallback mismatch and redundant GetParam calls
- fix(metadata): scope metaCache key to app:registryId:revision to
prevent cross-registry cache collisions
- fix(metadata/mapping): bind MappingListener to deterministic primary
report via GetMetadataReport() instead of non-deterministic i==0
- fix(metadata): include registryId in GetMetadataFromMetadataReport
error message for easier misconfiguration diagnosis
- test: add t.Cleanup to remove AddService/AddSubscribeURL entries and
prevent global state leakage between tests
- docs: restore TODO comment explaining GetMetadataService() singleton
limitation in multi-registry metadata service URL alignment
* fix: fix test isolation and cache key format after review changes
- fix(test): update metaCache keys in service_instances_changed_listener_impl_test
to match new app:registryId:revision format
- test: use t.Name()+UnixNano as regID in service_discovery_registry_test
to prevent cross-test global state pollution without expanding production API
---------
Co-authored-by: xnlemon <xianingawa@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent cdf6f2f commit fc7f14f
14 files changed
Lines changed: 642 additions & 71 deletions
File tree
- metadata
- mapping/metadata
- registry
- nacos
- servicediscovery
- customizer
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
46 | | - | |
| 45 | + | |
| 46 | + | |
47 | 47 | | |
48 | | - | |
| 48 | + | |
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| |||
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
| 66 | + | |
| 67 | + | |
65 | 68 | | |
66 | | - | |
| 69 | + | |
| 70 | + | |
67 | 71 | | |
68 | 72 | | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
73 | 80 | | |
74 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
75 | 112 | | |
76 | 113 | | |
77 | 114 | | |
78 | | - | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
79 | 122 | | |
80 | | - | |
| 123 | + | |
81 | 124 | | |
82 | 125 | | |
83 | 126 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
122 | | - | |
123 | | - | |
| 122 | + | |
| 123 | + | |
124 | 124 | | |
125 | 125 | | |
126 | | - | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
127 | 153 | | |
128 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
129 | 161 | | |
130 | 162 | | |
131 | | - | |
132 | | - | |
| 163 | + | |
| 164 | + | |
133 | 165 | | |
134 | 166 | | |
135 | | - | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
136 | 174 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
147 | 148 | | |
148 | 149 | | |
149 | 150 | | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
150 | 250 | | |
151 | 251 | | |
152 | 252 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
25 | | - | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| |||
41 | 42 | | |
42 | 43 | | |
43 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
44 | 51 | | |
45 | 52 | | |
46 | 53 | | |
| |||
51 | 58 | | |
52 | 59 | | |
53 | 60 | | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
54 | 65 | | |
55 | | - | |
56 | | - | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
57 | 76 | | |
58 | 77 | | |
59 | 78 | | |
60 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
61 | 88 | | |
62 | 89 | | |
63 | | - | |
| 90 | + | |
64 | 91 | | |
65 | 92 | | |
66 | 93 | | |
67 | 94 | | |
68 | | - | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
69 | 101 | | |
70 | 102 | | |
71 | 103 | | |
| |||
0 commit comments