github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/clusters/cluster.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 clusters 19 20 import ( 21 "fmt" 22 "github.com/aacfactory/configures" 23 "github.com/aacfactory/errors" 24 "github.com/aacfactory/fns/barriers" 25 "github.com/aacfactory/fns/clusters/proxy" 26 "github.com/aacfactory/fns/commons/versions" 27 "github.com/aacfactory/fns/context" 28 "github.com/aacfactory/fns/services" 29 "github.com/aacfactory/fns/shareds" 30 "github.com/aacfactory/fns/transports" 31 "github.com/aacfactory/logs" 32 "github.com/aacfactory/workers" 33 "strings" 34 ) 35 36 type ClusterOptions struct { 37 Log logs.Logger 38 Config configures.Config 39 Id string 40 Version versions.Version 41 Address string 42 } 43 44 type Cluster interface { 45 Construct(options ClusterOptions) (err error) 46 AddService(service Service) 47 Join(ctx context.Context) (err error) 48 Leave(ctx context.Context) (err error) 49 NodeEvents() (events <-chan NodeEvent) 50 Shared() (shared shareds.Shared) 51 Barrier() (barrier barriers.Barrier) 52 } 53 54 type ClusterBuilderOptions struct { 55 Config configures.Config 56 Log logs.Logger 57 } 58 59 var ( 60 clusterMap = make(map[string]Cluster) 61 ) 62 63 func RegisterCluster(name string, cluster Cluster) { 64 clusterMap[name] = cluster 65 } 66 67 func loadCluster(name string) (cluster Cluster, has bool) { 68 cluster, has = clusterMap[name] 69 return 70 } 71 72 type Options struct { 73 Id string 74 Version versions.Version 75 Port int 76 Log logs.Logger 77 Worker workers.Workers 78 Local services.EndpointsManager 79 Dialer transports.Dialer 80 Config Config 81 } 82 83 func New(options Options) (manager services.EndpointsManager, shared shareds.Shared, barrier barriers.Barrier, handlers []transports.MuxHandler, err error) { 84 // signature 85 signature := NewSignature(options.Config.Secret) 86 // host 87 hostRetrieverName := strings.TrimSpace(options.Config.HostRetriever) 88 if hostRetrieverName == "" { 89 hostRetrieverName = "default" 90 } 91 hostRetriever, hasHostRetriever := getHostRetriever(hostRetrieverName) 92 if !hasHostRetriever { 93 err = errors.Warning("fns: new cluster failed").WithCause(fmt.Errorf("host retriever was not found")).WithMeta("name", hostRetrieverName) 94 return 95 } 96 host, hostErr := hostRetriever() 97 if hostErr != nil { 98 err = errors.Warning("fns: new cluster failed").WithCause(hostErr) 99 return 100 } 101 address := fmt.Sprintf("%s:%d", host, options.Port) 102 // cluster 103 var cluster Cluster 104 if options.Config.Name == developmentName { 105 cluster = NewDevelopment(options.Dialer, signature) 106 } else { 107 has := false 108 cluster, has = loadCluster(options.Config.Name) 109 if !has { 110 err = errors.Warning("fns: new cluster failed").WithCause(fmt.Errorf("cluster was not found")).WithMeta("name", options.Config.Name) 111 return 112 } 113 } 114 if options.Config.Option == nil && len(options.Config.Option) < 2 { 115 options.Config.Option = []byte{'{', '}'} 116 } 117 clusterConfig, clusterConfigErr := configures.NewJsonConfig(options.Config.Option) 118 if clusterConfigErr != nil { 119 err = errors.Warning("fns: new cluster failed").WithCause(clusterConfigErr).WithMeta("name", options.Config.Name) 120 return 121 } 122 clusterErr := cluster.Construct(ClusterOptions{ 123 Log: options.Log.With("cluster", options.Config.Name), 124 Config: clusterConfig, 125 Id: options.Id, 126 Version: options.Version, 127 Address: address, 128 }) 129 if clusterErr != nil { 130 err = errors.Warning("fns: new cluster failed").WithCause(clusterErr).WithMeta("name", options.Config.Name) 131 return 132 } 133 // shared 134 shared = cluster.Shared() 135 // barrier 136 barrier = cluster.Barrier() 137 // manager 138 manager = NewManager(options.Id, options.Version, address, cluster, options.Local, options.Worker, options.Log, options.Dialer, signature) 139 // handlers 140 handlers = make([]transports.MuxHandler, 0, 1) 141 handlers = append(handlers, NewInternalHandler(options.Local, signature)) 142 if options.Config.Proxy { 143 // append proxy handler 144 handlers = append(handlers, proxy.NewHandler(signature, manager, cluster.Shared())) 145 } 146 return 147 }