refactor(server): Cache manifest entries for layer builds
MD5 hash checking is no longer performed by Nixery (it does not seem to be necessary), hence the layer cache now only keeps the SHA256 hash and size in the form of the manifest entry. This makes it possible to restructure the builder code to perform cache-fetching and cache-populating for layers in the same place.
This commit is contained in:
parent
355fe3f5ec
commit
f6b40ed6c7
2 changed files with 27 additions and 31 deletions
|
@ -21,12 +21,9 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
|
||||||
|
|
||||||
type Build struct {
|
"github.com/google/nixery/manifest"
|
||||||
SHA256 string `json:"sha256"`
|
)
|
||||||
MD5 string `json:"md5"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocalCache implements the structure used for local caching of
|
// LocalCache implements the structure used for local caching of
|
||||||
// manifests and layer uploads.
|
// manifests and layer uploads.
|
||||||
|
@ -37,13 +34,13 @@ type LocalCache struct {
|
||||||
|
|
||||||
// Layer cache
|
// Layer cache
|
||||||
lmtx sync.RWMutex
|
lmtx sync.RWMutex
|
||||||
lcache map[string]Build
|
lcache map[string]manifest.Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCache() LocalCache {
|
func NewCache() LocalCache {
|
||||||
return LocalCache{
|
return LocalCache{
|
||||||
mcache: make(map[string]string),
|
mcache: make(map[string]string),
|
||||||
lcache: make(map[string]Build),
|
lcache: make(map[string]manifest.Entry),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,19 +65,19 @@ func (c *LocalCache) localCacheManifest(key, path string) {
|
||||||
c.mmtx.Unlock()
|
c.mmtx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve a cached build from the local cache.
|
// Retrieve a layer build from the local cache.
|
||||||
func (c *LocalCache) buildFromLocalCache(key string) (*Build, bool) {
|
func (c *LocalCache) layerFromLocalCache(key string) (*manifest.Entry, bool) {
|
||||||
c.lmtx.RLock()
|
c.lmtx.RLock()
|
||||||
b, ok := c.lcache[key]
|
e, ok := c.lcache[key]
|
||||||
c.lmtx.RUnlock()
|
c.lmtx.RUnlock()
|
||||||
|
|
||||||
return &b, ok
|
return &e, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a build result to the local cache.
|
// Add a layer build result to the local cache.
|
||||||
func (c *LocalCache) localCacheBuild(key string, b Build) {
|
func (c *LocalCache) localCacheLayer(key string, e manifest.Entry) {
|
||||||
c.lmtx.Lock()
|
c.lmtx.Lock()
|
||||||
c.lcache[key] = b
|
c.lcache[key] = e
|
||||||
c.lmtx.Unlock()
|
c.lmtx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,12 +138,11 @@ func cacheManifest(ctx context.Context, s *State, key string, m json.RawMessage)
|
||||||
log.Printf("Cached manifest sha1:%s (%v bytes written)\n", key, size)
|
log.Printf("Cached manifest sha1:%s (%v bytes written)\n", key, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve a build from the cache, first checking the local cache
|
// Retrieve a layer build from the cache, first checking the local
|
||||||
// followed by the bucket cache.
|
// cache followed by the bucket cache.
|
||||||
func buildFromCache(ctx context.Context, s *State, key string) (*Build, bool) {
|
func layerFromCache(ctx context.Context, s *State, key string) (*manifest.Entry, bool) {
|
||||||
build, cached := s.Cache.buildFromLocalCache(key)
|
if entry, cached := s.Cache.layerFromLocalCache(key); cached {
|
||||||
if cached {
|
return entry, true
|
||||||
return build, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obj := s.Bucket.Object("builds/" + key)
|
obj := s.Bucket.Object("builds/" + key)
|
||||||
|
@ -157,7 +153,7 @@ func buildFromCache(ctx context.Context, s *State, key string) (*Build, bool) {
|
||||||
|
|
||||||
r, err := obj.NewReader(ctx)
|
r, err := obj.NewReader(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to retrieve build '%s' from cache: %s\n", key, err)
|
log.Printf("Failed to retrieve layer build '%s' from cache: %s\n", key, err)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
@ -165,27 +161,27 @@ func buildFromCache(ctx context.Context, s *State, key string) (*Build, bool) {
|
||||||
jb := bytes.NewBuffer([]byte{})
|
jb := bytes.NewBuffer([]byte{})
|
||||||
_, err = io.Copy(jb, r)
|
_, err = io.Copy(jb, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to read build '%s' from cache: %s\n", key, err)
|
log.Printf("Failed to read layer build '%s' from cache: %s\n", key, err)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var b Build
|
var entry manifest.Entry
|
||||||
err = json.Unmarshal(jb.Bytes(), &build)
|
err = json.Unmarshal(jb.Bytes(), &entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to unmarshal build '%s' from cache: %s\n", key, err)
|
log.Printf("Failed to unmarshal layer build '%s' from cache: %s\n", key, err)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
go s.Cache.localCacheBuild(key, b)
|
go s.Cache.localCacheLayer(key, entry)
|
||||||
return &b, true
|
return &entry, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func cacheBuild(ctx context.Context, s *State, key string, build Build) {
|
func cacheLayer(ctx context.Context, s *State, key string, entry manifest.Entry) {
|
||||||
go s.Cache.localCacheBuild(key, build)
|
s.Cache.localCacheLayer(key, entry)
|
||||||
|
|
||||||
obj := s.Bucket.Object("builds/" + key)
|
obj := s.Bucket.Object("builds/" + key)
|
||||||
|
|
||||||
j, _ := json.Marshal(&build)
|
j, _ := json.Marshal(&entry)
|
||||||
|
|
||||||
w := obj.NewWriter(ctx)
|
w := obj.NewWriter(ctx)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
MediaType string `json:"mediaType"`
|
MediaType string `json:"mediaType,omitempty"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
Digest string `json:"digest"`
|
Digest string `json:"digest"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue