Skip to content

Commit ab1d1ec

Browse files
Merge pull request #46 from bitrise-io/chunk-up-findmissingblobs
feat: ACI-2755 Chunk up FindMissingBlobs
2 parents 8ed8714 + a2c4323 commit ab1d1ec

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

cmd/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func createKVClient(ctx context.Context, authConfig common.CacheAuthConfig, envP
3434
DialTimeout: 5 * time.Second,
3535
ClientName: "kv",
3636
AuthConfig: authConfig,
37+
Logger: logger,
3738
})
3839
if err != nil {
3940
return nil, fmt.Errorf("new kv client: %w", err)

internal/build_cache/kv/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/bitrise-io/bitrise-build-cache-cli/internal/config/common"
1818
remoteexecution "github.com/bitrise-io/bitrise-build-cache-cli/proto/build/bazel/remote/execution/v2"
1919
"github.com/bitrise-io/bitrise-build-cache-cli/proto/kv_storage"
20+
"github.com/bitrise-io/go-utils/v2/log"
2021
)
2122

2223
type Client struct {
@@ -26,6 +27,7 @@ type Client struct {
2627
casClient remoteexecution.ContentAddressableStorageClient
2728
clientName string
2829
authConfig common.CacheAuthConfig
30+
logger log.Logger
2931
}
3032

3133
type NewClientParams struct {
@@ -34,6 +36,7 @@ type NewClientParams struct {
3436
DialTimeout time.Duration
3537
ClientName string
3638
AuthConfig common.CacheAuthConfig
39+
Logger log.Logger
3740
}
3841

3942
func NewClient(ctx context.Context, p NewClientParams) (*Client, error) {
@@ -57,6 +60,7 @@ func NewClient(ctx context.Context, p NewClientParams) (*Client, error) {
5760
casClient: remoteexecution.NewContentAddressableStorageClient(conn),
5861
clientName: p.ClientName,
5962
authConfig: p.AuthConfig,
63+
logger: p.Logger,
6064
}, nil
6165
}
6266

internal/build_cache/kv/methods.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99

1010
remoteexecution "github.com/bitrise-io/bitrise-build-cache-cli/proto/build/bazel/remote/execution/v2"
11+
"github.com/dustin/go-humanize"
1112
"google.golang.org/genproto/googleapis/bytestream"
1213
"google.golang.org/grpc/metadata"
1314
)
@@ -129,15 +130,43 @@ func (c *Client) FindMissing(ctx context.Context, digests []*FileDigest) ([]*Fil
129130
}
130131
ctx = metadata.NewOutgoingContext(ctx, md)
131132

132-
resp, err := c.casClient.FindMissingBlobs(ctx, &remoteexecution.FindMissingBlobsRequest{
133-
BlobDigests: convertToBlobDigests(digests),
134-
})
135-
136-
if err != nil {
137-
return nil, fmt.Errorf("find missing blobs: %w", err)
133+
var missingBlobs []*FileDigest
134+
blobDigests := convertToBlobDigests(digests)
135+
req := &remoteexecution.FindMissingBlobsRequest{
136+
BlobDigests: blobDigests,
137+
}
138+
c.logger.Debugf("Size of FindMissingBlobs request for %d blobs is %s", len(digests), humanize.Bytes(uint64(len(req.String()))))
139+
gRPCLimitBytes := 4 * 1024 * 1024 // gRPC limit is 4 MiB
140+
if len(req.String()) > gRPCLimitBytes {
141+
// Chunk up request blobs to fit into gRPC limits
142+
// Calculate the unit size of a blob (in practice can differ to the theoretical sha256(32 bytes) + size(8 bytes) = 40 bytes)
143+
digestUnitSize := float64(len(req.String())) / float64(len(digests))
144+
maxDigests := int(float64(gRPCLimitBytes) / digestUnitSize)
145+
for startIndex := 0; startIndex < len(digests); startIndex += maxDigests {
146+
endIndex := startIndex + maxDigests
147+
if endIndex > len(digests) {
148+
endIndex = len(digests)
149+
}
150+
req.BlobDigests = blobDigests[startIndex:endIndex]
151+
152+
c.logger.Debugf("Calling FindMissingBlobs for chunk: digests[%d:%d]", startIndex, endIndex)
153+
resp, err := c.casClient.FindMissingBlobs(ctx, req)
154+
155+
if err != nil {
156+
return nil, fmt.Errorf("find missing blobs[%d:%d]: %w", startIndex, endIndex, err)
157+
}
158+
missingBlobs = append(missingBlobs, convertToFileDigests(resp.GetMissingBlobDigests())...)
159+
}
160+
} else {
161+
resp, err := c.casClient.FindMissingBlobs(ctx, req)
162+
163+
if err != nil {
164+
return nil, fmt.Errorf("find missing blobs: %w", err)
165+
}
166+
missingBlobs = convertToFileDigests(resp.GetMissingBlobDigests())
138167
}
139168

140-
return convertToFileDigests(resp.GetMissingBlobDigests()), nil
169+
return missingBlobs, nil
141170
}
142171

143172
func convertToBlobDigests(digests []*FileDigest) []*remoteexecution.Digest {

0 commit comments

Comments
 (0)