Skip to content

Commit

Permalink
[nix-cache] Prevent checking cache twice per package (#2055)
Browse files Browse the repository at this point in the history
## Summary

Fixes bug described here #2054

A better (but a bit more involved) solution is to parallelize by output.
Currently we parallelize by meta-output (which includes
`__default_output__`). This has two downsides:

* `__default_output__` can be multiple outputs, in which case we don't
parallelize them at all.
* We still do redundant work when `__default_output__` is multiple
outputs. (once as `__default_output__` and once for each individual
outout that forms part of defaults).

## How was it tested?
  • Loading branch information
mikeland73 committed May 16, 2024
1 parent b23231a commit 2285a3e
Showing 1 changed file with 21 additions and 2 deletions.
23 changes: 21 additions & 2 deletions internal/devpkg/narinfo_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"io"
"net/http"
"slices"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -107,13 +109,30 @@ func (p *Package) fetchNarInfoStatusOnce(output string) (bool, error) {
type inCacheFunc func() (bool, error)
f, ok := narInfoStatusFnCache.Load(p.Raw)
if !ok {
key := fmt.Sprintf("%s^%s", p.Raw, output)
f = inCacheFunc(sync.OnceValues(func() (bool, error) { return p.fetchNarInfoStatus(output) }))
f, _ = narInfoStatusFnCache.LoadOrStore(key, f)
f, _ = narInfoStatusFnCache.LoadOrStore(p.keyForOutput(output), f)
}
return f.(inCacheFunc)()
}

func (p *Package) keyForOutput(output string) string {
if output == useDefaultOutput {
sysInfo, err := p.sysInfoIfExists()
// let's be super safe to always avoid empty key.
if err == nil && sysInfo != nil && len(sysInfo.DefaultOutputs()) > 0 {
names := make([]string, len(sysInfo.DefaultOutputs()))
for i, o := range sysInfo.DefaultOutputs() {
names[i] = o.Name
}
slices.Sort(names)
output = strings.Join(names, ",")
}
}
fmt.Println("output: ", output)

return fmt.Sprintf("%s^%s", p.Raw, output)
}

// fetchNarInfoStatus fetches the cache status for the package. It returns
// true if cache exists, false otherwise.
// NOTE: This function always performs an HTTP request and should not be called
Expand Down

0 comments on commit 2285a3e

Please sign in to comment.