|
8 | 8 | "strings"
|
9 | 9 |
|
10 | 10 | remoteexecution "github.com/bitrise-io/bitrise-build-cache-cli/proto/build/bazel/remote/execution/v2"
|
| 11 | + "github.com/dustin/go-humanize" |
11 | 12 | "google.golang.org/genproto/googleapis/bytestream"
|
12 | 13 | "google.golang.org/grpc/metadata"
|
13 | 14 | )
|
@@ -129,15 +130,43 @@ func (c *Client) FindMissing(ctx context.Context, digests []*FileDigest) ([]*Fil
|
129 | 130 | }
|
130 | 131 | ctx = metadata.NewOutgoingContext(ctx, md)
|
131 | 132 |
|
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()) |
138 | 167 | }
|
139 | 168 |
|
140 |
| - return convertToFileDigests(resp.GetMissingBlobDigests()), nil |
| 169 | + return missingBlobs, nil |
141 | 170 | }
|
142 | 171 |
|
143 | 172 | func convertToBlobDigests(digests []*FileDigest) []*remoteexecution.Digest {
|
|
0 commit comments