ronantakizawa/codereview-bench huggingface dataset:
Repository: prometheus/prometheus
File: scrape/scrape_test.go (Go)

Code before:
	)

	sl := newBasicScrapeLoop(t, context.Background(), scraper, app, 10*time.Millisecond)
	// Count scrapes and terminate loop after 2 scrapes.
	numScrapes, maxScrapes := 0, 2
	scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error {
		numScrapes++
		if numScrapes >= maxScrapes {
			go sl.stop()
			<-sl.ctx.Done()
		}
		if _, err := w.Write([]byte("metric_a 42\n")); err != nil {
			return err
		}
		return ctx.Err()
	}

	go func() {
		sl.run(nil)
		loopDone <- struct{}{}
	}()

	// Disable end of run staleness markers.
	sl.disableEndOfRunStalenessMarkers()

	select {
	case <-loopDone:
	case <-time.After(5 * time.Second):
		t.Fatalf("Scrape loop didn't stop.")
	}

	// No stale markers should be appended, since they were disabled.
	for _, s := range appender.resultFloats {
		if value.IsStaleNaN(s.f) {
			t.Fatalf("Got stale NaN samples while end of run staleness is disabled: %x", math.Float64bits(s.f))
		}
	}
}


Review comment (suggestion):
I think this is flaky. Scheduling is non deterministic so worst case the loop runs to completion before you get to this line. I think it would be better to synchronize the test more, logic:

- start the scrape loop
- wait for some samples to appear in the appender (so we know something is being tracked)
- disable the staleness markers
- stop the scrape loop from the outside by sending a message on a channel to the scraper function

This way you don't depend on the timing at all.

Code after:
		app      = func(_ context.Context) storage.Appender { return appender }
	)

	sl := newBasicScrapeLoop(t, context.Background(), scraper, app, 10*time.Millisecond)
	scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error {
		if _, err := w.Write([]byte("metric_a 42\n")); err != nil {
			return err
		}
		return ctx.Err()
	}

	// Start the scrape loop.
	go func() {
		sl.run(nil)
		loopDone.Store(true)
	}()

	// Wait for some samples to be appended.
	require.Eventually(t, func() bool {
		appender.mtx.Lock()
		defer appender.mtx.Unlock()
		return len(appender.resultFloats) > 2
	}, 5*time.Second, 100*time.Millisecond, "Scrape loop didn't append any samples.")

	// Disable end of run staleness markers and stop the loop.
	sl.disableEndOfRunStalenessMarkers()
	sl.stop()
	require.Eventually(t, func() bool {
		return loopDone.Load()
	}, 5*time.Second, 100*time.Millisecond, "Scrape loop didn't stop.")

	// No stale markers should be appended, since they were disabled.
	for _, s := range appender.resultFloats {
		if value.IsStaleNaN(s.f) {
			t.Fatalf("Got stale NaN samples while end of run staleness is disabled: %x", math.Float64bits(s.f))
		}
	}
}
Repository: prometheus/prometheus
File: scrape/scrape_test.go (Go)

Code before:

	ctx, cancelLoop := context.WithCancel(context.Background())
	sl := newBasicScrapeLoop(t, ctx, scraper, app, 10*time.Millisecond)
	scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error {
		if _, err := w.Write([]byte("metric_a 42\n")); err != nil {
			return err
		}
		return ctx.Err()
	}

	// Start the scrape loop.
	go func() {
		sl.run(nil)
		loopDone.Store(true)
	}()

	// Wait for some samples to be appended.
	require.Eventually(t, func() bool {
		appender.mtx.Lock()
		defer appender.mtx.Unlock()
		return len(appender.resultFloats) > 2
	}, 5*time.Second, 100*time.Millisecond, "Scrape loop didn't append any samples.")

	// Disable end of run staleness markers and stop the loop.
	sl.disableEndOfRunStalenessMarkers()
	cancelLoop()
	require.Eventually(t, func() bool {
		return loopDone.Load()
	}, 5*time.Second, 100*time.Millisecond, "Scrape loop didn't stop.")

	// No stale markers should be appended, since they were disabled.
	for _, s := range appender.resultFloats {
		if value.IsStaleNaN(s.f) {
			t.Fatalf("Got stale NaN samples while end of run staleness is disabled: %x", math.Float64bits(s.f))
		}
	}
}


