github.com/drone/runner-go@v1.12.0/client/single.go (about) 1 // Copyright 2019 Drone.IO Inc. All rights reserved. 2 // Use of this source code is governed by the Polyform License 3 // that can be found in the LICENSE file. 4 5 package client 6 7 import ( 8 "context" 9 "runtime/debug" 10 "sync" 11 12 "github.com/drone/drone-go/drone" 13 ) 14 15 var _ Client = (*SingleFlight)(nil) 16 17 // SingleFlight wraps a Client and limits to a single in-flight 18 // request to pull items from the queue. 19 type SingleFlight struct { 20 Client 21 mu sync.Mutex 22 } 23 24 // NewSingleFlight returns a Client that is limited to a single in-flight 25 // request to pull items from the queue. 26 func NewSingleFlight(endpoint, secret string, skipverify bool) *SingleFlight { 27 return &SingleFlight{Client: New(endpoint, secret, skipverify)} 28 } 29 30 // Request requests the next available build stage for execution. 31 func (t *SingleFlight) Request(ctx context.Context, args *Filter) (*drone.Stage, error) { 32 // if the context is canceled there is no need to make 33 // the request and we can exit early. 34 select { 35 case <-ctx.Done(): 36 return nil, ctx.Err() 37 default: 38 } 39 // if is critical to unlock the mutex when the function 40 // exits. although a panic is unlikely it is critical that 41 // we recover from the panic to avoid deadlock. 42 defer func() { 43 if r := recover(); r != nil { 44 debug.PrintStack() 45 } 46 t.mu.Unlock() 47 }() 48 // lock the mutex to ensure only a single in-flight 49 // request to request a resource from the server queue. 50 t.mu.Lock() 51 return t.Client.Request(ctx, args) 52 }