|
13 | 13 | import com.linkedin.venice.helix.HelixState;
|
14 | 14 | import com.linkedin.venice.helix.Replica;
|
15 | 15 | import com.linkedin.venice.helix.ResourceAssignment;
|
| 16 | +import com.linkedin.venice.meta.HybridStoreConfig; |
16 | 17 | import com.linkedin.venice.meta.Instance;
|
17 | 18 | import com.linkedin.venice.meta.Partition;
|
18 | 19 | import com.linkedin.venice.meta.PartitionAssignment;
|
19 | 20 | import com.linkedin.venice.meta.ReadOnlyStoreRepository;
|
20 | 21 | import com.linkedin.venice.meta.RoutingDataRepository;
|
21 | 22 | import com.linkedin.venice.meta.Store;
|
| 23 | +import com.linkedin.venice.meta.StoreInfo; |
22 | 24 | import com.linkedin.venice.meta.Version;
|
23 | 25 | import com.linkedin.venice.pubsub.api.PubSubTopic;
|
24 | 26 | import com.linkedin.venice.pubsub.api.PubSubTopicPartition;
|
|
66 | 68 | import org.apache.http.HttpStatus;
|
67 | 69 | import org.apache.logging.log4j.LogManager;
|
68 | 70 | import org.apache.logging.log4j.Logger;
|
| 71 | +import org.apache.logging.log4j.util.Strings; |
69 | 72 |
|
70 | 73 |
|
71 | 74 | /**
|
@@ -529,6 +532,101 @@ public static File getTempDataDirectory(String prefix) {
|
529 | 532 | }
|
530 | 533 | }
|
531 | 534 |
|
| 535 | + /** This method should only be used for system stores. |
| 536 | + * For other stores, use {@link Utils#getRealTimeTopicName(Store)}, {@link Utils#getRealTimeTopicName(StoreInfo)} or |
| 537 | + * {@link Utils#getRealTimeTopicName(Version)} |
| 538 | + */ |
| 539 | + public static String composeRealTimeTopic(String storeName) { |
| 540 | + return storeName + Version.REAL_TIME_TOPIC_SUFFIX; |
| 541 | + } |
| 542 | + |
| 543 | + /** |
| 544 | + * It follows the following order to search for real time topic name, |
| 545 | + * i) current store-version config, ii) store config, iii) other store-version configs, iv) default name |
| 546 | + */ |
| 547 | + public static String getRealTimeTopicName(Store store) { |
| 548 | + return getRealTimeTopicName( |
| 549 | + store.getName(), |
| 550 | + store.getVersions(), |
| 551 | + store.getCurrentVersion(), |
| 552 | + store.getHybridStoreConfig()); |
| 553 | + } |
| 554 | + |
| 555 | + public static String getRealTimeTopicName(StoreInfo storeInfo) { |
| 556 | + return getRealTimeTopicName( |
| 557 | + storeInfo.getName(), |
| 558 | + storeInfo.getVersions(), |
| 559 | + storeInfo.getCurrentVersion(), |
| 560 | + storeInfo.getHybridStoreConfig()); |
| 561 | + } |
| 562 | + |
| 563 | + public static String getRealTimeTopicName(Version version) { |
| 564 | + HybridStoreConfig hybridStoreConfig = version.getHybridStoreConfig(); |
| 565 | + if (hybridStoreConfig != null) { |
| 566 | + String realTimeTopicName = version.getHybridStoreConfig().getRealTimeTopicName(); |
| 567 | + return getRealTimeTopicNameIfEmpty(realTimeTopicName, version.getStoreName()); |
| 568 | + } else { |
| 569 | + // if the version is not hybrid, caller should not ask for the real time topic, |
| 570 | + // but unfortunately that happens, so instead of throwing exception, we just return a default name. |
| 571 | + return composeRealTimeTopic(version.getStoreName()); |
| 572 | + } |
| 573 | + } |
| 574 | + |
| 575 | + static String getRealTimeTopicName( |
| 576 | + String storeName, |
| 577 | + List<Version> versions, |
| 578 | + int currentVersionNumber, |
| 579 | + HybridStoreConfig hybridStoreConfig) { |
| 580 | + if (currentVersionNumber < 1) { |
| 581 | + return composeRealTimeTopic(storeName); |
| 582 | + } |
| 583 | + |
| 584 | + Optional<Version> currentVersion = |
| 585 | + versions.stream().filter(version -> version.getNumber() == currentVersionNumber).findFirst(); |
| 586 | + if (currentVersion.isPresent() && currentVersion.get().isHybrid()) { |
| 587 | + String realTimeTopicName = currentVersion.get().getHybridStoreConfig().getRealTimeTopicName(); |
| 588 | + if (Strings.isNotBlank(realTimeTopicName)) { |
| 589 | + return realTimeTopicName; |
| 590 | + } |
| 591 | + } |
| 592 | + |
| 593 | + if (hybridStoreConfig != null) { |
| 594 | + String realTimeTopicName = hybridStoreConfig.getRealTimeTopicName(); |
| 595 | + return getRealTimeTopicNameIfEmpty(realTimeTopicName, storeName); |
| 596 | + } |
| 597 | + |
| 598 | + Set<String> realTimeTopicNames = new HashSet<>(); |
| 599 | + |
| 600 | + for (Version version: versions) { |
| 601 | + try { |
| 602 | + if (version.isHybrid()) { |
| 603 | + String realTimeTopicName = version.getHybridStoreConfig().getRealTimeTopicName(); |
| 604 | + if (Strings.isNotBlank(realTimeTopicName)) { |
| 605 | + realTimeTopicNames.add(realTimeTopicName); |
| 606 | + } |
| 607 | + } |
| 608 | + } catch (VeniceException e) { |
| 609 | + // just try another version |
| 610 | + } |
| 611 | + } |
| 612 | + |
| 613 | + if (realTimeTopicNames.size() > 1) { |
| 614 | + LOGGER.warn( |
| 615 | + "Store " + storeName + " and current version are not hybrid, yet " + realTimeTopicNames.size() |
| 616 | + + " older versions are using real time topics. Will return one of them."); |
| 617 | + } |
| 618 | + |
| 619 | + if (!realTimeTopicNames.isEmpty()) { |
| 620 | + return realTimeTopicNames.iterator().next(); |
| 621 | + } |
| 622 | + |
| 623 | + return composeRealTimeTopic(storeName); |
| 624 | + } |
| 625 | + |
| 626 | + private static String getRealTimeTopicNameIfEmpty(String realTimeTopicName, String storeName) { |
| 627 | + return Strings.isBlank(realTimeTopicName) ? composeRealTimeTopic(storeName) : realTimeTopicName; |
| 628 | + } |
| 629 | + |
532 | 630 | private static class TimeUnitInfo {
|
533 | 631 | String suffix;
|
534 | 632 | int multiplier;
|
|
0 commit comments