Review comment (bug):
If you comment out `sl.disabledEndOfRunStalenessMarkers.Store(true)` in scrape.go, the test doesn't fail, because context cancel is too abrupt.

Use stop() instead.

```suggestion
	sl.stop()
```

Code after:

	sl := newBasicScrapeLoop(t, context.Background(), scraper, app, 10*time.Millisecond)
	scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error {
		if _, err := w.Write([]byte("metric_a 42\n")); err != nil {
			return err
		}
		return ctx.Err()
	}

	// Start the scrape loop.
	go func() {
		sl.run(nil)
		loopDone.Store(true)
	}()

	// Wait for some samples to be appended.
	require.Eventually(t, func() bool {
		appender.mtx.Lock()
		defer appender.mtx.Unlock()
		return len(appender.resultFloats) > 2
	}, 5*time.Second, 100*time.Millisecond, "Scrape loop didn't append any samples.")

	// Disable end of run staleness markers and stop the loop.
	sl.disableEndOfRunStalenessMarkers()
	sl.stop()
	require.Eventually(t, func() bool {
		return loopDone.Load()
	}, 5*time.Second, 100*time.Millisecond, "Scrape loop didn't stop.")

	// No stale markers should be appended, since they were disabled.
	for _, s := range appender.resultFloats {
		if value.IsStaleNaN(s.f) {
			t.Fatalf("Got stale NaN samples while end of run staleness is disabled: %x", math.Float64bits(s.f))
		}
	}
}
Repository: prometheus/prometheus
File: cmd/prometheus/main.go (Go)

Code before:
// passed to Prometheus using the --storage.tsdb.upload-meta-file=... flag.
// If the file does not exist or there's an error while reading it then we assume it is uploaded
// so we don't block compactions of TSDB blocks by Prometheus.
func isBlockUploaded(logger *slog.Logger, uploadMetaPath string, meta *tsdb.BlockMeta) bool {
	data, err := os.ReadFile(uploadMetaPath)
	if err != nil {
		logger.Warn("cannot open TSDB upload meta file", slog.String("path", uploadMetaPath), slog.Any("err", err))
		return true
	}

	var shipper UploadMetaFile
	err = json.Unmarshal(data, &shipper)
	if err != nil {
		logger.Warn("cannot parse TSDB upload meta file", slog.String("path", uploadMetaPath), slog.Any("err", err))
		return true
	}

	return slices.Contains(shipper.Uploaded, meta.ULID.String())
}

func exludeBlocksPendingUpload(logger *slog.Logger, uploadMetaPath string) tsdb.BlockExcludeFilterFunc {
	return func(meta *tsdb.BlockMeta) bool {
		if meta.Compaction.Level > 1 {
			// Blocks with level > 1 are compacted, sidecars like Thanos don't upload these normally,
			// so we never exlude them.
			return false
		}
		uploaded := isBlockUploaded(logger, uploadMetaPath, meta)
		if !uploaded {
			logger.Info("Block still pending upload, excluding it from compactions", slog.String("ulid", meta.ULID.String()))
		}
		return !uploaded
	}
}


Review comment (suggestion):
```suggestion
			// Blocks with level > 1 are assumed to be not uploaded, thus no need to delay those. See `storage.tsdb.delay-compact-file.path` flag for detail.
			return false
```

Code after:
)

