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  }