123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- // 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"
- "github.com/gogf/gf/v2/internal/intlog"
- "github.com/gogf/gf/v2/util/gutil"
- )
- // watchedServiceMap stores used service
- var watchedServiceMap = gmap.New(true)
- // ServiceWatch is used to watch the service status.
- type ServiceWatch func(service Service)
- // Get retrieves and returns the service by service name.
- func Get(ctx context.Context, name string) (service Service, err error) {
- return GetAndWatch(ctx, name, nil)
- }
- // GetAndWatch is used to getting the service with custom watch callback function.
- func GetAndWatch(ctx context.Context, name string, watch ServiceWatch) (service Service, err error) {
- v := watchedServiceMap.GetOrSetFuncLock(name, func() interface{} {
- var (
- services []Service
- watcher Watcher
- )
- services, err = Search(ctx, SearchInput{
- Name: name,
- })
- if err != nil {
- return nil
- }
- if len(services) == 0 {
- err = gerror.NewCodef(gcode.CodeNotFound, `service not found with name "%s"`, name)
- return nil
- }
- // Just pick one if multiple.
- service = services[0]
- // Watch the service changes in goroutine.
- if watch != nil {
- if watcher, err = Watch(ctx, service.GetPrefix()); err != nil {
- return nil
- }
- go watchAndUpdateService(watcher, service, watch)
- }
- return service
- })
- if v != nil {
- service = v.(Service)
- }
- return
- }
- // watchAndUpdateService watches and updates the service in memory if it is changed.
- func watchAndUpdateService(watcher Watcher, service Service, watchFunc ServiceWatch) {
- var (
- ctx = context.Background()
- err error
- services []Service
- )
- for {
- time.Sleep(time.Second)
- services, err = watcher.Proceed()
- if err != nil {
- intlog.Errorf(ctx, `%+v`, err)
- continue
- }
- if len(services) > 0 {
- watchedServiceMap.Set(service.GetName(), services[0])
- if watchFunc != nil {
- gutil.TryCatch(ctx, func(ctx context.Context) {
- watchFunc(services[0])
- }, func(ctx context.Context, exception error) {
- intlog.Errorf(ctx, `%+v`, exception)
- })
- }
- }
- }
- }
- // 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`)
- }
- ctx, _ = context.WithTimeout(ctx, defaultTimeout)
- 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)
- }
|