func exludeBlocksPendingUpload(logger *slog.Logger, uploadMetaPath string) tsdb.BlockExcludeFilterFunc {
	return func(meta *tsdb.BlockMeta) bool {
		if meta.Compaction.Level > 1 {
			// Blocks with level > 1 are assumed to be not uploaded, thus no need to delay those.
			// See `storage.tsdb.delay-compact-file.path` flag for detail.
			return false
		}

		// If we have cached uploadMetaPath content that was stored in the last minute the use it.
		if tsdbDelayCompactLastMeta != nil &&
			tsdbDelayCompactLastMetaTime.After(time.Now().UTC().Add(time.Minute*-1)) {
			return !slices.Contains(tsdbDelayCompactLastMeta.Uploaded, meta.ULID.String())
		}

		// We don't have anything cached or it's older than a minute. Try to open and parse the uploadMetaPath path.
		data, err := os.ReadFile(uploadMetaPath)
		if err != nil {
			logger.Warn("cannot open TSDB upload meta file", slog.String("path", uploadMetaPath), slog.Any("err", err))
			return false
		}

		var uploadMeta UploadMeta
		if err = json.Unmarshal(data, &uploadMeta); err != nil {
			logger.Warn("cannot parse TSDB upload meta file", slog.String("path", uploadMetaPath), slog.Any("err", err))
			return false
		}

		// We have parsed the uploadMetaPath file, cache it.
		tsdbDelayCompactLastMeta = &uploadMeta
		tsdbDelayCompactLastMetaTime = time.Now().UTC()

		return !slices.Contains(uploadMeta.Uploaded, meta.ULID.String())
	}
}
Repository: prometheus/prometheus
File: scrape/scrape.go (Go)

Code before:

	// Only record after the first scrape.
	if !last.IsZero() {
		sl.metrics.targetIntervalLength.WithLabelValues(sl.interval.String()).Observe(
			time.Since(last).Seconds(),
		)
		sl.metrics.targetIntervalLengthHistogram.WithLabelValues(sl.interval.String()).Observe(
			time.Since(last).Seconds(),
		)
	}

	var total, added, seriesAdded, bytesRead int
	var err, appErr, scrapeErr error

	app := sl.appender(sl.appenderCtx)
	defer func() {
		if err != nil {
			app.Rollback()
			return
		}
		err = app.Commit()
		totalDuration := time.Since(start)

		// Record total scrape duration metric.
		sl.metrics.targetScrapeDuration.Observe(totalDuration.Seconds())

		if err != nil {
			sl.l.Error("Scrape commit failed", "err", err)
		}
	}()

	defer func() {
		if err = sl.report(app, appendTime, time.Since(start), total, added, seriesAdded, bytesRead, scrapeErr); err != nil {
			sl.l.Warn("Appending scrape report failed", "err", err)
		}
	}()

	if forcedErr := sl.getForcedError(); forcedErr != nil {
		scrapeErr = forcedErr
		// Add stale markers.
		if _, _, _, err := sl.append(app, []byte{}, "", appendTime); err != nil {
			app.Rollback()
			app = sl.appender(sl.appenderCtx)
			sl.l.Warn("Append failed", "err", err)
		}
		if errc != nil {
			errc <- forcedErr
		}

		return start
	}

Review comment (suggestion):
I think what Julien had in mind was something like this:
```suggestion
		if sl.reportExtraMetrics {
			totalDuration := time.Since(start)

			// Record total scrape duration metric.
			sl.metrics.targetScrapeDuration.Observe(totalDuration.Seconds())
		}
```

Code after:
			_ = app.Rollback()
			app = sl.appender()
			sl.l.Warn("Append failed", "err", err)
		}
	}

	if scrapeErr == nil {
		scrapeErr = appErr
	}

	return start
}

func (sl *scrapeLoop) setForcedError(err error) {
	sl.forcedErrMtx.Lock()
	defer sl.forcedErrMtx.Unlock()
	sl.forcedErr = err
}

func (sl *scrapeLoop) getForcedError() error {
	sl.forcedErrMtx.Lock()
	defer sl.forcedErrMtx.Unlock()
	return sl.forcedErr
}

func (sl *scrapeLoop) endOfRunStaleness(last time.Time, ticker *time.Ticker, interval time.Duration) {
	// Scraping has stopped. We want to write stale markers but
	// the target may be recreated, so we wait just over 2 scrape intervals
	// before creating them.
	// If the context is canceled, we presume the server is shutting down
	// and will restart where is was. We do not attempt to write stale markers
	// in this case.

	if last.IsZero() {
		// There never was a scrape, so there will be no stale markers.
		return
	}

	// Wait for when the next scrape would have been, record its timestamp.
	var staleTime time.Time
	select {
	case <-sl.parentCtx.Done():
		return
	case <-ticker.C:
		staleTime = time.Now()
	}

	// Wait for when the next scrape would have been, if the target was recreated
	// samples should have been ingested by now.
	select {
	case <-sl.parentCtx.Done():
Repository: prometheus/prometheus
File: promql/parser/printer.go (Go)

Code before:
	}
	b.WriteString(elems[0])
	for _, s := range elems[1:] {
		b.WriteString(sep)
		b.WriteString(s)
	}
}

