diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-07-02 20:06:27 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-07-02 20:08:28 +0900 |
| commit | b538c69e01ea29217ccc4b442f2c8b2b7ce99c7d (patch) | |
| tree | 81a73c981e1328d57c807e1f3e1124046883c158 /internal/pkg | |
| parent | c921ba4680c3942022561831b64a6d23b60dbd35 (diff) | |
internal/pkg: cache extern responses
This prepares substitute computation for shallow extern replacements.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg')
| -rw-r--r-- | internal/pkg/pkg.go | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index f1e6279d..d8e059bd 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -770,6 +770,8 @@ type Cache struct { // Optional external cache implementation. extern External + // Caches responses from extern. + externCache map[unique.Handle[ID]]unique.Handle[Checksum] // Synchronises access to extern. externMu sync.RWMutex @@ -930,6 +932,7 @@ func readlinkChecksum(a *check.Absolute, buf *Checksum) error { // SetExternal sets e as the [External] implementation of c. func (c *Cache) SetExternal(e External) { c.externMu.Lock() + c.externCache = make(map[unique.Handle[ID]]unique.Handle[Checksum]) c.extern = e c.externMu.Unlock() } @@ -1849,37 +1852,45 @@ func (r *RContext) NewMeasuredReader( } // 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], - io.ReadCloser, error, ) { c.externMu.RLock() defer c.externMu.RUnlock() - if c.extern == nil { - return zeroChecksum, nil, nil - } + checksum, ok := c.externCache[id] + if !ok { + if c.extern == nil { + return zeroChecksum, nil + } - v, err := c.extern.Artifact(ctx, id) - if err != nil { - return zeroChecksum, nil, err - } - if v == nil { - return zeroChecksum, nil, nil - } - checksum := unique.Make(*v) + 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, nil, err - } else if got != checksum { - return zeroChecksum, nil, &ChecksumMismatchError{got.Value(), checksum.Value()} + 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()} + } } - var status io.ReadCloser - status, err = c.extern.Status(&RContext{common{ctx, c}}, id) - return checksum, status, err + var err error + if status != nil { + *status, err = c.extern.Status(&RContext{common{ctx, c}}, id) + } + return checksum, err } // 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] 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() { c.msg.Verbosef("extern %s: %v", reportName(ca, id), err) } |
