github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/sql/sessiondatapb/sequence_cache.go (about)

     1  // Copyright 2020 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sessiondatapb
    12  
    13  // SequenceCache stores sequence values that have already been created in KV
    14  // and are available to be given out as sequence numbers. Values for sequences
    15  // are keyed by the descpb.ID of each sequence. These IDs are represented as
    16  // uint32 to prevent an import cycle with the descpb package. The cache should
    17  // only be accessed using the provided API.
    18  //
    19  // The cache ensures that values are invalidated when new descriptor versions are seen. Note that
    20  // new descriptor versions may not monotonically increase. For example, the sequence schema
    21  // may be altered in a txn, so the cache sees a new version V and invalidates/repopulates itself. Then,
    22  // the txn may get rolled back, so the cache will see version V-1 and invalidate/repopulate itself again.
    23  type SequenceCache map[uint32]*SequenceCacheEntry
    24  
    25  // NextValue fetches the next value in the sequence cache. If the values in the cache have all been
    26  // given out or if the descriptor version has changed, then fetchNextValues() is used to repopulate the cache.
    27  func (sc SequenceCache) NextValue(
    28  	seqID uint32, clientVersion uint32, fetchNextValues func() (int64, int64, int64, error),
    29  ) (int64, error) {
    30  	// Create entry for this sequence ID if there are no existing entries.
    31  	if _, found := sc[seqID]; !found {
    32  		sc[seqID] = &SequenceCacheEntry{}
    33  	}
    34  	cacheEntry := sc[seqID]
    35  
    36  	if cacheEntry.NumValues > 0 && cacheEntry.CachedVersion == clientVersion {
    37  		cacheEntry.CurrentValue += cacheEntry.Increment
    38  		cacheEntry.NumValues--
    39  		return cacheEntry.CurrentValue - cacheEntry.Increment, nil
    40  	}
    41  
    42  	currentValue, increment, numValues, err := fetchNextValues()
    43  	if err != nil {
    44  		return 0, err
    45  	}
    46  
    47  	// One value must be returned, and the rest of the values are stored.
    48  	val := currentValue
    49  	cacheEntry.CurrentValue = currentValue + increment
    50  	cacheEntry.Increment = increment
    51  	cacheEntry.NumValues = numValues - 1
    52  	cacheEntry.CachedVersion = clientVersion
    53  	return val, nil
    54  }