func (node *BinaryExpr) returnBool() string {
	if node.ReturnBool {
		return " bool"
	}
	return ""
}

func (node *BinaryExpr) String() string {
	matching := node.getMatchingStr()
	return node.LHS.String() + " " + node.Op.String() + node.returnBool() + matching + " " + node.RHS.String()
}

func (node *BinaryExpr) ShortString() string {
	return node.Op.String() + node.returnBool() + node.getMatchingStr()
}

// joinLabels joins label names, quoting them if they are not valid legacy label names.
func joinLabels(labels []string) string {
	quoted := make([]string, 0, len(labels))
	for _, label := range labels {
		if model.LegacyValidation.IsValidLabelName(label) {
			quoted = append(quoted, label)
		} else {
			quoted = append(quoted, strconv.Quote(label))
		}
	}
	return strings.Join(quoted, ", ")
}

func (node *BinaryExpr) getMatchingStr() string {
	matching := ""
	vm := node.VectorMatching
	if vm != nil {
		if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmTag := "ignoring"
			if vm.On {
				vmTag = "on"
			}
			matching = fmt.Sprintf(" %s (%s)", vmTag, joinLabels(vm.MatchingLabels))
		}

		if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmCard := "right"

Review comment (security):
This feels duplicated with `writeLabels()` in terms of functionality, even if one returns a string and the other writes directly to the buffer. Could we restructure things to use the existing `writeLabels()` everywhere instead? Or if you prefer, you could also delete the existing `writeLabels()` function and use the new `joinLabels()` function in `writeAggOpStr()` instead. Writing directly to a buffer is more efficient, but I don't think the printer is performance sensitive at all, so this should be fine.

Code after:
	}
	b.WriteString(elems[0])
	for _, s := range elems[1:] {
		b.WriteString(sep)
		b.WriteString(s)
	}
}

func (node *BinaryExpr) returnBool() string {
	if node.ReturnBool {
		return " bool"
	}
	return ""
}

func (node *BinaryExpr) String() string {
	matching := node.getMatchingStr()
	return node.LHS.String() + " " + node.Op.String() + node.returnBool() + matching + " " + node.RHS.String()
}

func (node *BinaryExpr) ShortString() string {
	return node.Op.String() + node.returnBool() + node.getMatchingStr()
}

func (node *BinaryExpr) getMatchingStr() string {
	matching := ""
	var b bytes.Buffer
	vm := node.VectorMatching
	if vm != nil {
		if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmTag := "ignoring"
			if vm.On {
				vmTag = "on"
			}
			b.WriteString(" " + vmTag + " (")
			writeLabels(&b, vm.MatchingLabels)
			b.WriteString(")")
			matching = b.String()
		}

		if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmCard := "right"
			if vm.Card == CardManyToOne {
				vmCard = "left"
			}
			b.Reset()
			b.WriteString(" group_" + vmCard + " (")
			writeLabels(&b, vm.Include)
			b.WriteString(")")
			matching += b.String()
		}
Repository: prometheus/prometheus
File: promql/parser/printer.go (Go)

Code before:
}

func (node *BinaryExpr) String() string {
	matching := node.getMatchingStr()
	return node.LHS.String() + " " + node.Op.String() + node.returnBool() + matching + " " + node.RHS.String()
}

func (node *BinaryExpr) ShortString() string {
	return node.Op.String() + node.returnBool() + node.getMatchingStr()
}

func (node *BinaryExpr) getMatchingStr() string {
	matching := ""
	var b bytes.Buffer
	vm := node.VectorMatching
	if vm != nil {
		if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmTag := "ignoring"
			if vm.On {
				vmTag = "on"
			}
			// Format labels with proper UTF-8 quoting using writeLabels()
			b.Reset()
			b.WriteString(" ")
			b.WriteString(vmTag)
			b.WriteString(" (")
			writeLabels(&b, vm.MatchingLabels)
			b.WriteString(")")
			matching = b.String()
		}

		if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmCard := "right"
			if vm.Card == CardManyToOne {
				vmCard = "left"
			}
			// Format labels with proper UTF-8 quoting using writeLabels()
			b.Reset()
			b.WriteString(" group_")
			b.WriteString(vmCard)
			b.WriteString(" (")
			writeLabels(&b, vm.Include)
			b.WriteString(")")
			matching += b.String()
		}
	}
	return matching
}

