3535import com .google .api .client .googleapis .batch .json .JsonBatchCallback ;
3636import com .google .api .client .googleapis .json .GoogleJsonError ;
3737import com .google .api .client .googleapis .json .GoogleJsonResponseException ;
38- import com .google .api .client .googleapis .media .MediaHttpDownloader ;
3938import com .google .api .client .http .ByteArrayContent ;
4039import com .google .api .client .http .GenericUrl ;
4140import com .google .api .client .http .HttpHeaders ;
5958import com .google .api .services .storage .model .Objects ;
6059import com .google .api .services .storage .model .StorageObject ;
6160import com .google .common .base .MoreObjects ;
61+ import com .google .common .collect .ImmutableList ;
6262import com .google .common .collect .ImmutableSet ;
63+ import com .google .common .collect .Lists ;
6364import com .google .common .collect .Maps ;
64- import com .google .common .primitives .Ints ;
6565import com .google .gcloud .storage .StorageException ;
6666import com .google .gcloud .storage .StorageOptions ;
6767
6868import java .io .ByteArrayOutputStream ;
6969import java .io .IOException ;
7070import java .io .InputStream ;
7171import java .util .ArrayList ;
72+ import java .util .Iterator ;
7273import java .util .List ;
7374import java .util .Map ;
7475import java .util .Set ;
@@ -82,6 +83,7 @@ public class DefaultStorageRpc implements StorageRpc {
8283 // see: https://cloud.google.com/storage/docs/concepts-techniques#practices
8384 private static final Set <Integer > RETRYABLE_CODES = ImmutableSet .of (504 , 503 , 502 , 500 , 429 , 408 );
8485 private static final long MEGABYTE = 1024L * 1024L ;
86+ private static final int MAX_BATCH_DELETES = 100 ;
8587
8688 public DefaultStorageRpc (StorageOptions options ) {
8789 HttpTransport transport = options .httpTransportFactory ().create ();
@@ -361,6 +363,24 @@ public byte[] load(StorageObject from, Map<Option, ?> options)
361363
362364 @ Override
363365 public BatchResponse batch (BatchRequest request ) throws StorageException {
366+ List <List <Tuple <StorageObject , Map <Option , ?>>>> partitionedToDelete =
367+ Lists .partition (request .toDelete , MAX_BATCH_DELETES );
368+ Iterator <List <Tuple <StorageObject , Map <Option , ?>>>> iterator = partitionedToDelete .iterator ();
369+ BatchRequest chunkRequest = new BatchRequest (iterator .hasNext () ? iterator .next () :
370+ ImmutableList .<Tuple <StorageObject , Map <Option , ?>>>of (), request .toUpdate , request .toGet );
371+ BatchResponse response = batchChunk (chunkRequest );
372+ Map <StorageObject , Tuple <Boolean , StorageException >> deletes =
373+ Maps .newHashMapWithExpectedSize (request .toDelete .size ());
374+ deletes .putAll (response .deletes );
375+ while (iterator .hasNext ()) {
376+ chunkRequest = new BatchRequest (iterator .next (), null , null );
377+ BatchResponse deleteBatchResponse = batchChunk (chunkRequest );
378+ deletes .putAll (deleteBatchResponse .deletes );
379+ }
380+ return new BatchResponse (deletes , response .updates , response .gets );
381+ }
382+
383+ private BatchResponse batchChunk (BatchRequest request ) {
364384 com .google .api .client .googleapis .batch .BatchRequest batch = storage .batch ();
365385 final Map <StorageObject , Tuple <Boolean , StorageException >> deletes =
366386 Maps .newConcurrentMap ();
0 commit comments