github.com/anycable/anycable-go@v1.5.1/rpc/barrier.go (about) 1 package rpc 2 3 import ( 4 "fmt" 5 ) 6 7 type Barrier interface { 8 Acquire() 9 Release() 10 BusyCount() int 11 Capacity() int 12 CapacityInfo() string 13 Exhausted() 14 HasDynamicCapacity() bool 15 Start() 16 Stop() 17 } 18 19 type FixedSizeBarrier struct { 20 capacity int 21 capacityInfo string 22 sem chan (struct{}) 23 } 24 25 var _ Barrier = (*FixedSizeBarrier)(nil) 26 27 func NewFixedSizeBarrier(capacity int) (*FixedSizeBarrier, error) { 28 if capacity <= 0 { 29 return nil, fmt.Errorf("RPC concurrency must be > 0") 30 } 31 32 sem := make(chan struct{}, capacity) 33 34 for i := 0; i < capacity; i++ { 35 sem <- struct{}{} 36 } 37 38 return &FixedSizeBarrier{ 39 capacity: capacity, 40 capacityInfo: fmt.Sprintf("%d", capacity), 41 sem: sem, 42 }, nil 43 } 44 45 func (b *FixedSizeBarrier) Acquire() { 46 <-b.sem 47 } 48 49 func (b *FixedSizeBarrier) Release() { 50 b.sem <- struct{}{} 51 } 52 53 func (b *FixedSizeBarrier) BusyCount() int { 54 // The number of in-flight request is the 55 // the number of initial capacity "tickets" (concurrency) 56 // minus the size of the semaphore channel 57 return b.capacity - len(b.sem) 58 } 59 60 func (b *FixedSizeBarrier) Capacity() int { 61 return b.capacity 62 } 63 64 func (b *FixedSizeBarrier) CapacityInfo() string { 65 return b.capacityInfo 66 } 67 68 func (FixedSizeBarrier) Exhausted() {} 69 70 func (FixedSizeBarrier) HasDynamicCapacity() (res bool) { return } 71 72 func (FixedSizeBarrier) Start() {} 73 74 func (FixedSizeBarrier) Stop() {}