github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/services/endpoints.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 "github.com/aacfactory/fns/commons/futures" 22 "github.com/aacfactory/fns/commons/versions" 23 "github.com/aacfactory/fns/context" 24 "github.com/aacfactory/fns/services/documents" 25 "sort" 26 "strings" 27 "unsafe" 28 ) 29 30 type Endpoint interface { 31 Name() (name string) 32 Internal() (ok bool) 33 Document() (document documents.Endpoint) 34 Functions() (functions Fns) 35 Shutdown(ctx context.Context) 36 } 37 38 type EndpointInfo struct { 39 Id string `json:"id"` 40 Version versions.Version `json:"version"` 41 Address string `json:"address"` 42 Name string `json:"name"` 43 Internal bool `json:"internal"` 44 Functions FnInfos `json:"functions"` 45 Document documents.Endpoint `json:"document"` 46 } 47 48 type EndpointInfos []EndpointInfo 49 50 func (infos EndpointInfos) Len() int { 51 return len(infos) 52 } 53 54 func (infos EndpointInfos) Less(i, j int) bool { 55 x := infos[i] 56 y := infos[j] 57 n := strings.Compare(x.Name, y.Name) 58 if n < 0 { 59 return true 60 } else if n == 0 { 61 return x.Version.LessThan(y.Version) 62 } else { 63 return false 64 } 65 } 66 67 func (infos EndpointInfos) Swap(i, j int) { 68 infos[i], infos[j] = infos[j], infos[i] 69 } 70 71 func (infos EndpointInfos) Find(name []byte) (info EndpointInfo, found bool) { 72 ns := unsafe.String(unsafe.SliceData(name), len(name)) 73 n := infos.Len() 74 if n < 65 { 75 for _, endpoint := range infos { 76 if endpoint.Name == ns { 77 info = endpoint 78 found = true 79 break 80 } 81 } 82 return 83 } 84 i, j := 0, n 85 for i < j { 86 h := int(uint(i+j) >> 1) 87 if strings.Compare(infos[h].Name, ns) < 0 { 88 i = h + 1 89 } else { 90 j = h 91 } 92 } 93 found = i < n && infos[i].Name == ns 94 if found { 95 info = infos[i] 96 } 97 return 98 } 99 100 type EndpointGetOption func(options *EndpointGetOptions) 101 102 type EndpointGetOptions struct { 103 id []byte 104 requestVersions versions.Intervals 105 } 106 107 func (options EndpointGetOptions) Id() []byte { 108 return options.id 109 } 110 111 func (options EndpointGetOptions) Versions() versions.Intervals { 112 return options.requestVersions 113 } 114 115 func EndpointId(id []byte) EndpointGetOption { 116 return func(options *EndpointGetOptions) { 117 options.id = id 118 return 119 } 120 } 121 122 func EndpointVersions(requestVersions versions.Intervals) EndpointGetOption { 123 return func(options *EndpointGetOptions) { 124 options.requestVersions = requestVersions 125 return 126 } 127 } 128 129 type Endpoints interface { 130 Info() (infos EndpointInfos) 131 Get(ctx context.Context, name []byte, options ...EndpointGetOption) (endpoint Endpoint, has bool) 132 RequestAsync(ctx context.Context, name []byte, fn []byte, param any, options ...RequestOption) (future futures.Future, err error) 133 Request(ctx context.Context, name []byte, fn []byte, param any, options ...RequestOption) (response Response, err error) 134 } 135 136 type Services []Service 137 138 func (s Services) Len() int { 139 return len(s) 140 } 141 142 func (s Services) Less(i, j int) bool { 143 return strings.Compare(s[i].Name(), s[j].Name()) < 0 144 } 145 146 func (s Services) Swap(i, j int) { 147 s[i], s[j] = s[j], s[i] 148 } 149 150 func (s Services) Add(v Service) Services { 151 ss := append(s, v) 152 sort.Sort(ss) 153 return ss 154 } 155 156 func (s Services) Find(name []byte) (v Service, found bool) { 157 ns := unsafe.String(unsafe.SliceData(name), len(name)) 158 n := s.Len() 159 if n < 65 { 160 for _, endpoint := range s { 161 if endpoint.Name() == ns { 162 v = endpoint 163 found = true 164 break 165 } 166 } 167 return 168 } 169 i, j := 0, n 170 for i < j { 171 h := int(uint(i+j) >> 1) 172 if strings.Compare(s[h].Name(), ns) < 0 { 173 i = h + 1 174 } else { 175 j = h 176 } 177 } 178 found = i < n && s[i].Name() == ns 179 if found { 180 v = s[i] 181 } 182 return 183 }