Skip to content

Commit 7346bbd

Browse files
authored
lib/s3util: stream retrieved S3 data to disk on Get (#11)
On Get, forward the reader from the S3 transaction through to the disk store to avoid pulling the fetched value into memory in the plugin.
1 parent 1368780 commit 7346bbd

File tree

3 files changed

+10
-10
lines changed

3 files changed

+10
-10
lines changed

lib/gobuild/gobuild.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package gobuild
77

88
import (
9-
"bytes"
109
"context"
1110
"errors"
1211
"expvar"
@@ -121,21 +120,22 @@ func (s *S3Cache) Get(ctx context.Context, actionID string) (outputID, diskPath
121120
return "", "", err
122121
}
123122

124-
object, err := s.S3Client.GetData(ctx, s.outputKey(outputID))
123+
object, size, err := s.S3Client.Get(ctx, s.outputKey(outputID))
125124
if err != nil {
126125
// At this point we know the action exists, so if we can't read the
127126
// object report it as an error rather than a cache miss.
128127
return "", "", fmt.Errorf("[s3] read object %s: %w", outputID, err)
129128
}
129+
defer object.Close()
130130
s.getFaultHit.Add(1)
131131

132132
// Now we should have the body; poke it into the local cache. Preserve the
133133
// modification timestamp recorded with the original action.
134134
diskPath, err = s.Local.Put(ctx, gocache.Object{
135135
ActionID: actionID,
136136
OutputID: outputID,
137-
Size: int64(len(object)),
138-
Body: bytes.NewReader(object),
137+
Size: size,
138+
Body: object,
139139
ModTime: mtime,
140140
})
141141
return outputID, diskPath, err

lib/modproxy/modproxy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (c *S3Cacher) Get(ctx context.Context, name string) (_ io.ReadCloser, oerr
158158
}
159159
defer c.sema.Release(1)
160160

161-
obj, err := c.S3Client.Get(ctx, c.makeKey(hash))
161+
obj, _, err := c.S3Client.Get(ctx, c.makeKey(hash))
162162
if errors.Is(err, fs.ErrNotExist) {
163163
c.getFaultMiss.Add(1)
164164
return nil, err

lib/s3util/s3util.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,24 +122,24 @@ func (c *Client) Put(ctx context.Context, key string, data io.Reader) error {
122122
// close the reader when finished.
123123
//
124124
// If the key is not found, the resulting error satisfies [fs.ErrNotExist].
125-
func (c *Client) Get(ctx context.Context, key string) (io.ReadCloser, error) {
125+
func (c *Client) Get(ctx context.Context, key string) (io.ReadCloser, int64, error) {
126126
rsp, err := c.Client.GetObject(ctx, &s3.GetObjectInput{
127127
Bucket: &c.Bucket,
128128
Key: &key,
129129
})
130130
if err != nil {
131131
if IsNotExist(err) {
132-
return nil, fmt.Errorf("key %q: %w", key, fs.ErrNotExist)
132+
return nil, -1, fmt.Errorf("key %q: %w", key, fs.ErrNotExist)
133133
}
134-
return nil, err
134+
return nil, -1, err
135135
}
136-
return rsp.Body, nil
136+
return rsp.Body, *rsp.ContentLength, nil
137137
}
138138

139139
// GetData returns the contents of the specified key from S3. It is a shorthand
140140
// for calling Get followed by io.ReadAll on the result.
141141
func (c *Client) GetData(ctx context.Context, key string) ([]byte, error) {
142-
rc, err := c.Get(ctx, key)
142+
rc, _, err := c.Get(ctx, key)
143143
if err != nil {
144144
return nil, err
145145
}

0 commit comments

Comments
 (0)