2022-01-26 22:23:54 +08:00
|
|
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
|
|
|
|
package gsvc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/gogf/gf/v2/container/gmap"
|
|
|
|
"github.com/gogf/gf/v2/errors/gcode"
|
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
2022-01-28 14:51:49 +08:00
|
|
|
"github.com/gogf/gf/v2/internal/intlog"
|
2022-01-27 18:12:39 +08:00
|
|
|
"github.com/gogf/gf/v2/util/gutil"
|
2022-01-26 22:23:54 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
watchedServiceMap = gmap.New(true)
|
|
|
|
)
|
|
|
|
|
2022-01-27 18:12:39 +08:00
|
|
|
type ServiceWatch func(service *Service)
|
|
|
|
|
2022-01-26 22:23:54 +08:00
|
|
|
func Get(ctx context.Context, name string) (service *Service, err error) {
|
2022-01-27 18:12:39 +08:00
|
|
|
return GetWithWatch(ctx, name, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetWithWatch(ctx context.Context, name string, watch ServiceWatch) (service *Service, err error) {
|
2022-01-26 22:23:54 +08:00
|
|
|
v := watchedServiceMap.GetOrSetFuncLock(name, func() interface{} {
|
|
|
|
var (
|
|
|
|
s = NewServiceWithName(name)
|
|
|
|
services []*Service
|
2022-01-27 18:12:39 +08:00
|
|
|
watcher Watcher
|
2022-01-26 22:23:54 +08:00
|
|
|
)
|
|
|
|
services, err = Search(ctx, SearchInput{
|
|
|
|
Prefix: s.Prefix,
|
|
|
|
Deployment: s.Deployment,
|
|
|
|
Namespace: s.Namespace,
|
|
|
|
Name: s.Name,
|
|
|
|
Version: s.Version,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if len(services) == 0 {
|
|
|
|
err = gerror.NewCodef(gcode.CodeNotFound, `service not found with name "%s"`, name)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
service = services[0]
|
|
|
|
// Watch the service changes in goroutine.
|
2022-01-27 18:12:39 +08:00
|
|
|
watcher, err = Watch(ctx, service.KeyWithoutEndpoints())
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
go watchAndUpdateService(watcher, service, watch)
|
2022-01-26 22:23:54 +08:00
|
|
|
return service
|
|
|
|
})
|
|
|
|
if v != nil {
|
|
|
|
service = v.(*Service)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-01-27 18:12:39 +08:00
|
|
|
func watchAndUpdateService(watcher Watcher, service *Service, watchFunc ServiceWatch) {
|
2022-01-26 22:23:54 +08:00
|
|
|
var (
|
2022-01-27 18:12:39 +08:00
|
|
|
ctx = context.Background()
|
2022-01-26 22:23:54 +08:00
|
|
|
err error
|
|
|
|
services []*Service
|
|
|
|
)
|
|
|
|
for {
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
services, err = watcher.Proceed()
|
|
|
|
if err != nil {
|
2022-01-28 14:51:49 +08:00
|
|
|
intlog.Errorf(ctx, `%+v`, err)
|
2022-01-26 22:23:54 +08:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if len(services) > 0 {
|
|
|
|
watchedServiceMap.Set(service.Name, services[0])
|
2022-01-27 18:12:39 +08:00
|
|
|
if watchFunc != nil {
|
|
|
|
gutil.TryCatch(func() {
|
|
|
|
watchFunc(services[0])
|
|
|
|
}, func(exception error) {
|
2022-01-28 14:51:49 +08:00
|
|
|
intlog.Errorf(ctx, `%+v`, exception)
|
2022-01-27 18:12:39 +08:00
|
|
|
})
|
|
|
|
}
|
2022-01-26 22:23:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search searches and returns services with specified condition.
|
|
|
|
func Search(ctx context.Context, in SearchInput) ([]*Service, error) {
|
|
|
|
if defaultRegistry == nil {
|
|
|
|
return nil, gerror.NewCodef(gcode.CodeNotImplemented, `no Registry is registered`)
|
|
|
|
}
|
2022-01-28 16:00:16 +08:00
|
|
|
ctx, _ = context.WithTimeout(ctx, defaultTimeout)
|
2022-01-26 22:23:54 +08:00
|
|
|
return defaultRegistry.Search(ctx, in)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Watch watches specified condition changes.
|
|
|
|
func Watch(ctx context.Context, key string) (Watcher, error) {
|
|
|
|
if defaultRegistry == nil {
|
|
|
|
return nil, gerror.NewCodef(gcode.CodeNotImplemented, `no Registry is registered`)
|
|
|
|
}
|
|
|
|
return defaultRegistry.Watch(ctx, key)
|
|
|
|
}
|