internal/pkg: cache extern responses
Test / Create distribution (push) Successful in 58s
Test / Sandbox (push) Successful in 2m24s
Test / ShareFS (push) Successful in 3m27s
Test / Hakurei (push) Successful in 3m46s
Test / Sandbox (race detector) (push) Successful in 5m1s
Test / Hakurei (race detector) (push) Successful in 6m15s
Test / Flake checks (push) Successful in 1m19s

This prepares substitute computation for shallow extern replacements.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-07-02 20:06:27 +09:00
parent c921ba4680
commit b538c69e01
+34 -23
View File
@@ -770,6 +770,8 @@ type Cache struct {
// Optional external cache implementation. // Optional external cache implementation.
extern External extern External
// Caches responses from extern.
externCache map[unique.Handle[ID]]unique.Handle[Checksum]
// Synchronises access to extern. // Synchronises access to extern.
externMu sync.RWMutex externMu sync.RWMutex
@@ -930,6 +932,7 @@ func readlinkChecksum(a *check.Absolute, buf *Checksum) error {
// SetExternal sets e as the [External] implementation of c. // SetExternal sets e as the [External] implementation of c.
func (c *Cache) SetExternal(e External) { func (c *Cache) SetExternal(e External) {
c.externMu.Lock() c.externMu.Lock()
c.externCache = make(map[unique.Handle[ID]]unique.Handle[Checksum])
c.extern = e c.extern = e
c.externMu.Unlock() c.externMu.Unlock()
} }
@@ -1849,37 +1852,45 @@ func (r *RContext) NewMeasuredReader(
} }
// tryExtern attempts to obtain an [Artifact] outcome from extern. // tryExtern attempts to obtain an [Artifact] outcome from extern.
func (c *Cache) tryExtern(ctx context.Context, id unique.Handle[ID]) ( func (c *Cache) tryExtern(
ctx context.Context,
id unique.Handle[ID],
status *io.ReadCloser,
) (
unique.Handle[Checksum], unique.Handle[Checksum],
io.ReadCloser,
error, error,
) { ) {
c.externMu.RLock() c.externMu.RLock()
defer c.externMu.RUnlock() defer c.externMu.RUnlock()
if c.extern == nil { checksum, ok := c.externCache[id]
return zeroChecksum, nil, nil if !ok {
if c.extern == nil {
return zeroChecksum, nil
}
v, err := c.extern.Artifact(ctx, id)
if err != nil {
return zeroChecksum, err
}
if v == nil {
return zeroChecksum, nil
}
checksum = unique.Make(*v)
var got unique.Handle[Checksum]
if _, got, err = c.Cure(c.extern.Checksum(checksum)); err != nil {
return checksum, err
} else if got != checksum {
return zeroChecksum, &ChecksumMismatchError{got.Value(), checksum.Value()}
}
} }
v, err := c.extern.Artifact(ctx, id) var err error
if err != nil { if status != nil {
return zeroChecksum, nil, err *status, err = c.extern.Status(&RContext{common{ctx, c}}, id)
} }
if v == nil { return checksum, err
return zeroChecksum, nil, nil
}
checksum := unique.Make(*v)
var got unique.Handle[Checksum]
if _, got, err = c.Cure(c.extern.Checksum(checksum)); err != nil {
return checksum, nil, err
} else if got != checksum {
return zeroChecksum, nil, &ChecksumMismatchError{got.Value(), checksum.Value()}
}
var status io.ReadCloser
status, err = c.extern.Status(&RContext{common{ctx, c}}, id)
return checksum, status, err
} }
// cure implements Cure without acquiring a read lock on abortMu. cure must not // cure implements Cure without acquiring a read lock on abortMu. cure must not
@@ -2225,7 +2236,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
externChecksum unique.Handle[Checksum] externChecksum unique.Handle[Checksum]
externStatus io.ReadCloser externStatus io.ReadCloser
) )
if externChecksum, externStatus, err = c.tryExtern(ctx, id); err != nil { if externChecksum, err = c.tryExtern(ctx, id, &externStatus); err != nil {
if c.msg.IsVerbose() { if c.msg.IsVerbose() {
c.msg.Verbosef("extern %s: %v", reportName(ca, id), err) c.msg.Verbosef("extern %s: %v", reportName(ca, id), err)
} }