[REFACTOR] TSDB: Simplify series creation

Refactor the code so that everything proceeds linearly.

Also renamed `getOrSet` to `setUnlessAlreadySet` to emphasise that the
caller is expecting it not to be set.

Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
This commit is contained in:
Bryan Boreham 2025-10-17 10:26:46 +01:00
parent 16a9a827de
commit 2852c9c431
2 changed files with 16 additions and 42 deletions

View file

@ -1753,17 +1753,17 @@ func (h *Head) getOrCreate(hash uint64, lset labels.Labels, pendingCommit bool)
}
func (h *Head) getOrCreateWithID(id chunks.HeadSeriesRef, hash uint64, lset labels.Labels, pendingCommit bool) (*memSeries, bool, error) {
s, created, err := h.series.getOrSet(hash, lset, func() *memSeries {
shardHash := uint64(0)
if h.opts.EnableSharding {
shardHash = labels.StableHash(lset)
}
return newMemSeries(lset, id, shardHash, h.opts.IsolationDisabled, pendingCommit)
})
if err != nil {
return nil, false, err
if preCreationErr := h.series.seriesLifecycleCallback.PreCreation(lset); preCreationErr != nil {
return nil, false, preCreationErr
}
shardHash := uint64(0)
if h.opts.EnableSharding {
shardHash = labels.StableHash(lset)
}
optimisticallyCreatedSeries := newMemSeries(lset, id, shardHash, h.opts.IsolationDisabled, pendingCommit)
s, created := h.series.setUnlessAlreadySet(hash, lset, optimisticallyCreatedSeries)
if !created {
return s, false, nil
}
@ -2061,43 +2061,23 @@ func (s *stripeSeries) getByHash(hash uint64, lset labels.Labels) *memSeries {
return series
}
func (s *stripeSeries) getOrSet(hash uint64, lset labels.Labels, createSeries func() *memSeries) (*memSeries, bool, error) {
// PreCreation is called here to avoid calling it inside the lock.
// It is not necessary to call it just before creating a series,
// rather it gives a 'hint' whether to create a series or not.
preCreationErr := s.seriesLifecycleCallback.PreCreation(lset)
// Create the series, unless the PreCreation() callback as failed.
// If failed, we'll not allow to create a new series anyway.
var series *memSeries
if preCreationErr == nil {
series = createSeries()
}
func (s *stripeSeries) setUnlessAlreadySet(hash uint64, lset labels.Labels, series *memSeries) (*memSeries, bool) {
i := hash & uint64(s.size-1)
s.locks[i].Lock()
if prev := s.hashes[i].get(hash, lset); prev != nil {
s.locks[i].Unlock()
return prev, false, nil
}
if preCreationErr == nil {
s.hashes[i].set(hash, series)
return prev, false
}
s.hashes[i].set(hash, series)
s.locks[i].Unlock()
if preCreationErr != nil {
// The callback prevented creation of series.
return nil, false, preCreationErr
}
i = uint64(series.ref) & uint64(s.size-1)
s.locks[i].Lock()
s.series[i][series.ref] = series
s.locks[i].Unlock()
return series, true, nil
return series, true
}
func (s *stripeSeries) postCreation(lset labels.Labels) {

View file

@ -6628,18 +6628,12 @@ func stripeSeriesWithCollidingSeries(t *testing.T) (*stripeSeries, *memSeries, *
hash := lbls1.Hash()
s := newStripeSeries(1, noopSeriesLifecycleCallback{})
got, created, err := s.getOrSet(hash, lbls1, func() *memSeries {
return &ms1
})
require.NoError(t, err)
got, created := s.setUnlessAlreadySet(hash, lbls1, &ms1)
require.True(t, created)
require.Same(t, &ms1, got)
// Add a conflicting series
got, created, err = s.getOrSet(hash, lbls2, func() *memSeries {
return &ms2
})
require.NoError(t, err)
got, created = s.setUnlessAlreadySet(hash, lbls2, &ms2)
require.True(t, created)
require.Same(t, &ms2, got)