func (node *DurationExpr) String() string {
	b := bytes.NewBuffer(make([]byte, 0, 1024))

Review comment (suggestion):
I think `b.WriteString(" " + vmTag + " (")` should be sufficient here, let's not blow it up more than we need to :)

Similar below for `" group_" + vmCard + " ("`.

Code after:
}

func (node *BinaryExpr) String() string {
	matching := node.getMatchingStr()
	return node.LHS.String() + " " + node.Op.String() + node.returnBool() + matching + " " + node.RHS.String()
}

func (node *BinaryExpr) ShortString() string {
	return node.Op.String() + node.returnBool() + node.getMatchingStr()
}

func (node *BinaryExpr) getMatchingStr() string {
	matching := ""
	var b bytes.Buffer
	vm := node.VectorMatching
	if vm != nil {
		if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmTag := "ignoring"
			if vm.On {
				vmTag = "on"
			}
			b.WriteString(" " + vmTag + " (")
			writeLabels(&b, vm.MatchingLabels)
			b.WriteString(")")
			matching = b.String()
		}

		if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmCard := "right"
			if vm.Card == CardManyToOne {
				vmCard = "left"
			}
			b.Reset()
			b.WriteString(" group_" + vmCard + " (")
			writeLabels(&b, vm.Include)
			b.WriteString(")")
			matching += b.String()
		}
	}
	return matching
}

func (node *DurationExpr) String() string {
	b := bytes.NewBuffer(make([]byte, 0, 1024))
	node.writeTo(b)
	return b.String()
}

func (node *DurationExpr) writeTo(b *bytes.Buffer) {
	if node.Wrapped {
		b.WriteByte('(')
Repository: prometheus/prometheus
File: promql/parser/printer.go (Go)

Code before:
		return " bool"
	}
	return ""
}

func (node *BinaryExpr) String() string {
	matching := node.getMatchingStr()
	return node.LHS.String() + " " + node.Op.String() + node.returnBool() + matching + " " + node.RHS.String()
}

func (node *BinaryExpr) ShortString() string {
	return node.Op.String() + node.returnBool() + node.getMatchingStr()
}

func (node *BinaryExpr) getMatchingStr() string {
	matching := ""
	var b bytes.Buffer
	vm := node.VectorMatching
	if vm != nil {
		if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmTag := "ignoring"
			if vm.On {
				vmTag = "on"
			}
			// Format labels with proper UTF-8 quoting using writeLabels()
			b.Reset()
			b.WriteString(" ")
			b.WriteString(vmTag)
			b.WriteString(" (")
			writeLabels(&b, vm.MatchingLabels)
			b.WriteString(")")
			matching = b.String()
		}

		if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmCard := "right"
			if vm.Card == CardManyToOne {
				vmCard = "left"
			}
			// Format labels with proper UTF-8 quoting using writeLabels()
			b.Reset()
			b.WriteString(" group_")
			b.WriteString(vmCard)
			b.WriteString(" (")
			writeLabels(&b, vm.Include)
			b.WriteString(")")
			matching += b.String()
		}
	}
	return matching
}

Review comment (suggestion):
Since the `bytes.Buffer` is new here, you do not need to call `Reset()` on it. That would only be needed if there is already something in the buffer and you want to reuse it.

Code after:
		return " bool"
	}
	return ""
}

func (node *BinaryExpr) String() string {
	matching := node.getMatchingStr()
	return node.LHS.String() + " " + node.Op.String() + node.returnBool() + matching + " " + node.RHS.String()
}

func (node *BinaryExpr) ShortString() string {
	return node.Op.String() + node.returnBool() + node.getMatchingStr()
}

