Skip to content

Commit 5fc8533

Browse files
adrienthebocsweichel
authored andcommitted
Expand cache inline documentation, cleanup contexts
1 parent 81603dc commit 5fc8533

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

pkg/leeway/cache.go

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ import (
2424
"golang.org/x/xerrors"
2525
)
2626

27+
// The part size of S3 bucket uploads/downloads for multipart file operations.
28+
// See also: https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html
29+
const S3_PART_SIZE = 5 * 1024 * 1024
30+
2731
// Cache provides filesystem locations for package build artifacts.
2832
type Cache interface {
2933
// Location returns the absolute filesystem path for a package build artifact
@@ -241,7 +245,7 @@ func gsutilTransfer(target string, files []string) error {
241245
return nil
242246
}
243247

244-
// S3RemoteCache uses the AWS Go SDK to implement a remote cache
248+
// S3RemoteCache uses the AWS Go SDK to implement a remote cache.
245249
type S3RemoteCache struct {
246250
BucketName string
247251
s3Config *aws.Config
@@ -259,6 +263,8 @@ func NewS3RemoteCache(bucketName string, cfg *aws.Config) (*S3RemoteCache, error
259263
s3Client := s3.NewFromConfig(*cfg)
260264

261265
log.DebugFn(func() []interface{} {
266+
// When the log level is set to debug fetch the AWS caller identity in case there's uncertainty about
267+
// which AWS profile is active and interacting with the caching bucket.
262268
stsClient := sts.NewFromConfig(*cfg)
263269
identity, err := stsClient.GetCallerIdentity(context.TODO(), &sts.GetCallerIdentityInput{})
264270
if err != nil {
@@ -301,13 +307,16 @@ func (rs *S3RemoteCache) ExistingPackages(pkgs []*Package) (map[*Package]struct{
301307
existingPackages := make(map[*Package]struct{})
302308
wg := sync.WaitGroup{}
303309

310+
ctx := context.TODO()
304311
for pkg, key := range packagesToKeys {
305312
wg.Add(1)
306313
go func(pkg *Package, key string) {
307314
defer wg.Done()
308315

309-
stat, _ := rs.hasObject(context.TODO(), key)
310-
// TODO error handling
316+
stat, err := rs.hasObject(ctx, key)
317+
if err != nil {
318+
log.WithField("bucket", rs.BucketName).WithField("key", key).Debugf("Failed to check for remote cached object: %s", err)
319+
}
311320
if stat {
312321
ch <- pkg
313322
}
@@ -319,6 +328,7 @@ func (rs *S3RemoteCache) ExistingPackages(pkgs []*Package) (map[*Package]struct{
319328
for p := range ch {
320329
existingPackages[p] = struct{}{}
321330
}
331+
log.WithField("bucket", rs.BucketName).Debugf("%d/%d packages found in remote cache", len(existingPackages), len(packagesToKeys))
322332

323333
return existingPackages, nil
324334
}
@@ -350,6 +360,7 @@ func (rs *S3RemoteCache) Download(dst Cache, pkgs []*Package) error {
350360

351361
wg := sync.WaitGroup{}
352362

363+
ctx := context.TODO()
353364
for _, file := range files {
354365
wg.Add(1)
355366

@@ -363,7 +374,7 @@ func (rs *S3RemoteCache) Download(dst Cache, pkgs []*Package) error {
363374
"region": rs.s3Config.Region,
364375
}
365376
log.WithFields(fields).Debug("downloading object from s3")
366-
len, err := rs.getObject(context.TODO(), key, fmt.Sprintf("%s/%s", dest, key))
377+
len, err := rs.getObject(ctx, key, fmt.Sprintf("%s/%s", dest, key))
367378
if err != nil {
368379
log.WithFields(fields).Warnf("failed to download and store object %s from s3: %s", key, err)
369380
} else {
@@ -392,6 +403,7 @@ func (rs *S3RemoteCache) Upload(src Cache, pkgs []*Package) error {
392403

393404
wg := sync.WaitGroup{}
394405

406+
ctx := context.TODO()
395407
for _, file := range files {
396408
wg.Add(1)
397409
go func(file string) {
@@ -403,7 +415,7 @@ func (rs *S3RemoteCache) Upload(src Cache, pkgs []*Package) error {
403415
"region": rs.s3Config.Region,
404416
}
405417
log.WithFields(fields).Debug("uploading object to s3")
406-
res, err := rs.uploadObject(context.TODO(), filepath.Base(file), file)
418+
res, err := rs.uploadObject(ctx, filepath.Base(file), file)
407419
if err != nil {
408420
log.WithFields(fields).Warnf("Failed to upload object to s3: %s", err)
409421
} else {
@@ -447,6 +459,10 @@ func (rs *S3RemoteCache) hasObject(ctx context.Context, key string) (bool, error
447459
}
448460
log.WithFields(fields).Debugf("Checking s3 for cached package")
449461

462+
// The AWS HeadObject API call would be slightly more suitable here but the Go API
463+
// buries missing object errors behind some internal types. Using GetObject with a zero
464+
// byte range provides a more clear error message that can indicate the absence of an
465+
// object at the expense of performing a slightly more expensive API call.
450466
_, err := rs.s3Client.GetObject(ctx, &s3.GetObjectInput{
451467
Bucket: aws.String(rs.BucketName),
452468
Key: aws.String(key),
@@ -459,7 +475,8 @@ func (rs *S3RemoteCache) hasObject(ctx context.Context, key string) (bool, error
459475
return false, nil
460476
}
461477

462-
// We've received an error that's not a simple missing key error. Collect more information
478+
// We've received an error that's not a simple missing key error. Attempt to look up
479+
// the cache bucket in case we're trying to use a bucket that doesn't exist.
463480
hasBucket, _ := rs.hasBucket(ctx)
464481
if !hasBucket {
465482
return false, err
@@ -469,15 +486,13 @@ func (rs *S3RemoteCache) hasObject(ctx context.Context, key string) (bool, error
469486
return false, err
470487
}
471488

472-
// XXX
473489
return true, nil
474490
}
475491

476492
func (rs *S3RemoteCache) getObject(ctx context.Context, key string, path string) (int64, error) {
477493

478-
var partMiBs int64 = 10
479494
downloader := manager.NewDownloader(rs.s3Client, func(d *manager.Downloader) {
480-
d.PartSize = partMiBs * 1024 * 1024
495+
d.PartSize = S3_PART_SIZE
481496
})
482497
buffer := manager.NewWriteAtBuffer([]byte{})
483498
res, err := downloader.Download(context.TODO(), buffer, &s3.GetObjectInput{
@@ -502,9 +517,8 @@ func (rs *S3RemoteCache) uploadObject(ctx context.Context, key string, path stri
502517
return nil, xerrors.Errorf("cannot open %s for S3 upload: %s", path, err)
503518
}
504519

505-
var partMiBs int64 = 10
506520
uploader := manager.NewUploader(rs.s3Client, func(u *manager.Uploader) {
507-
u.PartSize = partMiBs * 1024 * 1024
521+
u.PartSize = S3_PART_SIZE
508522
})
509523
res, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
510524
Bucket: aws.String(rs.BucketName),

0 commit comments

Comments
 (0)