|
23 | 23 | import com.google.cloud.bigquery.storage.v1.AppendRowsRequest; |
24 | 24 | import java.io.IOException; |
25 | 25 | import java.nio.ByteBuffer; |
| 26 | +import java.nio.charset.StandardCharsets; |
26 | 27 | import java.util.Map; |
27 | 28 | import java.util.concurrent.ThreadLocalRandom; |
28 | 29 | import java.util.function.Predicate; |
|
38 | 39 | import org.apache.beam.sdk.transforms.ParDo; |
39 | 40 | import org.apache.beam.sdk.transforms.Redistribute; |
40 | 41 | import org.apache.beam.sdk.transforms.SerializableFunction; |
| 42 | +import org.apache.beam.sdk.transforms.Values; |
| 43 | +import org.apache.beam.sdk.transforms.WithKeys; |
41 | 44 | import org.apache.beam.sdk.transforms.errorhandling.BadRecord; |
42 | 45 | import org.apache.beam.sdk.transforms.errorhandling.BadRecordRouter; |
43 | 46 | import org.apache.beam.sdk.transforms.errorhandling.BadRecordRouter.ThrowingBadRecordRouter; |
|
50 | 53 | import org.apache.beam.sdk.values.PCollectionList; |
51 | 54 | import org.apache.beam.sdk.values.PCollectionTuple; |
52 | 55 | import org.apache.beam.sdk.values.TupleTag; |
| 56 | +import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.hash.Hashing; |
53 | 57 | import org.joda.time.Duration; |
54 | 58 |
|
55 | 59 | /** This {@link PTransform} manages loads into BigQuery using the Storage API. */ |
@@ -379,12 +383,32 @@ public WriteResult expandUntriggered( |
379 | 383 | PCollection<KV<DestinationT, StorageApiWritePayload>> successfulConvertedRows = |
380 | 384 | convertMessagesResult.get(successfulConvertedRowsTag); |
381 | 385 |
|
382 | | - if (numShards > 0) { |
| 386 | + if (numShards > 0 && input.isBounded() == PCollection.IsBounded.UNBOUNDED) { |
383 | 387 | successfulConvertedRows = |
384 | 388 | successfulConvertedRows.apply( |
385 | 389 | "ResdistibuteNumShards", |
386 | 390 | Redistribute.<KV<DestinationT, StorageApiWritePayload>>arbitrarily() |
387 | 391 | .withNumBuckets(numShards)); |
| 392 | + } else if (numShards > 0 && input.isBounded() == PCollection.IsBounded.BOUNDED) { |
| 393 | + successfulConvertedRows = |
| 394 | + successfulConvertedRows |
| 395 | + .apply( |
| 396 | + "Add shard", |
| 397 | + WithKeys.of( |
| 398 | + (SerializableFunction<KV<DestinationT, StorageApiWritePayload>, Integer>) |
| 399 | + kv -> |
| 400 | + Math.abs( |
| 401 | + Hashing.murmur3_32_fixed() |
| 402 | + .hashString( |
| 403 | + dynamicDestinations |
| 404 | + .getTable(kv.getKey()) |
| 405 | + .getShortTableUrn(), |
| 406 | + StandardCharsets.UTF_8) |
| 407 | + .asInt() |
| 408 | + ^ ThreadLocalRandom.current().nextInt(numShards)) |
| 409 | + % numShards)) |
| 410 | + .apply("RedistributeNumShards", Redistribute.byKey()) |
| 411 | + .apply("Remove shard", Values.create()); |
388 | 412 | } |
389 | 413 |
|
390 | 414 | PCollectionTuple writeRecordsResult = |
|
0 commit comments