func (node *BinaryExpr) getMatchingStr() string {
	matching := ""
	var b bytes.Buffer
	vm := node.VectorMatching
	if vm != nil {
		if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmTag := "ignoring"
			if vm.On {
				vmTag = "on"
			}
			b.WriteString(" " + vmTag + " (")
			writeLabels(&b, vm.MatchingLabels)
			b.WriteString(")")
			matching = b.String()
		}

		if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
			vmCard := "right"
			if vm.Card == CardManyToOne {
				vmCard = "left"
			}
			b.Reset()
			b.WriteString(" group_" + vmCard + " (")
			writeLabels(&b, vm.Include)
			b.WriteString(")")
			matching += b.String()
		}
	}
	return matching
}

func (node *DurationExpr) String() string {
	b := bytes.NewBuffer(make([]byte, 0, 1024))
	node.writeTo(b)
	return b.String()
}
Repository: prometheus/prometheus
File: tsdb/db.go (Go)

Code before:
	select {
	case <-db.closed:
		return nil, ErrClosed
	default:
	}
	loadable, corrupted, err := openBlocks(db.logger, db.dir, nil, nil, DefaultPostingsDecoderFactory)
	if err != nil {
		return nil, err
	}

	// Corrupted blocks that have been superseded by a loadable block can be safely ignored.
	for _, block := range loadable {
		for _, b := range block.Meta().Compaction.Parents {
			delete(corrupted, b.ULID)
		}
	}
	if len(corrupted) > 0 {
		for _, b := range loadable {
			if err := b.Close(); err != nil {
				db.logger.Warn("Closing block failed", "err", err, "block", b)
			}
		}
		var returnErr error
		for ulid, err := range corrupted {
			if err != nil {
				returnErr = errors.Join(returnErr, fmt.Errorf("corrupted block %s: %w", ulid.String(), err))
			}
		}
		return nil, returnErr
	}

	if len(loadable) == 0 {
		return nil, nil
	}

	slices.SortFunc(loadable, func(a, b *Block) int {
		switch {
		case a.Meta().MinTime < b.Meta().MinTime:
			return -1
		case a.Meta().MinTime > b.Meta().MinTime:
			return 1
		default:
			return 0
		}
	})

	blockMetas := make([]BlockMeta, 0, len(loadable))
	for _, b := range loadable {
		blockMetas = append(blockMetas, b.Meta())
	}
	if overlaps := OverlappingBlocks(blockMetas); len(overlaps) > 0 {

Review comment (suggestion):
Note that the Prometheus `errs.Add` implementation `append`s all errors to a single slice, while `errors.Join` creates a linked list of 2-element slices.
This may not be worth worrying about.

Code after:
		return nil, err
	}
	return q.Querier(mint, maxt)
}

// ChunkQuerier loads blocks and the wal and returns a new chunk querier over the data partition for the given time range.
// Current implementation doesn't support multiple ChunkQueriers.
func (db *DBReadOnly) ChunkQuerier(mint, maxt int64) (storage.ChunkQuerier, error) {
	q, err := db.loadDataAsQueryable(maxt)
	if err != nil {
		return nil, err
	}
	return q.ChunkQuerier(mint, maxt)
}

// Blocks returns a slice of block readers for persisted blocks.
func (db *DBReadOnly) Blocks() ([]BlockReader, error) {
	select {
	case <-db.closed:
		return nil, ErrClosed
	default:
	}
	loadable, corrupted, err := openBlocks(db.logger, db.dir, nil, nil, DefaultPostingsDecoderFactory)
	if err != nil {
		return nil, err
	}

	// Corrupted blocks that have been superseded by a loadable block can be safely ignored.
	for _, block := range loadable {
		for _, b := range block.Meta().Compaction.Parents {
			delete(corrupted, b.ULID)
		}
	}
	if len(corrupted) > 0 {
		for _, b := range loadable {
			if err := b.Close(); err != nil {
				db.logger.Warn("Closing block failed", "err", err, "block", b)
			}
		}
		var errs []error
		for ulid, err := range corrupted {
			if err != nil {
				errs = append(errs, fmt.Errorf("corrupted block %s: %w", ulid.String(), err))
			}
		}
		return nil, errors.Join(errs...)
	}

	if len(loadable) == 0 {
		return nil, nil
	}