mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 16:32:26 -05:00 
			
		
		
		
	
		
			
	
	
		
			82 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			82 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | /* | ||
|  |  * | ||
|  |  * Copyright 2017 gRPC authors. | ||
|  |  * | ||
|  |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||
|  |  * you may not use this file except in compliance with the License. | ||
|  |  * You may obtain a copy of the License at | ||
|  |  * | ||
|  |  *     http://www.apache.org/licenses/LICENSE-2.0 | ||
|  |  * | ||
|  |  * Unless required by applicable law or agreed to in writing, software | ||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|  |  * See the License for the specific language governing permissions and | ||
|  |  * limitations under the License. | ||
|  |  * | ||
|  |  */ | ||
|  | 
 | ||
|  | // Package roundrobin defines a roundrobin balancer. Roundrobin balancer is | ||
|  | // installed as one of the default balancers in gRPC, users don't need to | ||
|  | // explicitly install this balancer. | ||
|  | package roundrobin | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"sync/atomic" | ||
|  | 
 | ||
|  | 	"google.golang.org/grpc/balancer" | ||
|  | 	"google.golang.org/grpc/balancer/base" | ||
|  | 	"google.golang.org/grpc/grpclog" | ||
|  | 	"google.golang.org/grpc/internal/grpcrand" | ||
|  | ) | ||
|  | 
 | ||
|  | // Name is the name of round_robin balancer. | ||
|  | const Name = "round_robin" | ||
|  | 
 | ||
|  | var logger = grpclog.Component("roundrobin") | ||
|  | 
 | ||
|  | // newBuilder creates a new roundrobin balancer builder. | ||
|  | func newBuilder() balancer.Builder { | ||
|  | 	return base.NewBalancerBuilder(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true}) | ||
|  | } | ||
|  | 
 | ||
|  | func init() { | ||
|  | 	balancer.Register(newBuilder()) | ||
|  | } | ||
|  | 
 | ||
|  | type rrPickerBuilder struct{} | ||
|  | 
 | ||
|  | func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker { | ||
|  | 	logger.Infof("roundrobinPicker: Build called with info: %v", info) | ||
|  | 	if len(info.ReadySCs) == 0 { | ||
|  | 		return base.NewErrPicker(balancer.ErrNoSubConnAvailable) | ||
|  | 	} | ||
|  | 	scs := make([]balancer.SubConn, 0, len(info.ReadySCs)) | ||
|  | 	for sc := range info.ReadySCs { | ||
|  | 		scs = append(scs, sc) | ||
|  | 	} | ||
|  | 	return &rrPicker{ | ||
|  | 		subConns: scs, | ||
|  | 		// Start at a random index, as the same RR balancer rebuilds a new | ||
|  | 		// picker when SubConn states change, and we don't want to apply excess | ||
|  | 		// load to the first server in the list. | ||
|  | 		next: uint32(grpcrand.Intn(len(scs))), | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | type rrPicker struct { | ||
|  | 	// subConns is the snapshot of the roundrobin balancer when this picker was | ||
|  | 	// created. The slice is immutable. Each Get() will do a round robin | ||
|  | 	// selection from it and return the selected SubConn. | ||
|  | 	subConns []balancer.SubConn | ||
|  | 	next     uint32 | ||
|  | } | ||
|  | 
 | ||
|  | func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { | ||
|  | 	subConnsLen := uint32(len(p.subConns)) | ||
|  | 	nextIndex := atomic.AddUint32(&p.next, 1) | ||
|  | 
 | ||
|  | 	sc := p.subConns[nextIndex%subConnsLen] | ||
|  | 	return balancer.PickResult{SubConn: sc}, nil | ||
|  | } |