Oxidaner commented on code in PR #3711:
URL: https://github.com/apache/dubbo-go/pull/3711#discussion_r3895361665


##########
metadata/service_definition.go:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package metadata
+
+import (
+       "encoding/json"
+       "sort"
+)
+
+import (
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common"
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+       "dubbo.apache.org/dubbo-go/v3/metadata/definition"
+       "dubbo.apache.org/dubbo-go/v3/metadata/report"
+)
+
+// PublishServiceDefinitions builds and publishes an interface-level service
+// definition for each exported URL that carries a describable contract, and
+// returns the URLs whose publish failed for a reason worth retrying.
+//
+// No error is returned and nothing here blocks. A provider whose definition 
did
+// not reach the metadata center is still a working provider — it is only
+// invisible to Admin's console — so a metadata-center outage must not keep
+// instances out of traffic. Java reaches the same outcome by a different 
route:
+// AbstractMetadataReport defaults sync-report to false and hands the write to 
an
+// executor, so export never observes the result at all.
+//
+// Only write failures come back. A service that has no describable contract —
+// unregistered, unbuildable, or with no publishable methods — is reported in 
the
+// log and dropped, because retrying cannot change any of those.
+//
+// Publishing is idempotent and keyed only by service identity, so calling this
+// on every start, on each cycle-report pass, and on every retry simply
+// overwrites the previous document.
+func PublishServiceDefinitions(urls []*common.URL) []*common.URL {
+       publishers := serviceDefinitionPublishers()
+       if len(publishers) == 0 {
+               return nil
+       }
+
+       var failed []*common.URL
+       for _, u := range dedupeByService(urls) {
+               if !publishServiceDefinition(u, publishers) {
+                       failed = append(failed, u)
+               }
+       }
+       return failed
+}
+
+// publishServiceDefinition reports whether the caller should retry.
+//
+// A partial failure across several reports counts as a failure: the retry
+// republishes to all of them, which is harmless because each write overwrites.
+func publishServiceDefinition(u *common.URL, publishers 
[]report.ServiceDefinitionPublisher) bool {
+       svc := common.ServiceMap.GetServiceByServiceKey(u.Protocol, 
u.ServiceKey())
+       if svc == nil {
+               logger.Warnf("[Metadata][Definition] no registered service for 
%s/%s, skipping definition",
+                       u.Protocol, u.ServiceKey())
+               return true
+       }
+
+       def, skips, err := definition.BuildFromURL(u, svc.ServiceType())
+       if err != nil {
+               logger.Errorf("[Metadata][Definition] could not build 
definition for %s: %v", u.ServiceKey(), err)
+               return true
+       }
+       for _, skip := range skips {
+               logger.Warnf("[Metadata][Definition] method %s.%s is not 
published: %s",
+                       def.CanonicalName, skip.Name, skip.Reason)
+       }
+       if len(def.Methods) == 0 {
+               logger.Warnf("[Metadata][Definition] %s has no publishable 
methods, skipping definition",
+                       def.CanonicalName)
+               return true
+       }
+
+       payload, err := json.Marshal(def)
+       if err != nil {
+               logger.Errorf("[Metadata][Definition] could not serialize 
definition for %s: %v",
+                       def.CanonicalName, err)
+               return true
+       }
+
+       application := u.GetParam(constant.ApplicationKey, "")
+       published := true
+       for _, publisher := range publishers {
+               if err := publisher.PublishServiceDefinition(
+                       def.CanonicalName, u.Version(), u.Group(), application, 
string(payload),
+               ); err != nil {
+                       logger.Errorf("[Metadata][Definition] could not publish 
definition for %s: %v",
+                               def.CanonicalName, err)
+                       published = false
+                       continue
+               }
+               logger.Infof("[Metadata][Definition] published definition for 
%s, methods=%d types=%d",
+                       def.CanonicalName, len(def.Methods), len(def.Types))
+       }
+       return published
+}
+
+// ServiceDefinitionsEnabled reports whether any configured metadata report 
will
+// accept interface-level service definitions.
+//
+// Callers use this to decide whether work that only exists to serve 
definitions
+// — the daily re-publish, for one — is worth scheduling at all.
+func ServiceDefinitionsEnabled() bool {
+       return len(serviceDefinitionPublishers()) > 0
+}
+
+// serviceDefinitionPublishers returns the configured reports that both support
+// the capability and have it switched on.
+//
+// The instance table stores *DelegateMetadataReport, so the capability has to 
be
+// queried through the wrapper rather than type-asserted off the interface 
value.
+func serviceDefinitionPublishers() []report.ServiceDefinitionPublisher {
+       var publishers []report.ServiceDefinitionPublisher
+       for _, r := range GetMetadataReports() {

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to