github.com/koko1123/flow-go-1@v0.29.6/module/mempool/chunk_requests.go (about)

     1  package mempool
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/koko1123/flow-go-1/model/chunks"
     7  	"github.com/koko1123/flow-go-1/model/flow"
     8  	"github.com/koko1123/flow-go-1/model/verification"
     9  )
    10  
    11  // ChunkRequestHistoryUpdaterFunc is a function type that used by ChunkRequests mempool to perform atomic and isolated updates on the
    12  // underlying chunk requests history.
    13  type ChunkRequestHistoryUpdaterFunc func(uint64, time.Duration) (uint64, time.Duration, bool)
    14  
    15  // ExponentialUpdater is a chunk request history updater factory that updates the retryAfter value of a request to
    16  // multiplier * retryAfter. For example, if multiplier = 2,
    17  // then invoking it n times results in a retryAfter value of 2^n * retryAfter, which follows an exponential series.
    18  //
    19  // It also keeps updated retryAfter value between the minInterval and maxInterval inclusive. It means that if updated retryAfter value
    20  // is below minInterval, it is bumped up to the minInterval. Also, if updated retryAfter value is above maxInterval, it is skimmed off back
    21  // to the maxInterval.
    22  //
    23  // Note: if initial retryAfter is below minInterval, the first call to this function returns minInterval, and hence after the nth invocations,
    24  // the retryAfter value is set to 2^(n-1) * minInterval.
    25  func ExponentialUpdater(multiplier float64, maxInterval time.Duration, minInterval time.Duration) ChunkRequestHistoryUpdaterFunc {
    26  	return func(attempts uint64, retryAfter time.Duration) (uint64, time.Duration, bool) {
    27  		if float64(retryAfter) >= float64(maxInterval)/multiplier {
    28  			retryAfter = maxInterval
    29  		} else {
    30  			retryAfter = time.Duration(float64(retryAfter) * multiplier)
    31  
    32  			if retryAfter < minInterval {
    33  				retryAfter = minInterval
    34  			}
    35  		}
    36  
    37  		return attempts + 1, retryAfter, true
    38  	}
    39  }
    40  
    41  // IncrementalAttemptUpdater is a chunk request history updater factory that increments the attempt field of request status
    42  // and makes it instantly available against any retryAfter qualifier.
    43  func IncrementalAttemptUpdater() ChunkRequestHistoryUpdaterFunc {
    44  	return func(attempts uint64, _ time.Duration) (uint64, time.Duration, bool) {
    45  		attempts++
    46  		// makes request instantly qualified against any retry after qualifier.
    47  		return attempts, time.Nanosecond, true
    48  	}
    49  }
    50  
    51  // ChunkRequests is an in-memory storage for maintaining chunk data pack requests.
    52  type ChunkRequests interface {
    53  	// RequestHistory returns the number of times the chunk has been requested,
    54  	// last time the chunk has been requested, and the retryAfter duration of the
    55  	// underlying request status of this chunk.
    56  	//
    57  	// The last boolean parameter returns whether a chunk request for this chunk ID
    58  	// exists in memory-pool.
    59  	RequestHistory(chunkID flow.Identifier) (uint64, time.Time, time.Duration, bool)
    60  
    61  	// Add provides insertion functionality into the memory pool.
    62  	// The insertion is only successful if there is no duplicate chunk request with the same
    63  	// chunk ID in the memory. Otherwise, it aborts the insertion and returns false.
    64  	Add(request *verification.ChunkDataPackRequest) bool
    65  
    66  	// Remove provides deletion functionality from the memory pool.
    67  	// If there is a chunk request with this ID, Remove removes it and returns true.
    68  	// Otherwise, it returns false.
    69  	Remove(chunkID flow.Identifier) bool
    70  
    71  	// PopAll atomically returns all locators associated with this chunk ID while clearing out the
    72  	// chunk request status for this chunk id.
    73  	// Boolean return value indicates whether there are requests in the memory pool associated
    74  	// with chunk ID.
    75  	PopAll(chunkID flow.Identifier) (chunks.LocatorMap, bool)
    76  
    77  	// IncrementAttempt increments the Attempt field of the corresponding status of the
    78  	// chunk request in memory pool that has the specified chunk ID.
    79  	// If such chunk ID does not exist in the memory pool, it returns false.
    80  	//
    81  	// The increments are done atomically, thread-safe, and in isolation.
    82  	IncrementAttempt(chunkID flow.Identifier) bool
    83  
    84  	// UpdateRequestHistory updates the request history of the specified chunk ID. If the update was successful, i.e.,
    85  	// the updater returns true, the result of update is committed to the mempool, and the time stamp of the chunk request
    86  	// is updated to the current time. Otherwise, it aborts and returns false.
    87  	//
    88  	// It returns the updated request history values.
    89  	//
    90  	// The updates under this method are atomic, thread-safe, and done in isolation.
    91  	UpdateRequestHistory(chunkID flow.Identifier, updater ChunkRequestHistoryUpdaterFunc) (uint64, time.Time, time.Duration, bool)
    92  
    93  	// All returns all chunk requests stored in this memory pool.
    94  	All() verification.ChunkDataPackRequestInfoList
    95  
    96  	// Size returns total number of chunk requests in the memory pool.
    97  	Size() uint
    98  }
    99  
   100  const DefaultChunkDataPackRequestQueueSize = 100_000
   101  
   102  // ChunkDataPackRequest is an internal data type for Execution Nodes that
   103  // represents a request for a chunk data pack.
   104  type ChunkDataPackRequest struct {
   105  	// Identifier of the chunk.
   106  	ChunkId flow.Identifier
   107  	// Identifier of the requester node.
   108  	RequesterId flow.Identifier
   109  }