github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/services/service.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package services 19 20 import ( 21 "fmt" 22 "github.com/aacfactory/configures" 23 "github.com/aacfactory/errors" 24 "github.com/aacfactory/fns/commons/versions" 25 "github.com/aacfactory/fns/context" 26 "github.com/aacfactory/fns/services/documents" 27 "github.com/aacfactory/logs" 28 "sort" 29 ) 30 31 type Options struct { 32 Id string 33 Version versions.Version 34 Log logs.Logger 35 Config configures.Config 36 } 37 38 type Service interface { 39 Endpoint 40 Construct(options Options) (err error) 41 Components() (components Components) 42 } 43 44 type Listenable interface { 45 Service 46 // Listen 47 // ctx with runtime 48 Listen(ctx context.Context) (err error) 49 } 50 51 func NewAbstract(name string, internal bool, components ...Component) Abstract { 52 svc := Abstract{ 53 name: name, 54 internal: internal, 55 log: nil, 56 components: make(Components, 0, 1), 57 functions: make(Fns, 0, 1), 58 } 59 if components != nil && len(components) > 0 { 60 for _, component := range components { 61 if component == nil { 62 continue 63 } 64 svc.components = append(svc.components, component) 65 } 66 } 67 return svc 68 } 69 70 type Abstract struct { 71 id string 72 name string 73 version versions.Version 74 internal bool 75 log logs.Logger 76 components Components 77 functions Fns 78 } 79 80 func (abstract *Abstract) Construct(options Options) (err error) { 81 abstract.log = options.Log 82 abstract.id = options.Id 83 abstract.version = options.Version 84 if abstract.components != nil { 85 for _, component := range abstract.components { 86 config, hasConfig := options.Config.Node(component.Name()) 87 if !hasConfig { 88 config, _ = configures.NewJsonConfig([]byte{'{', '}'}) 89 } 90 constructErr := component.Construct(Options{ 91 Id: abstract.id, 92 Version: abstract.version, 93 Log: abstract.log.With("component", component.Name()), 94 Config: config, 95 }) 96 if constructErr != nil { 97 if abstract.log.ErrorEnabled() { 98 abstract.log.Error().Caller().Cause(errors.Wrap(constructErr).WithMeta("component", component.Name())).Message("service: construct component failed") 99 } 100 err = errors.Warning(fmt.Sprintf("fns: %s construct failed", abstract.name)).WithMeta("service", abstract.name).WithCause(constructErr) 101 return 102 } 103 return 104 } 105 } 106 return 107 } 108 109 func (abstract *Abstract) Id() string { 110 return abstract.id 111 } 112 113 func (abstract *Abstract) Name() (name string) { 114 name = abstract.name 115 return 116 } 117 118 func (abstract *Abstract) Version() versions.Version { 119 return abstract.version 120 } 121 122 func (abstract *Abstract) Internal() (internal bool) { 123 internal = abstract.internal 124 return 125 } 126 127 func (abstract *Abstract) Components() (components Components) { 128 components = abstract.components 129 return 130 } 131 132 func (abstract *Abstract) Document() (document documents.Endpoint) { 133 return 134 } 135 136 func (abstract *Abstract) AddFunction(fn Fn) { 137 abstract.functions = abstract.functions.Add(fn) 138 sort.Sort(abstract.functions) 139 } 140 141 func (abstract *Abstract) Functions() (functions Fns) { 142 functions = abstract.functions 143 return 144 } 145 146 func (abstract *Abstract) Shutdown(ctx context.Context) { 147 if abstract.components != nil && len(abstract.components) > 0 { 148 for _, component := range abstract.components { 149 component.Shutdown(ctx) 150 } 151 } 152 if abstract.log.DebugEnabled() { 153 abstract.log.Debug().Message(fmt.Sprintf("%s: closed", abstract.name)) 154 } 155 return 156 } 157 158 func (abstract *Abstract) Log() (log logs.Logger) { 159 log = abstract.log 160 return 161 }