From 7e7475fc05623467899738946cf10ebb7b8c8a17 Mon Sep 17 00:00:00 2001 From: dogemanttv <80775876+dogemanttv@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:07:46 -0600 Subject: [PATCH] Delete product-mixer directory --- product-mixer/README.md | 41 - ...tRecommendationsMixerCandidateSource.scala | 57 - .../account_recommendations_mixer/BUILD | 22 - .../ads/AdsProdStratoCandidateSource.scala | 29 - .../ads/AdsProdThriftCandidateSource.scala | 22 - .../ads/AdsStagingCandidateSource.scala | 28 - .../candidate_source/ads/BUILD | 18 - .../ann/AnnCandidateSource.scala | 43 - .../candidate_source/ann/AnnIdQuery.scala | 18 - .../candidate_source/ann/BUILD.bazel | 17 - .../candidate_source/audiospace/BUILD.bazel | 14 - .../CreatedSpacesCandidateSource.scala | 49 - .../candidate_source/business_profiles/BUILD | 13 - .../TeamMembersCandidateSource.scala | 53 - .../candidate_source/cr_mixer/BUILD.bazel | 12 - ...dTweetRecommendationsCandidateSource.scala | 25 - ...rTweetRecommendationsCandidateSource.scala | 21 - .../candidate_source/earlybird/BUILD.bazel | 12 - .../EarlybirdTweetCandidateSource.scala | 26 - .../explore_ranker/BUILD.bazel | 12 - .../ExploreRankerCandidateSource.scala | 31 - .../flexible_injection_pipeline/BUILD | 17 - .../PromptCandidateSource.scala | 50 - .../candidate_source/hermit/BUILD.bazel | 16 - .../UsersSimilarToMeCandidateSource.scala | 32 - .../candidate_source/interest_discovery/BUILD | 18 - .../RelatedTopicsCandidateSource.scala | 34 - .../candidate_source/lists/BUILD.bazel | 14 - .../OrganicPopGeoListsCandidateSource.scala | 39 - .../candidate_source/people_discovery/BUILD | 23 - .../PeopleDiscoveryCandidateSource.scala | 71 -- .../recommendations/BUILD.bazel | 21 - ...FollowRecommendationsCandidateSource.scala | 41 - .../candidate_source/social_graph/BUILD.bazel | 22 - .../SocialgraphCandidateSource.scala | 57 - .../SocialgraphCursorConstants.scala | 7 - .../timeline_ranker/BUILD.bazel | 13 - ...melineRankerInNetworkCandidateSource.scala | 51 - .../TimelineRankerRecapCandidateSource.scala | 28 - .../TimelineRankerUtegCandidateSource.scala | 49 - .../timeline_scorer/BUILD.bazel | 16 - .../TimelineScorerCandidateSource.scala | 156 --- .../candidate_source/timeline_service/BUILD | 18 - .../TimelineServiceTweetCandidateSource.scala | 48 - .../timelines_impression_store/BUILD | 16 - ...inesImpressionStoreCandidateSourceV2.scala | 30 - .../candidate_source/topics/BUILD | 11 - .../FollowedTopicsCandidateSource.scala | 21 - .../tweetconvosvc/BUILD.bazel | 26 - .../ConversationServiceCandidateSource.scala | 173 --- ...ionServiceResponseFeatureTransformer.scala | 49 - ...pMaxConversationModuleItemCandidates.scala | 55 - .../component_library/decorator/slice/BUILD | 23 - .../slice/SliceItemCandidateDecorator.scala | 41 - .../decorator/slice/builder/BUILD | 17 - .../CursorCandidateSliceItemBuilder.scala | 29 - .../component_library/decorator/urt/BUILD | 108 -- ...rtConversationItemCandidateDecorator.scala | 44 - .../urt/UrtItemCandidateDecorator.scala | 40 - .../urt/UrtItemInModuleDecorator.scala | 52 - .../urt/UrtMultipleModulesDecorator.scala | 108 -- .../ContextualTweetRefBuilder.scala | 12 - .../ConversationModuleMetadataBuilder.scala | 38 - .../FlipPromptCandidateUrtItemBuilder.scala | 205 ---- .../FlipPromptModuleGrouping.scala | 23 - .../FlipPromptUrtModuleBuilder.scala | 54 - .../OnboardingInjectionConversions.scala | 361 ------ .../RelevancePromptConversions.scala | 76 -- .../TilesCarouselConversions.scala | 154 --- .../urt/builder/icon/HorizonIconBuilder.scala | 17 - .../item/ad/AdsCandidateUrtItemBuilder.scala | 274 ----- .../item/alert/DurationParamBuilder.scala | 20 - .../ShowAlertCandidateUrtItemBuilder.scala | 61 - ...icShowAlertColorConfigurationBuilder.scala | 18 - ...taticShowAlertDisplayLocationBuilder.scala | 18 - ...taticShowAlertIconDisplayInfoBuilder.scala | 18 - .../ArticleCandidateUrtItemBuilder.scala | 52 - .../AudioSpaceCandidateUrtItemBuilder.scala | 39 - .../card/CardCandidateUtrItemBuilder.scala | 51 - ...mmerceProductCandidateUrtItemBuilder.scala | 41 - ...eProductGroupCandidateUrtItemBuilder.scala | 42 - .../EventCandidateUrtItemBuilder.scala | 51 - .../GenericSummaryActionBuilder.scala | 32 - ...enericSummaryCandidateUrtItemBuilder.scala | 64 - .../GenericSummaryContextBuilder.scala | 22 - .../IconLabelCandidateUrtItemBuilder.scala | 42 - ...tCandidateUrtItemStringCenterBuilder.scala | 59 - ...tCandidateUrtItemStringCenterBuilder.scala | 74 -- .../message/MessageTextActionBuilder.scala | 36 - .../item/message/UserFacePileBuilder.scala | 24 - ...entAnnotationCandidateUrtItemBuilder.scala | 46 - ...tCandidateUrtItemStringCenterBuilder.scala | 62 - ...ingSuggestionCandidateUrtItemBuilder.scala | 41 - .../tile/TileCandidateUrtItemBuilder.scala | 48 - .../topic/ParamTopicDisplayTypeBuilder.scala | 41 - .../ParamTopicFunctionalityTypeBuilder.scala | 38 - .../topic/StaticTopicDisplayTypeBuilder.scala | 18 - .../StaticTopicFunctionalityTypeBuilder.scala | 18 - .../topic/TopicCandidateUrtItemBuilder.scala | 47 - ...icalGridTopicCandidateUrtItemBuilder.scala | 46 - .../trend/TrendCandidateUrtItemBuilder.scala | 63 - .../trend/TrendMetaDescriptionBuilder.scala | 38 - .../trend/TrendPromotedMetadataBuilder.scala | 41 - .../tweet/TweetCandidateUrtItemBuilder.scala | 92 -- .../TwitterListCandidateUrtItemBuilder.scala | 41 - ...iedTrendEventCandidateUrtItemBuilder.scala | 36 - .../user/UserCandidateUrtItemBuilder.scala | 62 - .../metadata/ClientEventInfoBuilder.scala | 48 - ...sationTweetClientEventDetailsBuilder.scala | 63 - .../builder/metadata/StaticUrlBuilder.scala | 18 - .../TopicClientEventDetailsBuilder.scala | 56 - ...tInterestedFeedbackActionInfoBuilder.scala | 45 - .../TopicTweetClientEventDetailsBuilder.scala | 66 - .../TopicsToFollowModuleMetadataBuilder.scala | 39 - ...WhoToFollowFeedbackActionInfoBuilder.scala | 60 - .../CursorCandidateUrtOperationBuilder.scala | 29 - .../FeaturePromotedMetadataBuilder.scala | 106 -- .../builder/richtext/RichTextBuilder.scala | 28 - .../builder/richtext/RichTextMarkupUtil.scala | 135 --- .../RichTextReferenceObjectBuilder.scala | 8 - .../richtext/RichTextRtlOptionBuilder.scala | 12 - .../richtext/StaticRichTextBuilder.scala | 17 - .../TwitterTextEntityProcessor.scala | 51 - .../TwitterTextFormatProcessor.scala | 67 - .../twitter_text/TwitterTextRenderer.scala | 390 ------ .../TwitterTextRendererProcessor.scala | 5 - .../TwitterTextRichTextBuilder.scala | 37 - .../FeatureSocialContextBuilder.scala | 101 -- .../GeneralModuleSocialContextBuilder.scala | 38 - .../GeneralSocialContextBuilder.scala | 32 - .../WhoToFollowSocialContextBuilder.scala | 48 - .../urt/builder/stringcenter/ModuleStr.scala | 31 - .../urt/builder/stringcenter/Str.scala | 36 - .../FeatureModuleDisplayTypeBuilder.scala | 22 - ...ShowMoreBehaviorRevealByCountBuilder.scala | 22 - .../timeline_module/ModuleFooterBuilder.scala | 27 - .../timeline_module/ModuleHeaderBuilder.scala | 41 - .../ModuleHeaderDisplayTypeBuilder.scala | 22 - .../timeline_module/ModuleIdGeneration.scala | 51 - ...ShowMoreBehaviorRevealByCountBuilder.scala | 25 - .../ParamGatedModuleFooterBuilder.scala | 26 - .../ParamGatedModuleHeaderBuilder.scala | 26 - ...mWhoToFollowModuleDisplayTypeBuilder.scala | 53 - .../StaticModuleDisplayTypeBuilder.scala | 16 - .../TimelineModuleBuilder.scala | 56 - .../experiments/metrics/BUILD | 11 - .../metrics/MetricDefinitions.scala | 116 -- .../experiments/metrics/MetricGroup.scala | 54 - .../metrics/MetricTemplateCLIRunner.scala | 101 -- .../experiments/metrics/MetricTemplates.scala | 123 -- .../metrics/PlaceholderConfig.scala | 37 - .../feature/featurestorev1/BUILD | 14 - .../FeatureStoreV1QueryUserIdFeature.scala | 46 - ...yUserIdTweetCandidateAuthorIdFeature.scala | 68 -- ...ryUserIdTweetCandidateTweetIdFeature.scala | 66 - ...StoreV1TweetCandidateAuthorIdFeature.scala | 60 - ...eStoreV1TweetCandidateTweetIdFeature.scala | 58 - ...ureStoreV1UserCandidateUserIdFeature.scala | 40 - .../component_library/feature_hydrator/BUILD | 35 - ...erBrandSafetySettingsFeatureHydrator.scala | 52 - .../feature_hydrator/candidate/ads/BUILD | 21 - .../candidate/decay/BUILD.bazel | 16 - .../decay/DecayCandidateFeatureHydrator.scala | 65 - .../candidate/param_gated/BUILD | 25 - ...ramGatedBulkCandidateFeatureHydrator.scala | 51 - .../ParamGatedCandidateFeatureHydrator.scala | 51 - .../param_gated/featurestorev1/BUILD | 27 - ...atureStoreV1CandidateFeatureHydrator.scala | 58 - .../candidate/qualityfactor_gated/BUILD.bazel | 14 - ...yFactorGatedCandidateFeatureHydrator.scala | 59 - .../candidate/tweet_is_nsfw/BUILD | 37 - .../TweetIsNsfwCandidateFeatureHydrator.scala | 109 -- .../candidate/tweet_tlx/BUILD.bazel | 42 - ...weetTLXScoreCandidateFeatureHydrator.scala | 59 - .../candidate/tweet_tweetypie/BUILD | 29 - ...eetTweetypieCandidateFeatureHydrator.scala | 241 ---- .../candidate/tweet_visibility_reason/BUILD | 31 - ...tyReasonBulkCandidateFeatureHydrator.scala | 98 -- .../async/AsyncQueryFeatureHydrator.scala | 97 -- .../feature_hydrator/query/async/BUILD | 23 - .../query/cr_ml_ranker/BUILD.bazel | 19 - ...CrMlRankerCommonQueryFeatureHydrator.scala | 37 - ...kerCommonQueryFeatureHydratorBuilder.scala | 18 - .../cr_ml_ranker/RankingConfigBuilder.scala | 11 - .../query/impressed_tweets/BUILD | 23 - .../ImpressedTweetsQueryFeatureHydrator.scala | 57 - .../query/logged_in_only/BUILD | 25 - .../LoggedInOnlyQueryFeatureHydrator.scala | 31 - .../AsyncParamGatedQueryFeatureHydrator.scala | 48 - .../feature_hydrator/query/param_gated/BUILD | 25 - .../ParamGatedQueryFeatureHydrator.scala | 39 - ...edFeatureStoreV1QueryFeatureHydrator.scala | 53 - .../query/param_gated/featurestorev1/BUILD | 27 - ...edFeatureStoreV1QueryFeatureHydrator.scala | 47 - .../query/qualityfactor_gated/BUILD.bazel | 14 - ...alityFactorGatedQueryFeatureHydrator.scala | 54 - ...daptiveLongIntBloomFilterDedupFilter.scala | 40 - .../component_library/filter/BUILD | 30 - .../filter/ExcludedIdsFilter.scala | 28 - .../filter/FeatureFilter.scala | 63 - .../FeatureValueConditionalFilter.scala | 64 - .../filter/HasAuthorIdFeatureFilter.scala | 27 - .../filter/ParamGatedFilter.scala | 41 - .../filter/PredicateFilter.scala | 63 - .../filter/SnowflakeIdAgeFilter.scala | 42 - .../filter/TweetAuthorCountryFilter.scala | 47 - .../filter/TweetAuthorIsSelfFilter.scala | 37 - .../filter/TweetIsNotReplyFilter.scala | 36 - .../filter/TweetLanguageFilter.scala | 40 - .../filter/TweetVisibilityFilter.scala | 71 -- .../UrtUnorderedExcludeIdsCursorFilter.scala | 32 - .../filter/list_visibility/BUILD.bazel | 17 - .../ListVisibilityFilter.scala | 52 - .../filter/tweet_impression/BUILD.bazel | 14 - .../TweetImpressionFilter.scala | 37 - .../component_library/gate/BUILD | 16 - .../gate/DefinedCountryCodeGate.scala | 13 - .../component_library/gate/FeatureGate.scala | 83 -- .../gate/FirstPageGate.scala | 19 - .../gate/NoCandidatesGate.scala | 21 - .../gate/NonEmptyAdsQueryStringGate.scala | 16 - .../gate/NonEmptyCandidatesGate.scala | 22 - .../gate/QualityFactorGate.scala | 25 - .../AnyCandidatesWithoutFeatureGate.scala | 34 - .../BUILD.bazel | 13 - .../model/candidate/ArticleCandidate.scala | 77 -- .../model/candidate/AudioSpaceCandidate.scala | 75 -- .../component_library/model/candidate/BUILD | 13 - .../model/candidate/CardCandidate.scala | 75 -- .../candidate/CommerceItemCandidate.scala | 160 --- .../model/candidate/CursorCandidate.scala | 87 -- .../model/candidate/DMConvoCandidate.scala | 160 --- .../model/candidate/DMEventCandidate.scala | 152 --- .../candidate/GenericSummaryCandidate.scala | 75 -- .../model/candidate/LabelCandidate.scala | 72 -- .../candidate/MomentAnnotationCandidate.scala | 86 -- .../model/candidate/PromptCandidate.scala | 433 ------- .../model/candidate/ShowAlertCandidate.scala | 80 -- .../model/candidate/TopicCandidate.scala | 159 --- .../model/candidate/TweetCandidate.scala | 93 -- .../candidate/TwitterListCandidate.scala | 74 -- .../model/candidate/UserCandidate.scala | 87 -- .../model/candidate/ads/AdsCandidate.scala | 95 -- .../model/candidate/ads/BUILD | 22 - .../hubble/AdCreativeCandidate.scala | 91 -- .../candidate/hubble/AdGroupCandidate.scala | 86 -- .../candidate/hubble/AdUnitCandidate.scala | 86 -- .../model/candidate/hubble/BUILD | 15 - .../candidate/hubble/CampaignCandidate.scala | 76 -- .../hubble/FundingSourceCandidate.scala | 83 -- .../model/candidate/suggestion/BUILD | 17 - .../suggestion/QuerySuggestionCandidate.scala | 296 ----- .../SpellingSuggestionCandidate.scala | 93 -- .../model/candidate/trends_events/BUILD | 17 - .../UnifiedTrendEventCandidate.scala | 119 -- .../component_library/model/cursor/BUILD | 19 - .../model/cursor/OrderedCursor.scala | 30 - .../model/cursor/PassThroughCursor.scala | 35 - .../cursor/UnorderedBloomFilterCursor.scala | 25 - .../cursor/UnorderedExcludeIdsCursor.scala | 30 - .../model/cursor/UrtPlaceholderCursor.scala | 17 - .../flexible_injection_pipeline/BUILD.bazel | 22 - .../model/presentation/slice/BUILD | 15 - .../slice/SliceItemPresentation.scala | 7 - .../model/presentation/urt/BUILD | 13 - .../urt/ConversationModuleItem.scala | 10 - .../urt/UrtItemPresentation.scala | 10 - .../urt/UrtModulePresentation.scala | 8 - .../urt/UrtOperationPresentation.scala | 8 - .../model/query/ads/AdsQuery.scala | 59 - .../component_library/model/query/ads/BUILD | 17 - .../AccountRecommendationsMixerModule.scala | 60 - .../component_library/module/BUILD | 72 -- .../module/ConversationServiceModule.scala | 42 - .../module/CrMixerClientModule.scala | 33 - .../module/DarkTrafficFilterModule.scala | 27 - .../module/EarlybirdModule.scala | 60 - .../module/ExploreRankerClientModule.scala | 38 - .../FollowRecommenderServiceModule.scala | 34 - .../module/GizmoduckClientModule.scala | 47 - .../module/HomeScorerClientModule.scala | 33 - .../InterestsDiscoveryServiceModule.scala | 34 - .../module/OnboardingTaskServiceModule.scala | 30 - .../module/PeopleDiscoveryServiceModule.scala | 42 - .../module/SocialGraphServiceModule.scala | 36 - .../module/TimelineMixerClientModule.scala | 33 - .../module/TimelineRankerClientModule.scala | 47 - .../module/TimelineScorerClientModule.scala | 33 - .../module/TimelineServiceClientModule.scala | 44 - .../module/TweetImpressionStoreModule.scala | 66 - .../module/TweetyPieClientModule.scala | 58 - .../module/UserSessionStoreModule.scala | 74 -- .../module/cr_ml_ranker/BUILD.bazel | 13 - .../cr_ml_ranker/CrMlRankerModule.scala | 39 - .../component_library/module/http/BUILD | 30 - .../module/http/FinagleHttpClientModule.scala | 69 -- ...eHttpClientWithCredentialProxyModule.scala | 75 -- .../FinagleHttpClientWithProxyModule.scala | 81 -- .../module/http/FinatraHttpClientModule.scala | 79 -- ...aHttpClientWithCredentialProxyModule.scala | 93 -- .../FinatraHttpClientWithProxyModule.scala | 89 -- .../module/http/ProxyCredentialsModule.scala | 27 - .../ads/AdsCandidatePipelineConfig.scala | 56 - .../AdsCandidatePipelineConfigBuilder.scala | 56 - ...AdsCandidatePipelineQueryTransformer.scala | 79 -- ...sCandidatePipelineResultsTransformer.scala | 39 - .../AdsDependentCandidatePipelineConfig.scala | 60 - ...endentCandidatePipelineConfigBuilder.scala | 58 - ...entCandidatePipelineQueryTransformer.scala | 33 - .../ads/AdsDisplayLocationBuilder.scala | 16 - .../pipeline/candidate/ads/BUILD | 22 - .../candidate/ads/CountNumOrganicItems.scala | 54 - .../candidate/ads/GetOrganicItemIds.scala | 29 - .../ads/PromotedTweetsOnlyFilter.scala | 39 - .../ads/ValidAdImpressionIdFilter.scala | 24 - .../flexible_injection_pipeline/BUILD.bazel | 23 - .../FlipPromptCandidatePipelineConfig.scala | 67 - ...PromptCandidatePipelineConfigBuilder.scala | 35 - ...omptDependentCandidatePipelineConfig.scala | 69 -- ...endentCandidatePipelineConfigBuilder.scala | 35 - .../transformer/BUILD | 22 - .../FlipCandidateFeatureTransformer.scala | 37 - .../transformer/FlipInjectionParams.scala | 11 - .../transformer/FlipQueryTransformer.scala | 62 - .../PromptResultsTransformer.scala | 54 - .../who_to_follow_module/BUILD.bazel | 20 - .../WhoToFollowArmCandidateDecorator.scala | 82 -- ...hoToFollowArmCandidatePipelineConfig.scala | 10 - ...ArmCandidatePipelineQueryTransformer.scala | 72 -- ...wArmDependentCandidatePipelineConfig.scala | 76 -- ...endentCandidatePipelineConfigBuilder.scala | 66 - ...oFollowArmResponseFeatureTransformer.scala | 38 - .../WhoToFollowCandidateDecorator.scala | 89 -- .../WhoToFollowCandidatePipelineConfig.scala | 77 -- ...FollowCandidatePipelineConfigBuilder.scala | 69 -- ...lowCandidatePipelineQueryTransformer.scala | 39 - ...WhoToFollowClientEventDetailsBuilder.scala | 67 - ...llowDependentCandidatePipelineConfig.scala | 75 -- ...endentCandidatePipelineConfigBuilder.scala | 70 -- ...hoToFollowResponseFeatureTransformer.scala | 39 - .../premarshaller/cursor/BUILD | 25 - .../cursor/CursorSerializer.scala | 149 --- .../cursor/UrtCursorSerializer.scala | 161 --- .../premarshaller/slice/BUILD | 25 - .../slice/SliceDomainMarshaller.scala | 96 -- .../premarshaller/slice/builder/BUILD | 19 - .../builder/OrderedNextCursorBuilder.scala | 38 - .../builder/OrderedNextCursorUpdater.scala | 28 - .../OrderedPreviousCursorBuilder.scala | 40 - .../OrderedPreviousCursorUpdater.scala | 30 - .../slice/builder/ShouldInclude.scala | 16 - .../slice/builder/SliceBuilder.scala | 62 - .../slice/builder/SliceCursorBuilder.scala | 24 - .../slice/builder/SliceCursorUpdater.scala | 58 - .../component_library/premarshaller/urp/BUILD | 21 - .../urp/UrpDomainMarshaller.scala | 52 - .../premarshaller/urp/builder/BUILD | 16 - .../urp/builder/PageBodyBuilder.scala | 18 - .../urp/builder/PageHeaderBuilder.scala | 18 - .../urp/builder/PageNavBarBuilder.scala | 18 - .../StaticTimelineScribeConfigBuilder.scala | 19 - .../builder/TimelineScribeConfigBuilder.scala | 22 - .../component_library/premarshaller/urt/BUILD | 27 - .../urt/UndecoratedUrtDomainMarshaller.scala | 148 --- .../urt/UrtDomainMarshaller.scala | 112 -- .../AddEntriesInstructionBuilder.scala | 19 - ...iesWithAddToModuleInstructionBuilder.scala | 33 - ...thPinnedAndReplaceInstructionBuilder.scala | 31 - ...eplaceAndShowAlertInstructionBuilder.scala | 25 - ...EntriesWithReplaceInstructionBuilder.scala | 31 - ...triesWithShowCoverInstructionBuilder.scala | 29 - .../AddToModuleInstructionBuilder.scala | 37 - .../premarshaller/urt/builder/BUILD | 29 - ...orderedExcludeIdsBottomCursorBuilder.scala | 49 - .../ClearCacheInstructionBuilder.scala | 16 - .../FeaturePassThroughCursorBuilder.scala | 33 - .../urt/builder/IncludeInstruction.scala | 31 - .../MarkUnreadInstructionBuilder.scala | 32 - .../builder/OrderedBottomCursorBuilder.scala | 45 - .../urt/builder/OrderedGapCursorBuilder.scala | 54 - .../urt/builder/OrderedTopCursorBuilder.scala | 52 - .../builder/PinEntryInstructionBuilder.scala | 23 - .../builder/PlaceholderTopCursorBuilder.scala | 34 - .../ReplaceEntryInstructionBuilder.scala | 63 - .../builder/ShowAlertInstructionBuilder.scala | 23 - .../builder/ShowCoverInstructionBuilder.scala | 24 - .../StaticTimelineScribeConfigBuilder.scala | 15 - .../builder/TerminateInstructionBuilder.scala | 44 - .../builder/TimelineScribeConfigBuilder.scala | 18 - ...rderedBloomFilterBottomCursorBuilder.scala | 43 - ...orderedExcludeIdsBottomCursorBuilder.scala | 26 - ...eredExcludeIdsSeqBottomCursorBuilder.scala | 30 - .../urt/builder/UrtBuilder.scala | 94 -- .../urt/builder/UrtCursorBuilder.scala | 134 -- .../urt/builder/UrtCursorUpdater.scala | 44 - .../urt/builder/UrtInstructionBuilder.scala | 15 - .../urt/builder/UrtMetadataBuilder.scala | 43 - .../component_library/scorer/common/BUILD | 30 - .../common/MLModelInferenceClient.scala | 12 - .../scorer/common/ManagedModelClient.scala | 33 - .../scorer/common/ModelSelector.scala | 28 - .../scorer/common/NaviModelClient.scala | 50 - .../component_library/scorer/cortex/BUILD | 35 - ...agedInferenceServiceDataRecordScorer.scala | 137 --- ...erenceServiceDataRecordScorerBuilder.scala | 67 - ...xManagedInferenceServiceTensorScorer.scala | 97 -- ...dInferenceServiceTensorScorerBuilder.scala | 47 - .../scorer/cortex/ModelFeatureExtractor.scala | 15 - .../scorer/cr_ml_ranker/BUILD.bazel | 18 - .../cr_ml_ranker/CrMlRankerScorer.scala | 52 - .../cr_ml_ranker/CrMlRankerStitchClient.scala | 79 -- .../component_library/scorer/deepbird/BUILD | 42 - .../deepbird/BaseDeepbirdV2Scorer.scala | 91 -- .../DeepbirdV2PredictionServerScorer.scala | 55 - .../LollyPredictionEngineScorer.scala | 61 - .../TensorflowPredictionEngineScorer.scala | 58 - .../scorer/param_gated/BUILD | 16 - .../scorer/param_gated/ParamGatedScorer.scala | 43 - .../scorer/qualityfactor_gated/BUILD | 16 - .../QualityFactorGatedScorer.scala | 59 - .../scorer/tensorbuilder/BUILD | 21 - .../BooleanInferInputTensorBuilder.scala | 13 - .../BytesInferInputTensorBuilder.scala | 13 - .../CandidateInferInputTensorBuilder.scala | 70 -- .../Float32InferInputTensorBuilder.scala | 27 - .../FloatTensorInferInputTensorBuilder.scala | 33 - .../InferInputTensorBuilder.scala | 151 --- .../Int64InferInputTensorBuilder.scala | 26 - .../ModelInferRequestBuilder.scala | 40 - .../QueryInferInputTensorBuilder.scala | 61 - .../SparseMapInferInputTensorBuilder.scala | 61 - .../scorer/tweet_tlx/BUILD.bazel | 26 - .../tweet_tlx/TweetTLXStratoScorer.scala | 58 - .../tweet_tlx/TweetTLXThriftScorer.scala | 79 -- .../component_library/selector/BUILD | 47 - .../component_library/selector/Bucketer.scala | 20 - .../selector/CandidateMergeStrategy.scala | 82 -- .../selector/CandidatePositionInResults.scala | 33 - .../selector/DeduplicationKey.scala | 33 - .../selector/DropAllCandidates.scala | 29 - .../selector/DropDuplicateCandidates.scala | 45 - .../DropDuplicateModuleItemCandidates.scala | 88 -- .../selector/DropDuplicateResults.scala | 46 - .../selector/DropFilteredCandidates.scala | 48 - .../DropFilteredModuleItemCandidates.scala | 50 - .../selector/DropMaxCandidates.scala | 84 -- .../DropMaxModuleItemCandidates.scala | 54 - .../selector/DropMaxResults.scala | 40 - .../DropModuleTooFewModuleItemResults.scala | 46 - .../selector/DropNonDuplicateCandidates.scala | 75 -- .../selector/DropOrthogonalCandidates.scala | 54 - ...DropRequestedMaxModuleItemCandidates.scala | 68 -- .../selector/DropRequestedMaxResults.scala | 55 - .../selector/DropSelector.scala | 111 -- .../selector/DropTooFewResults.scala | 35 - .../selector/DynamicPositionSelector.scala | 124 -- .../InsertAppendIntoModuleCandidates.scala | 56 - .../selector/InsertAppendPatternResults.scala | 105 -- .../selector/InsertAppendRatioResults.scala | 171 --- .../selector/InsertAppendResults.scala | 53 - .../selector/InsertAppendWeaveResults.scala | 120 -- .../InsertAppendWithoutFeatureResults.scala | 35 - .../InsertDynamicPositionResults.scala | 69 -- ...ertFixedPositionIntoModuleCandidates.scala | 69 -- .../selector/InsertFixedPositionResults.scala | 46 - .../selector/InsertIntoModule.scala | 70 -- ...rtPerCandidateDynamicPositionResults.scala | 78 -- .../InsertRandomPositionResults.scala | 139 --- .../InsertRelativePositionResults.scala | 58 - .../selector/InsertSelector.scala | 39 - .../selector/SelectConditionally.scala | 85 -- .../SelectFromSubpoolCandidates.scala | 147 --- .../selector/UpdateSortCandidates.scala | 86 -- .../UpdateSortModuleItemCandidates.scala | 96 -- .../selector/UpdateSortResults.scala | 43 - .../selector/ads/AdsInjector.scala | 73 -- .../selector/ads/BUILD.bazel | 30 - .../selector/ads/InsertAdResults.scala | 95 -- .../component_library/selector/sorter/BUILD | 20 - .../selector/sorter/FeatureValueSorter.scala | 248 ---- .../selector/sorter/RandomShuffleSorter.scala | 16 - .../selector/sorter/ReverseSorter.scala | 14 - .../selector/sorter/SortOrder.scala | 5 - .../selector/sorter/SorterFromOrdering.scala | 25 - .../selector/sorter/SorterProvider.scala | 40 - .../selector/sorter/featurestorev1/BUILD | 18 - .../FeatureStoreV1FeatureValueSorter.scala | 98 -- .../component_library/side_effect/BUILD | 30 - .../KafkaPublishingSideEffect.scala | 233 ---- .../ParamGatedPipelineResultSideEffect.scala | 76 -- .../ScribeClientEventSideEffect.scala | 118 -- .../ScribeLogEventAsyncSideEffect.scala | 58 - .../ScribeLogEventSideEffect.scala | 58 - .../side_effect/StratoInsertSideEffect.scala | 70 -- .../UserSessionStoreUpdateSideEffect.scala | 35 - .../side_effect/metrics/BUILD.bazel | 18 - .../metrics/CandidateMetricFunction.scala | 59 - .../ScribeClientEventMetricsSideEffect.scala | 74 -- ...eClientEventMetricsSideEffectBuilder.scala | 84 -- .../core/product/guice/scope/BUILD | 8 - .../product/guice/scope/ProductScoped.java | 14 - .../core/controllers/AlertConfig.scala | 38 - .../product_mixer/core/controllers/BUILD | 39 - .../controllers/DebugTwitterContext.scala | 55 - .../GetComponentRegistryHandler.scala | 114 -- .../GetDebugConfigurationHandler.scala | 60 - .../core/controllers/PredicateConfig.scala | 22 - .../controllers/ProductMixerController.scala | 79 -- .../QualityFactorMonitoringConfig.scala | 6 - .../twitter/product_mixer/core/feature/BUILD | 10 - .../product_mixer/core/feature/Feature.scala | 74 -- .../core/feature/datarecord/BUILD | 21 - .../datarecord/DataRecordCompatible.scala | 316 ----- .../datarecord/DataRecordFeature.scala | 42 - .../core/feature/featuremap/BUILD | 16 - .../core/feature/featuremap/FeatureMap.scala | 195 --- .../featuremap/FeatureMapBuilder.scala | 110 -- .../featuremap/FeatureMapException.scala | 12 - .../featuremap/FeatureMapSerializer.scala | 63 - .../asyncfeaturemap/AsyncFeatureMap.scala | 134 -- .../AsyncFeatureMapSerializer.scala | 45 - .../feature/featuremap/asyncfeaturemap/BUILD | 18 - .../core/feature/featuremap/datarecord/BUILD | 23 - .../datarecord/DataRecordConverter.scala | 51 - .../datarecord/DataRecordExtractor.scala | 60 - .../featuremap/datarecord/FeaturesScope.scala | 157 --- .../feature/featuremap/featurestorev1/BUILD | 17 - .../FeatureStoreV1FeatureMap.scala | 191 --- .../core/feature/featurestorev1/BUILD | 29 - .../featurestorev1/FeatureStoreV1Entity.scala | 35 - .../FeatureStoreV1Feature.scala | 312 ----- .../feature/featurestorev1/featurevalue/BUILD | 19 - .../featurevalue/FeatureStoreV1Response.scala | 39 - .../functional_component/access_policy/BUILD | 9 - .../candidate_source/BUILD | 21 - .../candidate_source/CandidateSource.scala | 50 - .../CandidatesWithSourceFeatures.scala | 16 - .../PassthroughCandidateSource.scala | 59 - .../StaticCandidateSource.scala | 15 - .../candidate_source/product_pipeline/BUILD | 23 - .../ProductPipelineCandidateSource.scala | 71 -- .../candidate_source/strato/BUILD | 21 - .../strato/StratoErrCategorizer.scala | 21 - .../strato/StratoKeyFetcherSeqSource.scala | 27 - .../strato/StratoKeyFetcherSource.scala | 45 - ...toKeyFetcherWithSourceFeaturesSource.scala | 65 - .../strato/StratoKeyView.scala | 4 - .../StratoKeyViewFetcherSeqSource.scala | 30 - .../strato/StratoKeyViewFetcherSource.scala | 51 - ...yViewFetcherWithSourceFeaturesSource.scala | 75 -- .../core/functional_component/common/BUILD | 15 - .../common/CandidateScope.scala | 98 -- .../common/access_policy/AccessPolicy.scala | 38 - .../access_policy/AccessPolicyEvaluator.scala | 12 - .../common/access_policy/BUILD | 15 - .../WithDebugAccessPolicies.scala | 10 - .../common/alert/Alert.scala | 31 - .../common/alert/AlertType.scala | 25 - .../functional_component/common/alert/BUILD | 21 - .../common/alert/EmptyResponseRateAlert.scala | 27 - .../alert/GenericClientLatencyAlert.scala | 19 - .../alert/GenericClientSuccessRateAlert.scala | 29 - .../alert/GenericClientThroughputAlert.scala | 25 - .../common/alert/IsObservableFromStrato.scala | 10 - .../common/alert/LatencyAlert.scala | 20 - .../common/alert/NotificationGroup.scala | 36 - .../common/alert/Percentile.scala | 17 - .../common/alert/ResponseSizeAlert.scala | 27 - .../common/alert/Source.scala | 47 - .../common/alert/StratoColumnAlert.scala | 34 - .../common/alert/SuccessRateAlert.scala | 27 - .../common/alert/ThroughputAlert.scala | 24 - .../common/alert/predicate/BUILD | 13 - .../alert/predicate/MetricGranularity.scala | 35 - .../common/alert/predicate/Operator.scala | 14 - .../common/alert/predicate/Predicate.scala | 52 - .../alert/predicate/TriggerIfAbove.scala | 15 - .../alert/predicate/TriggerIfBelow.scala | 15 - .../predicate/TriggerIfLatencyAbove.scala | 22 - .../core/functional_component/configapi/BUILD | 25 - .../configapi/ConfigBuilder.scala | 17 - .../configapi/ParamsBuilder.scala | 34 - .../configapi/RequestContext.scala | 19 - .../configapi/RequestContextBuilder.scala | 72 -- .../configapi/StaticParam.scala | 6 - .../configapi/registry/BUILD | 23 - .../registry/GlobalParamConfig.scala | 7 - .../registry/GlobalParamRegistry.scala | 21 - .../configapi/registry/ParamConfig.scala | 74 -- .../registry/ParamConfigBuilder.scala | 49 - .../core/functional_component/decorator/BUILD | 37 - .../decorator/CandidateDecorator.scala | 61 - .../decorator/Decoration.scala | 11 - .../decorator/slice/builder/BUILD | 21 - .../builder/CandidateSliceItemBuilder.scala | 14 - .../decorator/urt/builder/BUILD | 27 - .../builder/CandidateUrtEntryBuilder.scala | 14 - .../builder/icon/BaseHorizonIconBuilder.scala | 14 - .../item/alert/BaseDurationBuilder.scala | 11 - ...seShowAlertColorConfigurationBuilder.scala | 15 - .../BaseShowAlertDisplayLocationBuilder.scala | 15 - .../BaseShowAlertIconDisplayInfoBuilder.scala | 15 - ...seShowAlertNavigationMetadataBuilder.scala | 15 - .../alert/BaseShowAlertUserIdsBuilder.scala | 10 - .../topic/BaseTopicDisplayTypeBuilder.scala | 15 - .../BaseTopicFunctionalityTypeBuilder.scala | 15 - .../tweet/BaseEntryIdToReplaceBuilder.scala | 14 - .../tweet/BaseTimelinesScoreInfoBuilder.scala | 15 - .../tweet/BaseTweetHighlightsBuilder.scala | 15 - .../BaseUserReactiveTriggersBuilder.scala | 15 - .../BaseClientEventDetailsBuilder.scala | 19 - .../metadata/BaseClientEventInfoBuilder.scala | 20 - .../BaseFeedbackActionInfoBuilder.scala | 15 - .../urt/builder/metadata/BaseModuleStr.scala | 10 - .../urt/builder/metadata/BaseStr.scala | 10 - .../urt/builder/metadata/BaseUrlBuilder.scala | 11 - .../BasePromotedMetadataBuilder.scala | 15 - .../richtext/BaseRichTextBuilder.scala | 11 - .../BaseModuleSocialContextBuilder.scala | 14 - .../BaseSocialContextBuilder.scala | 15 - ...ModuleStringCenterPlaceholderBuilder.scala | 12 - .../BaseStringCenterPlaceholderBuilder.scala | 12 - .../BaseModuleDisplayTypeBuilder.scala | 14 - .../BaseModuleFooterBuilder.scala | 14 - .../BaseModuleHeaderBuilder.scala | 14 - .../BaseModuleHeaderDisplayTypeBuilder.scala | 16 - .../BaseModuleMetadataBuilder.scala | 14 - .../BaseModuleShowMoreBehaviorBuilder.scala | 14 - .../BaseTimelineModuleBuilder.scala | 14 - .../feature_hydrator/BUILD | 21 - .../CandidateFeatureHydrator.scala | 96 -- .../feature_hydrator/FeatureHydrator.scala | 9 - .../HydratorCandidateResult.scala | 10 - .../QueryFeatureHydrator.scala | 79 -- .../feature_hydrator/featurestorev1/BUILD | 24 - .../FeatureStoreDatasetErrorHandler.scala | 74 -- ...atureStoreV1CandidateFeatureHydrator.scala | 97 -- .../FeatureStoreV1DynamicClientBuilder.scala | 12 - .../FeatureStoreV1HydrationConfig.scala | 25 - .../FeatureStoreV1QueryFeatureHydrator.scala | 79 -- .../core/functional_component/filter/BUILD | 21 - .../functional_component/filter/Filter.scala | 67 - .../filter/FilterResult.scala | 4 - .../core/functional_component/gate/BUILD | 21 - .../core/functional_component/gate/Gate.scala | 127 -- .../gate/GateResult.scala | 47 - .../gate/ShouldContinue.scala | 7 - .../functional_component/marshaller/BUILD | 17 - .../marshaller/TransportMarshaller.scala | 42 - .../marshaller/request/BUILD | 17 - .../request/ClientContextMarshaller.scala | 27 - .../request/ClientContextUnmarshaller.scala | 30 - .../request/FeatureValueUnmarshaller.scala | 31 - .../response/graphql/contextual_ref/BUILD | 21 - .../ContextualTweetRefMarshaller.scala | 17 - .../OuterTweetContextMarshaller.scala | 18 - .../TweetHydrationContextMarshaller.scala | 20 - .../response/rtf/safety_level/BUILD | 17 - .../safety_level/SafetyLevelMarshaller.scala | 24 - .../marshaller/response/slice/BUILD | 16 - .../response/slice/CursorTypeMarshaller.scala | 29 - .../response/slice/SliceItemMarshaller.scala | 147 --- .../slice/SliceTransportMarshaller.scala | 26 - .../marshaller/response/urp/BUILD | 22 - .../response/urp/PageBodyMarshaller.scala | 21 - .../response/urp/PageHeaderMarshaller.scala | 17 - .../response/urp/PageNavBarMarshaller.scala | 21 - .../urp/SegmentedTimelineMarshaller.scala | 21 - .../urp/SegmentedTimelinesMarshaller.scala | 17 - .../response/urp/TimelineKeyMarshaller.scala | 54 - .../response/urp/TitleNavBarMarshaller.scala | 19 - ...TopicPageHeaderDisplayTypeMarshaller.scala | 19 - .../TopicPageHeaderFacepileMarshaller.scala | 18 - .../urp/TopicPageHeaderMarshaller.scala | 25 - .../urp/TopicPageNavBarMarshaller.scala | 18 - .../response/urp/UrpTransportMarshaller.scala | 29 - .../urp/UrpTransportMarshallerBuilder.scala | 65 - .../urt/AddEntriesInstructionMarshaller.scala | 15 - .../AddToModuleInstructionMarshaller.scala | 17 - .../marshaller/response/urt/BUILD | 40 - .../response/urt/CoverMarshaller.scala | 32 - ...rkEntriesUnreadInstructionMarshaller.scala | 13 - .../response/urt/ModuleItemMarshaller.scala | 23 - .../urt/ModuleItemTreeDisplayMarshaller.scala | 20 - .../urt/PinEntryInstructionMarshaller.scala | 15 - .../urt/ReaderModeConfigMarshaller.scala | 17 - .../ReplaceEntryInstructionMarshaller.scala | 26 - .../urt/ShowAlertInstructionMarshaller.scala | 41 - ...rminateTimelineInstructionMarshaller.scala | 22 - .../urt/TimelineEntryContentMarshaller.scala | 25 - .../urt/TimelineEntryMarshaller.scala | 22 - .../urt/TimelineInstructionMarshaller.scala | 50 - .../urt/TimelineItemContentMarshaller.scala | 130 -- .../response/urt/TimelineItemMarshaller.scala | 22 - .../urt/TimelineMetadataMarshaller.scala | 18 - .../urt/TimelineModuleMarshaller.scala | 36 - .../urt/TimelineOperationMarshaller.scala | 24 - .../urt/TimelineScribeConfigMarshaller.scala | 17 - .../response/urt/UrtTransportMarshaller.scala | 101 -- .../urt/UrtTransportMarshallerBuilder.scala | 711 ----------- .../marshaller/response/urt/alert/BUILD | 25 - ...howAlertColorConfigurationMarshaller.scala | 19 - .../ShowAlertDisplayLocationMarshaller.scala | 19 - .../ShowAlertIconDisplayInfoMarshaller.scala | 21 - .../urt/alert/ShowAlertIconMarshaller.scala | 17 - ...howAlertNavigationMetadataMarshaller.scala | 14 - .../urt/alert/ShowAlertTypeMarshaller.scala | 17 - .../marshaller/response/urt/button/BUILD | 21 - .../urt/button/ButtonStyleMarshaller.scala | 29 - .../urt/button/CtaButtonMarshaller.scala | 19 - .../urt/button/IconCtaButtonMarshaller.scala | 21 - .../urt/button/TextCtaButtonMarshaller.scala | 18 - .../marshaller/response/urt/color/BUILD | 17 - .../response/urt/color/ColorMarshaller.scala | 16 - .../urt/color/ColorPaletteMarshaller.scala | 16 - .../urt/color/RosettaColorMarshaller.scala | 48 - .../marshaller/response/urt/cover/BUILD | 28 - .../urt/cover/CoverContentMarshaller.scala | 19 - .../cover/CoverCtaBehaviorMarshaller.scala | 25 - .../urt/cover/CoverCtaMarshaller.scala | 28 - .../urt/cover/CoverImageMarshaller.scala | 23 - .../cover/FullCoverContentMarshaller.scala | 37 - .../FullCoverDisplayTypeMarshaller.scala | 16 - .../cover/HalfCoverContentMarshaller.scala | 33 - .../HalfCoverDisplayTypeMarshaller.scala | 18 - .../marshaller/response/urt/icon/BUILD | 17 - .../urt/icon/HorizonIconMarshaller.scala | 52 - .../marshaller/response/urt/item/BUILD | 28 - .../ArticleDisplayTypeMarshaller.scala | 15 - .../item/article/ArticleItemMarshaller.scala | 23 - .../article/ArticleSeedTypeMarshaller.scala | 20 - .../AudioSpaceItemMarshaller.scala | 17 - .../item/card/CardDisplayTypeMarshaller.scala | 16 - .../urt/item/card/CardItemMarshaller.scala | 25 - .../CommerceProductGroupItemMarshaller.scala | 14 - .../CommerceProductItemMarshaller.scala | 13 - .../ConversationAnnotationMarshaller.scala | 22 - ...ConversationAnnotationTypeMarshaller.scala | 20 - .../EventSummaryDisplayTypeMarshaller.scala | 24 - .../event/EventSummaryItemMarshaller.scala | 27 - .../ForwardPivotDisplayTypeMarshaller.scala | 20 - .../ForwardPivotMarshaller.scala | 35 - ...oftInterventionDisplayTypeMarshaller.scala | 24 - .../GenericSummaryActionMarshaller.scala | 20 - .../GenericSummaryContextMarshaller.scala | 20 - .../GenericSummaryDisplayTypeMarshaller.scala | 18 - .../GenericSummaryItemMarshaller.scala | 33 - .../HighlightedSectionMarshaller.scala | 16 - .../icon_label/IconLabelItemMarshaller.scala | 22 - .../label/LabelDisplayTypeMarshaller.scala | 15 - .../urt/item/label/LabelItemMarshaller.scala | 25 - ...ompactPromptMessageContentMarshaller.scala | 29 - ...rImagePromptMessageContentMarshaller.scala | 33 - ...InlinePromptMessageContentMarshaller.scala | 32 - .../message/MessageActionMarshaller.scala | 25 - .../message/MessageActionTypeMarshaller.scala | 15 - .../message/MessageContentMarshaller.scala | 25 - .../item/message/MessageImageMarshaller.scala | 19 - .../message/MessagePromptItemMarshaller.scala | 23 - .../message/MessageTextActionMarshaller.scala | 17 - .../UserFacepileDisplayTypeMarshaller.scala | 18 - .../item/message/UserFacepileMarshaller.scala | 23 - .../MomentAnnotationItemMarshaller.scala | 20 - .../item/prompt/PromptContentMarshaller.scala | 17 - .../item/prompt/PromptItemMarshaller.scala | 26 - .../RelevancePromptContentMarshaller.scala | 29 - ...RelevancePromptDisplayTypeMarshaller.scala | 18 - ...PromptFollowUpFeedbackTypeMarshaller.scala | 19 - ...ncePromptFollowUpTextInputMarshaller.scala | 20 - .../SpellingActionTypeMarshaller.scala | 16 - .../suggestion/SpellingItemMarshaller.scala | 22 - .../suggestion/TextResultMarshaller.scala | 25 - .../ThreadHeaderContentMarshaller.scala | 14 - .../thread/ThreadHeaderItemMarshaller.scala | 18 - .../CallToActionTileContentMarshaller.scala | 21 - .../tile/StandardTileContentMarshaller.scala | 19 - .../urt/item/tile/TileContentMarshaller.scala | 21 - .../urt/item/tile/TileItemMarshaller.scala | 28 - .../TombstoneDisplayTypeMarshaller.scala | 24 - .../tombstone/TombstoneInfoMarshaller.scala | 18 - .../tombstone/TombstoneItemMarshaller.scala | 23 - .../topic/TopicDisplayTypeMarshaller.scala | 21 - ...picFollowPromptDisplayTypeMarshaller.scala | 21 - .../TopicFollowPromptItemMarshaller.scala | 22 - .../TopicFunctionalityTypeMarshaller.scala | 20 - .../urt/item/topic/TopicItemMarshaller.scala | 26 - .../urt/item/trend/TrendItemMarshaller.scala | 37 - .../tweet/TimelinesScoreInfoMarshaller.scala | 13 - .../tweet/TweetDisplayTypeMarshaller.scala | 25 - .../tweet/TweetHighlightsMarshaller.scala | 22 - .../urt/item/tweet/TweetItemMarshaller.scala | 52 - .../TweetComposerDisplayTypeMarshaller.scala | 18 - .../TweetComposerItemMarshaller.scala | 22 - .../TwitterListDisplayTypeMarshaller.scala | 22 - .../TwitterListItemMarshaller.scala | 19 - .../item/user/UserDisplayTypeMarshaller.scala | 20 - .../urt/item/user/UserItemMarshaller.scala | 28 - .../user/UserReactiveTriggersMarshaller.scala | 17 - .../VerticalGridItemContentMarshaller.scala | 17 - .../VerticalGridItemMarshaller.scala | 18 - .../VerticalGridItemTileStyleMarshaller.scala | 20 - ...ItemTopicFunctionalityTypeMarshaller.scala | 21 - .../VerticalGridItemTopicTileMarshaller.scala | 28 - .../urt/media/AspectRatioMarshaller.scala | 15 - .../marshaller/response/urt/media/BUILD | 17 - .../urt/media/BroadcastIdMarshaller.scala | 14 - .../urt/media/MediaEntityMarshaller.scala | 23 - .../urt/media/MediaKeyMarshaller.scala | 15 - .../response/urt/media/MediaMarshaller.scala | 23 - .../response/urt/media/RectMarshaller.scala | 17 - .../urt/media/TweetMediaMarshaller.scala | 15 - .../metadata/ArticleDetailsMarshaller.scala | 15 - .../marshaller/response/urt/metadata/BUILD | 21 - .../urt/metadata/BadgeMarshaller.scala | 18 - .../urt/metadata/CallbackMarshaller.scala | 14 - .../ChildFeedbackActionMarshaller.scala | 33 - .../ClientEventDetailsMarshaller.scala | 26 - .../metadata/ClientEventInfoMarshaller.scala | 21 - .../metadata/CommerceDetailsMarshaller.scala | 18 - .../ConfirmationDisplayTypeMarshaller.scala | 18 - .../ConversationDetailsMarshaller.scala | 15 - .../ConversationSectionMarshaller.scala | 21 - .../urt/metadata/DismissInfoMarshaller.scala | 13 - .../metadata/FeedbackActionMarshaller.scala | 48 - .../FeedbackDisplayContextMarshaller.scala | 15 - .../urt/metadata/FeedbackInfoMarshaller.scala | 22 - .../urt/metadata/FeedbackTypeMarshaller.scala | 27 - .../metadata/GeneralContextMarshaller.scala | 24 - .../GeneralContextTypeMarshaller.scala | 35 - .../ImageAnimationTypeMarshaller.scala | 16 - .../metadata/ImageDisplayTypeMarshaller.scala | 20 - .../urt/metadata/ImageVariantMarshaller.scala | 19 - .../metadata/LiveEventDetailsMarshaller.scala | 14 - .../RichFeedbackBehaviorMarshaller.scala | 55 - .../metadata/SocialContextMarshaller.scala | 22 - .../metadata/TimelinesDetailsMarshaller.scala | 16 - ...icContextFunctionalityTypeMarshaller.scala | 20 - .../urt/metadata/TopicContextMarshaller.scala | 21 - .../response/urt/metadata/UrlMarshaller.scala | 18 - .../urt/metadata/UrlTypeMarshaller.scala | 19 - .../UrtEndpointOptionsMarshaller.scala | 18 - .../marshaller/response/urt/operation/BUILD | 17 - .../CursorDisplayTreatmentMarshaller.scala | 16 - .../urt/operation/CursorItemMarshaller.scala | 21 - .../operation/CursorOperationMarshaller.scala | 21 - .../urt/operation/CursorTypeMarshaller.scala | 38 - .../AdMetadataContainerMarshaller.scala | 26 - .../marshaller/response/urt/promoted/BUILD | 17 - .../urt/promoted/CallToActionMarshaller.scala | 15 - .../ClickTrackingInfoMarshaller.scala | 18 - .../promoted/DisclaimerTypeMarshaller.scala | 17 - .../promoted/DisclosureTypeMarshaller.scala | 21 - .../DynamicPrerollTypeMarshaller.scala | 20 - .../urt/promoted/MediaInfoMarshaller.scala | 24 - .../urt/promoted/PrerollMarshaller.scala | 19 - .../promoted/PrerollMetadataMarshaller.scala | 16 - .../promoted/PromotedMetadataMarshaller.scala | 35 - .../promoted/SkAdNetworkDataMarshaller.scala | 23 - .../promoted/SponsorshipTypeMarshaller.scala | 19 - .../promoted/UrlOverrideTypeMarshaller.scala | 17 - .../promoted/VideoVariantsMarshaller.scala | 17 - .../marshaller/response/urt/reaction/BUILD | 17 - .../reaction/TimelineReactionMarshaller.scala | 28 - .../marshaller/response/urt/richtext/BUILD | 21 - .../richtext/ReferenceObjectMarshaller.scala | 31 - .../RichTextAlignmentMarshaller.scala | 17 - .../richtext/RichTextEntityMarshaller.scala | 19 - .../richtext/RichTextFormatMarshaller.scala | 17 - .../urt/richtext/RichTextMarshaller.scala | 19 - .../AdsMetadataMarshaller.scala | 13 - .../response/urt/timeline_module/BUILD | 19 - .../GridCarouselMetadataMarshaller.scala | 13 - ...ModuleConversationMetadataMarshaller.scala | 20 - .../ModuleDisplayTypeMarshaller.scala | 29 - .../ModuleFooterMarshaller.scala | 16 - .../ModuleHeaderDisplayTypeMarshaller.scala | 21 - .../ModuleHeaderMarshaller.scala | 26 - .../ModuleMetadataMarshaller.scala | 21 - .../ModuleShowMoreBehaviorMarshaller.scala | 19 - ...wMoreBehaviorRevealByCountMarshaller.scala | 20 - .../functional_component/premarshaller/BUILD | 17 - .../premarshaller/DomainMarshaller.scala | 66 - .../core/functional_component/scorer/BUILD | 23 - .../scorer/ScoredCandidateResult.scala | 13 - .../functional_component/scorer/Scorer.scala | 36 - .../core/functional_component/selector/BUILD | 19 - .../selector/Selector.scala | 24 - .../selector/SelectorResult.scala | 11 - .../functional_component/side_effect/BUILD | 19 - .../side_effect/ExecuteSynchronously.scala | 22 - .../PipelineResultSideEffect.scala | 60 - .../side_effect/SideEffect.scala | 28 - .../functional_component/transformer/BUILD | 23 - .../CandidateFeatureTransformer.scala | 8 - .../CandidatePipelineQueryTransformer.scala | 85 -- .../CandidatePipelineResultsTransformer.scala | 45 - .../transformer/FeatureTransformer.scala | 27 - .../transformer/Transformer.scala | 15 - .../com/twitter/product_mixer/core/gate/BUILD | 15 - .../core/gate/DenyLoggedOutUsersGate.scala | 31 - .../product_mixer/core/gate/ParamGate.scala | 22 - .../core/gate/ParamNotGate.scala | 14 - .../product_mixer/core/model/common/BUILD | 25 - .../model/common/CandidateWithFeatures.scala | 18 - .../core/model/common/Component.scala | 18 - .../core/model/common/Conditionally.scala | 57 - .../core/model/common/UniversalNoun.scala | 8 - .../core/model/common/identifier/BUILD | 15 - .../CandidatePipelineIdentifier.scala | 70 -- .../CandidateSourceIdentifier.scala | 70 -- .../identifier/ComponentIdentifier.scala | 111 -- .../ComponentIdentifierSerializer.scala | 21 - .../identifier/ComponentIdentifierStack.scala | 64 - .../ComponentIdentifierStackSerializer.scala | 14 - .../identifier/DecoratorIdentifier.scala | 70 -- .../DomainMarshallerIdentifier.scala | 70 -- .../FeatureHydratorIdentifier.scala | 70 -- .../common/identifier/FilterIdentifier.scala | 70 -- .../common/identifier/GateIdentifier.scala | 70 -- .../identifier/MixerPipelineIdentifier.scala | 70 -- .../identifier/PipelineStepIdentifier.scala | 90 -- .../identifier/PlatformIdentifier.scala | 70 -- .../common/identifier/ProductIdentifier.scala | 70 -- .../ProductPipelineIdentifier.scala | 70 -- .../RecommendationPipelineIdentifier.scala | 74 -- .../common/identifier/RootIdentifier.scala | 66 - .../common/identifier/ScorerIdentifier.scala | 70 -- .../ScoringPipelineIdentifier.scala | 70 -- .../identifier/SelectorIdentifier.scala | 79 -- .../identifier/SideEffectIdentifier.scala | 70 -- .../identifier/TransformerIdentifier.scala | 70 -- .../TransportMarshallerIdentifier.scala | 70 -- .../core/model/common/presentation/BUILD | 19 - .../presentation/CandidateFeatures.scala | 32 - .../presentation/CandidateWithDetails.scala | 140 --- .../presentation/ItemPresentation.scala | 6 - .../presentation/ModulePresentation.scala | 3 - .../presentation/UniversalPresentation.scala | 16 - .../model/common/presentation/slice/BUILD | 15 - .../slice/BaseSliceItemPresentation.scala | 8 - .../core/model/common/presentation/urt/BUILD | 15 - .../urt/BaseUrtItemPresentation.scala | 9 - .../urt/BaseUrtModulePresentation.scala | 8 - .../urt/BaseUrtOperationPresentation.scala | 9 - .../presentation/urt/IsDispensable.scala | 14 - .../urt/WithItemTreeDisplay.scala | 11 - .../core/model/marshalling/BUILD | 8 - .../model/marshalling/HasMarshalling.scala | 3 - .../core/model/marshalling/request/BUILD | 24 - .../marshalling/request/ClientContext.scala | 94 -- .../marshalling/request/DebugOptions.scala | 15 - .../marshalling/request/DebugParams.scala | 8 - .../marshalling/request/HasExcludedIds.scala | 8 - .../request/HasSerializedRequestCursor.scala | 11 - .../model/marshalling/request/Product.scala | 25 - .../marshalling/request/ProductContext.scala | 7 - .../model/marshalling/request/Request.scala | 10 - .../response/rtf/safety_level/BUILD | 13 - .../rtf/safety_level/SafetyLevel.scala | 13 - .../model/marshalling/response/slice/BUILD | 13 - .../response/slice/SliceItem.scala | 84 -- .../core/model/marshalling/response/urp/BUILD | 15 - .../model/marshalling/response/urp/Page.scala | 12 - .../marshalling/response/urp/PageBody.scala | 10 - .../marshalling/response/urp/PageHeader.scala | 15 - .../marshalling/response/urp/PageNavBar.scala | 19 - .../response/urp/SegmentedTimeline.scala | 10 - .../response/urp/TimelineKey.scala | 32 - .../urp/TopicPageHeaderDisplayType.scala | 6 - .../urp/TopicPageHeaderFacepile.scala | 7 - .../core/model/marshalling/response/urt/BUILD | 24 - .../marshalling/response/urt/Cover.scala | 3 - .../response/urt/EntryNamespace.scala | 50 - .../response/urt/HasEntryIdentifier.scala | 8 - .../response/urt/HasExpirationTime.scala | 9 - .../response/urt/HasSortIndex.scala | 7 - .../response/urt/ModuleItemTreeDisplay.scala | 9 - .../response/urt/ReaderModeConfig.scala | 5 - .../marshalling/response/urt/ShowAlert.scala | 46 - .../marshalling/response/urt/Timeline.scala | 10 - .../response/urt/TimelineEntry.scala | 56 - .../response/urt/TimelineInstruction.scala | 65 - .../response/urt/TimelineMetadata.scala | 6 - .../response/urt/TimelineScribeConfig.scala | 6 - .../marshalling/response/urt/alert/BUILD | 19 - .../alert/ShowAlertColorConfiguration.scala | 9 - .../urt/alert/ShowAlertDisplayLocation.scala | 5 - .../response/urt/alert/ShowAlertIcon.scala | 5 - .../urt/alert/ShowAlertIconDisplayInfo.scala | 5 - .../alert/ShowAlertNavigationMetadata.scala | 3 - .../response/urt/alert/ShowAlertType.scala | 5 - .../marshalling/response/urt/button/BUILD | 15 - .../response/urt/button/ButtonStyle.scala | 12 - .../response/urt/button/CtaButton.scala | 11 - .../marshalling/response/urt/color/BUILD | 8 - .../response/urt/color/Color.scala | 7 - .../response/urt/color/ColorPalette.scala | 5 - .../response/urt/color/RosettaColor.scala | 47 - .../response/urt/contextual_ref/BUILD | 15 - .../contextual_ref/ContextualTweetRef.scala | 5 - .../contextual_ref/OuterTweetContext.scala | 6 - .../TweetHydrationContext.scala | 7 - .../marshalling/response/urt/cover/BUILD | 16 - .../response/urt/cover/CoverContent.scala | 34 - .../response/urt/cover/CoverCta.scala | 14 - .../response/urt/cover/CoverCtaBehavior.scala | 9 - .../response/urt/cover/CoverImage.scala | 10 - .../urt/cover/FullCoverDisplayType.scala | 5 - .../urt/cover/HalfCoverDisplayType.scala | 6 - .../response/urt/cover/ShowCover.scala | 49 - .../model/marshalling/response/urt/icon/BUILD | 9 - .../response/urt/icon/HorizonIcon.scala | 43 - .../model/marshalling/response/urt/item/BUILD | 24 - .../urt/item/article/ArticleDisplayType.scala | 5 - .../urt/item/article/ArticleItem.scala | 26 - .../urt/item/article/ArticleSeedType.scala | 18 - .../urt/item/audio_space/AudioSpaceItem.scala | 22 - .../urt/item/card/CardDisplayType.scala | 7 - .../response/urt/item/card/CardItem.scala | 28 - .../commerce/CommerceProductGroupItem.scala | 23 - .../item/commerce/CommerceProductItem.scala | 23 - .../ConversationAnnotation.scala | 8 - .../ConversationAnnotationType.scala | 6 - .../item/event/EventSummaryDisplayType.scala | 7 - .../urt/item/event/EventSummaryItem.scala | 30 - .../urt/item/forward_pivot/ForwardPivot.scala | 18 - .../ForwardPivotDisplayType.scala | 7 - .../SoftInterventionDisplayType.scala | 8 - .../GenericSummaryAction.scala | 8 - .../GenericSummaryContext.scala | 8 - .../GenericSummaryDisplayType.scala | 5 - .../generic_summary/GenericSummaryItem.scala | 34 - .../item/highlight/HighlightedSection.scala | 3 - .../urt/item/icon_label/IconLabelItem.scala | 26 - .../urt/item/label/LabelDisplayType.scala | 6 - .../response/urt/item/label/LabelItem.scala | 28 - .../urt/item/message/MessageAction.scala | 10 - .../urt/item/message/MessageActionType.scala | 5 - .../urt/item/message/MessageContent.scala | 38 - .../urt/item/message/MessageImage.scala | 7 - .../urt/item/message/MessagePromptItem.scala | 27 - .../urt/item/message/MessageTextAction.scala | 5 - .../urt/item/message/UserFacepile.scala | 9 - .../message/UserFacepileDisplayType.scala | 6 - .../item/moment/MomentAnnotationItem.scala | 33 - .../urt/item/prompt/PromptContent.scala | 28 - .../response/urt/item/prompt/PromptItem.scala | 26 - .../prompt/RelevancePromptDisplayType.scala | 13 - .../RelevancePromptFollowUpFeedbackType.scala | 16 - .../item/suggestion/SpellingActionType.scala | 26 - .../urt/item/suggestion/SpellingItem.scala | 32 - .../urt/item/suggestion/TextResult.scala | 14 - .../urt/item/thread/ThreadHeaderContent.scala | 5 - .../urt/item/thread/ThreadHeaderItem.scala | 24 - .../response/urt/item/tile/TileContent.scala | 21 - .../response/urt/item/tile/TileItem.scala | 29 - .../item/tombstone/TombstoneDisplayType.scala | 9 - .../urt/item/tombstone/TombstoneInfo.scala | 8 - .../urt/item/tombstone/TombstoneItem.scala | 26 - .../urt/item/topic/TopicDisplayType.scala | 8 - .../topic/TopicFollowPromptDisplayType.scala | 6 - .../item/topic/TopicFollowPromptItem.scala | 26 - .../item/topic/TopicFunctionalityType.scala | 7 - .../response/urt/item/topic/TopicItem.scala | 24 - .../response/urt/item/trend/TrendItem.scala | 35 - .../urt/item/tweet/TimelinesScoreInfo.scala | 3 - .../urt/item/tweet/TweetDisplayType.scala | 16 - .../urt/item/tweet/TweetHighlights.scala | 8 - .../response/urt/item/tweet/TweetItem.scala | 62 - .../TweetComposerDisplayType.scala | 6 - .../tweet_composer/TweetComposerItem.scala | 26 - .../twitter_list/TwitterListDisplayType.scala | 8 - .../item/twitter_list/TwitterListItem.scala | 23 - .../urt/item/user/UserDisplayType.scala | 7 - .../response/urt/item/user/UserItem.scala | 30 - .../urt/item/user/UserReactiveTriggers.scala | 5 - .../vertical_grid_item/VerticalGridItem.scala | 29 - .../VerticalGridItemTileStyle.scala | 6 - ...rticalGridItemTopicFunctionalityType.scala | 8 - .../response/urt/media/AspectRatio.scala | 5 - .../marshalling/response/urt/media/BUILD | 13 - .../response/urt/media/Media.scala | 7 - .../response/urt/media/MediaEntity.scala | 14 - .../response/urt/media/MediaKey.scala | 5 - .../marshalling/response/urt/media/Rect.scala | 7 - .../urt/metadata/ArticleDetails.scala | 5 - .../marshalling/response/urt/metadata/BUILD | 17 - .../response/urt/metadata/Badge.scala | 8 - .../response/urt/metadata/Callback.scala | 3 - .../urt/metadata/ClientEventInfo.scala | 29 - .../urt/metadata/CommerceDetails.scala | 8 - .../metadata/ConfirmationDisplayType.scala | 6 - .../urt/metadata/ConversationDetails.scala | 3 - .../urt/metadata/ConversationSection.scala | 8 - .../response/urt/metadata/DismissInfo.scala | 3 - .../urt/metadata/FeedbackAction.scala | 29 - .../urt/metadata/FeedbackActionInfo.scala | 15 - .../response/urt/metadata/FeedbackInfo.scala | 13 - .../response/urt/metadata/FeedbackType.scala | 18 - .../urt/metadata/ImageAnimationType.scala | 5 - .../urt/metadata/ImageDisplayType.scala | 7 - .../response/urt/metadata/ImageVariant.scala | 9 - .../urt/metadata/LiveEventDetails.scala | 3 - .../urt/metadata/MarkUnreadableEntry.scala | 6 - .../response/urt/metadata/PinnableEntry.scala | 5 - .../urt/metadata/ReplaceableEntry.scala | 5 - .../response/urt/metadata/ReplyPinState.scala | 7 - .../urt/metadata/RichFeedbackBehavior.scala | 15 - .../response/urt/metadata/SocialContext.scala | 49 - .../urt/metadata/TimelinesDetails.scala | 6 - .../response/urt/metadata/Url.scala | 17 - .../marshalling/response/urt/operation/BUILD | 15 - .../operation/CursorDisplayTreatment.scala | 5 - .../response/urt/operation/CursorItem.scala | 31 - .../urt/operation/CursorOperation.scala | 31 - .../response/urt/operation/CursorType.scala | 37 - .../urt/promoted/AdMetadataContainer.scala | 11 - .../marshalling/response/urt/promoted/BUILD | 11 - .../response/urt/promoted/CallToAction.scala | 5 - .../urt/promoted/ClickTrackingInfo.scala | 8 - .../urt/promoted/DisclaimerType.scala | 6 - .../urt/promoted/DisclosureType.scala | 8 - .../urt/promoted/DynamicPrerollType.scala | 7 - .../response/urt/promoted/MediaInfo.scala | 11 - .../response/urt/promoted/Preroll.scala | 6 - .../urt/promoted/PrerollMetadata.scala | 5 - .../urt/promoted/PromotedMetadata.scala | 23 - .../urt/promoted/SkAdNetworkData.scala | 13 - .../urt/promoted/SponsorshipType.scala | 7 - .../urt/promoted/UrlOverrideType.scala | 6 - .../response/urt/promoted/VideoVariant.scala | 6 - .../marshalling/response/urt/reaction/BUILD | 11 - .../urt/reaction/TimelineReaction.scala | 5 - .../reaction/TimelineReactionExecution.scala | 10 - .../marshalling/response/urt/richtext/BUILD | 11 - .../urt/richtext/ReferenceObject.scala | 9 - .../response/urt/richtext/RichText.scala | 7 - .../urt/richtext/RichTextAlignment.scala | 6 - .../urt/richtext/RichTextEntity.scala | 7 - .../urt/richtext/RichTextFormat.scala | 13 - .../urt/timeline_module/AdsMetadata.scala | 3 - .../response/urt/timeline_module/BUILD | 13 - .../GridCarouselMetadata.scala | 3 - .../ModuleConversationMetadata.scala | 8 - .../timeline_module/ModuleDisplayType.scala | 12 - .../urt/timeline_module/ModuleFooter.scala | 7 - .../urt/timeline_module/ModuleHeader.scala | 13 - .../ModuleHeaderDisplayType.scala | 7 - .../urt/timeline_module/ModuleMetadata.scala | 11 - .../ModuleShowMoreBehavior.scala | 8 - .../core/module/ABDeciderModule.scala | 51 - .../twitter/product_mixer/core/module/BUILD | 49 - .../core/module/ConfigApiModule.scala | 21 - .../core/module/FeatureSwitchesModule.scala | 53 - .../LoggingThrowableExceptionMapper.scala | 24 - .../PipelineExecutionLoggerModule.scala | 12 - .../core/module/ProductMixerModule.scala | 30 - .../core/module/StratoClientModule.scala | 39 - .../core/module/product_mixer_flags/BUILD | 15 - .../ProductMixerFlagModule.scala | 74 -- .../core/module/stringcenter/BUILD | 25 - .../ProductScopeStringCenterModule.scala | 135 --- .../twitter/product_mixer/core/pipeline/BUILD | 92 -- .../pipeline/CandidatePipelineFeatures.scala | 7 - .../core/pipeline/FailOpenPolicy.scala | 42 - .../pipeline/InvalidStepStateException.scala | 8 - .../pipeline/NewPipelineArrowBuilder.scala | 181 --- .../core/pipeline/NewPipelineBuilder.scala | 31 - .../core/pipeline/NewPipelineResult.scala | 22 - .../core/pipeline/NewStepData.scala | 13 - .../core/pipeline/Pipeline.scala | 46 - .../core/pipeline/PipelineBuilder.scala | 194 --- .../core/pipeline/PipelineConfig.scala | 20 - .../core/pipeline/PipelineCursor.scala | 38 - .../pipeline/PipelineCursorSerializer.scala | 57 - .../core/pipeline/PipelineQuery.scala | 32 - .../core/pipeline/PipelineResult.scala | 59 - .../core/pipeline/candidate/BUILD | 77 -- .../candidate/CandidatePipeline.scala | 30 - .../candidate/CandidatePipelineBuilder.scala | 735 ----------- .../CandidatePipelineBuilderFactory.scala | 56 - .../candidate/CandidatePipelineConfig.scala | 264 ---- .../candidate/CandidatePipelineResult.scala | 93 -- .../PassthroughCandidatePipelineConfig.scala | 47 - .../StaticCandidatePipelineConfig.scala | 51 - .../product_mixer/core/pipeline/mixer/BUILD | 62 - .../core/pipeline/mixer/MixerPipeline.scala | 24 - .../pipeline/mixer/MixerPipelineBuilder.scala | 582 --------- .../mixer/MixerPipelineBuilderFactory.scala | 49 - .../pipeline/mixer/MixerPipelineConfig.scala | 175 --- .../pipeline/mixer/MixerPipelineResult.scala | 70 -- .../core/pipeline/pipeline_failure/BUILD | 14 - .../pipeline_failure/PipelineFailure.scala | 49 - .../PipelineFailureCategory.scala | 190 --- .../PipelineFailureClassifier.scala | 13 - .../PipelineFailureSerializer.scala | 67 - .../product_mixer/core/pipeline/product/BUILD | 51 - .../pipeline/product/ProductPipeline.scala | 28 - .../product/ProductPipelineBuilder.scala | 385 ------ .../ProductPipelineBuilderFactory.scala | 39 - .../product/ProductPipelineConfig.scala | 107 -- .../product/ProductPipelineRequest.scala | 5 - .../product/ProductPipelineResult.scala | 62 - .../core/pipeline/recommendation/BUILD | 62 - .../RecommendationPipeline.scala | 29 - .../RecommendationPipelineBuilder.scala | 1076 ----------------- ...RecommendationPipelineBuilderFactory.scala | 67 - .../RecommendationPipelineConfig.scala | 262 ---- .../RecommendationPipelineResult.scala | 84 -- .../product_mixer/core/pipeline/scoring/BUILD | 36 - .../scoring/NewScoringPipelineBuilder.scala | 202 ---- .../pipeline/scoring/ScoringPipeline.scala | 32 - .../scoring/ScoringPipelineBuilder.scala | 367 ------ .../ScoringPipelineBuilderFactory.scala | 30 - .../scoring/ScoringPipelineConfig.scala | 131 -- .../scoring/ScoringPipelineResult.scala | 51 - .../product_mixer/core/pipeline/state/BUILD | 33 - .../pipeline/state/HasAsyncFeatureMap.scala | 9 - .../core/pipeline/state/HasCandidates.scala | 8 - .../state/HasCandidatesWithDetails.scala | 11 - .../state/HasCandidatesWithFeatures.scala | 9 - .../pipeline/state/HasExecutorResults.scala | 13 - .../core/pipeline/state/HasParams.scala | 7 - .../core/pipeline/state/HasQuery.scala | 8 - .../core/pipeline/state/HasRequest.scala | 7 - .../core/pipeline/state/HasResult.scala | 10 - .../product_mixer/core/pipeline/step/BUILD | 17 - .../core/pipeline/step/Step.scala | 52 - .../AsyncFeatureMapStep.scala | 70 -- .../step/async_feature_map/BUILD.bazel | 36 - .../step/candidate_feature_hydrator/BUILD | 36 - .../CandidateFeatureHydratorStep.scala | 71 -- .../step/candidate_source/BUILD.bazel | 36 - .../CandidateSourceStep.scala | 84 -- .../core/pipeline/step/decorator/BUILD.bazel | 36 - .../step/decorator/DecoratorStep.scala | 63 - .../step/domain_marshaller/BUILD.bazel | 30 - .../DomainMarshallerStep.scala | 54 - .../core/pipeline/step/filter/BUILD.bazel | 36 - .../pipeline/step/filter/FilterStep.scala | 64 - .../core/pipeline/step/gate/BUILD | 36 - .../core/pipeline/step/gate/GateStep.scala | 43 - .../pipeline/step/group_results/BUILD.bazel | 29 - .../step/group_results/GroupResultsStep.scala | 67 - .../step/pipeline_executor/BUILD.bazel | 32 - .../PipelineExecutorStep.scala | 81 -- .../pipeline/step/pipeline_selector/BUILD | 26 - .../PipelineSelectorStep.scala | 43 - .../pipeline/step/quality_factor/BUILD.bazel | 31 - .../quality_factor/QualityFactorStep.scala | 72 -- .../step/query_feature_hydrator/BUILD.bazel | 36 - .../QueryFeatureHydratorStep.scala | 59 - .../step/query_transformer/BUILD.bazel | 29 - .../QueryTransformerStep.scala | 52 - .../core/pipeline/step/scorer/BUILD | 36 - .../pipeline/step/scorer/ScorerStep.scala | 69 -- .../core/pipeline/step/selector/BUILD | 36 - .../pipeline/step/selector/SelectorStep.scala | 53 - .../pipeline/step/side_effect/BUILD.bazel | 32 - .../step/side_effect/SideEffectStep.scala | 102 -- .../step/transport_marshaller/BUILD.bazel | 31 - .../TransportMarshallerStep.scala | 76 -- .../twitter/product_mixer/core/product/BUILD | 21 - .../core/product/ProductParamConfig.scala | 36 - .../product/ProductParamConfigBuilder.scala | 21 - .../product_mixer/core/product/guice/BUILD | 18 - .../core/product/guice/ProductScope.scala | 10 - .../product/guice/ProductScopeModule.scala | 27 - .../core/product/guice/SimpleScope.scala | 68 -- .../product_mixer/core/product/registry/BUILD | 26 - .../registry/ProductParamRegistry.scala | 26 - .../registry/ProductPipelineRegistry.scala | 189 --- .../ProductPipelineRegistryConfig.scala | 9 - .../product_mixer/core/quality_factor/BUILD | 18 - .../core/quality_factor/Bounds.scala | 33 - .../LinearLatencyQualityFactor.scala | 34 - .../LinearLatencyQualityFactorObserver.scala | 18 - .../core/quality_factor/QualityFactor.scala | 33 - .../quality_factor/QualityFactorConfig.scala | 120 -- .../QualityFactorObserver.scala | 18 - .../quality_factor/QualityFactorStatus.scala | 60 - .../QueriesPerSecondBasedQualityFactor.scala | 51 - ...sPerSecondBasedQualityFactorObserver.scala | 21 - .../quality_factor/QueryRateCounter.scala | 21 - .../twitter/product_mixer/core/service/BUILD | 32 - .../product_mixer/core/service/Executor.scala | 700 ----------- .../core/service/ExecutorObserver.scala | 146 --- .../core/service/ExecutorResult.scala | 3 - .../AsyncFeatureMapExecutor.scala | 58 - .../service/async_feature_map_executor/BUILD | 19 - .../candidate_decorator_executor/BUILD | 22 - .../CandidateDecoratorExecutor.scala | 38 - .../CandidateDecoratorExecutorResult.scala | 6 - .../candidate_feature_hydrator_executor/BUILD | 25 - .../CandidateFeatureHydratorExecutor.scala | 277 ----- ...ndidateFeatureHydratorExecutorResult.scala | 20 - .../BUILD | 22 - .../CandidateFeatureTransformerExecutor.scala | 93 -- ...dateFeatureTransformerExecutorResult.scala | 8 - .../service/candidate_pipeline_executor/BUILD | 27 - .../CandidatePipelineExecutor.scala | 82 -- .../CandidatePipelineExecutorResult.scala | 8 - .../service/candidate_source_executor/BUILD | 35 - .../CandidateSourceExecutor.scala | 173 --- .../CandidateSourceExecutorResult.scala | 10 - .../core/service/component_registry/BUILD | 16 - .../ComponentRegistry.scala | 182 --- .../RegisteredComponent.scala | 15 - .../debug_query/AuthorizationService.scala | 82 -- .../core/service/debug_query/BUILD | 20 - .../DebugQueryNotSupportedService.scala | 43 - .../debug_query/DebugQueryService.scala | 109 -- .../debug_query/ParamsSerializerModule.scala | 35 - .../service/domain_marshaller_executor/BUILD | 23 - .../DomainMarshallerExecutor.scala | 44 - .../service/feature_hydrator_observer/BUILD | 21 - .../FeatureHydratorObserver.scala | 136 --- .../core/service/filter_executor/BUILD | 24 - .../filter_executor/FilterExecutor.scala | 172 --- .../FilterExecutorResult.scala | 18 - .../core/service/gate_executor/BUILD | 25 - .../gate_executor/ExecutedGateResult.scala | 6 - .../service/gate_executor/GateExecutor.scala | 107 -- .../gate_executor/GateExecutorResult.scala | 7 - .../gate_executor/StoppedGateException.scala | 29 - .../core/service/group_results_executor/BUILD | 35 - .../GroupResultsExecutor.scala | 122 -- .../AllowListedPipelineExecutionLogger.scala | 183 --- .../service/pipeline_execution_logger/BUILD | 33 - .../PipelineExecutionLogger.scala | 7 - .../core/service/pipeline_executor/BUILD | 25 - .../pipeline_executor/PipelineExecutor.scala | 66 - .../PipelineExecutorResult.scala | 8 - .../BUILD | 24 - .../PipelineResultSideEffectExecutor.scala | 91 -- .../service/pipeline_selector_executor/BUILD | 26 - .../PipelineSelectorExecutor.scala | 48 - .../PipelineSelectorExecutorResult.scala | 5 - .../service/quality_factor_executor/BUILD | 23 - .../QualityFactorExecutorResult.scala | 10 - ...idualFeatureHydratorResultSerializer.scala | 24 - .../query_feature_hydrator_executor/BUILD | 28 - .../QueryFeatureHydratorExecutor.scala | 217 ---- .../service/scoring_pipeline_executor/BUILD | 24 - .../ScoringPipelineExecutor.scala | 172 --- .../ScoringPipelineExecutorResult.scala | 9 - .../core/service/selector_executor/BUILD | 26 - .../selector_executor/SelectorExecutor.scala | 105 -- .../SelectorExecutorResult.scala | 12 - .../product_mixer/core/service/slice/BUILD | 22 - .../core/service/slice/SliceService.scala | 29 - .../core/service/transformer_executor/BUILD | 17 - .../PerCandidateTransformerExecutor.scala | 35 - .../TransformerExecutor.scala | 22 - .../transport_marshaller_executor/BUILD | 23 - .../TransportMarshallerExecutor.scala | 40 - .../product_mixer/core/service/urp/BUILD | 18 - .../core/service/urp/UrpService.scala | 26 - .../product_mixer/core/service/urt/BUILD | 20 - .../core/service/urt/UrtService.scala | 60 - .../com/twitter/product_mixer/core/util/BUILD | 24 - .../product_mixer/core/util/FuturePools.scala | 101 -- .../core/util/OffloadFuturePools.scala | 59 - .../core/util/SortIndexBuilder.scala | 17 - .../shared_library/http_client/BUILD | 22 - .../FinagleHttpClientBuilder.scala | 57 - .../FinagleHttpClientWithProxyBuilder.scala | 97 -- .../http_client/HttpHostPort.scala | 5 - .../shared_library/manhattan_client/BUILD | 24 - .../ManhattanClientBuilder.scala | 116 -- .../shared_library/memcached_client/BUILD | 18 - .../MemcachedClientBuilder.scala | 117 -- .../shared_library/observer/BUILD | 19 - .../shared_library/observer/Observer.scala | 203 ---- .../observer/ResultsObserver.scala | 281 ----- .../observer/ResultsStatsObserver.scala | 243 ---- .../shared_library/thrift_client/BUILD | 20 - .../FinagleThriftClientBuilder.scala | 198 --- 1378 files changed, 59681 deletions(-) delete mode 100644 product-mixer/README.md delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala delete mode 100644 product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala delete mode 100644 product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD delete mode 100644 product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala delete mode 100644 product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD delete mode 100644 product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala diff --git a/product-mixer/README.md b/product-mixer/README.md deleted file mode 100644 index 1852d96c0..000000000 --- a/product-mixer/README.md +++ /dev/null @@ -1,41 +0,0 @@ -Product Mixer -============= - -## Overview - -Product Mixer is a common service framework and set of libraries that make it easy to build, -iterate on, and own product surface areas. It consists of: - -- **Core Libraries:** A set of libraries that enable you to build execution pipelines out of - reusable components. You define your logic in small, well-defined, reusable components and focus - on expressing the business logic you want to have. Then you can define easy to understand pipelines - that compose your components. Product Mixer handles the execution and monitoring of your pipelines - allowing you to focus on what really matters, your business logic. - -- **Service Framework:** A common service skeleton for teams to host their Product Mixer products. - -- **Component Library:** A shared library of components made by the Product Mixer Team, or - contributed by users. This enables you to both easily share the reusable components you make as well - as benefit from the work other teams have done by utilizing their shared components in the library. - -## Architecture - -The bulk of a Product Mixer can be broken down into Pipelines and Components. Components allow you -to break business logic into separate, standardized, reusable, testable, and easily composable -pieces, where each component has a well defined abstraction. Pipelines are essentially configuration -files specifying which Components should be used and when. This makes it easy to understand how your -code will execute while keeping it organized and structured in a maintainable way. - -Requests first go to Product Pipelines, which are used to select which Mixer Pipeline or -Recommendation Pipeline to run for a given request. Each Mixer or Recommendation -Pipeline may run multiple Candidate Pipelines to fetch candidates to include in the response. - -Mixer Pipelines combine the results of multiple heterogeneous Candidate Pipelines together -(e.g. ads, tweets, users) while Recommendation Pipelines are used to score (via Scoring Pipelines) -and rank the results of homogenous Candidate Pipelines so that the top ranked ones can be returned. -These pipelines also marshall candidates into a domain object and then into a transport object -to return to the caller. - -Candidate Pipelines fetch candidates from underlying Candidate Sources and perform some basic -operations on the Candidates, such as filtering out unwanted candidates, applying decorations, -and hydrating features. diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala deleted file mode 100644 index 72698e1c7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/AccountRecommendationsMixerCandidateSource.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer - -import com.twitter.account_recommendations_mixer.{thriftscala => t} -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -object WhoToFollowModuleHeaderFeature extends Feature[UserCandidate, t.Header] -object WhoToFollowModuleFooterFeature extends Feature[UserCandidate, Option[t.Footer]] -object WhoToFollowModuleDisplayOptionsFeature - extends Feature[UserCandidate, Option[t.DisplayOptions]] - -@Singleton -class AccountRecommendationsMixerCandidateSource @Inject() ( - accountRecommendationsMixer: t.AccountRecommendationsMixer.MethodPerEndpoint) - extends CandidateSourceWithExtractedFeatures[ - t.AccountRecommendationsMixerRequest, - t.RecommendedUser - ] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier(name = "AccountRecommendationsMixer") - - override def apply( - request: t.AccountRecommendationsMixerRequest - ): Stitch[CandidatesWithSourceFeatures[t.RecommendedUser]] = { - Stitch - .callFuture(accountRecommendationsMixer.getWtfRecommendations(request)) - .map { response: t.WhoToFollowResponse => - responseToCandidatesWithSourceFeatures( - response.userRecommendations, - response.header, - response.footer, - response.displayOptions) - } - } - - private def responseToCandidatesWithSourceFeatures( - userRecommendations: Seq[t.RecommendedUser], - header: t.Header, - footer: Option[t.Footer], - displayOptions: Option[t.DisplayOptions], - ): CandidatesWithSourceFeatures[t.RecommendedUser] = { - val features = FeatureMapBuilder() - .add(WhoToFollowModuleHeaderFeature, header) - .add(WhoToFollowModuleFooterFeature, footer) - .add(WhoToFollowModuleDisplayOptionsFeature, displayOptions) - .build() - CandidatesWithSourceFeatures(userRecommendations, features) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD deleted file mode 100644 index d5eaef320..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - "stitch/stitch-core", - ], - exports = [ - "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala deleted file mode 100644 index 0509738a0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdStratoCandidateSource.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.ads - -import com.twitter.adserver.thriftscala.AdImpression -import com.twitter.adserver.thriftscala.AdRequestParams -import com.twitter.adserver.thriftscala.AdRequestResponse -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.ads.admixer.MakeAdRequestClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdsProdStratoCandidateSource @Inject() (adsClient: MakeAdRequestClientColumn) - extends StratoKeyFetcherSource[ - AdRequestParams, - AdRequestResponse, - AdImpression - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("AdsProdStrato") - - override val fetcher: Fetcher[AdRequestParams, Unit, AdRequestResponse] = adsClient.fetcher - - override protected def stratoResultTransformer( - stratoResult: AdRequestResponse - ): Seq[AdImpression] = - stratoResult.impressions -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala deleted file mode 100644 index 08df2eb0d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsProdThriftCandidateSource.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.ads - -import com.twitter.adserver.thriftscala.AdImpression -import com.twitter.adserver.thriftscala.AdRequestParams -import com.twitter.adserver.thriftscala.NewAdServer -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdsProdThriftCandidateSource @Inject() ( - adServerClient: NewAdServer.MethodPerEndpoint) - extends CandidateSource[AdRequestParams, AdImpression] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("AdsProdThrift") - - override def apply(request: AdRequestParams): Stitch[Seq[AdImpression]] = - Stitch.callFuture(adServerClient.makeAdRequest(request)).map(_.impressions) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala deleted file mode 100644 index d719f7608..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/AdsStagingCandidateSource.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.ads - -import com.twitter.adserver.thriftscala.AdImpression -import com.twitter.adserver.thriftscala.AdRequestParams -import com.twitter.adserver.thriftscala.AdRequestResponse -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.ads.admixer.MakeAdRequestStagingClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdsStagingCandidateSource @Inject() (adsClient: MakeAdRequestStagingClientColumn) - extends StratoKeyFetcherSource[ - AdRequestParams, - AdRequestResponse, - AdImpression - ] { - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("AdsStaging") - - override val fetcher: Fetcher[AdRequestParams, Unit, AdRequestResponse] = adsClient.fetcher - - override protected def stratoResultTransformer( - stratoResult: AdRequestResponse - ): Seq[AdImpression] = - stratoResult.impressions -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD deleted file mode 100644 index f3b49ec31..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala", - "strato/config/columns/ads/admixer:admixer-strato-client", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala deleted file mode 100644 index 53bbb8d4f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnCandidateSource.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.ann - -import com.twitter.ann.common._ -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import com.twitter.util.{Time => _, _} -import com.twitter.finagle.util.DefaultTimer - -/** - * @param annQueryableById Ann Queryable by Id client that returns nearest neighbors for a sequence of queries - * @param identifier Candidate Source Identifier - * @tparam T1 type of the query. - * @tparam T2 type of the result. - * @tparam P runtime parameters supported by the index. - * @tparam D distance function used in the index. - */ -class AnnCandidateSource[T1, T2, P <: RuntimeParams, D <: Distance[D]]( - val annQueryableById: QueryableById[T1, T2, P, D], - val batchSize: Int, - val timeoutPerRequest: Duration, - override val identifier: CandidateSourceIdentifier) - extends CandidateSource[AnnIdQuery[T1, P], NeighborWithDistanceWithSeed[T1, T2, D]] { - - implicit val timer = DefaultTimer - - override def apply( - request: AnnIdQuery[T1, P] - ): Stitch[Seq[NeighborWithDistanceWithSeed[T1, T2, D]]] = { - val ids = request.ids - val numOfNeighbors = request.numOfNeighbors - val runtimeParams = request.runtimeParams - Stitch - .collect( - ids - .grouped(batchSize).map { batchedIds => - annQueryableById - .batchQueryWithDistanceById(batchedIds, numOfNeighbors, runtimeParams).map { - annResult => annResult.toSeq - }.within(timeoutPerRequest).handle { case _ => Seq.empty } - }.toSeq).map(_.flatten) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala deleted file mode 100644 index b262f6ac4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/AnnIdQuery.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.ann - -import com.twitter.ann.common._ - -/** - * A [[AnnIdQuery]] is a query class which defines the ann entities with runtime params and number of neighbors requested - * - * @param ids Sequence of queries - * @param numOfNeighbors Number of neighbors requested - * @param runtimeParams ANN Runtime Params - * @param batchSize Batch size to the stitch client - * @tparam T type of query. - * @tparam P runtime parameters supported by the index. - */ -case class AnnIdQuery[T, P <: RuntimeParams]( - ids: Seq[T], - numOfNeighbors: Int, - runtimeParams: P) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel deleted file mode 100644 index 46b1efdbb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ann/BUILD.bazel +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "ann/src/main/scala/com/twitter/ann/common", - "ann/src/main/scala/com/twitter/ann/hnsw", - "ann/src/main/thrift/com/twitter/ann/common:ann-common-scala", - "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "servo/manhattan/src/main/scala", - "servo/repo/src/main/scala", - "servo/util/src/main/scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel deleted file mode 100644 index 8b93dea9f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/periscope/audio_space:audio_space-scala", - "strato/config/columns/periscope:periscope-strato-client", - "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala", - "strato/src/main/scala/com/twitter/strato/client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala deleted file mode 100644 index c5b820065..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/audiospace/CreatedSpacesCandidateSource.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.audiospace - -import com.twitter.periscope.audio_space.thriftscala.CreatedSpacesView -import com.twitter.periscope.audio_space.thriftscala.SpaceSlice -import com.twitter.product_mixer.component_library.model.cursor.NextCursorFeature -import com.twitter.product_mixer.component_library.model.cursor.PreviousCursorFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherWithSourceFeaturesSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.periscope.CreatedSpacesSliceOnUserClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CreatedSpacesCandidateSource @Inject() ( - column: CreatedSpacesSliceOnUserClientColumn) - extends StratoKeyViewFetcherWithSourceFeaturesSource[ - Long, - CreatedSpacesView, - SpaceSlice, - String - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("CreatedSpaces") - - override val fetcher: Fetcher[Long, CreatedSpacesView, SpaceSlice] = column.fetcher - - override def stratoResultTransformer( - stratoKey: Long, - stratoResult: SpaceSlice - ): Seq[String] = - stratoResult.items - - override protected def extractFeaturesFromStratoResult( - stratoKey: Long, - stratoResult: SpaceSlice - ): FeatureMap = { - val featureMapBuilder = FeatureMapBuilder() - stratoResult.sliceInfo.previousCursor.foreach { cursor => - featureMapBuilder.add(PreviousCursorFeature, cursor) - } - stratoResult.sliceInfo.nextCursor.foreach { cursor => - featureMapBuilder.add(NextCursorFeature, cursor) - } - featureMapBuilder.build() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD deleted file mode 100644 index 0f5552bb5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "strato/config/columns/consumer-identity/business-profiles:business-profiles-strato-client", - "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala", - "strato/src/main/scala/com/twitter/strato/client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala deleted file mode 100644 index c728194ab..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/business_profiles/TeamMembersCandidateSource.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.business_profiles - -import com.twitter.product_mixer.component_library.model.cursor.NextCursorFeature -import com.twitter.product_mixer.component_library.model.cursor.PreviousCursorFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherWithSourceFeaturesSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.consumer_identity.business_profiles.BusinessProfileTeamMembersOnUserClientColumn -import com.twitter.strato.generated.client.consumer_identity.business_profiles.BusinessProfileTeamMembersOnUserClientColumn.{ - Value => TeamMembersSlice -} -import com.twitter.strato.generated.client.consumer_identity.business_profiles.BusinessProfileTeamMembersOnUserClientColumn.{ - View => TeamMembersView -} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TeamMembersCandidateSource @Inject() ( - column: BusinessProfileTeamMembersOnUserClientColumn) - extends StratoKeyViewFetcherWithSourceFeaturesSource[ - Long, - TeamMembersView, - TeamMembersSlice, - Long - ] { - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier( - "BusinessProfileTeamMembers") - - override val fetcher: Fetcher[Long, TeamMembersView, TeamMembersSlice] = column.fetcher - - override def stratoResultTransformer( - stratoKey: Long, - stratoResult: TeamMembersSlice - ): Seq[Long] = - stratoResult.members - - override protected def extractFeaturesFromStratoResult( - stratoKey: Long, - stratoResult: TeamMembersSlice - ): FeatureMap = { - val featureMapBuilder = FeatureMapBuilder() - stratoResult.previousCursor.foreach { cursor => - featureMapBuilder.add(PreviousCursorFeature, cursor.toString) - } - stratoResult.nextCursor.foreach { cursor => - featureMapBuilder.add(NextCursorFeature, cursor.toString) - } - featureMapBuilder.build() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel deleted file mode 100644 index 1eef70e77..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "cr-mixer/thrift/src/main/thrift:thrift-scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala deleted file mode 100644 index c1e79f238..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerFrsBasedTweetRecommendationsCandidateSource.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.cr_mixer - -import com.twitter.cr_mixer.{thriftscala => t} -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Returns out-of-network Tweet recommendations by using user recommendations - * from FollowRecommendationService as an input seed-set to Earlybird - */ -@Singleton -class CrMixerFrsBasedTweetRecommendationsCandidateSource @Inject() ( - crMixerClient: t.CrMixer.MethodPerEndpoint) - extends CandidateSource[t.FrsTweetRequest, t.FrsTweet] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("CrMixerFrsBasedTweetRecommendations") - - override def apply(request: t.FrsTweetRequest): Stitch[Seq[t.FrsTweet]] = Stitch - .callFuture(crMixerClient.getFrsBasedTweetRecommendations(request)) - .map(_.tweets) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala deleted file mode 100644 index a0cbd666c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/cr_mixer/CrMixerTweetRecommendationsCandidateSource.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.cr_mixer - -import com.twitter.cr_mixer.{thriftscala => t} -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CrMixerTweetRecommendationsCandidateSource @Inject() ( - crMixerClient: t.CrMixer.MethodPerEndpoint) - extends CandidateSource[t.CrMixerTweetRequest, t.TweetRecommendation] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("CrMixerTweetRecommendations") - - override def apply(request: t.CrMixerTweetRequest): Stitch[Seq[t.TweetRecommendation]] = Stitch - .callFuture(crMixerClient.getTweetRecommendations(request)) - .map(_.tweets) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel deleted file mode 100644 index 638f549d3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "src/thrift/com/twitter/search:earlybird-scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala deleted file mode 100644 index 9049849be..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/earlybird/EarlybirdTweetCandidateSource.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.earlybird - -import com.twitter.search.earlybird.{thriftscala => t} -import com.twitter.inject.Logging -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class EarlybirdTweetCandidateSource @Inject() ( - earlybirdService: t.EarlybirdService.MethodPerEndpoint) - extends CandidateSource[t.EarlybirdRequest, t.ThriftSearchResult] - with Logging { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("EarlybirdTweets") - - override def apply(request: t.EarlybirdRequest): Stitch[Seq[t.ThriftSearchResult]] = { - Stitch - .callFuture(earlybirdService.search(request)) - .map { response: t.EarlybirdResponse => - response.searchResults.map(_.results).getOrElse(Seq.empty) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel deleted file mode 100644 index 6633be199..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "explore/explore-ranker/thrift/src/main/thrift:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala deleted file mode 100644 index bd57b785a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/explore_ranker/ExploreRankerCandidateSource.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.explore_ranker - -import com.twitter.explore_ranker.{thriftscala => t} -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ExploreRankerCandidateSource @Inject() ( - exploreRankerService: t.ExploreRanker.MethodPerEndpoint) - extends CandidateSource[t.ExploreRankerRequest, t.ImmersiveRecsResult] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("ExploreRanker") - - override def apply( - request: t.ExploreRankerRequest - ): Stitch[Seq[t.ImmersiveRecsResult]] = { - Stitch - .callFuture(exploreRankerService.getRankedResults(request)) - .map { - case t.ExploreRankerResponse( - t.ExploreRankerProductResponse - .ImmersiveRecsResponse(t.ImmersiveRecsResponse(immersiveRecsResults))) => - immersiveRecsResults - case response => - throw new UnsupportedOperationException(s"Unknown response type: $response") - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD deleted file mode 100644 index b456956db..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - ], - exports = [ - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala deleted file mode 100644 index 48891d7ec..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline/PromptCandidateSource.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline - -import com.twitter.inject.Logging -import com.twitter.onboarding.injections.{thriftscala => injectionsthrift} -import com.twitter.onboarding.task.service.{thriftscala => servicethrift} -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Returns a list of prompts to insert into a user's timeline (inline prompt, cover modals, etc) - * from go/flip (the prompting platform for Twitter). - */ -@Singleton -class PromptCandidateSource @Inject() (taskService: servicethrift.TaskService.MethodPerEndpoint) - extends CandidateSource[servicethrift.GetInjectionsRequest, IntermediatePrompt] - with Logging { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier( - "InjectionPipelinePrompts") - - override def apply( - request: servicethrift.GetInjectionsRequest - ): Stitch[Seq[IntermediatePrompt]] = { - Stitch - .callFuture(taskService.getInjections(request)).map { - _.injections.flatMap { - // The entire carousel is getting added to each IntermediatePrompt item with a - // corresponding index to be unpacked later on to populate its TimelineEntry counterpart. - case injection: injectionsthrift.Injection.TilesCarousel => - injection.tilesCarousel.tiles.zipWithIndex.map { - case (tile: injectionsthrift.Tile, index: Int) => - IntermediatePrompt(injection, Some(index), Some(tile)) - } - case injection => Seq(IntermediatePrompt(injection, None, None)) - } - } - } -} - -/** - * Gives an intermediate step to help 'explosion' of tile carousel tiles due to TimelineModule - * not being an extension of TimelineItem - */ -case class IntermediatePrompt( - injection: injectionsthrift.Injection, - offsetInModule: Option[Int], - carouselTile: Option[injectionsthrift.Tile]) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel deleted file mode 100644 index c6bcf152a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/BUILD.bazel +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/hermit:hermit-scala", - "strato/config/columns/onboarding:onboarding-strato-client", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/hermit:hermit-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala deleted file mode 100644 index 9bbfe234a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/hermit/UsersSimilarToMeCandidateSource.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.hermit - -import com.twitter.hermit.thriftscala.RecommendationRequest -import com.twitter.hermit.thriftscala.RecommendationResponse -import com.twitter.hermit.thriftscala.RelatedUser -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.onboarding.HermitRecommendUsersClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UsersSimilarToMeCandidateSource @Inject() ( - column: HermitRecommendUsersClientColumn) - extends StratoKeyViewFetcherSource[ - Long, - RecommendationRequest, - RecommendationResponse, - RelatedUser - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("UsersSimilarToMe") - - override val fetcher: Fetcher[Long, RecommendationRequest, RecommendationResponse] = - column.fetcher - - override def stratoResultTransformer( - stratoKey: Long, - result: RecommendationResponse - ): Seq[RelatedUser] = result.suggestions.getOrElse(Seq.empty).filter(_.id.isDefined) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD deleted file mode 100644 index da4c6d794..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "interests-service/thrift/src/main/thrift:thrift-scala", - "interests_discovery/thrift/src/main/thrift:service-thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - ], - exports = [ - "interests-service/thrift/src/main/thrift:thrift-scala", - "interests_discovery/thrift/src/main/thrift:service-thrift-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala deleted file mode 100644 index 30465089c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/interest_discovery/RelatedTopicsCandidateSource.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.interest_discovery - -import com.google.inject.Inject -import com.google.inject.Singleton -import com.twitter.inject.Logging -import com.twitter.interests_discovery.{thriftscala => t} -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch - -/** - * Generate a list of related topics results from IDS getRelatedTopics (thrift) endpoint. - * Returns related topics, given a topic, whereas [[RecommendedTopicsCandidateSource]] returns - * recommended topics, given a user. - */ -@Singleton -class RelatedTopicsCandidateSource @Inject() ( - interestDiscoveryService: t.InterestsDiscoveryService.MethodPerEndpoint) - extends CandidateSource[t.RelatedTopicsRequest, t.RelatedTopic] - with Logging { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier(name = "RelatedTopics") - - override def apply( - request: t.RelatedTopicsRequest - ): Stitch[Seq[t.RelatedTopic]] = { - Stitch - .callFuture(interestDiscoveryService.getRelatedTopics(request)) - .map { response: t.RelatedTopicsResponse => - response.topics - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel deleted file mode 100644 index c62b67377..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "interests_discovery/thrift/src/main/thrift:service-thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "strato/config/columns/recommendations/interests_discovery/recommendations_mh:recommendations_mh-strato-client", - ], - exports = [ - "strato/config/columns/recommendations/interests_discovery/recommendations_mh:recommendations_mh-strato-client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala deleted file mode 100644 index a8b6f214c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/lists/OrganicPopGeoListsCandidateSource.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.lists - -import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.recommendations.interests_discovery.recommendations_mh.OrganicPopgeoListsClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class OrganicPopGeoListsCandidateSource @Inject() ( - organicPopgeoListsClientColumn: OrganicPopgeoListsClientColumn) - extends StratoKeyFetcherSource[ - OrganicPopgeoListsClientColumn.Key, - OrganicPopgeoListsClientColumn.Value, - TwitterListCandidate - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier( - "OrganicPopGeoLists") - - override val fetcher: Fetcher[ - OrganicPopgeoListsClientColumn.Key, - Unit, - OrganicPopgeoListsClientColumn.Value - ] = - organicPopgeoListsClientColumn.fetcher - - override def stratoResultTransformer( - stratoResult: OrganicPopgeoListsClientColumn.Value - ): Seq[TwitterListCandidate] = { - stratoResult.recommendedListsByAlgo.flatMap { topLists => - topLists.lists.map { list => - TwitterListCandidate(list.listId) - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD deleted file mode 100644 index a54812ce9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "people-discovery/api/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - "src/thrift/com/twitter/hermit:hermit-scala", - "stitch/stitch-core", - ], - exports = [ - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "people-discovery/api/thrift:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala deleted file mode 100644 index 0b3dacccb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery/PeopleDiscoveryCandidateSource.scala +++ /dev/null @@ -1,71 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.people_discovery - -import com.twitter.peoplediscovery.api.{thriftscala => t} -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult -import com.twitter.stitch.Stitch -import com.twitter.util.logging.Logging -import javax.inject.Inject -import javax.inject.Singleton - -object WhoToFollowModuleHeaderFeature extends Feature[UserCandidate, t.Header] -object WhoToFollowModuleDisplayOptionsFeature - extends Feature[UserCandidate, Option[t.DisplayOptions]] -object WhoToFollowModuleShowMoreFeature extends Feature[UserCandidate, Option[t.ShowMore]] - -@Singleton -class PeopleDiscoveryCandidateSource @Inject() ( - peopleDiscoveryService: t.ThriftPeopleDiscoveryService.MethodPerEndpoint) - extends CandidateSourceWithExtractedFeatures[t.GetModuleRequest, t.RecommendedUser] - with Logging { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier(name = "PeopleDiscovery") - - override def apply( - request: t.GetModuleRequest - ): Stitch[CandidatesWithSourceFeatures[t.RecommendedUser]] = { - Stitch - .callFuture(peopleDiscoveryService.getModules(request)) - .map { response: t.GetModuleResponse => - // under the assumption getModules returns a maximum of one module - response.modules - .collectFirst { module => - module.layout match { - case t.Layout.UserBioList(layout) => - layoutToCandidatesWithSourceFeatures( - layout.userRecommendations, - layout.header, - layout.displayOptions, - layout.showMore) - case t.Layout.UserTweetCarousel(layout) => - layoutToCandidatesWithSourceFeatures( - layout.userRecommendations, - layout.header, - layout.displayOptions, - layout.showMore) - } - }.getOrElse(throw PipelineFailure(UnexpectedCandidateResult, "unexpected missing module")) - } - } - - private def layoutToCandidatesWithSourceFeatures( - userRecommendations: Seq[t.RecommendedUser], - header: t.Header, - displayOptions: Option[t.DisplayOptions], - showMore: Option[t.ShowMore], - ): CandidatesWithSourceFeatures[t.RecommendedUser] = { - val features = FeatureMapBuilder() - .add(WhoToFollowModuleHeaderFeature, header) - .add(WhoToFollowModuleDisplayOptionsFeature, displayOptions) - .add(WhoToFollowModuleShowMoreFeature, showMore) - .build() - CandidatesWithSourceFeatures(userRecommendations, features) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel deleted file mode 100644 index cb69d82ec..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/BUILD.bazel +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "follow-recommendations-service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "strato/config/columns/onboarding/follow-recommendations-service:follow-recommendations-service-strato-client", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala deleted file mode 100644 index dcfed2ec9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/recommendations/UserFollowRecommendationsCandidateSource.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.recommendations - -import com.twitter.follow_recommendations.{thriftscala => fr} -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.onboarding.follow_recommendations_service.GetRecommendationsClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Returns a list of FollowRecommendations as [[fr.UserRecommendation]]s fetched from Strato - */ -@Singleton -class UserFollowRecommendationsCandidateSource @Inject() ( - getRecommendationsClientColumn: GetRecommendationsClientColumn) - extends StratoKeyViewFetcherSource[ - fr.RecommendationRequest, - Unit, - fr.RecommendationResponse, - fr.UserRecommendation - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier( - "FollowRecommendationsService") - - override val fetcher: Fetcher[fr.RecommendationRequest, Unit, fr.RecommendationResponse] = - getRecommendationsClientColumn.fetcher - - override def stratoResultTransformer( - stratoKey: fr.RecommendationRequest, - stratoResult: fr.RecommendationResponse - ): Seq[fr.UserRecommendation] = { - stratoResult.recommendations.map { - case fr.Recommendation.User(userRec: fr.UserRecommendation) => - userRec - case _ => - throw new Exception("Invalid recommendation type returned from FRS") - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel deleted file mode 100644 index dbc8cba53..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "socialgraph/server/src/main/scala/com/twitter/socialgraph/util", - "src/thrift/com/twitter/socialgraph:thrift-scala", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/socialgraph:thrift-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala deleted file mode 100644 index b3cf838f2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCandidateSource.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.social_graph - -import com.twitter.product_mixer.component_library.model.candidate.CursorType -import com.twitter.product_mixer.component_library.model.candidate.NextCursor -import com.twitter.product_mixer.component_library.model.candidate.PreviousCursor -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.socialgraph.thriftscala -import com.twitter.socialgraph.thriftscala.IdsRequest -import com.twitter.socialgraph.thriftscala.IdsResult -import com.twitter.socialgraph.util.ByteBufferUtil -import com.twitter.strato.client.Fetcher -import javax.inject.Inject -import javax.inject.Singleton - -sealed trait SocialgraphResponse -case class SocialgraphResult(id: Long) extends SocialgraphResponse -case class SocialgraphCursor(cursor: Long, cursorType: CursorType) extends SocialgraphResponse - -@Singleton -class SocialgraphCandidateSource @Inject() ( - override val fetcher: Fetcher[thriftscala.IdsRequest, Option[ - thriftscala.RequestContext - ], thriftscala.IdsResult]) - extends StratoKeyViewFetcherSource[ - thriftscala.IdsRequest, - Option[thriftscala.RequestContext], - thriftscala.IdsResult, - SocialgraphResponse - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("Socialgraph") - - override def stratoResultTransformer( - stratoKey: IdsRequest, - stratoResult: IdsResult - ): Seq[SocialgraphResponse] = { - val prevCursor = - SocialgraphCursor(ByteBufferUtil.toLong(stratoResult.pageResult.prevCursor), PreviousCursor) - /* When an end cursor is passed to Socialgraph, - * Socialgraph returns the start cursor. To prevent - * clients from circularly fetching the timeline again, - * if we see a start cursor returned from Socialgraph, - * we replace it with an end cursor. - */ - val nextCursor = ByteBufferUtil.toLong(stratoResult.pageResult.nextCursor) match { - case SocialgraphCursorConstants.StartCursor => - SocialgraphCursor(SocialgraphCursorConstants.EndCursor, NextCursor) - case cursor => SocialgraphCursor(cursor, NextCursor) - } - - stratoResult.ids - .map { id => - SocialgraphResult(id) - } ++ Seq(nextCursor, prevCursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala deleted file mode 100644 index 8f187d0cb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/social_graph/SocialgraphCursorConstants.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.social_graph - -object SocialgraphCursorConstants { - val EndCursor: Long = 0L - val StartCursor: Long = -1L - val LastSortIndex: Long = 0L -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel deleted file mode 100644 index c83297fd8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "src/thrift/com/twitter/timelineranker:thrift-scala", - "src/thrift/com/twitter/timelineranker/server/model:thrift-scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala deleted file mode 100644 index 9f1262e53..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerInNetworkCandidateSource.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.timeline_ranker - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelineranker.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Map of tweetId -> sourceTweet of retweets present in Timeline Ranker candidates list. - * These tweets are used only for further ranking. They are not returned to the end user. - */ -object TimelineRankerInNetworkSourceTweetsByTweetIdMapFeature - extends Feature[PipelineQuery, Map[Long, t.CandidateTweet]] - -@Singleton -class TimelineRankerInNetworkCandidateSource @Inject() ( - timelineRankerClient: t.TimelineRanker.MethodPerEndpoint) - extends CandidateSourceWithExtractedFeatures[t.RecapQuery, t.CandidateTweet] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("TimelineRankerInNetwork") - - override def apply( - request: t.RecapQuery - ): Stitch[CandidatesWithSourceFeatures[t.CandidateTweet]] = { - Stitch - .callFuture(timelineRankerClient.getRecycledTweetCandidates(Seq(request))) - .map { response: Seq[t.GetCandidateTweetsResponse] => - val candidates = - response.headOption.flatMap(_.candidates).getOrElse(Seq.empty).filter(_.tweet.nonEmpty) - val sourceTweetsByTweetId = - response.headOption - .flatMap(_.sourceTweets).getOrElse(Seq.empty).filter(_.tweet.nonEmpty) - .map { candidate => - (candidate.tweet.get.id, candidate) - }.toMap - val sourceTweetsByTweetIdMapFeature = FeatureMapBuilder() - .add(TimelineRankerInNetworkSourceTweetsByTweetIdMapFeature, sourceTweetsByTweetId) - .build() - CandidatesWithSourceFeatures( - candidates = candidates, - features = sourceTweetsByTweetIdMapFeature) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala deleted file mode 100644 index 7cd36fb92..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerRecapCandidateSource.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.timeline_ranker - -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import com.twitter.timelineranker.{thriftscala => t} - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineRankerRecapCandidateSource @Inject() ( - timelineRankerClient: t.TimelineRanker.MethodPerEndpoint) - extends CandidateSource[t.RecapQuery, t.CandidateTweet] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("TimelineRankerRecap") - - override def apply( - request: t.RecapQuery - ): Stitch[Seq[t.CandidateTweet]] = { - Stitch - .callFuture(timelineRankerClient.getRecapCandidatesFromAuthors(Seq(request))) - .map { response: Seq[t.GetCandidateTweetsResponse] => - response.headOption.flatMap(_.candidates).getOrElse(Seq.empty).filter(_.tweet.nonEmpty) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala deleted file mode 100644 index bee6fe128..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_ranker/TimelineRankerUtegCandidateSource.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.timeline_ranker - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult -import com.twitter.stitch.Stitch -import com.twitter.timelineranker.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Source tweets of retweets present in Timeline Ranker candidates list. - * These tweets are used only for further ranking. They are not returned to the end user. - */ -case object TimelineRankerUtegSourceTweetsFeature - extends Feature[PipelineQuery, Seq[t.CandidateTweet]] - -@Singleton -class TimelineRankerUtegCandidateSource @Inject() ( - timelineRankerClient: t.TimelineRanker.MethodPerEndpoint) - extends CandidateSourceWithExtractedFeatures[t.UtegLikedByTweetsQuery, t.CandidateTweet] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("TimelineRankerUteg") - - override def apply( - request: t.UtegLikedByTweetsQuery - ): Stitch[CandidatesWithSourceFeatures[t.CandidateTweet]] = { - Stitch - .callFuture(timelineRankerClient.getUtegLikedByTweetCandidates(Seq(request))) - .map { response => - val result = response.headOption.getOrElse( - throw PipelineFailure(UnexpectedCandidateResult, "Empty Timeline Ranker response")) - val candidates = result.candidates.toSeq.flatten - val sourceTweets = result.sourceTweets.toSeq.flatten - - val candidateSourceFeatures = FeatureMapBuilder() - .add(TimelineRankerUtegSourceTweetsFeature, sourceTweets) - .build() - - CandidatesWithSourceFeatures(candidates = candidates, features = candidateSourceFeatures) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel deleted file mode 100644 index e4435bc0a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/BUILD.bazel +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "src/thrift/com/twitter/timelineservice/server/suggests/features:thrift-scala", - "src/thrift/com/twitter/timelineservice/server/suggests/logging:thrift-scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala deleted file mode 100644 index b2d6f3912..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_scorer/TimelineScorerCandidateSource.scala +++ /dev/null @@ -1,156 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.timeline_scorer - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelinescorer.common.scoredtweetcandidate.thriftscala.v1 -import com.twitter.timelinescorer.common.scoredtweetcandidate.thriftscala.v1.Ancestor -import com.twitter.timelinescorer.common.scoredtweetcandidate.{thriftscala => ct} -import com.twitter.timelinescorer.{thriftscala => t} -import com.twitter.timelineservice.suggests.logging.candidate_tweet_source_id.thriftscala.CandidateTweetSourceId -import javax.inject.Inject -import javax.inject.Singleton - -case class ScoredTweetCandidateWithFocalTweet( - candidate: v1.ScoredTweetCandidate, - focalTweetIdOpt: Option[Long]) - -case object TimelineScorerCandidateSourceSucceededFeature extends Feature[PipelineQuery, Boolean] - -@Singleton -class TimelineScorerCandidateSource @Inject() ( - timelineScorerClient: t.TimelineScorer.MethodPerEndpoint) - extends CandidateSourceWithExtractedFeatures[ - t.ScoredTweetsRequest, - ScoredTweetCandidateWithFocalTweet - ] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("TimelineScorer") - - private val MaxConversationAncestors = 2 - - override def apply( - request: t.ScoredTweetsRequest - ): Stitch[CandidatesWithSourceFeatures[ScoredTweetCandidateWithFocalTweet]] = { - Stitch - .callFuture(timelineScorerClient.getScoredTweets(request)) - .map { response => - val scoredTweetsOpt = response match { - case t.ScoredTweetsResponse.V1(v1) => v1.scoredTweets - case t.ScoredTweetsResponse.UnknownUnionField(field) => - throw new UnsupportedOperationException(s"Unknown response type: ${field.field.name}") - } - val scoredTweets = scoredTweetsOpt.getOrElse(Seq.empty) - - val allAncestors = scoredTweets.flatMap { - case ct.ScoredTweetCandidate.V1(v1) if isEligibleReply(v1) => - v1.ancestors.get.map(_.tweetId) - case _ => Seq.empty - }.toSet - - // Remove tweets within ancestor list of other tweets to avoid serving duplicates - val keptTweets = scoredTweets.collect { - case ct.ScoredTweetCandidate.V1(v1) if !allAncestors.contains(originalTweetId(v1)) => v1 - } - - // Add parent and root tweet for eligible reply focal tweets - val candidates = keptTweets - .flatMap { - case v1 if isEligibleReply(v1) => - val ancestors = v1.ancestors.get - val focalTweetId = v1.tweetId - - // Include root tweet if the conversation has atleast 2 ancestors - val optionallyIncludedRootTweet = if (ancestors.size >= MaxConversationAncestors) { - val rootTweet = toScoredTweetCandidateFromAncestor( - ancestor = ancestors.last, - inReplyToTweetId = None, - conversationId = v1.conversationId, - ancestors = None, - candidateTweetSourceId = v1.candidateTweetSourceId - ) - Seq((rootTweet, Some(v1))) - } else Seq.empty - - /** - * Setting the in-reply-to tweet id on the immediate parent, if one exists, - * helps ensure tweet type metrics correctly distinguish roots from non-roots. - */ - val inReplyToTweetId = ancestors.tail.headOption.map(_.tweetId) - val parentAncestor = toScoredTweetCandidateFromAncestor( - ancestor = ancestors.head, - inReplyToTweetId = inReplyToTweetId, - conversationId = v1.conversationId, - ancestors = Some(ancestors.tail), - candidateTweetSourceId = v1.candidateTweetSourceId - ) - - optionallyIncludedRootTweet ++ - Seq((parentAncestor, Some(v1)), (v1, Some(v1))) - - case any => Seq((any, None)) // Set focalTweetId to None if not eligible for convo - } - - /** - * Dedup each tweet keeping the one with highest scored Focal Tweet - * Focal Tweet ID != the Conversation ID, which is set to the root of the conversation - * Focal Tweet ID will be defined for tweets with ancestors that should be - * in conversation modules and None for standalone tweets. - */ - val sortedDedupedCandidates = candidates - .groupBy { case (v1, _) => v1.tweetId } - .mapValues { group => - val (candidate, focalTweetOpt) = group.maxBy { - case (_, Some(focal)) => focal.score - case (_, None) => 0 - } - ScoredTweetCandidateWithFocalTweet(candidate, focalTweetOpt.map(focal => focal.tweetId)) - }.values.toSeq.sortBy(_.candidate.tweetId) - - CandidatesWithSourceFeatures( - candidates = sortedDedupedCandidates, - features = FeatureMapBuilder() - .add(TimelineScorerCandidateSourceSucceededFeature, true) - .build() - ) - } - } - - private def isEligibleReply(candidate: ct.ScoredTweetCandidateAliases.V1Alias): Boolean = { - candidate.inReplyToTweetId.nonEmpty && - !candidate.isRetweet.getOrElse(false) && - candidate.ancestors.exists(_.nonEmpty) - } - - /** - * If we have a retweet, get the source tweet id. - * If it is not a retweet, get the regular tweet id. - */ - private def originalTweetId(candidate: ct.ScoredTweetCandidateAliases.V1Alias): Long = { - candidate.sourceTweetId.getOrElse(candidate.tweetId) - } - - private def toScoredTweetCandidateFromAncestor( - ancestor: Ancestor, - inReplyToTweetId: Option[Long], - conversationId: Option[Long], - ancestors: Option[Seq[Ancestor]], - candidateTweetSourceId: Option[CandidateTweetSourceId] - ): ct.ScoredTweetCandidateAliases.V1Alias = { - ct.v1.ScoredTweetCandidate( - tweetId = ancestor.tweetId, - authorId = ancestor.userId.getOrElse(0L), - score = 0.0, - isAncestorCandidate = Some(true), - inReplyToTweetId = inReplyToTweetId, - conversationId = conversationId, - ancestors = ancestors, - candidateTweetSourceId = candidateTweetSourceId - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD deleted file mode 100644 index f9453b9a1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala", - "stitch/stitch-timelineservice/src/main/scala", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-timelineservice/src/main/scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala deleted file mode 100644 index 053c16a3e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timeline_service/TimelineServiceTweetCandidateSource.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.timeline_service - -import com.twitter.product_mixer.component_library.model.cursor.NextCursorFeature -import com.twitter.product_mixer.component_library.model.cursor.PreviousCursorFeature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.stitch.timelineservice.TimelineService -import com.twitter.timelineservice.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -case object TimelineServiceResponseWasTruncatedFeature - extends FeatureWithDefaultOnFailure[PipelineQuery, Boolean] { - override val defaultValue: Boolean = false -} - -@Singleton -class TimelineServiceTweetCandidateSource @Inject() ( - timelineService: TimelineService) - extends CandidateSourceWithExtractedFeatures[t.TimelineQuery, t.Tweet] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("TimelineServiceTweet") - - override def apply(request: t.TimelineQuery): Stitch[CandidatesWithSourceFeatures[t.Tweet]] = { - timelineService - .getTimeline(request).map { timeline => - val candidates = timeline.entries.collect { - case t.TimelineEntry.Tweet(tweet) => tweet - } - - val candidateSourceFeatures = - FeatureMapBuilder() - .add(TimelineServiceResponseWasTruncatedFeature, timeline.wasTruncated.getOrElse(false)) - .add(PreviousCursorFeature, timeline.responseCursor.flatMap(_.top).getOrElse("")) - .add(NextCursorFeature, timeline.responseCursor.flatMap(_.bottom).getOrElse("")) - .build() - - CandidatesWithSourceFeatures(candidates = candidates, features = candidateSourceFeatures) - } - } - -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD deleted file mode 100644 index 60d486676..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "src/thrift/com/twitter/timelines/impression:thrift-scala", - "strato/config/columns/timelines/impression-store:impression-store-strato-client", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "strato/config/columns/timelines/impression-store:impression-store-strato-client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala deleted file mode 100644 index 3c4b615bb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/timelines_impression_store/TimelinesImpressionStoreCandidateSourceV2.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.timelines_impression_store - -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyFetcherSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.timelines.impression_store.TweetImpressionStoreManhattanV2OnUserClientColumn -import com.twitter.timelines.impression.thriftscala.TweetImpressionsEntries -import com.twitter.timelines.impression.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelinesImpressionStoreCandidateSourceV2 @Inject() ( - client: TweetImpressionStoreManhattanV2OnUserClientColumn) - extends StratoKeyFetcherSource[ - Long, - t.TweetImpressionsEntries, - t.TweetImpressionsEntry - ] { - - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier( - "TimelinesImpressionStore") - - override val fetcher: Fetcher[Long, Unit, TweetImpressionsEntries] = client.fetcher - - override def stratoResultTransformer( - stratoResult: t.TweetImpressionsEntries - ): Seq[t.TweetImpressionsEntry] = - stratoResult.entries -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD deleted file mode 100644 index d145edc44..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/BUILD +++ /dev/null @@ -1,11 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "strato/config/columns/interests:interests-strato-client", - "strato/src/main/scala/com/twitter/strato/client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala deleted file mode 100644 index 6b46e1298..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/topics/FollowedTopicsCandidateSource.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.topics - -import com.twitter.product_mixer.core.functional_component.candidate_source.strato.StratoKeyViewFetcherSeqSource -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.strato.client.Fetcher -import com.twitter.strato.generated.client.interests.FollowedTopicsGetterClientColumn -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FollowedTopicsCandidateSource @Inject() ( - column: FollowedTopicsGetterClientColumn) - extends StratoKeyViewFetcherSeqSource[ - Long, - Unit, - Long - ] { - override val identifier: CandidateSourceIdentifier = CandidateSourceIdentifier("FollowedTopics") - - override val fetcher: Fetcher[Long, Unit, Seq[Long]] = column.fetcher -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel deleted file mode 100644 index acfc37015..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/BUILD.bazel +++ /dev/null @@ -1,26 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala", - "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala", - "strato/config/columns/tweetconvosvc:tweetconvosvc-strato-client", - "tweetconvosvc/common/src/main/thrift/com/twitter/tweetconvosvc/tweet_ancestor:thrift-scala", - "tweetconvosvc/thrift/src/main/thrift:thrift-scala", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "strato/config/columns/tweetconvosvc:tweetconvosvc-strato-client", - "tweetconvosvc/thrift/src/main/thrift:thrift-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala deleted file mode 100644 index 889a0164d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceCandidateSource.scala +++ /dev/null @@ -1,173 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.tweetconvosvc - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch -import com.twitter.tweetconvosvc.tweet_ancestor.{thriftscala => ta} -import com.twitter.tweetconvosvc.{thriftscala => tcs} -import com.twitter.util.Return -import com.twitter.util.Throw -import javax.inject.Inject -import javax.inject.Singleton - -case class ConversationServiceCandidateSourceRequest( - tweetsWithConversationMetadata: Seq[TweetWithConversationMetadata]) - -case class TweetWithConversationMetadata( - tweetId: Long, - userId: Option[Long], - sourceTweetId: Option[Long], - sourceUserId: Option[Long], - inReplyToTweetId: Option[Long], - conversationId: Option[Long], - ancestors: Seq[ta.TweetAncestor]) - -/** - * Candidate source that fetches ancestors of input candidates from Tweetconvosvc and - * returns a flattened list of input and ancestor candidates. - */ -@Singleton -class ConversationServiceCandidateSource @Inject() ( - conversationServiceClient: tcs.ConversationService.MethodPerEndpoint) - extends CandidateSourceWithExtractedFeatures[ - ConversationServiceCandidateSourceRequest, - TweetWithConversationMetadata - ] { - - override val identifier: CandidateSourceIdentifier = - CandidateSourceIdentifier("ConversationService") - - private val maxModuleSize = 3 - private val maxAncestorsInConversation = 2 - private val numberOfRootTweets = 1 - private val maxTweetsInConversationWithSameId = 1 - - override def apply( - request: ConversationServiceCandidateSourceRequest - ): Stitch[CandidatesWithSourceFeatures[TweetWithConversationMetadata]] = { - val inputTweetsWithConversationMetadata: Seq[TweetWithConversationMetadata] = - request.tweetsWithConversationMetadata - val ancestorsRequest = - tcs.GetAncestorsRequest(inputTweetsWithConversationMetadata.map(_.tweetId)) - - // build the tweets with conversation metadata by calling the conversation service with reduced - // ancestors to limit to maxModuleSize - val tweetsWithConversationMetadataFromAncestors: Stitch[Seq[TweetWithConversationMetadata]] = - Stitch - .callFuture(conversationServiceClient.getAncestors(ancestorsRequest)) - .map { getAncestorsResponse: tcs.GetAncestorsResponse => - inputTweetsWithConversationMetadata - .zip(getAncestorsResponse.ancestors).collect { - case (focalTweet, tcs.TweetAncestorsResult.TweetAncestors(ancestorsResult)) - if ancestorsResult.nonEmpty => - getTweetsInThread(focalTweet, ancestorsResult.head) - }.flatten - } - - // dedupe the tweets in the list and transform the calling error to - // return the requested tweets with conversation metadata - val transformedTweetsWithConversationMetadata: Stitch[Seq[TweetWithConversationMetadata]] = - tweetsWithConversationMetadataFromAncestors.transform { - case Return(ancestors) => - Stitch.value(dedupeCandidates(inputTweetsWithConversationMetadata, ancestors)) - case Throw(_) => - Stitch.value(inputTweetsWithConversationMetadata) - } - - // return the candidates with empty source features from transformed tweetsWithConversationMetadata - transformedTweetsWithConversationMetadata.map { - responseTweetsWithConversationMetadata: Seq[TweetWithConversationMetadata] => - CandidatesWithSourceFeatures( - responseTweetsWithConversationMetadata, - FeatureMap.empty - ) - } - } - - private def getTweetsInThread( - focalTweet: TweetWithConversationMetadata, - ancestors: ta.TweetAncestors - ): Seq[TweetWithConversationMetadata] = { - // Re-add the focal tweet so we can easily build modules and dedupe later. - // Note, TweetConvoSVC returns the bottom of the thread first, so we - // reverse them for easy rendering. - val focalTweetWithConversationMetadata = TweetWithConversationMetadata( - tweetId = focalTweet.tweetId, - userId = focalTweet.userId, - sourceTweetId = focalTweet.sourceTweetId, - sourceUserId = focalTweet.sourceUserId, - inReplyToTweetId = focalTweet.inReplyToTweetId, - conversationId = Some(focalTweet.tweetId), - ancestors = ancestors.ancestors - ) - - val parentTweets = ancestors.ancestors.map { ancestor => - TweetWithConversationMetadata( - tweetId = ancestor.tweetId, - userId = Some(ancestor.userId), - sourceTweetId = None, - sourceUserId = None, - inReplyToTweetId = None, - conversationId = Some(focalTweet.tweetId), - ancestors = Seq.empty - ) - } ++ getTruncatedRootTweet(ancestors, focalTweet.tweetId) - - val (intermediates, root) = parentTweets.splitAt(parentTweets.size - numberOfRootTweets) - val truncatedIntermediates = - intermediates.take(maxModuleSize - maxAncestorsInConversation).reverse - root ++ truncatedIntermediates :+ focalTweetWithConversationMetadata - } - - /** - * Ancestor store truncates at 256 ancestors. For very large reply threads, we try best effort - * to append the root tweet to the ancestor list based on the conversationId and - * conversationRootAuthorId. When rendering conversation modules, we can display the root tweet - * instead of the 256th highest ancestor. - */ - private def getTruncatedRootTweet( - ancestors: ta.TweetAncestors, - focalTweetId: Long - ): Option[TweetWithConversationMetadata] = { - ancestors.conversationRootAuthorId.collect { - case rootAuthorId - if ancestors.state == ta.ReplyState.Partial && - ancestors.ancestors.last.tweetId != ancestors.conversationId => - TweetWithConversationMetadata( - tweetId = ancestors.conversationId, - userId = Some(rootAuthorId), - sourceTweetId = None, - sourceUserId = None, - inReplyToTweetId = None, - conversationId = Some(focalTweetId), - ancestors = Seq.empty - ) - } - } - - private def dedupeCandidates( - inputTweetsWithConversationMetadata: Seq[TweetWithConversationMetadata], - ancestors: Seq[TweetWithConversationMetadata] - ): Seq[TweetWithConversationMetadata] = { - val dedupedAncestors: Iterable[TweetWithConversationMetadata] = ancestors - .groupBy(_.tweetId).map { - case (_, duplicateAncestors) - if duplicateAncestors.size > maxTweetsInConversationWithSameId => - duplicateAncestors.maxBy(_.conversationId.getOrElse(0L)) - case (_, nonDuplicateAncestors) => nonDuplicateAncestors.head - } - // Sort by tweet id to prevent issues with future assumptions of the root being the first - // tweet and the focal being the last tweet in a module. The tweets as a whole do not need - // to be sorted overall, only the relative order within modules must be kept. - val sortedDedupedAncestors: Seq[TweetWithConversationMetadata] = - dedupedAncestors.toSeq.sortBy(_.tweetId) - - val ancestorIds = sortedDedupedAncestors.map(_.tweetId).toSet - val updatedCandidates = inputTweetsWithConversationMetadata.filterNot { candidate => - ancestorIds.contains(candidate.tweetId) - } - sortedDedupedAncestors ++ updatedCandidates - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala deleted file mode 100644 index 59a0c725f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/ConversationServiceResponseFeatureTransformer.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.tweetconvosvc - -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier -import com.twitter.timelineservice.suggests.thriftscala.SuggestType - -object AuthorIdFeature extends Feature[TweetCandidate, Option[Long]] -object AncestorIdsFeature extends Feature[TweetCandidate, Seq[Long]] -object ConversationModuleFocalTweetIdFeature extends Feature[TweetCandidate, Option[Long]] -object InReplyToFeature extends Feature[TweetCandidate, Option[Long]] -object IsRetweetFeature extends Feature[TweetCandidate, Boolean] -object SourceTweetIdFeature extends Feature[TweetCandidate, Option[Long]] -object SourceUserIdFeature extends Feature[TweetCandidate, Option[Long]] -object SuggestTypeFeature extends Feature[TweetCandidate, Option[SuggestType]] - -object ConversationServiceResponseFeatureTransformer - extends CandidateFeatureTransformer[TweetWithConversationMetadata] { - override val identifier: TransformerIdentifier = - TransformerIdentifier("ConversationServiceResponse") - - override val features: Set[Feature[_, _]] = - Set( - AuthorIdFeature, - InReplyToFeature, - IsRetweetFeature, - SourceTweetIdFeature, - SourceUserIdFeature, - ConversationModuleFocalTweetIdFeature, - AncestorIdsFeature, - SuggestTypeFeature - ) - - override def transform(candidate: TweetWithConversationMetadata): FeatureMap = { - FeatureMapBuilder() - .add(AuthorIdFeature, candidate.userId) - .add(InReplyToFeature, candidate.inReplyToTweetId) - .add(IsRetweetFeature, candidate.sourceTweetId.isDefined) - .add(SourceTweetIdFeature, candidate.sourceTweetId) - .add(SourceUserIdFeature, candidate.sourceUserId) - .add(ConversationModuleFocalTweetIdFeature, candidate.conversationId) - .add(AncestorIdsFeature, candidate.ancestors.map(_.tweetId)) - .add(SuggestTypeFeature, Some(SuggestType.OrganicConversation)) - .build() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala deleted file mode 100644 index 426adb98c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/tweetconvosvc/DropMaxConversationModuleItemCandidates.scala +++ /dev/null @@ -1,55 +0,0 @@ -package com.twitter.product_mixer.component_library.candidate_source.tweetconvosvc - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Takes a conversation module item and truncates it to be at most the focal tweet, the focal tweet's - * in reply to tweet and optionally, the root conversation tweet if desired. - * @param pipelineScope What pipeline scopes to include in this. - * @param includeRootTweet Whether to include the root tweet at the top of the conversation or not. - * @tparam Query - */ -case class DropMaxConversationModuleItemCandidates[-Query <: PipelineQuery]( - override val pipelineScope: CandidateScope, - includeRootTweet: Boolean) - extends Selector[Query] { - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val updatedCandidates = remainingCandidates.collect { - case moduleCandidate: ModuleCandidateWithDetails if pipelineScope.contains(moduleCandidate) => - updateConversationModule(moduleCandidate, includeRootTweet) - case candidates => candidates - } - SelectorResult(remainingCandidates = updatedCandidates, result = result) - } - - private def updateConversationModule( - module: ModuleCandidateWithDetails, - includeRootTweet: Boolean - ): ModuleCandidateWithDetails = { - // If the thread is only the root tweet & a focal tweet replying to it, no truncation can be done. - if (module.candidates.length <= 2) { - module - } else { - // If a thread is more 3 or more tweets, we optionally keep the root tweet if desired, and take - // the focal tweet tweet and its direct ancestor (the one it would have replied to) and return - // those. - val tweetCandidates = module.candidates - val replyAndFocalTweet = tweetCandidates.takeRight(2) - val updatedConversation = if (includeRootTweet) { - tweetCandidates.headOption ++ replyAndFocalTweet - } else { - replyAndFocalTweet - } - module.copy(candidates = updatedConversation.toSeq) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD deleted file mode 100644 index 2ed1a6316..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala deleted file mode 100644 index abe128926..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/SliceItemCandidateDecorator.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.slice - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.component_library.model.presentation.slice.SliceItemPresentation -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.functional_component.decorator.slice.builder.CandidateSliceItemBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.stitch.Stitch - -/** - * Adds a [[Decoration]] for all `candidates` that are [[CursorCandidate]]s - * - * @note Only [[CursorCandidate]]s get decorated in [[SliceItemCandidateDecorator]] - * because the [[com.twitter.product_mixer.component_library.premarshaller.slice.SliceDomainMarshaller]] - * handles the undecorated non-[[CursorCandidate]] `candidates` directly. - */ -case class SliceItemCandidateDecorator[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - cursorBuilder: CandidateSliceItemBuilder[Query, CursorCandidate, CursorItem], - override val identifier: DecoratorIdentifier = DecoratorIdentifier("SliceItemCandidate")) - extends CandidateDecorator[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[Decoration]] = { - val cursorPresentations = candidates.collect { - case CandidateWithFeatures(candidate: CursorCandidate, features) => - val cursorItem = cursorBuilder(query, candidate, features) - val presentation = SliceItemPresentation(sliceItem = cursorItem) - - Decoration(candidate, presentation) - } - - Stitch.value(cursorPresentations) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD deleted file mode 100644 index bbbde90f6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala deleted file mode 100644 index 307911c85..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/slice/builder/CursorCandidateSliceItemBuilder.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.slice.builder - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.component_library.model.candidate.{ - NextCursor => CursorCandidateNextCursor -} -import com.twitter.product_mixer.component_library.model.candidate.{ - PreviousCursor => CursorCandidatePreviousCursor -} -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem -import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.slice.builder.CandidateSliceItemBuilder - -case class CursorCandidateSliceItemBuilder() - extends CandidateSliceItemBuilder[PipelineQuery, CursorCandidate, CursorItem] { - - override def apply( - query: PipelineQuery, - candidate: CursorCandidate, - featureMap: FeatureMap - ): CursorItem = - candidate.cursorType match { - case CursorCandidateNextCursor => CursorItem(candidate.value, NextCursor) - case CursorCandidatePreviousCursor => CursorItem(candidate.value, PreviousCursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD deleted file mode 100644 index ea3b7b298..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/BUILD +++ /dev/null @@ -1,108 +0,0 @@ -scala_library( - name = "urt", - sources = ["**/*.scala"] + exclude_globs(["builder/richtext/*.scala"]), - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ":richtext", - "3rdparty/jvm/com/twitter/bijection:json", - "3rdparty/jvm/com/twitter/bijection:scrooge", - "explore/explore-mixer/server/src/main/scala/com/twitter/explore_mixer/model/request", - "interests-mixer/server/src/main/scala/com/twitter/interests_mixer/model/request", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ads/adserver:ad_metadata_container-scala", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - "src/thrift/com/twitter/hermit:hermit-scala", - "src/thrift/com/twitter/suggests/controller_data:controller_data-scala", - "src/thrift/com/twitter/timelines/service:thrift-scala", - "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala", - "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala", - "stringcenter/client", - "stringcenter/client/src/main/java", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client", - "timelines/src/main/scala/com/twitter/timelines/util", - "trends/trending_content/src/main/scala/com/twitter/trends/trending_content/util:compacting-number-localizer", - "tweetconvosvc/common/src/main/thrift/com/twitter/tweetconvosvc/tweet_ancestor:thrift-scala", - "twitter-text/lib/java/src/main/java/com/twitter/twittertext", - ], - exports = [ - ":richtext", - "3rdparty/jvm/com/twitter/bijection:json", - "3rdparty/jvm/com/twitter/bijection:scrooge", - "explore/explore-mixer/server/src/main/scala/com/twitter/explore_mixer/model/request", - "interests-mixer/server/src/main/scala/com/twitter/interests_mixer/model/request", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ads/adserver:ad_metadata_container-scala", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - "src/thrift/com/twitter/suggests/controller_data:controller_data-scala", - "src/thrift/com/twitter/timelines/service:thrift-scala", - "src/thrift/com/twitter/timelinescorer/common/scoredtweetcandidate:thrift-scala", - "src/thrift/com/twitter/timelineservice/server/internal:thrift-scala", - "stringcenter/client", - "stringcenter/client/src/main/java", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client", - "timelines/src/main/scala/com/twitter/timelines/util", - "tweetconvosvc/common/src/main/thrift/com/twitter/tweetconvosvc/tweet_ancestor:thrift-scala", - "twitter-text/lib/java/src/main/java/com/twitter/twittertext", - ], -) - -scala_library( - name = "richtext", - sources = ["builder/richtext/*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "twitter-text/lib/java/src/main/java/com/twitter/twittertext", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "twitter-text/lib/java/src/main/java/com/twitter/twittertext", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala deleted file mode 100644 index d0a517b2d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtConversationItemCandidateDecorator.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.presentation.urt.ConversationModuleItem -import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItemTreeDisplay -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -case class UrtConversationItemCandidateDecorator[ - Query <: PipelineQuery, - Candidate <: BaseTweetCandidate -]( - tweetCandidateUrtItemBuilder: TweetCandidateUrtItemBuilder[Query, Candidate], - override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtConversationItem")) - extends CandidateDecorator[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[Decoration]] = { - val candidatePresentations = candidates.view.zipWithIndex.map { - case (candidate, index) => - val itemPresentation = new UrtItemPresentation( - timelineItem = tweetCandidateUrtItemBuilder( - pipelineQuery = query, - tweetCandidate = candidate.candidate, - candidateFeatures = candidate.features) - ) with ConversationModuleItem { - override val treeDisplay: Option[ModuleItemTreeDisplay] = None - override val dispensable: Boolean = index < candidates.length - 1 - } - - Decoration(candidate.candidate, itemPresentation) - } - - Stitch.value(candidatePresentations) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala deleted file mode 100644 index 81398cd3d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemCandidateDecorator.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt - -import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.stitch.Stitch - -/** - * Decorator that will apply the provided [[CandidateUrtEntryBuilder]] to each candidate independently to make a [[TimelineItem]] - */ -case class UrtItemCandidateDecorator[ - Query <: PipelineQuery, - BuilderInput <: UniversalNoun[Any], - BuilderOutput <: TimelineItem -]( - builder: CandidateUrtEntryBuilder[Query, BuilderInput, BuilderOutput], - override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtItemCandidate")) - extends CandidateDecorator[Query, BuilderInput] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[BuilderInput]] - ): Stitch[Seq[Decoration]] = { - val candidatePresentations = candidates.map { candidate => - val itemPresentation = UrtItemPresentation( - timelineItem = builder(query, candidate.candidate, candidate.features) - ) - - Decoration(candidate.candidate, itemPresentation) - } - - Stitch.value(candidatePresentations) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala deleted file mode 100644 index 928b506b9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtItemInModuleDecorator.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt - -import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation -import com.twitter.product_mixer.component_library.model.presentation.urt.UrtModulePresentation -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.stitch.Stitch - -/** - * Decorator that will apply the provided [[urtItemCandidateDecorator]] to all the `candidates` and apply - * the same [[UrtModulePresentation]] from [[moduleBuilder]] to each Candidate. - */ -case class UrtItemInModuleDecorator[ - Query <: PipelineQuery, - BuilderInput <: UniversalNoun[Any], - BuilderOutput <: TimelineItem -]( - urtItemCandidateDecorator: CandidateDecorator[Query, BuilderInput], - moduleBuilder: BaseTimelineModuleBuilder[Query, BuilderInput], - override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtItemInModule")) - extends CandidateDecorator[Query, BuilderInput] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[BuilderInput]] - ): Stitch[Seq[Decoration]] = { - if (candidates.nonEmpty) { - val urtItemCandidatesWithDecoration = urtItemCandidateDecorator(query, candidates) - - // Pass candidates to support when the module is constructed dynamically based on the list - val modulePresentation = - UrtModulePresentation(moduleBuilder(query, candidates)) - - urtItemCandidatesWithDecoration.map { candidates => - candidates.collect { - case Decoration(candidate, urtItemPresentation: UrtItemPresentation) => - Decoration( - candidate, - urtItemPresentation.copy(modulePresentation = Some(modulePresentation))) - } - } - } else { - Stitch.Nil - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala deleted file mode 100644 index 3c13056b3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/UrtMultipleModulesDecorator.scala +++ /dev/null @@ -1,108 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt - -import com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation -import com.twitter.product_mixer.component_library.model.presentation.urt.UrtModulePresentation -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.stitch.Stitch -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleIdGeneration -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.AutomaticUniqueModuleId -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder - -/** - * Given a [[CandidateWithFeatures]] return the corresponding group with which it should be - * associated. Returning none will result in the candidate not being assigned to any module. - */ -trait GroupByKey[-Query <: PipelineQuery, -BuilderInput <: UniversalNoun[Any], Key] { - def apply(query: Query, candidate: BuilderInput, candidateFeatures: FeatureMap): Option[Key] -} - -/** - * Similar to [[UrtItemInModuleDecorator]] except that this decorator can assign items to different - * modules based on the provided [[GroupByKey]]. - * - * @param urtItemCandidateDecorator decorates individual item candidates - * @param moduleBuilder builds a module from a particular candidate group - * @param groupByKey assigns each candidate a module group. Returning [[None]] will result in the - * candidate not being assigned to a module - */ -case class UrtMultipleModulesDecorator[ - -Query <: PipelineQuery, - -BuilderInput <: UniversalNoun[Any], - GroupKey -]( - urtItemCandidateDecorator: CandidateDecorator[Query, BuilderInput], - moduleBuilder: BaseTimelineModuleBuilder[Query, BuilderInput], - groupByKey: GroupByKey[Query, BuilderInput, GroupKey], - override val identifier: DecoratorIdentifier = DecoratorIdentifier("UrtMultipleModules")) - extends CandidateDecorator[Query, BuilderInput] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[BuilderInput]] - ): Stitch[Seq[Decoration]] = { - if (candidates.nonEmpty) { - - /** Individual candidates with [[UrtItemPresentation]]s */ - val decoratedCandidatesStitch: Stitch[ - Seq[(CandidateWithFeatures[BuilderInput], Decoration)] - ] = urtItemCandidateDecorator(query, candidates).map(candidates.zip(_)) - - decoratedCandidatesStitch.map { decoratedCandidates => - // Group candidates into modules - val candidatesByModule: Map[Option[GroupKey], Seq[ - (CandidateWithFeatures[BuilderInput], Decoration) - ]] = - decoratedCandidates.groupBy { - case (CandidateWithFeatures(candidate, features), _) => - groupByKey(query, candidate, features) - } - - candidatesByModule.iterator.zipWithIndex.flatMap { - - // A None group key indicates these candidates should not be put into a module. Return - // the decorated candidates. - case ((None, candidateGroup), _) => - candidateGroup.map { - case (_, decoration) => decoration - } - - // Build a UrtModulePresentation and add it to each candidate's decoration. - case ((_, candidateGroup), index) => - val (candidatesWithFeatures, decorations) = candidateGroup.unzip - - /** - * Build the module and update its ID if [[AutomaticUniqueModuleId]]s are being used. - * Forcing IDs to be different ensures that modules are never accidentally grouped - * together, since all other fields might otherwise be equal (candidates aren't added - * to modules until the domain marshalling phase). - */ - val timelineModule = { - val module = moduleBuilder(query, candidatesWithFeatures) - - ModuleIdGeneration(module.id) match { - case id: AutomaticUniqueModuleId => module.copy(id = id.withOffset(index).moduleId) - case _ => module - } - } - - val modulePresentation = UrtModulePresentation(timelineModule) - - decorations.collect { - case Decoration(candidate, urtItemPresentation: UrtItemPresentation) => - Decoration( - candidate, - urtItemPresentation.copy(modulePresentation = Some(modulePresentation))) - } - }.toSeq - } - } else { - Stitch.Nil - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala deleted file mode 100644 index 0dd1234fc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/contextual_ref/ContextualTweetRefBuilder.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.contextual_ref - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.ContextualTweetRef -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.TweetHydrationContext - -case class ContextualTweetRefBuilder[-Candidate <: BaseTweetCandidate]( - tweetHydrationContext: TweetHydrationContext) { - - def apply(candidate: Candidate): Option[ContextualTweetRef] = - Some(ContextualTweetRef(candidate.id, Some(tweetHydrationContext))) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala deleted file mode 100644 index fdb5c4e48..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/conversations/ConversationModuleMetadataBuilder.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.conversations - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleMetadataBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleConversationMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ConversationModuleMetadataBuilder[ - Query <: PipelineQuery, - Candidate <: BaseTweetCandidate -]( - ancestorIdsFeature: Feature[_, Seq[Long]], - allIdsOrdering: Ordering[Long]) - extends BaseModuleMetadataBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): ModuleMetadata = { - - val ancestors = candidates.last.features.getOrElse(ancestorIdsFeature, Seq.empty) - val sortedAllTweetIds = (candidates.last.candidate.id +: ancestors).sorted(allIdsOrdering) - - ModuleMetadata( - adsMetadata = None, - conversationMetadata = Some( - ModuleConversationMetadata( - allTweetIds = Some(sortedAllTweetIds), - socialContext = None, - enableDeduplication = Some(true) - )), - gridCarouselMetadata = None - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala deleted file mode 100644 index 2387271da..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,205 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline - -import com.twitter.onboarding.injections.thriftscala.Injection -import com.twitter.onboarding.injections.{thriftscala => onboardingthrift} -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.OnboardingInjectionConversions._ -import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptCarouselTileFeature -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptInjectionsFeature -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptOffsetInModuleFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverFullCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverHalfCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCover -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCover -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.HeaderImagePromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object FlipPromptCandidateUrtItemBuilder { - val FlipPromptClientEventInfoElement: String = "flip-prompt-message" -} - -case class FlipPromptCandidateUrtItemBuilder[-Query <: PipelineQuery]() - extends CandidateUrtEntryBuilder[Query, BasePromptCandidate[Any], TimelineItem] { - - override def apply( - query: Query, - promptCandidate: BasePromptCandidate[Any], - candidateFeatures: FeatureMap - ): TimelineItem = { - val injection = candidateFeatures.get(FlipPromptInjectionsFeature) - - injection match { - case onboardingthrift.Injection.InlinePrompt(candidate) => - MessagePromptItem( - id = promptCandidate.id.toString, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = buildClientEventInfo(injection), - feedbackActionInfo = candidate.feedbackInfo.map(convertFeedbackInfo), - isPinned = Some(candidate.isPinnedEntry), - content = getInlinePromptMessageContent(candidate), - impressionCallbacks = candidate.impressionCallbacks.map(_.map(convertCallback).toList) - ) - case onboardingthrift.Injection.FullCover(candidate) => - FullCover( - id = promptCandidate.id.toString, - // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId - sortIndex = None, - clientEventInfo = - Some(OnboardingInjectionConversions.convertClientEventInfo(candidate.clientEventInfo)), - content = getFullCoverContent(candidate) - ) - case onboardingthrift.Injection.HalfCover(candidate) => - HalfCover( - id = promptCandidate.id.toString, - // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId - sortIndex = None, - clientEventInfo = - Some(OnboardingInjectionConversions.convertClientEventInfo(candidate.clientEventInfo)), - content = getHalfCoverContent(candidate) - ) - case Injection.TilesCarousel(_) => - val offsetInModuleOption = - candidateFeatures.get(FlipPromptOffsetInModuleFeature) - val offsetInModule = - offsetInModuleOption.getOrElse(throw FlipPromptOffsetInModuleMissing) - val tileOption = - candidateFeatures.get(FlipPromptCarouselTileFeature) - val tile = tileOption.getOrElse(throw FlipPromptCarouselTileMissing) - TilesCarouselConversions.convertTile(tile, offsetInModule) - case onboardingthrift.Injection.RelevancePrompt(candidate) => - PromptItem( - id = promptCandidate.id.toString, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = buildClientEventInfo(injection), - content = RelevancePromptConversions.convertContent(candidate), - impressionCallbacks = Some(candidate.impressionCallbacks.map(convertCallback).toList) - ) - case _ => throw new UnsupportedFlipPromptException(injection) - } - } - - private def getInlinePromptMessageContent( - candidate: onboardingthrift.InlinePrompt - ): MessageContent = { - candidate.image match { - case Some(image) => - HeaderImagePromptMessageContent( - headerImage = convertImage(image), - headerText = Some(candidate.headerText.text), - bodyText = candidate.bodyText.map(_.text), - primaryButtonAction = candidate.primaryAction.map(convertButtonAction), - secondaryButtonAction = candidate.secondaryAction.map(convertButtonAction), - headerRichText = Some(convertRichText(candidate.headerText)), - bodyRichText = candidate.bodyText.map(convertRichText), - action = - None - ) - case None => - InlinePromptMessageContent( - headerText = candidate.headerText.text, - bodyText = candidate.bodyText.map(_.text), - primaryButtonAction = candidate.primaryAction.map(convertButtonAction), - secondaryButtonAction = candidate.secondaryAction.map(convertButtonAction), - headerRichText = Some(convertRichText(candidate.headerText)), - bodyRichText = candidate.bodyText.map(convertRichText), - socialContext = candidate.socialContext.map(convertSocialContext), - userFacepile = candidate.promptUserFacepile.map(convertUserFacePile) - ) - } - } - - private def getFullCoverContent( - candidate: onboardingthrift.FullCover - ): FullCoverContent = - FullCoverContent( - displayType = CoverFullCoverDisplayType, - primaryText = convertRichText(candidate.primaryText), - primaryCoverCta = convertCoverCta(candidate.primaryButtonAction), - secondaryCoverCta = candidate.secondaryButtonAction.map(convertCoverCta), - secondaryText = candidate.secondaryText.map(convertRichText), - imageVariant = candidate.image.map(img => convertImageVariant(img.image)), - details = candidate.detailText.map(convertRichText), - dismissInfo = candidate.dismissInfo.map(convertDismissInfo), - imageDisplayType = candidate.image.map(img => convertImageDisplayType(img.imageDisplayType)), - impressionCallbacks = candidate.impressionCallbacks.map(_.map(convertCallback).toList) - ) - - private def getHalfCoverContent( - candidate: onboardingthrift.HalfCover - ): HalfCoverContent = - HalfCoverContent( - displayType = - candidate.displayType.map(convertHalfCoverDisplayType).getOrElse(CoverHalfCoverDisplayType), - primaryText = convertRichText(candidate.primaryText), - primaryCoverCta = convertCoverCta(candidate.primaryButtonAction), - secondaryCoverCta = candidate.secondaryButtonAction.map(convertCoverCta), - secondaryText = candidate.secondaryText.map(convertRichText), - coverImage = candidate.image.map(convertCoverImage), - dismissible = candidate.dismissible, - dismissInfo = candidate.dismissInfo.map(convertDismissInfo), - impressionCallbacks = candidate.impressionCallbacks.map(_.map(convertCallback).toList) - ) - - private def buildClientEventInfo( - injection: Injection - ): Option[ClientEventInfo] = { - injection match { - //To keep parity between TimelineMixer and Product Mixer, inline prompt switches sets the prompt product identifier as the component and no element. Also includes clientEventDetails - case onboardingthrift.Injection.InlinePrompt(candidate) => - val clientEventDetails: ClientEventDetails = - ClientEventDetails( - conversationDetails = None, - timelinesDetails = Some(TimelinesDetails(injectionType = Some("Message"), None, None)), - articleDetails = None, - liveEventDetails = None, - commerceDetails = None - ) - Some( - ClientEventInfo( - component = candidate.injectionIdentifier, - element = None, - details = Some(clientEventDetails), - action = None, - entityToken = None)) - // To keep parity between TLM and PM we swap component and elements. - case onboardingthrift.Injection.RelevancePrompt(candidate) => - Some( - ClientEventInfo( - // Identifier is prefixed with onboarding per TLM - component = Some("onboarding_" + candidate.injectionIdentifier), - element = Some("relevance_prompt"), - details = None, - action = None, - entityToken = None - )) - - case _ => None - } - } - -} - -class UnsupportedFlipPromptException(injection: onboardingthrift.Injection) - extends UnsupportedOperationException( - "Unsupported timeline item " + TransportMarshaller.getSimpleName(injection.getClass)) - -object FlipPromptOffsetInModuleMissing - extends NoSuchElementException( - "FlipPromptOffsetInModuleFeature must be set for the TilesCarousel FLIP injection in PromptCandidateSource") - -object FlipPromptCarouselTileMissing - extends NoSuchElementException( - "FlipPromptCarouselTileFeature must be set for the TilesCarousel FLIP injection in PromptCandidateSource") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala deleted file mode 100644 index ab6d21057..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptModuleGrouping.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline - -import com.twitter.product_mixer.component_library.decorator.urt.GroupByKey -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptInjectionsFeature -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptOffsetInModuleFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object FlipPromptModuleGrouping extends GroupByKey[PipelineQuery, UniversalNoun[Any], Int] { - override def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): Option[Int] = { - val injection = candidateFeatures.get(FlipPromptInjectionsFeature) - val offsetInModule = candidateFeatures.getOrElse(FlipPromptOffsetInModuleFeature, None) - - // We return None for any candidate that doesn't have an offsetInModule, so that they are left as independent items. - // Otherwise, we return a hash of the injection instance which will be used to aggregate candidates with matching values into a module. - offsetInModule.map(_ => injection.hashCode()) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala deleted file mode 100644 index 00383f6ce..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/FlipPromptUrtModuleBuilder.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline - -import com.twitter.onboarding.injections.thriftscala.Injection -import com.twitter.onboarding.injections.{thriftscala => onboardingthrift} -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.AutomaticUniqueModuleId -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleIdGeneration -import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipPromptInjectionsFeature -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Carousel -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class FlipPromptUrtModuleBuilder[-Query <: PipelineQuery]( - moduleIdGeneration: ModuleIdGeneration = AutomaticUniqueModuleId()) - extends BaseTimelineModuleBuilder[Query, BasePromptCandidate[Any]] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[BasePromptCandidate[Any]]] - ): TimelineModule = { - val firstCandidate = candidates.head - val injection = firstCandidate.features.get(FlipPromptInjectionsFeature) - injection match { - case Injection.TilesCarousel(candidate) => - TimelineModule( - id = moduleIdGeneration.moduleId, - sortIndex = None, - entryNamespace = EntryNamespace("flip-timeline-module"), - clientEventInfo = - Some(OnboardingInjectionConversions.convertClientEventInfo(candidate.clientEventInfo)), - feedbackActionInfo = - candidate.feedbackInfo.map(OnboardingInjectionConversions.convertFeedbackInfo), - isPinned = Some(candidate.isPinnedEntry), - // Items are automatically set in the domain marshaller phase - items = Seq.empty, - displayType = Carousel, - header = candidate.header.map(TilesCarouselConversions.convertModuleHeader), - footer = None, - metadata = None, - showMoreBehavior = None - ) - case _ => throw new UnsupportedFlipPromptInModuleException(injection) - } - } -} - -class UnsupportedFlipPromptInModuleException(injection: onboardingthrift.Injection) - extends UnsupportedOperationException( - "Unsupported timeline item in a Flip prompt module " + TransportMarshaller.getSimpleName( - injection.getClass)) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala deleted file mode 100644 index 92c8d97d7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/OnboardingInjectionConversions.scala +++ /dev/null @@ -1,361 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline - -import com.twitter.onboarding.injections.{thriftscala => onboardingthrift} -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CenterCoverHalfCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorDismiss -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorNavigate -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCta -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCtaBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverHalfCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverImage -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon._ -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.FollowAllMessageActionType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.LargeUserFacepileDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageActionType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageImage -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepile -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Bounce -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.ButtonStyle -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Default -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Primary -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Secondary -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Text -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Destructive -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Neutral -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveSecondary -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveText -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Dismiss -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DismissInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FollowGeneralContextType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageAnimationType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FullWidth -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Icon -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.IconSmall -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpoint -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpointOptions -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Center -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Natural -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextCashtag -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextHashtag -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextList -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextMention -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextUser -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong - -/*** - * Helper class to convert onboarding thrift to product-mixer models - */ -object OnboardingInjectionConversions { - - def convertFeedbackInfo( - feedbackInfo: onboardingthrift.FeedbackInfo - ): FeedbackActionInfo = { - val actions = feedbackInfo.actions.map { - case onboardingthrift.FeedbackAction.DismissAction(dismissAction) => - FeedbackAction( - Dismiss, - prompt = dismissAction.prompt, - confirmation = dismissAction.confirmation, - hasUndoAction = dismissAction.hasUndoAction, - feedbackUrl = dismissAction.feedbackUrl, - childFeedbackActions = - None, - confirmationDisplayType = None, - clientEventInfo = None, - icon = None, - richBehavior = None, - subprompt = None, - encodedFeedbackRequest = None - ) - case onboardingthrift.FeedbackAction.UnknownUnionField(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - FeedbackActionInfo( - feedbackActions = actions, - feedbackMetadata = None, - displayContext = None, - clientEventInfo = None) - } - - def convertClientEventInfo(input: onboardingthrift.ClientEventInfo): ClientEventInfo = - ClientEventInfo( - component = input.component, - element = input.element, - details = None, - action = input.action, - entityToken = None) - - def convertCallback(callback: onboardingthrift.Callback): Callback = - Callback(callback.endpoint) - - def convertImage(image: onboardingthrift.Image): MessageImage = - MessageImage( - Set(convertImageVariant(image.image)), - backgroundColor = - None - ) - - def convertCoverImage(image: onboardingthrift.Image): CoverImage = - CoverImage( - convertImageVariant(image.image), - imageDisplayType = convertImageDisplayType(image.imageDisplayType), - imageAnimationType = image.imageAnimationType.map(convertImageAnimationType), - ) - - def convertImageDisplayType( - imageDisplayType: onboardingthrift.ImageDisplayType - ): ImageDisplayType = - imageDisplayType match { - case onboardingthrift.ImageDisplayType.Icon => Icon - case onboardingthrift.ImageDisplayType.FullWidth => FullWidth - case onboardingthrift.ImageDisplayType.IconSmall => IconSmall - case onboardingthrift.ImageDisplayType.EnumUnknownImageDisplayType(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - private def convertImageAnimationType( - imageAnimationType: onboardingthrift.ImageAnimationType - ): ImageAnimationType = - imageAnimationType match { - case onboardingthrift.ImageAnimationType.Bounce => Bounce - case onboardingthrift.ImageAnimationType.EnumUnknownImageAnimationType(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - def convertImageVariant(imageVariant: onboardingthrift.ImageVariant): ImageVariant = - ImageVariant( - url = imageVariant.url, - width = imageVariant.width, - height = imageVariant.height, - palette = None) - - def convertButtonAction( - buttonAction: onboardingthrift.ButtonAction - ): MessageTextAction = - MessageTextAction( - buttonAction.text, - MessageAction( - dismissOnClick = buttonAction.dismissOnClick.getOrElse(true), - url = getActionUrl(buttonAction), - clientEventInfo = Some(convertClientEventInfo(buttonAction.clientEventInfo)), - onClickCallbacks = buttonAction.callbacks.map(_.map(convertCallback).toList) - ) - ) - - private def getActionUrl(buttonAction: onboardingthrift.ButtonAction) = - buttonAction.buttonBehavior match { - case onboardingthrift.ButtonBehavior.Navigate(navigate) => Some(navigate.url.url) - case onboardingthrift.ButtonBehavior.Dismiss(_) => None - case onboardingthrift.ButtonBehavior.UnknownUnionField(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - def convertRichText( - richText: com.twitter.onboarding.injections.thriftscala.RichText - ): RichText = { - val entities = richText.entities.map(entity => - RichTextEntity( - entity.fromIndex, - entity.toIndex, - entity.ref.map(convertRef), - entity.format.map(convertFormat))) - RichText( - text = richText.text, - entities = entities.toList, - rtl = richText.rtl, - alignment = richText.alignment.map(convertAlignment)) - } - - private def convertAlignment(alignment: onboardingthrift.RichTextAlignment): RichTextAlignment = - alignment match { - case onboardingthrift.RichTextAlignment.Natural => Natural - case onboardingthrift.RichTextAlignment.Center => Center - case onboardingthrift.RichTextAlignment.EnumUnknownRichTextAlignment(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - private def convertRef(ref: onboardingthrift.ReferenceObject): ReferenceObject = - ref match { - case onboardingthrift.ReferenceObject.User(user) => RichTextUser(user.id) - case onboardingthrift.ReferenceObject.Mention(mention) => - RichTextMention(mention.id, mention.screenName) - case onboardingthrift.ReferenceObject.Hashtag(hashtag) => RichTextHashtag(hashtag.text) - - case onboardingthrift.ReferenceObject.Cashtag(cashtag) => RichTextCashtag(cashtag.text) - case onboardingthrift.ReferenceObject.TwitterList(twList) => - RichTextList(twList.id, twList.url) - case onboardingthrift.ReferenceObject.Url(url) => RichTextHashtag(url.url) - case onboardingthrift.ReferenceObject.UnknownUnionField(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - private def convertFormat(format: onboardingthrift.RichTextFormat): RichTextFormat = - format match { - case onboardingthrift.RichTextFormat.Plain => Plain - case onboardingthrift.RichTextFormat.Strong => Strong - case onboardingthrift.RichTextFormat.EnumUnknownRichTextFormat(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - // Specific to Message prompt - def convertSocialContext(socialContext: onboardingthrift.RichText): SocialContext = - GeneralContext( - contextType = FollowGeneralContextType, - text = socialContext.text, - url = None, - contextImageUrls = None, - landingUrl = None) - - def convertUserFacePile( - userFacepile: onboardingthrift.PromptUserFacepile - ): UserFacepile = - UserFacepile( - userIds = userFacepile.userIds.toList, - featuredUserIds = userFacepile.featuredUserIds.toList, - action = userFacepile.action.map(convertButtonAction), - actionType = userFacepile.actionType.map(convertUserFacePileActionType), - displaysFeaturingText = userFacepile.displaysFeaturingText, - displayType = Some(LargeUserFacepileDisplayType) - ) - - private def convertUserFacePileActionType( - actionType: onboardingthrift.FacepileActionType - ): MessageActionType = - actionType match { - case onboardingthrift.FacepileActionType.FollowAll => FollowAllMessageActionType - case onboardingthrift.FacepileActionType.EnumUnknownFacepileActionType(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - // Specific to Cover - - def convertHalfCoverDisplayType( - displayType: onboardingthrift.HalfCoverDisplayType - ): HalfCoverDisplayType = - displayType match { - case onboardingthrift.HalfCoverDisplayType.Cover => CoverHalfCoverDisplayType - case onboardingthrift.HalfCoverDisplayType.CenterCover => - CenterCoverHalfCoverDisplayType - case onboardingthrift.HalfCoverDisplayType.EnumUnknownHalfCoverDisplayType(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - def convertDismissInfo(dismissInfo: onboardingthrift.DismissInfo): DismissInfo = - DismissInfo(dismissInfo.callbacks.map(_.map(convertCallback))) - - def convertCoverCta( - buttonAction: onboardingthrift.ButtonAction - ): CoverCta = - CoverCta( - buttonAction.text, - ctaBehavior = convertCoverCtaBehavior(buttonAction.buttonBehavior), - callbacks = buttonAction.callbacks.map(_.map(convertCallback).toList), - clientEventInfo = Some(convertClientEventInfo(buttonAction.clientEventInfo)), - icon = buttonAction.icon.map(covertHorizonIcon), - buttonStyle = buttonAction.buttonStyle.map(covertButtonStyle) - ) - - private def convertCoverCtaBehavior( - behavior: onboardingthrift.ButtonBehavior - ): CoverCtaBehavior = - behavior match { - case onboardingthrift.ButtonBehavior.Navigate(navigate) => - CoverBehaviorNavigate(convertUrl(navigate.url)) - case onboardingthrift.ButtonBehavior.Dismiss(dismiss) => - CoverBehaviorDismiss(dismiss.feedbackMessage.map(convertRichText)) - case onboardingthrift.ButtonBehavior.UnknownUnionField(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - private def covertButtonStyle(bStyle: onboardingthrift.CtaButtonStyle): ButtonStyle = - bStyle match { - case onboardingthrift.CtaButtonStyle.Default => Default - case onboardingthrift.CtaButtonStyle.Primary => Primary - case onboardingthrift.CtaButtonStyle.Secondary => Secondary - case onboardingthrift.CtaButtonStyle.Text => Text - case onboardingthrift.CtaButtonStyle.Destructive => Destructive - case onboardingthrift.CtaButtonStyle.Neutral => Neutral - case onboardingthrift.CtaButtonStyle.DestructiveSecondary => DestructiveSecondary - case onboardingthrift.CtaButtonStyle.DestructiveText => DestructiveText - case onboardingthrift.CtaButtonStyle.EnumUnknownCtaButtonStyle(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - - private def covertHorizonIcon(icon: onboardingthrift.HorizonIcon): HorizonIcon = - icon match { - case onboardingthrift.HorizonIcon.Bookmark => Bookmark - case onboardingthrift.HorizonIcon.Moment => Moment - case onboardingthrift.HorizonIcon.Debug => Debug - case onboardingthrift.HorizonIcon.Error => Error - case onboardingthrift.HorizonIcon.Follow => Follow - case onboardingthrift.HorizonIcon.Unfollow => Unfollow - case onboardingthrift.HorizonIcon.Smile => Smile - case onboardingthrift.HorizonIcon.Frown => Frown - case onboardingthrift.HorizonIcon.Help => Help - case onboardingthrift.HorizonIcon.Link => Link - case onboardingthrift.HorizonIcon.Message => Message - case onboardingthrift.HorizonIcon.No => No - case onboardingthrift.HorizonIcon.Outgoing => Outgoing - case onboardingthrift.HorizonIcon.Pin => Pin - case onboardingthrift.HorizonIcon.Retweet => Retweet - case onboardingthrift.HorizonIcon.Speaker => Speaker - case onboardingthrift.HorizonIcon.Trashcan => Trashcan - case onboardingthrift.HorizonIcon.Feedback => Feedback - case onboardingthrift.HorizonIcon.FeedbackClose => FeedbackClose - case onboardingthrift.HorizonIcon.EyeOff => EyeOff - case onboardingthrift.HorizonIcon.Moderation => Moderation - case onboardingthrift.HorizonIcon.Topic => Topic - case onboardingthrift.HorizonIcon.TopicClose => TopicClose - case onboardingthrift.HorizonIcon.Flag => Flag - case onboardingthrift.HorizonIcon.TopicFilled => TopicFilled - case onboardingthrift.HorizonIcon.NotificationsFollow => NotificationsFollow - case onboardingthrift.HorizonIcon.Person => Person - case onboardingthrift.HorizonIcon.Logo => Logo - case onboardingthrift.HorizonIcon.EnumUnknownHorizonIcon(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - - } - - def convertUrl(url: onboardingthrift.Url): Url = { - val urlType = url.urlType match { - case onboardingthrift.UrlType.ExternalUrl => ExternalUrl - case onboardingthrift.UrlType.DeepLink => DeepLink - case onboardingthrift.UrlType.UrtEndpoint => UrtEndpoint - case onboardingthrift.UrlType.EnumUnknownUrlType(value) => - throw new UnsupportedOperationException(s"Unknown product: $value") - } - Url(urlType, url.url, url.urtEndpointOptions.map(convertUrtEndpointOptions)) - } - - private def convertUrtEndpointOptions( - urtEndpointOptions: onboardingthrift.UrtEndpointOptions - ): UrtEndpointOptions = - UrtEndpointOptions( - requestParams = urtEndpointOptions.requestParams.map(_.toMap), - title = urtEndpointOptions.title, - cacheId = urtEndpointOptions.cacheId, - subtitle = urtEndpointOptions.subtitle - ) - -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala deleted file mode 100644 index 78e69ee3e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/RelevancePromptConversions.scala +++ /dev/null @@ -1,76 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline - -import com.twitter.onboarding.injections.{thriftscala => onboardingthrift} -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.Compact -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.Large -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.Normal -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback - -/*** - * Helper class to convert Relevance Prompt related onboarding thrift to product-mixer models - */ -object RelevancePromptConversions { - def convertContent( - candidate: onboardingthrift.RelevancePrompt - ): RelevancePromptContent = - RelevancePromptContent( - displayType = convertDisplayType(candidate.displayType), - title = candidate.title.text, - confirmation = buildConfirmation(candidate), - isRelevantText = candidate.isRelevantButton.text, - notRelevantText = candidate.notRelevantButton.text, - isRelevantCallback = convertCallbacks(candidate.isRelevantButton.callbacks), - notRelevantCallback = convertCallbacks(candidate.notRelevantButton.callbacks), - isRelevantFollowUp = None, - notRelevantFollowUp = None - ) - - // Based on com.twitter.timelinemixer.injection.model.candidate.OnboardingRelevancePromptDisplayType#fromThrift - def convertDisplayType( - displayType: onboardingthrift.RelevancePromptDisplayType - ): RelevancePromptDisplayType = - displayType match { - case onboardingthrift.RelevancePromptDisplayType.Normal => Normal - case onboardingthrift.RelevancePromptDisplayType.Compact => Compact - case onboardingthrift.RelevancePromptDisplayType.Large => Large - case onboardingthrift.RelevancePromptDisplayType - .EnumUnknownRelevancePromptDisplayType(value) => - throw new UnsupportedOperationException(s"Unknown display type: $value") - } - - // Based on com.twitter.timelinemixer.injection.model.injection.OnboardingRelevancePromptInjection#buildConfirmation - def buildConfirmation(candidate: onboardingthrift.RelevancePrompt): String = { - val isRelevantTextConfirmation = - buttonToDismissFeedbackText(candidate.isRelevantButton).getOrElse("") - val notRelevantTextConfirmation = - buttonToDismissFeedbackText(candidate.notRelevantButton).getOrElse("") - if (isRelevantTextConfirmation != notRelevantTextConfirmation) - throw new IllegalArgumentException( - s"""confirmation text not consistent for two buttons, : - isRelevantConfirmation: ${isRelevantTextConfirmation} - notRelevantConfirmation: ${notRelevantTextConfirmation} - """ - ) - isRelevantTextConfirmation - } - - // Based on com.twitter.timelinemixer.injection.model.candidate.OnboardingInjectionAction#fromThrift - def buttonToDismissFeedbackText(button: onboardingthrift.ButtonAction): Option[String] = { - button.buttonBehavior match { - case onboardingthrift.ButtonBehavior.Dismiss(d) => d.feedbackMessage.map(_.text) - case _ => None - } - } - - // Based on com.twitter.timelinemixer.injection.model.injection.OnboardingRelevancePromptInjection#buildCallback - def convertCallbacks(onboardingCallbacks: Option[Seq[onboardingthrift.Callback]]): Callback = { - OnboardingInjectionConversions.convertCallback( - onboardingCallbacks - .flatMap(_.headOption) - .getOrElse( - throw new NoSuchElementException(s"Callback must be provided for the Relevance Prompt") - )) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala deleted file mode 100644 index dd4ce7c75..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/flexible_injection_pipeline/TilesCarouselConversions.scala +++ /dev/null @@ -1,154 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline - -import com.twitter.onboarding.injections.{thriftscala => onboardingthrift} -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.OnboardingInjectionConversions.convertImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.BlackRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.ClearRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepBlueRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepGrayRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepGreenRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepOrangeRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepPurpleRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepRedRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.DeepYellowRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedBlueRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedGrayRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedGreenRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedOrangeRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedPurpleRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedRedRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FadedYellowRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FaintBlueRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.FaintGrayRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightBlueRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightGrayRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightGreenRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightOrangeRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightPurpleRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightRedRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.LightYellowRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumGrayRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumGreenRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumOrangeRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumPurpleRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumRedRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.MediumYellowRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.TextBlackRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.TextBlueRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.TwitterBlueRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.WhiteRosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.CallToActionTileContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader - -object TilesCarouselConversions { - // Tiles Carousel Conversions - def convertTile(tile: onboardingthrift.Tile, id: Long): TileItem = { - tile.content match { - case standard: onboardingthrift.TileContent.Standard => - TileItem( - id = id, - sortIndex = None, - clientEventInfo = - Some(OnboardingInjectionConversions.convertClientEventInfo(tile.clientEventInfo)), - feedbackActionInfo = None, - title = standard.standard.title, - supportingText = "", - url = tile.url.map(OnboardingInjectionConversions.convertUrl), - image = tile.image.map(img => convertImageVariant(img.image)), - content = StandardTileContent( - title = standard.standard.title, - supportingText = "", - badge = standard.standard.badge.map(convertTileBadge) - ) - ) - case cta: onboardingthrift.TileContent.CallToAction => - TileItem( - id = id, - sortIndex = None, - clientEventInfo = - Some(OnboardingInjectionConversions.convertClientEventInfo(tile.clientEventInfo)), - feedbackActionInfo = None, - title = cta.callToAction.text, - supportingText = "", - url = tile.url.map(OnboardingInjectionConversions.convertUrl), - image = None, - content = CallToActionTileContent( - text = cta.callToAction.text, - richText = None, - ctaButton = None - ) - ) - case _ => - throw new UnsupportedTileCarouselConversionException(s"Tile Content: ${tile.content}") - } - } - - private def convertTileBadge(badge: onboardingthrift.Badge): Badge = { - Badge( - text = badge.text, - textColorName = badge.textColor.map(convertRosettaColor), - backgroundColorName = badge.backgroundColor.map(convertRosettaColor)) - } - - def convertModuleHeader(header: onboardingthrift.TilesCarouselHeader): ModuleHeader = { - ModuleHeader(header.header, None, None, None, None, Classic) - } - - private def convertRosettaColor(color: onboardingthrift.RosettaColor): RosettaColor = - color match { - case onboardingthrift.RosettaColor.White => WhiteRosettaColor - case onboardingthrift.RosettaColor.Black => BlackRosettaColor - case onboardingthrift.RosettaColor.Clear => ClearRosettaColor - case onboardingthrift.RosettaColor.TextBlack => TextBlackRosettaColor - case onboardingthrift.RosettaColor.TextBlue => TextBlueRosettaColor - - case onboardingthrift.RosettaColor.DeepGray => DeepGrayRosettaColor - case onboardingthrift.RosettaColor.MediumGray => MediumGrayRosettaColor - case onboardingthrift.RosettaColor.LightGray => LightGrayRosettaColor - case onboardingthrift.RosettaColor.FadedGray => FadedGrayRosettaColor - case onboardingthrift.RosettaColor.FaintGray => FaintGrayRosettaColor - - case onboardingthrift.RosettaColor.DeepOrange => DeepOrangeRosettaColor - case onboardingthrift.RosettaColor.MediumOrange => MediumOrangeRosettaColor - case onboardingthrift.RosettaColor.LightOrange => LightOrangeRosettaColor - case onboardingthrift.RosettaColor.FadedOrange => FadedOrangeRosettaColor - - case onboardingthrift.RosettaColor.DeepYellow => DeepYellowRosettaColor - case onboardingthrift.RosettaColor.MediumYellow => MediumYellowRosettaColor - case onboardingthrift.RosettaColor.LightYellow => LightYellowRosettaColor - case onboardingthrift.RosettaColor.FadedYellow => FadedYellowRosettaColor - - case onboardingthrift.RosettaColor.DeepGreen => DeepGreenRosettaColor - case onboardingthrift.RosettaColor.MediumGreen => MediumGreenRosettaColor - case onboardingthrift.RosettaColor.LightGreen => LightGreenRosettaColor - case onboardingthrift.RosettaColor.FadedGreen => FadedGreenRosettaColor - - case onboardingthrift.RosettaColor.DeepBlue => DeepBlueRosettaColor - case onboardingthrift.RosettaColor.TwitterBlue => TwitterBlueRosettaColor - case onboardingthrift.RosettaColor.LightBlue => LightBlueRosettaColor - case onboardingthrift.RosettaColor.FadedBlue => FadedBlueRosettaColor - case onboardingthrift.RosettaColor.FaintBlue => FaintBlueRosettaColor - - case onboardingthrift.RosettaColor.DeepPurple => DeepPurpleRosettaColor - case onboardingthrift.RosettaColor.MediumPurple => MediumPurpleRosettaColor - case onboardingthrift.RosettaColor.LightPurple => LightPurpleRosettaColor - case onboardingthrift.RosettaColor.FadedPurple => FadedPurpleRosettaColor - - case onboardingthrift.RosettaColor.DeepRed => DeepRedRosettaColor - case onboardingthrift.RosettaColor.MediumRed => MediumRedRosettaColor - case onboardingthrift.RosettaColor.LightRed => LightRedRosettaColor - case onboardingthrift.RosettaColor.FadedRed => FadedRedRosettaColor - case onboardingthrift.RosettaColor.EnumUnknownRosettaColor(i) => - throw new UnknownThriftEnumException("RosettaColor") - } - class UnknownThriftEnumException(enumName: String) - extends Exception(s"Unknown Thrift Enum Found: ${enumName}") - - class UnsupportedTileCarouselConversionException(UnsupportedTileType: String) - extends Exception(s"Unsupported Tile Type Found: ${UnsupportedTileType}") -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala deleted file mode 100644 index dd9a59e6c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/icon/HorizonIconBuilder.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.icon - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.icon.BaseHorizonIconBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class HorizonIconBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - icon: HorizonIcon) - extends BaseHorizonIconBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[HorizonIcon] = Some(icon) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala deleted file mode 100644 index 1593485fc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/ad/AdsCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,274 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.ad - -import com.twitter.ads.adserver.{thriftscala => ads} -import com.twitter.adserver.{thriftscala => adserver} -import com.twitter.product_mixer.component_library.decorator.urt.builder.contextual_ref.ContextualTweetRefBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder.TweetClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsTweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.Tweet -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.AdMetadataContainer -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Amplify -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.CallToAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.ClickTrackingInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DcmUrlOverrideType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DirectSponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerIssue -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerPolitical -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclosureType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DynamicPrerollType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Earned -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.IndirectSponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Issue -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.LiveTvEvent -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Marketplace -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.MediaInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoDisclosure -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoSponsorshipSponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Political -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Preroll -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SkAdNetworkData -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.UnknownUrlOverrideType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.VideoVariant -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.util.AdMetadataContainerSerializer -import com.twitter.timelines.util.PrerollMetadataSerializer - -/** - * [[AdsCandidateUrtItemBuilder]] takes a [[AdsCandidate]] (with a [[Query]] as additional context) - * and converts it into the Product Mixer URT representation, or throws an error. - * - * Currently, the only supported form for URT representation of the [[AdsCandidate]] is a [[Tweet]], - * but in the future it could be expanded to handle other forms of ads. - * - * @param tweetClientEventInfoBuilder Optionally, provide a ClientEventInfoBuilder for Tweets - * that given an AdsTweetCandidate and element of "tweet". - * @param tweetDisplayType Should be [[EmphasizedPromotedTweet]] on Profile timelines, - * otherwise [[Tweet]] - */ -case class AdsCandidateUrtItemBuilder[Query <: PipelineQuery]( - tweetClientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, AdsTweetCandidate]] = None, - contextualTweetRefBuilder: Option[ContextualTweetRefBuilder[AdsTweetCandidate]] = None, - tweetDisplayType: TweetDisplayType = Tweet) - extends CandidateUrtEntryBuilder[Query, AdsCandidate, TimelineItem] { - - override def apply( - pipelineQuery: Query, - candidate: AdsCandidate, - candidateFeatures: FeatureMap - ): TimelineItem = { - candidate match { - case tweetCandidate: AdsTweetCandidate => - TweetItem( - id = tweetCandidate.id, - entryNamespace = TweetItem.PromotedTweetEntryNamespace, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = tweetClientEventInfoBuilder.flatMap( - _.apply( - pipelineQuery, - tweetCandidate, - candidateFeatures, - Some(TweetClientEventInfoElement))), - feedbackActionInfo = None, - isPinned = None, - entryIdToReplace = None, - socialContext = None, - highlights = None, - innerTombstoneInfo = None, - timelinesScoreInfo = None, - hasModeratedReplies = None, - forwardPivot = None, - innerForwardPivot = None, - conversationAnnotation = None, - promotedMetadata = Some(promotedMetadata(tweetCandidate.adImpression)), - displayType = tweetDisplayType, - contextualTweetRef = contextualTweetRefBuilder.flatMap(_.apply(tweetCandidate)), - prerollMetadata = prerollMetadata(tweetCandidate.adImpression), - replyBadge = None, - destination = None - ) - } - } - - private def promotedMetadata(impression: adserver.AdImpression) = { - PromotedMetadata( - advertiserId = impression.advertiserId, - impressionString = impression.impressionString, - disclosureType = impression.disclosureType.map(convertDisclosureType), - experimentValues = impression.experimentValues.map(_.toMap), - promotedTrendId = impression.promotedTrendId.map(_.toLong), - promotedTrendName = impression.promotedTrendName, - promotedTrendQueryTerm = impression.promotedTrendQueryTerm, - promotedTrendDescription = impression.promotedTrendDescription, - clickTrackingInfo = impression.clickTrackingInfo.map(convertClickTrackingInfo), - adMetadataContainer = adMetadataContainer(impression) - ) - } - - private def convertDisclosureType( - disclosureType: adserver.DisclosureType - ): DisclosureType = disclosureType match { - case adserver.DisclosureType.None => NoDisclosure - case adserver.DisclosureType.Political => Political - case adserver.DisclosureType.Earned => Earned - case adserver.DisclosureType.Issue => Issue - case _ => throw new UnsupportedDisclosureTypeException(disclosureType) - } - - private def convertClickTrackingInfo( - clickTracking: adserver.ClickTrackingInfo - ): ClickTrackingInfo = ClickTrackingInfo( - urlParams = clickTracking.urlParams.getOrElse(Map.empty), - urlOverride = clickTracking.urlOverride, - urlOverrideType = clickTracking.urlOverrideType.map { - case adserver.UrlOverrideType.Unknown => UnknownUrlOverrideType - case adserver.UrlOverrideType.Dcm => DcmUrlOverrideType - case _ => throw new UnsupportedClickTrackingInfoException(clickTracking) - } - ) - - private def prerollMetadata(adImpression: adserver.AdImpression): Option[PrerollMetadata] = { - adImpression.serializedPrerollMetadata - .flatMap(PrerollMetadataSerializer.deserialize).map { metadata => - PrerollMetadata( - metadata.preroll.map(convertPreroll), - metadata.videoAnalyticsScribePassthrough - ) - } - } - - private def adMetadataContainer( - adImpression: adserver.AdImpression - ): Option[AdMetadataContainer] = { - adImpression.serializedAdMetadataContainer - .flatMap(AdMetadataContainerSerializer.deserialize).map { container => - AdMetadataContainer( - removePromotedAttributionForPreroll = container.removePromotedAttributionForPreroll, - sponsorshipCandidate = container.sponsorshipCandidate, - sponsorshipOrganization = container.sponsorshipOrganization, - sponsorshipOrganizationWebsite = container.sponsorshipOrganizationWebsite, - sponsorshipType = container.sponsorshipType.map(convertSponsorshipType), - disclaimerType = container.disclaimerType.map(convertDisclaimerType), - skAdNetworkDataList = container.skAdNetworkDataList.map(convertSkAdNetworkDataList), - unifiedCardOverride = container.unifiedCardOverride - ) - } - } - - private def convertSponsorshipType( - sponsorshipType: ads.SponsorshipType - ): SponsorshipType = sponsorshipType match { - case ads.SponsorshipType.Direct => DirectSponsorshipType - case ads.SponsorshipType.Indirect => IndirectSponsorshipType - case ads.SponsorshipType.NoSponsorship => NoSponsorshipSponsorshipType - // Thrift has extras (e.g. Sponsorship4) that are not used in practice - case _ => throw new UnsupportedSponsorshipTypeException(sponsorshipType) - } - - private def convertDisclaimerType( - disclaimerType: ads.DisclaimerType - ): DisclaimerType = disclaimerType match { - case ads.DisclaimerType.Political => DisclaimerPolitical - case ads.DisclaimerType.Issue => DisclaimerIssue - case _ => throw new UnsupportedDisclaimerTypeException(disclaimerType) - } - - private def convertDynamicPrerollType( - dynamicPrerollType: ads.DynamicPrerollType - ): DynamicPrerollType = - dynamicPrerollType match { - case ads.DynamicPrerollType.Amplify => Amplify - case ads.DynamicPrerollType.Marketplace => Marketplace - case ads.DynamicPrerollType.LiveTvEvent => LiveTvEvent - case _ => throw new UnsupportedDynamicPrerollTypeException(dynamicPrerollType) - } - - private def convertMediaInfo(mediaInfo: ads.MediaInfo): MediaInfo = { - MediaInfo( - uuid = mediaInfo.uuid, - publisherId = mediaInfo.publisherId, - callToAction = mediaInfo.callToAction.map(convertCallToAction), - durationMillis = mediaInfo.durationMillis, - videoVariants = mediaInfo.videoVariants.map(convertVideoVariants), - advertiserName = mediaInfo.advertiserName, - renderAdByAdvertiserName = mediaInfo.renderAdByAdvertiserName, - advertiserProfileImageUrl = mediaInfo.advertiserProfileImageUrl - ) - } - - private def convertVideoVariants(videoVariants: Seq[ads.VideoVariant]): Seq[VideoVariant] = { - videoVariants.map(videoVariant => - VideoVariant( - url = videoVariant.url, - contentType = videoVariant.contentType, - bitrate = videoVariant.bitrate - )) - } - - private def convertCallToAction(callToAction: ads.CallToAction): CallToAction = { - CallToAction( - callToActionType = callToAction.callToActionType, - url = callToAction.url - ) - } - - private def convertPreroll( - preroll: ads.Preroll - ): Preroll = { - Preroll( - preroll.prerollId, - preroll.dynamicPrerollType.map(convertDynamicPrerollType), - preroll.mediaInfo.map(convertMediaInfo) - ) - } - - private def convertSkAdNetworkDataList( - skAdNetworkDataList: Seq[ads.SkAdNetworkData] - ): Seq[SkAdNetworkData] = skAdNetworkDataList.map(sdAdNetwork => - SkAdNetworkData( - version = sdAdNetwork.version, - srcAppId = sdAdNetwork.srcAppId, - dstAppId = sdAdNetwork.dstAppId, - adNetworkId = sdAdNetwork.adNetworkId, - campaignId = sdAdNetwork.campaignId, - impressionTimeInMillis = sdAdNetwork.impressionTimeInMillis, - nonce = sdAdNetwork.nonce, - signature = sdAdNetwork.signature, - fidelityType = sdAdNetwork.fidelityType - )) -} - -class UnsupportedClickTrackingInfoException(clickTrackingInfo: adserver.ClickTrackingInfo) - extends UnsupportedOperationException( - s"Unsupported ClickTrackingInfo: $clickTrackingInfo" - ) - -class UnsupportedDisclaimerTypeException(disclaimerType: ads.DisclaimerType) - extends UnsupportedOperationException( - s"Unsupported DisclaimerType: $disclaimerType" - ) - -class UnsupportedDisclosureTypeException(disclosureType: adserver.DisclosureType) - extends UnsupportedOperationException( - s"Unsupported DisclosureType: $disclosureType" - ) - -class UnsupportedDynamicPrerollTypeException(dynamicPrerollType: ads.DynamicPrerollType) - extends UnsupportedOperationException( - s"Unsupported DynamicPrerollType: $dynamicPrerollType" - ) - -class UnsupportedSponsorshipTypeException(sponsorshipType: ads.SponsorshipType) - extends UnsupportedOperationException( - s"Unsupported SponsorshipType: $sponsorshipType" - ) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala deleted file mode 100644 index 0a4e76319..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/DurationParamBuilder.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseDurationBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param -import com.twitter.util.Duration - -case class DurationParamBuilder( - durationParam: Param[Duration]) - extends BaseDurationBuilder[PipelineQuery] { - - def apply( - query: PipelineQuery, - candidate: ShowAlertCandidate, - features: FeatureMap - ): Option[Duration] = - Some(query.params(durationParam)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala deleted file mode 100644 index d2028181c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/ShowAlertCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert.ShowAlertCandidateUrtItemBuilder.ShowAlertClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseDurationBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertColorConfigurationBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertDisplayLocationBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertIconDisplayInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertNavigationMetadataBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertUserIdsBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertType - -object ShowAlertCandidateUrtItemBuilder { - val ShowAlertClientEventInfoElement: String = "showAlert" -} - -case class ShowAlertCandidateUrtItemBuilder[-Query <: PipelineQuery]( - alertType: ShowAlertType, - displayLocationBuilder: BaseShowAlertDisplayLocationBuilder[Query], - colorConfigBuilder: BaseShowAlertColorConfigurationBuilder[Query], - triggerDelayBuilder: Option[BaseDurationBuilder[Query]] = None, - displayDurationBuilder: Option[BaseDurationBuilder[Query]] = None, - clientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, ShowAlertCandidate]] = None, - collapseDelayBuilder: Option[BaseDurationBuilder[Query]] = None, - userIdsBuilder: Option[BaseShowAlertUserIdsBuilder[Query]] = None, - richTextBuilder: Option[BaseRichTextBuilder[Query, ShowAlertCandidate]] = None, - iconDisplayInfoBuilder: Option[BaseShowAlertIconDisplayInfoBuilder[Query]] = None, - navigationMetadataBuilder: Option[BaseShowAlertNavigationMetadataBuilder[Query]] = None) - extends CandidateUrtEntryBuilder[ - Query, - ShowAlertCandidate, - ShowAlert - ] { - - override def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap, - ): ShowAlert = ShowAlert( - id = candidate.id, - sortIndex = None, - alertType = alertType, - triggerDelay = triggerDelayBuilder.flatMap(_.apply(query, candidate, features)), - displayDuration = displayDurationBuilder.flatMap(_.apply(query, candidate, features)), - clientEventInfo = clientEventInfoBuilder.flatMap( - _.apply(query, candidate, features, Some(ShowAlertClientEventInfoElement))), - collapseDelay = collapseDelayBuilder.flatMap(_.apply(query, candidate, features)), - userIds = userIdsBuilder.flatMap(_.apply(query, candidate, features)), - richText = richTextBuilder.map(_.apply(query, candidate, features)), - iconDisplayInfo = iconDisplayInfoBuilder.flatMap(_.apply(query, candidate, features)), - displayLocation = displayLocationBuilder(query, candidate, features), - colorConfig = colorConfigBuilder(query, candidate, features), - navigationMetadata = navigationMetadataBuilder.flatMap(_.apply(query, candidate, features)), - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala deleted file mode 100644 index 322d16401..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertColorConfigurationBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertColorConfigurationBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticShowAlertColorConfigurationBuilder[-Query <: PipelineQuery]( - configuration: ShowAlertColorConfiguration) - extends BaseShowAlertColorConfigurationBuilder[Query] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): ShowAlertColorConfiguration = configuration -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala deleted file mode 100644 index 74ea989dd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertDisplayLocationBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertDisplayLocationBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticShowAlertDisplayLocationBuilder[-Query <: PipelineQuery]( - location: ShowAlertDisplayLocation) - extends BaseShowAlertDisplayLocationBuilder[Query] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): ShowAlertDisplayLocation = location -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala deleted file mode 100644 index 4c5dcf2a0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/alert/StaticShowAlertIconDisplayInfoBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert.BaseShowAlertIconDisplayInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticShowAlertIconDisplayInfoBuilder[-Query <: PipelineQuery]( - iconDisplayInfo: ShowAlertIconDisplayInfo) - extends BaseShowAlertIconDisplayInfoBuilder[Query] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): Option[ShowAlertIconDisplayInfo] = Some(iconDisplayInfo) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala deleted file mode 100644 index 87d611183..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/article/ArticleCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.article - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.article.ArticleCandidateUrtItemBuilder.ArticleClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.BaseArticleCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleSeedType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FollowingListSeed -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object ArticleCandidateUrtItemBuilder { - val ArticleClientEventInfoElement: String = "article" -} - -case class ArticleCandidateUrtItemBuilder[ - -Query <: PipelineQuery, - Candidate <: BaseArticleCandidate -]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate], - articleSeedType: ArticleSeedType = FollowingListSeed, - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, Candidate] - ] = None, - displayType: Option[ArticleDisplayType] = None, - socialContextBuilder: Option[BaseSocialContextBuilder[Query, Candidate]] = None, -) extends CandidateUrtEntryBuilder[Query, Candidate, ArticleItem] { - - override def apply( - query: Query, - articleCandidate: Candidate, - candidateFeatures: FeatureMap - ): ArticleItem = ArticleItem( - id = articleCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - articleCandidate, - candidateFeatures, - Some(ArticleClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, articleCandidate, candidateFeatures)), - displayType = displayType, - socialContext = - socialContextBuilder.flatMap(_.apply(query, articleCandidate, candidateFeatures)), - articleSeedType = articleSeedType - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala deleted file mode 100644 index 1d1f7c90a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/audio_space/AudioSpaceCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.audio_space - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.audio_space.AudioSpaceCandidateUrtItemBuilder.AudioSpaceClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.AudioSpaceCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object AudioSpaceCandidateUrtItemBuilder { - val AudioSpaceClientEventInfoElement: String = "audiospace" -} - -case class AudioSpaceCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UniversalNoun[Any]], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, UniversalNoun[Any]] - ] = None) - extends CandidateUrtEntryBuilder[Query, AudioSpaceCandidate, AudioSpaceItem] { - - override def apply( - query: Query, - audioSpaceCandidate: AudioSpaceCandidate, - candidateFeatures: FeatureMap - ): AudioSpaceItem = AudioSpaceItem( - id = audioSpaceCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - audioSpaceCandidate, - candidateFeatures, - Some(AudioSpaceClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, audioSpaceCandidate, candidateFeatures)) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala deleted file mode 100644 index e935df9dd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/card/CardCandidateUtrItemBuilder.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.card - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.card.CardCandidateUtrItemBuilder.CardClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.CardCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object CardCandidateUtrItemBuilder { - val CardClientEventInfoElement: String = "card" -} - -case class CardCandidateUtrItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CardCandidate], - cardUrlBuilder: BaseStr[Query, CardCandidate], - textBuilder: Option[BaseStr[Query, CardCandidate]], - subtextBuilder: Option[BaseStr[Query, CardCandidate]], - urlBuilder: Option[BaseUrlBuilder[Query, CardCandidate]], - cardDisplayType: Option[CardDisplayType], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, CardCandidate], - ] = None) - extends CandidateUrtEntryBuilder[Query, CardCandidate, CardItem] { - - override def apply( - query: Query, - cardCandidate: CardCandidate, - candidateFeatures: FeatureMap - ): CardItem = CardItem( - id = cardCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - cardCandidate, - candidateFeatures, - Some(CardClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, cardCandidate, candidateFeatures)), - cardUrl = cardUrlBuilder(query, cardCandidate, candidateFeatures), - text = textBuilder.map(_.apply(query, cardCandidate, candidateFeatures)), - subtext = textBuilder.map(_.apply(query, cardCandidate, candidateFeatures)), - url = urlBuilder.map(_.apply(query, cardCandidate, candidateFeatures)), - displayType = cardDisplayType - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala deleted file mode 100644 index a56385a7d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce.CommerceProductCandidateUrtItemBuilder.CommerceProductClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.CommerceProductCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object CommerceProductCandidateUrtItemBuilder { - val CommerceProductClientEventInfoElement: String = "commerce-product" -} - -case class CommerceProductCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CommerceProductCandidate], - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, CommerceProductCandidate]]) - extends CandidateUrtEntryBuilder[ - Query, - CommerceProductCandidate, - CommerceProductItem - ] { - - override def apply( - query: Query, - candidate: CommerceProductCandidate, - candidateFeatures: FeatureMap - ): CommerceProductItem = - CommerceProductItem( - id = candidate.id, - sortIndex = None, - clientEventInfo = clientEventInfoBuilder( - query, - candidate, - candidateFeatures, - Some(CommerceProductClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala deleted file mode 100644 index a48049314..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/commerce/CommerceProductGroupCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.commerce.CommerceProductGroupCandidateUrtItemBuilder.CommerceProductGroupClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.CommerceProductGroupCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object CommerceProductGroupCandidateUrtItemBuilder { - val CommerceProductGroupClientEventInfoElement: String = "commerce-product-group" -} - -case class CommerceProductGroupCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CommerceProductGroupCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, CommerceProductGroupCandidate] - ]) extends CandidateUrtEntryBuilder[ - Query, - CommerceProductGroupCandidate, - CommerceProductGroupItem - ] { - - override def apply( - query: Query, - candidate: CommerceProductGroupCandidate, - candidateFeatures: FeatureMap - ): CommerceProductGroupItem = - CommerceProductGroupItem( - id = candidate.id, - sortIndex = None, - clientEventInfo = clientEventInfoBuilder( - query, - candidate, - candidateFeatures, - Some(CommerceProductGroupClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala deleted file mode 100644 index 27d7f1e19..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/event_summary/EventCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.event_summary - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.event_summary.EventCandidateUrtItemBuilder.EventClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventDisplayType -import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventImage -import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventTimeString -import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventTitleFeature -import com.twitter.product_mixer.component_library.model.candidate.trends_events.EventUrl -import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedEventCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object EventCandidateUrtItemBuilder { - val EventClientEventInfoElement = "event" -} - -case class EventCandidateUrtItemBuilder[Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UnifiedEventCandidate], - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, UnifiedEventCandidate]] = - None) - extends CandidateUrtEntryBuilder[Query, UnifiedEventCandidate, TimelineItem] { - - override def apply( - query: Query, - candidate: UnifiedEventCandidate, - candidateFeatures: FeatureMap - ): TimelineItem = { - EventSummaryItem( - id = candidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query = query, - candidate = candidate, - candidateFeatures = candidateFeatures, - element = Some(EventClientEventInfoElement) - ), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)), - title = candidateFeatures.get(EventTitleFeature), - displayType = candidateFeatures.get(EventDisplayType), - url = candidateFeatures.get(EventUrl), - image = candidateFeatures.getOrElse(EventImage, None), - timeString = candidateFeatures.getOrElse(EventTimeString, None) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala deleted file mode 100644 index 8cdbb065d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryActionBuilder.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary.GenericSummaryActionBuilder.GenericSummaryActionClientEventInfoElement -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryAction -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object GenericSummaryActionBuilder { - val GenericSummaryActionClientEventInfoElement: String = "genericsummary-action" -} - -case class GenericSummaryActionBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - urlBuilder: BaseUrlBuilder[Query, Candidate], - clientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, Candidate]] = None) { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): GenericSummaryAction = GenericSummaryAction( - url = urlBuilder.apply(query, candidate, candidateFeatures), - clientEventInfo = clientEventInfoBuilder.flatMap( - _.apply( - query, - candidate, - candidateFeatures, - Some(GenericSummaryActionClientEventInfoElement))) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala deleted file mode 100644 index 759dd48c2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary.GenericSummaryCandidateUrtItemBuilder.GenericSummaryClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.GenericSummaryCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItemDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Media -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.util.Time - -object GenericSummaryCandidateUrtItemBuilder { - val GenericSummaryClientEventInfoElement: String = "genericsummary" -} - -case class GenericSummaryCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, GenericSummaryCandidate], - headlineRichTextBuilder: BaseRichTextBuilder[Query, GenericSummaryCandidate], - displayType: GenericSummaryItemDisplayType, - genericSummaryContextCandidateUrtItemBuilder: Option[ - GenericSummaryContextBuilder[Query, GenericSummaryCandidate] - ] = None, - genericSummaryActionCandidateUrtItemBuilder: Option[ - GenericSummaryActionBuilder[Query, GenericSummaryCandidate] - ] = None, - timestamp: Option[Time] = None, - userAttributionIds: Option[Seq[Long]] = None, - media: Option[Media] = None, - promotedMetadata: Option[PromotedMetadata] = None, - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, GenericSummaryCandidate]] = - None) - extends CandidateUrtEntryBuilder[Query, GenericSummaryCandidate, GenericSummaryItem] { - - override def apply( - query: Query, - genericSummaryCandidate: GenericSummaryCandidate, - candidateFeatures: FeatureMap - ): GenericSummaryItem = GenericSummaryItem( - id = genericSummaryCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - genericSummaryCandidate, - candidateFeatures, - Some(GenericSummaryClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, genericSummaryCandidate, candidateFeatures)), - headline = headlineRichTextBuilder.apply(query, genericSummaryCandidate, candidateFeatures), - displayType = displayType, - userAttributionIds = userAttributionIds.getOrElse(Seq.empty), - media = media, - context = genericSummaryContextCandidateUrtItemBuilder.map( - _.apply(query, genericSummaryCandidate, candidateFeatures)), - timestamp = timestamp, - onClickAction = genericSummaryActionCandidateUrtItemBuilder.map( - _.apply(query, genericSummaryCandidate, candidateFeatures)), - promotedMetadata = promotedMetadata - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala deleted file mode 100644 index e78476280..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/generic_summary/GenericSummaryContextBuilder.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.generic_summary - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryContext -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class GenericSummaryContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - richTextBuilder: BaseRichTextBuilder[Query, Candidate], - icon: Option[HorizonIcon] = None) { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): GenericSummaryContext = GenericSummaryContext( - richTextBuilder.apply(query, candidate, candidateFeatures), - icon - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala deleted file mode 100644 index 698b64f3b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/icon_label/IconLabelCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.icon_label - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.icon_label.IconLabelCandidateUrtItemBuilder.IconLabelClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.LabelCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label.IconLabelItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object IconLabelCandidateUrtItemBuilder { - val IconLabelClientEventInfoElement: String = "iconlabel" -} - -case class IconLabelCandidateUrtItemBuilder[-Query <: PipelineQuery, Candidate <: LabelCandidate]( - richTextBuilder: BaseRichTextBuilder[Query, Candidate], - icon: Option[HorizonIcon] = None, - entities: Option[List[RichTextEntity]] = None, - clientEventInfoBuilder: Option[BaseClientEventInfoBuilder[Query, Candidate]] = None, - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, Candidate]] = None) - extends CandidateUrtEntryBuilder[Query, Candidate, IconLabelItem] { - - override def apply( - query: Query, - labelCandidate: Candidate, - candidateFeatures: FeatureMap - ): IconLabelItem = - IconLabelItem( - id = labelCandidate.id.toString, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder.flatMap( - _.apply(query, labelCandidate, candidateFeatures, Some(IconLabelClientEventInfoElement))), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, labelCandidate, candidateFeatures)), - text = richTextBuilder(query, labelCandidate, candidateFeatures), - icon = icon, - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala deleted file mode 100644 index 8f3d7826b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/CompactPromptCandidateUrtItemStringCenterBuilder.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.message.CompactPromptCandidateUrtItemStringCenterBuilder.CompactPromptClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.CompactPromptCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactPromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object CompactPromptCandidateUrtItemStringCenterBuilder { - val CompactPromptClientEventInfoElement: String = "message" -} - -case class CompactPromptCandidateUrtItemStringCenterBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, CompactPromptCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, CompactPromptCandidate] - ] = None, - headerTextBuilder: BaseStr[Query, CompactPromptCandidate], - bodyTextBuilder: Option[BaseStr[Query, CompactPromptCandidate]] = None, - headerRichTextBuilder: Option[BaseRichTextBuilder[Query, CompactPromptCandidate]] = None, - bodyRichTextBuilder: Option[BaseRichTextBuilder[Query, CompactPromptCandidate]] = None) - extends CandidateUrtEntryBuilder[Query, CompactPromptCandidate, MessagePromptItem] { - - override def apply( - query: Query, - compactPromptCandidate: CompactPromptCandidate, - candidateFeatures: FeatureMap - ): MessagePromptItem = - MessagePromptItem( - id = compactPromptCandidate.id.toString, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - compactPromptCandidate, - candidateFeatures, - Some(CompactPromptClientEventInfoElement)), - feedbackActionInfo = feedbackActionInfoBuilder.flatMap( - _.apply(query, compactPromptCandidate, candidateFeatures)), - isPinned = None, - content = CompactPromptMessageContent( - headerText = headerTextBuilder.apply(query, compactPromptCandidate, candidateFeatures), - bodyText = bodyTextBuilder.map(_.apply(query, compactPromptCandidate, candidateFeatures)), - primaryButtonAction = None, - secondaryButtonAction = None, - action = None, - headerRichText = - headerRichTextBuilder.map(_.apply(query, compactPromptCandidate, candidateFeatures)), - bodyRichText = - bodyRichTextBuilder.map(_.apply(query, compactPromptCandidate, candidateFeatures)) - ), - impressionCallbacks = None - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala deleted file mode 100644 index 0ebee8e8c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/InlinePromptCandidateUrtItemStringCenterBuilder.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.message.InlinePromptCandidateUrtItemStringCenterBuilder.InlinePromptClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.InlinePromptCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object InlinePromptCandidateUrtItemStringCenterBuilder { - val InlinePromptClientEventInfoElement: String = "message" -} - -case class InlinePromptCandidateUrtItemStringCenterBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, InlinePromptCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, InlinePromptCandidate] - ] = None, - headerTextBuilder: BaseStr[Query, InlinePromptCandidate], - bodyTextBuilder: Option[BaseStr[Query, InlinePromptCandidate]] = None, - headerRichTextBuilder: Option[BaseRichTextBuilder[Query, InlinePromptCandidate]] = None, - bodyRichTextBuilder: Option[BaseRichTextBuilder[Query, InlinePromptCandidate]] = None, - primaryMessageTextActionBuilder: Option[ - MessageTextActionBuilder[Query, InlinePromptCandidate] - ] = None, - secondaryMessageTextActionBuilder: Option[ - MessageTextActionBuilder[Query, InlinePromptCandidate] - ] = None, - socialContextBuilder: Option[BaseSocialContextBuilder[Query, InlinePromptCandidate]] = None, - userFacePileBuilder: Option[ - UserFacePileBuilder - ] = None) - extends CandidateUrtEntryBuilder[Query, InlinePromptCandidate, MessagePromptItem] { - - override def apply( - query: Query, - inlinePromptCandidate: InlinePromptCandidate, - candidateFeatures: FeatureMap - ): MessagePromptItem = - MessagePromptItem( - id = inlinePromptCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - inlinePromptCandidate, - candidateFeatures, - Some(InlinePromptClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, inlinePromptCandidate, candidateFeatures)), - isPinned = None, - content = InlinePromptMessageContent( - headerText = headerTextBuilder.apply(query, inlinePromptCandidate, candidateFeatures), - bodyText = bodyTextBuilder.map(_.apply(query, inlinePromptCandidate, candidateFeatures)), - primaryButtonAction = primaryMessageTextActionBuilder.map( - _.apply(query, inlinePromptCandidate, candidateFeatures)), - secondaryButtonAction = secondaryMessageTextActionBuilder.map( - _.apply(query, inlinePromptCandidate, candidateFeatures)), - headerRichText = - headerRichTextBuilder.map(_.apply(query, inlinePromptCandidate, candidateFeatures)), - bodyRichText = - bodyRichTextBuilder.map(_.apply(query, inlinePromptCandidate, candidateFeatures)), - socialContext = - socialContextBuilder.flatMap(_.apply(query, inlinePromptCandidate, candidateFeatures)), - userFacepile = userFacePileBuilder.map(_.apply()) - ), - impressionCallbacks = None - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala deleted file mode 100644 index 2871ac682..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/MessageTextActionBuilder.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object MessageTextActionBuilder { - val MessageTextActionClientEventInfoElement: String = "message-text-action" -} - -case class MessageTextActionBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - textBuilder: BaseStr[Query, Candidate], - dismissOnClick: Boolean, - url: Option[String] = None, - clientEventInfo: Option[ClientEventInfo] = None, - onClickCallbacks: Option[List[Callback]] = None) { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): MessageTextAction = MessageTextAction( - text = textBuilder(query, candidate, candidateFeatures), - action = MessageAction( - dismissOnClick, - url, - clientEventInfo, - onClickCallbacks - ) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala deleted file mode 100644 index ce87e64cb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/message/UserFacePileBuilder.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageActionType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepile -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepileDisplayType - -case class UserFacePileBuilder( - userIds: Seq[Long], - featuredUserIds: Seq[Long], - action: Option[MessageTextAction], - actionType: Option[MessageActionType], - displaysFeaturingText: Option[Boolean], - displayType: Option[UserFacepileDisplayType]) { - - def apply(): UserFacepile = UserFacepile( - userIds = userIds, - featuredUserIds = featuredUserIds, - action = action, - actionType = actionType, - displaysFeaturingText = displaysFeaturingText, - displayType = displayType - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala deleted file mode 100644 index 5d916f424..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/moment/MomentAnnotationCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.moment - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.moment.MomentAnnotationCandidateUrtItemBuilder.MomentAnnotationItemClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.MomentAnnotationCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment.MomentAnnotationItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object MomentAnnotationCandidateUrtItemBuilder { - val MomentAnnotationItemClientEventInfoElement = "metadata" -} - -case class MomentAnnotationCandidateUrtItemBuilder[Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, MomentAnnotationCandidate], - annotationTextRichTextBuilder: BaseRichTextBuilder[Query, MomentAnnotationCandidate], - annotationHeaderRichTextBuilder: BaseRichTextBuilder[Query, MomentAnnotationCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, MomentAnnotationCandidate] - ] = None, -) extends CandidateUrtEntryBuilder[Query, MomentAnnotationCandidate, MomentAnnotationItem] { - - override def apply( - query: Query, - candidate: MomentAnnotationCandidate, - candidateFeatures: FeatureMap - ): MomentAnnotationItem = MomentAnnotationItem( - id = candidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - candidate, - candidateFeatures, - Some(MomentAnnotationItemClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)), - isPinned = None, - text = - candidate.text.map(_ => annotationTextRichTextBuilder(query, candidate, candidateFeatures)), - header = candidate.header.map(_ => - annotationHeaderRichTextBuilder(query, candidate, candidateFeatures)), - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala deleted file mode 100644 index 7ab7308b2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/relevance_prompt/RelevancePromptCandidateUrtItemStringCenterBuilder.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.relevance_prompt - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.relevance_prompt.RelevancePromptCandidateUrtItemStringCenterBuilder.RelevancePromptClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.RelevancePromptCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptFollowUpFeedbackType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object RelevancePromptCandidateUrtItemStringCenterBuilder { - val RelevancePromptClientEventInfoElement: String = "relevance_prompt" -} - -case class RelevancePromptCandidateUrtItemStringCenterBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, RelevancePromptCandidate], - titleTextBuilder: BaseStr[Query, RelevancePromptCandidate], - confirmationTextBuilder: BaseStr[Query, RelevancePromptCandidate], - isRelevantTextBuilder: BaseStr[Query, RelevancePromptCandidate], - notRelevantTextBuilder: BaseStr[Query, RelevancePromptCandidate], - displayType: RelevancePromptDisplayType, - isRelevantCallback: Callback, - notRelevantCallback: Callback, - isRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType] = None, - notRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType] = None, - impressionCallbacks: Option[List[Callback]] = None) - extends CandidateUrtEntryBuilder[Query, RelevancePromptCandidate, PromptItem] { - - override def apply( - query: Query, - relevancePromptCandidate: RelevancePromptCandidate, - candidateFeatures: FeatureMap - ): PromptItem = - PromptItem( - id = relevancePromptCandidate.id, - sortIndex = None, - clientEventInfo = clientEventInfoBuilder( - query, - relevancePromptCandidate, - candidateFeatures, - Some(RelevancePromptClientEventInfoElement)), - feedbackActionInfo = None, - content = RelevancePromptContent( - title = titleTextBuilder(query, relevancePromptCandidate, candidateFeatures), - confirmation = confirmationTextBuilder(query, relevancePromptCandidate, candidateFeatures), - isRelevantText = isRelevantTextBuilder(query, relevancePromptCandidate, candidateFeatures), - notRelevantText = - notRelevantTextBuilder(query, relevancePromptCandidate, candidateFeatures), - isRelevantCallback = isRelevantCallback, - notRelevantCallback = notRelevantCallback, - displayType = displayType, - isRelevantFollowUp = isRelevantFollowUp, - notRelevantFollowUp = notRelevantFollowUp, - ), - impressionCallbacks = impressionCallbacks - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala deleted file mode 100644 index ce0beeb9e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/suggestion/SpellingSuggestionCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.suggestion - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.suggestion.SpellingSuggestionCandidateUrtItemBuilder.SpellingItemClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.suggestion.SpellingSuggestionCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object SpellingSuggestionCandidateUrtItemBuilder { - val SpellingItemClientEventInfoElement: String = "spelling" -} - -case class SpellingSuggestionCandidateUrtItemBuilder[Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, SpellingSuggestionCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, SpellingSuggestionCandidate] - ] = None, -) extends CandidateUrtEntryBuilder[Query, SpellingSuggestionCandidate, SpellingItem] { - - override def apply( - query: Query, - candidate: SpellingSuggestionCandidate, - candidateFeatures: FeatureMap - ): SpellingItem = SpellingItem( - id = candidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - candidate, - candidateFeatures, - Some(SpellingItemClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, candidate, candidateFeatures)), - textResult = candidate.textResult, - spellingActionType = candidate.spellingActionType, - originalQuery = candidate.originalQuery - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala deleted file mode 100644 index 4c449637f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tile/TileCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.tile - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tile.TileCandidateUrtItemBuilder.TopicTileClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.PromptCarouselTileCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object TileCandidateUrtItemBuilder { - val TopicTileClientEventInfoElement: String = "tile" -} - -case class TileCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, PromptCarouselTileCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, PromptCarouselTileCandidate] - ] = None) - extends CandidateUrtEntryBuilder[Query, PromptCarouselTileCandidate, TileItem] { - - override def apply( - query: Query, - tileCandidate: PromptCarouselTileCandidate, - candidateFeatures: FeatureMap - ): TileItem = TileItem( - id = tileCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - tileCandidate, - candidateFeatures, - Some(TopicTileClientEventInfoElement)), - title = "", //This data is ignored do - supportingText = "", - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, tileCandidate, candidateFeatures)), - image = None, - url = None, - content = StandardTileContent( - title = "", - supportingText = "", - badge = None - ) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala deleted file mode 100644 index 20253fea0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicDisplayTypeBuilder.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSEnumParam -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillTopicDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.NoIconTopicDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillWithoutActionIconDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicDisplayTypeBuilder - -object TopicCandidateDisplayType extends Enumeration { - type TopicDisplayType = Value - - val Basic = Value - val Pill = Value - val NoIcon = Value - val PillWithoutActionIcon = Value -} - -case class ParamTopicDisplayTypeBuilder( - displayTypeParam: FSEnumParam[TopicCandidateDisplayType.type]) - extends BaseTopicDisplayTypeBuilder[PipelineQuery, TopicCandidate] { - - override def apply( - query: PipelineQuery, - candidate: TopicCandidate, - candidateFeatures: FeatureMap - ): Option[TopicDisplayType] = { - val displayType = query.params(displayTypeParam) - displayType match { - case TopicCandidateDisplayType.Basic => Some(BasicTopicDisplayType) - case TopicCandidateDisplayType.Pill => Some(PillTopicDisplayType) - case TopicCandidateDisplayType.NoIcon => - Some(NoIconTopicDisplayType) - case TopicCandidateDisplayType.PillWithoutActionIcon => Some(PillWithoutActionIconDisplayType) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala deleted file mode 100644 index 78d941c19..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/ParamTopicFunctionalityTypeBuilder.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PivotTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.RecommendationTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicFunctionalityTypeBuilder -import com.twitter.timelines.configapi.FSEnumParam - -object TopicFunctionalityTypeParamValue extends Enumeration { - type TopicFunctionalityType = Value - - val Basic = Value - val Pivot = Value - val Recommendation = Value -} - -case class ParamTopicFunctionalityTypeBuilder( - functionalityTypeParam: FSEnumParam[TopicFunctionalityTypeParamValue.type]) - extends BaseTopicFunctionalityTypeBuilder[PipelineQuery, TopicCandidate] { - - override def apply( - query: PipelineQuery, - candidate: TopicCandidate, - candidateFeatures: FeatureMap - ): Option[TopicFunctionalityType] = { - val functionalityType = query.params(functionalityTypeParam) - functionalityType match { - case TopicFunctionalityTypeParamValue.Basic => Some(BasicTopicFunctionalityType) - case TopicFunctionalityTypeParamValue.Pivot => Some(PivotTopicFunctionalityType) - case TopicFunctionalityTypeParamValue.Recommendation => - Some(RecommendationTopicFunctionalityType) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala deleted file mode 100644 index fbe8c2783..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicDisplayTypeBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicDisplayTypeBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType - -case class StaticTopicDisplayTypeBuilder( - displayType: TopicDisplayType) - extends BaseTopicDisplayTypeBuilder[PipelineQuery, BaseTopicCandidate] { - - override def apply( - query: PipelineQuery, - candidate: BaseTopicCandidate, - candidateFeatures: FeatureMap - ): Option[TopicDisplayType] = Some(displayType) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala deleted file mode 100644 index 73e99d0a3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/StaticTopicFunctionalityTypeBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicFunctionalityTypeBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticTopicFunctionalityTypeBuilder( - functionalityType: TopicFunctionalityType) - extends BaseTopicFunctionalityTypeBuilder[PipelineQuery, BaseTopicCandidate] { - - override def apply( - query: PipelineQuery, - candidate: BaseTopicCandidate, - candidateFeatures: FeatureMap - ): Option[TopicFunctionalityType] = Some(functionalityType) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala deleted file mode 100644 index a049e08fd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/TopicCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic.TopicCandidateUrtItemBuilder.TopicClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic.BaseTopicFunctionalityTypeBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object TopicCandidateUrtItemBuilder { - val TopicClientEventInfoElement: String = "topic" -} - -case class TopicCandidateUrtItemBuilder[-Query <: PipelineQuery, Candidate <: BaseTopicCandidate]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate], - topicFunctionalityTypeBuilder: Option[BaseTopicFunctionalityTypeBuilder[Query, Candidate]] = None, - topicDisplayTypeBuilder: Option[BaseTopicDisplayTypeBuilder[Query, Candidate]] = None, - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, Candidate] - ] = None) - extends CandidateUrtEntryBuilder[Query, Candidate, TopicItem] { - - override def apply( - query: Query, - topicCandidate: Candidate, - candidateFeatures: FeatureMap - ): TopicItem = - TopicItem( - id = topicCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - topicCandidate, - candidateFeatures, - Some(TopicClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)), - topicFunctionalityType = - topicFunctionalityTypeBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)), - topicDisplayType = - topicDisplayTypeBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala deleted file mode 100644 index 40f436159..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/topic/VerticalGridTopicCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.topic.TopicCandidateUrtItemBuilder.TopicClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTileStyle -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicTile -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class VerticalGridTopicCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, TopicCandidate], - verticalGridItemTopicFunctionalityType: VerticalGridItemTopicFunctionalityType, - verticalGridItemTileStyle: VerticalGridItemTileStyle, - urlBuilder: Option[BaseUrlBuilder[Query, TopicCandidate]] = None, - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, TopicCandidate] - ] = None) - extends CandidateUrtEntryBuilder[Query, TopicCandidate, VerticalGridItem] { - - override def apply( - query: Query, - topicCandidate: TopicCandidate, - candidateFeatures: FeatureMap - ): VerticalGridItem = { - VerticalGridItemTopicTile( - id = topicCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - topicCandidate, - candidateFeatures, - Some(TopicClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, topicCandidate, candidateFeatures)), - style = Some(verticalGridItemTileStyle), - functionalityType = Some(verticalGridItemTopicFunctionalityType), - url = urlBuilder.map(_.apply(query, topicCandidate, candidateFeatures)) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala deleted file mode 100644 index c3f5c45ad..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend.TrendCandidateUrtItemBuilder.TrendsClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendDescription -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendDomainContext -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendGroupedTrends -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendNormalizedTrendName -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendTrendName -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendTweetCount -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendUrl -import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedTrendCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.TrendItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object TrendCandidateUrtItemBuilder { - final val TrendsClientEventInfoElement = "trend" -} - -case class TrendCandidateUrtItemBuilder[Query <: PipelineQuery]( - trendMetaDescriptionBuilder: TrendMetaDescriptionBuilder[Query, UnifiedTrendCandidate], - promotedMetadataBuilder: BasePromotedMetadataBuilder[Query, UnifiedTrendCandidate], - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UnifiedTrendCandidate], - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, UnifiedTrendCandidate]] = - None) - extends CandidateUrtEntryBuilder[Query, UnifiedTrendCandidate, TimelineItem] { - - override def apply( - query: Query, - candidate: UnifiedTrendCandidate, - candidateFeatures: FeatureMap - ): TimelineItem = { - TrendItem( - id = candidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query = query, - candidate = candidate, - candidateFeatures = candidateFeatures, - element = Some(TrendsClientEventInfoElement) - ), - feedbackActionInfo = None, - normalizedTrendName = candidateFeatures.get(TrendNormalizedTrendName), - trendName = candidateFeatures.get(TrendTrendName), - url = candidateFeatures.get(TrendUrl), - description = candidateFeatures.getOrElse(TrendDescription, None), - metaDescription = trendMetaDescriptionBuilder(query, candidate, candidateFeatures), - tweetCount = candidateFeatures.getOrElse(TrendTweetCount, None), - domainContext = candidateFeatures.getOrElse(TrendDomainContext, None), - promotedMetadata = promotedMetadataBuilder( - query = query, - candidate = candidate, - candidateFeatures = candidateFeatures - ), - groupedTrends = candidateFeatures.getOrElse(TrendGroupedTrends, None) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala deleted file mode 100644 index b8cc639a0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendMetaDescriptionBuilder.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend - -import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.Str -import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendAdvertiserNameFeature -import com.twitter.product_mixer.component_library.model.candidate.trends_events.TrendTweetCount -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.trends.trending_content.util.CompactingNumberLocalizer - -case class TrendMetaDescriptionBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - promotedByMetaDescriptionStr: Str[PipelineQuery, UniversalNoun[Any]], - tweetCountMetaDescriptionStr: Str[PipelineQuery, UniversalNoun[Any]], - compactingNumberLocalizer: CompactingNumberLocalizer) { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[String] = { - val promotedMetaDescription = - candidateFeatures.getOrElse(PromotedTrendAdvertiserNameFeature, None).map { advertiserName => - promotedByMetaDescriptionStr(query, candidate, candidateFeatures).format(advertiserName) - } - - val organicMetaDescription = candidateFeatures.getOrElse(TrendTweetCount, None).map { - tweetCount => - val compactedTweetCount = compactingNumberLocalizer.localizeAndCompact( - query.getLanguageCode - .getOrElse("en"), - tweetCount) - tweetCountMetaDescriptionStr(query, candidate, candidateFeatures).format( - compactedTweetCount) - } - - promotedMetaDescription.orElse(organicMetaDescription) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala deleted file mode 100644 index 9c1c34fa5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/trend/TrendPromotedMetadataBuilder.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend - -import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendDescriptionFeature -import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendDisclosureTypeFeature -import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendIdFeature -import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendImpressionIdFeature -import com.twitter.product_mixer.component_library.model.candidate.trends_events.PromotedTrendNameFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object TrendPromotedMetadataBuilder - extends BasePromotedMetadataBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): Option[PromotedMetadata] = { - // If a promoted trend name exists, then this is a promoted trend - candidateFeatures.getOrElse(PromotedTrendNameFeature, None).map { promotedTrendName => - PromotedMetadata( - // This is the current product behavior that advertiserId is always set to 0L. - // Correct advertiser name comes from Trend's trendMetadata.metaDescription. - advertiserId = 0L, - disclosureType = candidateFeatures.getOrElse(PromotedTrendDisclosureTypeFeature, None), - experimentValues = None, - promotedTrendId = candidateFeatures.getOrElse(PromotedTrendIdFeature, None), - promotedTrendName = Some(promotedTrendName), - promotedTrendQueryTerm = None, - adMetadataContainer = None, - promotedTrendDescription = - candidateFeatures.getOrElse(PromotedTrendDescriptionFeature, None), - impressionString = candidateFeatures.getOrElse(PromotedTrendImpressionIdFeature, None), - clickTrackingInfo = None - ) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala deleted file mode 100644 index d02b96f1c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/tweet/TweetCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,92 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet - -import com.twitter.product_mixer.component_library.decorator.urt.builder.contextual_ref.ContextualTweetRefBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder.TweetClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.IsPinnedFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet.BaseEntryIdToReplaceBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet.BaseTimelinesScoreInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet.BaseTweetHighlightsBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotation -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivot -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.Tweet -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case object TweetCandidateUrtItemBuilder { - val TweetClientEventInfoElement = "tweet" -} - -case class TweetCandidateUrtItemBuilder[Query <: PipelineQuery, Candidate <: BaseTweetCandidate]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate], - displayType: TweetDisplayType = Tweet, - entryIdToReplaceBuilder: Option[BaseEntryIdToReplaceBuilder[Query, Candidate]] = None, - socialContextBuilder: Option[BaseSocialContextBuilder[Query, Candidate]] = None, - highlightsBuilder: Option[BaseTweetHighlightsBuilder[Query, Candidate]] = None, - innerTombstoneInfo: Option[TombstoneInfo] = None, - timelinesScoreInfoBuilder: Option[BaseTimelinesScoreInfoBuilder[Query, Candidate]] = None, - hasModeratedReplies: Option[Boolean] = None, - forwardPivot: Option[ForwardPivot] = None, - innerForwardPivot: Option[ForwardPivot] = None, - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[Query, Candidate]] = None, - promotedMetadata: Option[PromotedMetadata] = None, - conversationAnnotation: Option[ConversationAnnotation] = None, - contextualTweetRefBuilder: Option[ContextualTweetRefBuilder[Candidate]] = None, - prerollMetadata: Option[PrerollMetadata] = None, - replyBadge: Option[Badge] = None, - destinationBuilder: Option[BaseUrlBuilder[Query, Candidate]] = None) - extends CandidateUrtEntryBuilder[Query, Candidate, TweetItem] { - - override def apply( - pipelineQuery: Query, - tweetCandidate: Candidate, - candidateFeatures: FeatureMap - ): TweetItem = { - val isPinned = candidateFeatures.getTry(IsPinnedFeature).toOption - - TweetItem( - id = tweetCandidate.id, - entryNamespace = TweetItem.TweetEntryNamespace, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - pipelineQuery, - tweetCandidate, - candidateFeatures, - Some(TweetClientEventInfoElement)), - feedbackActionInfo = feedbackActionInfoBuilder.flatMap( - _.apply(pipelineQuery, tweetCandidate, candidateFeatures)), - isPinned = isPinned, - entryIdToReplace = - entryIdToReplaceBuilder.flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)), - socialContext = - socialContextBuilder.flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)), - highlights = - highlightsBuilder.flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)), - displayType = displayType, - innerTombstoneInfo = innerTombstoneInfo, - timelinesScoreInfo = timelinesScoreInfoBuilder - .flatMap(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)), - hasModeratedReplies = hasModeratedReplies, - forwardPivot = forwardPivot, - innerForwardPivot = innerForwardPivot, - promotedMetadata = promotedMetadata, - conversationAnnotation = conversationAnnotation, - contextualTweetRef = contextualTweetRefBuilder.flatMap(_.apply(tweetCandidate)), - prerollMetadata = prerollMetadata, - replyBadge = replyBadge, - destination = - destinationBuilder.map(_.apply(pipelineQuery, tweetCandidate, candidateFeatures)) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala deleted file mode 100644 index 41ed4ed71..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/twitter_list/TwitterListCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.twitter_list - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.twitter_list.TwitterListCandidateUrtItemBuilder.ListClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object TwitterListCandidateUrtItemBuilder { - val ListClientEventInfoElement: String = "list" -} - -case class TwitterListCandidateUrtItemBuilder[-Query <: PipelineQuery]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, TwitterListCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, TwitterListCandidate] - ] = None, - displayType: Option[TwitterListDisplayType] = None) - extends CandidateUrtEntryBuilder[Query, TwitterListCandidate, TwitterListItem] { - - override def apply( - query: Query, - twitterListCandidate: TwitterListCandidate, - candidateFeatures: FeatureMap - ): TwitterListItem = TwitterListItem( - id = twitterListCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - twitterListCandidate, - candidateFeatures, - Some(ListClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, twitterListCandidate, candidateFeatures)), - displayType = displayType - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala deleted file mode 100644 index c4b67ce04..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/unified_trend_event/UnifiedTrendEventCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.unified_trend_event - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.event_summary.EventCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.trend.TrendCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedEventCandidate -import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedTrendCandidate -import com.twitter.product_mixer.component_library.model.candidate.trends_events.UnifiedTrendEventCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class UnifiedTrendEventCandidateUrtItemBuilder[Query <: PipelineQuery]( - eventCandidateUrtItemBuilder: EventCandidateUrtItemBuilder[Query], - trendCandidateUrtItemBuilder: TrendCandidateUrtItemBuilder[Query]) - extends CandidateUrtEntryBuilder[Query, UnifiedTrendEventCandidate[Any], TimelineItem] { - - override def apply( - query: Query, - candidate: UnifiedTrendEventCandidate[Any], - candidateFeatures: FeatureMap - ): TimelineItem = { - candidate match { - case event: UnifiedEventCandidate => - eventCandidateUrtItemBuilder( - query = query, - candidate = event, - candidateFeatures = candidateFeatures) - case trend: UnifiedTrendCandidate => - trendCandidateUrtItemBuilder( - query = query, - candidate = trend, - candidateFeatures = candidateFeatures) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala deleted file mode 100644 index 95a7e6bd9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/item/user/UserCandidateUrtItemBuilder.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.item.user - -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.user.UserCandidateUrtItemBuilder.UserClientEventInfoElement -import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate -import com.twitter.product_mixer.component_library.model.candidate.IsMarkUnreadFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.user.BaseUserReactiveTriggersBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.User -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object UserCandidateUrtItemBuilder { - val UserClientEventInfoElement: String = "user" -} - -case class UserCandidateUrtItemBuilder[Query <: PipelineQuery, UserCandidate <: BaseUserCandidate]( - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, UserCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, UserCandidate] - ] = None, - displayType: UserDisplayType = User, - promotedMetadataBuilder: Option[BasePromotedMetadataBuilder[Query, UserCandidate]] = None, - socialContextBuilder: Option[BaseSocialContextBuilder[Query, UserCandidate]] = None, - reactiveTriggersBuilder: Option[BaseUserReactiveTriggersBuilder[Query, UserCandidate]] = None, - enableReactiveBlending: Option[Boolean] = None) - extends CandidateUrtEntryBuilder[Query, UserCandidate, UserItem] { - - override def apply( - query: Query, - userCandidate: UserCandidate, - candidateFeatures: FeatureMap - ): UserItem = { - val isMarkUnread = candidateFeatures.getTry(IsMarkUnreadFeature).toOption - - UserItem( - id = userCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - clientEventInfo = clientEventInfoBuilder( - query, - userCandidate, - candidateFeatures, - Some(UserClientEventInfoElement)), - feedbackActionInfo = - feedbackActionInfoBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)), - isMarkUnread = isMarkUnread, - displayType = displayType, - promotedMetadata = - promotedMetadataBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)), - socialContext = - socialContextBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)), - reactiveTriggers = - reactiveTriggersBuilder.flatMap(_.apply(query, userCandidate, candidateFeatures)), - enableReactiveBlending = enableReactiveBlending - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala deleted file mode 100644 index 0c0eca37b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ClientEventInfoBuilder.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder - -/** - * Sets the [[ClientEventInfo]] with the `component` field set to [[component]] - * @see [[http://go/client-events]] - */ -case class ClientEventInfoBuilder[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - component: String, - detailsBuilder: Option[BaseClientEventDetailsBuilder[Query, Candidate]] = None) - extends BaseClientEventInfoBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap, - element: Option[String] - ): Option[ClientEventInfo] = - Some( - ClientEventInfo( - component = Some(component), - element = element, - details = detailsBuilder.flatMap(_.apply(query, candidate, candidateFeatures)), - action = None, - entityToken = None) - ) -} - -/** - * In rare cases you might not want to send client event info. For - * example, this might be set already on the client for some legacy - * timelines. - */ -object EmptyClientEventInfoBuilder - extends BaseClientEventInfoBuilder[PipelineQuery, UniversalNoun[Any]] { - override def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap, - element: Option[String] - ): Option[ClientEventInfo] = None -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala deleted file mode 100644 index ad8034dbc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/ConversationTweetClientEventDetailsBuilder.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.bijection.scrooge.BinaryScalaCodec -import com.twitter.bijection.Base64String -import com.twitter.bijection.{Injection => Serializer} -import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.ConversationTweetClientEventDetailsBuilder.ControllerDataSerializer -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.suggests.controller_data.home_tweets.thriftscala.HomeTweetsControllerData -import com.twitter.suggests.controller_data.thriftscala.ControllerData -import com.twitter.suggests.controller_data.home_tweets.v1.thriftscala.{ - HomeTweetsControllerData => HomeTweetsControllerDataV1 -} -import com.twitter.suggests.controller_data.v2.thriftscala.{ControllerData => ControllerDataV2} - -object ConversationTweetClientEventDetailsBuilder { - implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] = - BinaryScalaCodec(ControllerData) - - val ControllerDataSerializer: Serializer[ControllerData, String] = - Serializer.connect[ControllerData, Array[Byte], Base64String, String] -} - -case class ConversationTweetClientEventDetailsBuilder[-Query <: PipelineQuery]( - injectionType: Option[String]) - extends BaseClientEventDetailsBuilder[Query, BaseTweetCandidate] { - - override def apply( - query: Query, - tweetCandidate: BaseTweetCandidate, - candidateFeatures: FeatureMap - ): Option[ClientEventDetails] = - Some( - ClientEventDetails( - conversationDetails = None, - timelinesDetails = Some( - TimelinesDetails( - injectionType = injectionType, - controllerData = Some(buildControllerData(query.getUserOrGuestId)), - sourceData = None)), - articleDetails = None, - liveEventDetails = None, - commerceDetails = None - )) - - private def buildControllerData(traceId: Option[Long]): String = - ControllerDataSerializer( - ControllerData.V2( - ControllerDataV2.HomeTweets( - HomeTweetsControllerData.V1( - HomeTweetsControllerDataV1( - tweetTypesBitmap = 0L, - traceId = traceId, - ) - ) - ) - ) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala deleted file mode 100644 index 7db66990f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/StaticUrlBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticUrlBuilder(url: String, urlType: UrlType) - extends BaseUrlBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): Url = Url(url = url, urlType = urlType) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala deleted file mode 100644 index af28b49f3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicClientEventDetailsBuilder.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.bijection.scrooge.BinaryScalaCodec -import com.twitter.bijection.Base64String -import com.twitter.bijection.{Injection => Serializer} -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder -import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.suggests.controller_data.thriftscala.ControllerData -import com.twitter.suggests.controller_data.timelines_topic.thriftscala.TimelinesTopicControllerData -import com.twitter.suggests.controller_data.timelines_topic.v1.thriftscala.{ - TimelinesTopicControllerData => TimelinesTopicControllerDataV1 -} -import com.twitter.suggests.controller_data.v2.thriftscala.{ControllerData => ControllerDataV2} - -object TopicClientEventDetailsBuilder { - implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] = - BinaryScalaCodec(ControllerData) - - val ControllerDataSerializer: Serializer[ControllerData, String] = - Serializer.connect[ControllerData, Array[Byte], Base64String, String] -} - -case class TopicClientEventDetailsBuilder[-Query <: PipelineQuery]() - extends BaseClientEventDetailsBuilder[Query, BaseTopicCandidate] { - - import TopicClientEventDetailsBuilder._ - - override def apply( - query: Query, - topicCandidate: BaseTopicCandidate, - candidateFeatures: FeatureMap - ): Option[ClientEventDetails] = - Some( - ClientEventDetails( - conversationDetails = None, - timelinesDetails = Some( - TimelinesDetails( - injectionType = None, - controllerData = buildControllerData(topicCandidate.id), - sourceData = None)), - articleDetails = None, - liveEventDetails = None, - commerceDetails = None - )) - - private def buildControllerData(topicId: Long): Option[String] = - Some( - ControllerData - .V2(ControllerDataV2.TimelinesTopic(TimelinesTopicControllerData.V1( - TimelinesTopicControllerDataV1(topicTypesBitmap = 0L, topicId = topicId))))) - .map(ControllerDataSerializer) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala deleted file mode 100644 index cfb7cb5ff..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicNotInterestedFeedbackActionInfoBuilder.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.product_mixer.component_library.model.candidate.BaseTopicCandidate -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorMarkNotInterestedTopic -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class TopicNotInterestedFeedbackActionInfoBuilder[-Query <: PipelineQuery]() - extends BaseFeedbackActionInfoBuilder[Query, BaseTopicCandidate] { - - override def apply( - query: Query, - topicCandidate: BaseTopicCandidate, - candidateFeatures: FeatureMap - ): Option[FeedbackActionInfo] = { - Some( - FeedbackActionInfo( - feedbackActions = Seq( - FeedbackAction( - feedbackType = RichBehavior, - richBehavior = Some( - RichFeedbackBehaviorMarkNotInterestedTopic(topicCandidate.id.toString) - ), - hasUndoAction = Some(true), - prompt = None, - confirmation = None, - feedbackUrl = None, - clientEventInfo = None, - childFeedbackActions = None, - confirmationDisplayType = None, - icon = None, - subprompt = None, - encodedFeedbackRequest = None - ) - ), - feedbackMetadata = None, - displayContext = None, - clientEventInfo = None - )) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala deleted file mode 100644 index 451b347ae..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicTweetClientEventDetailsBuilder.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.bijection.scrooge.BinaryScalaCodec -import com.twitter.bijection.Base64String -import com.twitter.bijection.{Injection => Serializer} -import com.twitter.interests_mixer.model.request.{HasTopicId => InterestsMixerHasTopicId} -import com.twitter.explore_mixer.model.request.{HasTopicId => ExploreMixerHasTopicId} -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.suggests.controller_data.home_tweets.thriftscala.HomeTweetsControllerData -import com.twitter.suggests.controller_data.home_tweets.v1.thriftscala.{ - HomeTweetsControllerData => HomeTweetsControllerDataV1 -} -import com.twitter.suggests.controller_data.thriftscala.ControllerData -import com.twitter.suggests.controller_data.v2.thriftscala.{ControllerData => ControllerDataV2} - -object TopicTweetClientEventDetailsBuilder { - implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] = - BinaryScalaCodec(ControllerData) - - val ControllerDataSerializer: Serializer[ControllerData, String] = - Serializer.connect[ControllerData, Array[Byte], Base64String, String] -} - -case class TopicTweetClientEventDetailsBuilder[-Query <: PipelineQuery]() - extends BaseClientEventDetailsBuilder[Query, TweetCandidate] { - - import TopicTweetClientEventDetailsBuilder._ - - override def apply( - query: Query, - topicTweetCandidate: TweetCandidate, - candidateFeatures: FeatureMap - ): Option[ClientEventDetails] = - Some( - ClientEventDetails( - conversationDetails = None, - timelinesDetails = Some( - TimelinesDetails( - injectionType = None, - controllerData = buildControllerData(getTopicId(query)), - sourceData = None)), - articleDetails = None, - liveEventDetails = None, - commerceDetails = None - )) - - private def getTopicId(query: Query): Option[Long] = { - query match { - case query: InterestsMixerHasTopicId => query.topicId - case query: ExploreMixerHasTopicId => query.topicId - case _ => None - } - } - - private def buildControllerData(topicId: Option[Long]): Option[String] = - Some( - ControllerData - .V2(ControllerDataV2.HomeTweets(HomeTweetsControllerData.V1( - HomeTweetsControllerDataV1(tweetTypesBitmap = 0L, topicId = topicId))))) - .map(ControllerDataSerializer) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala deleted file mode 100644 index fa32e2127..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/TopicsToFollowModuleMetadataBuilder.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleMetadataBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarouselMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -object TopicsToFollowModuleMetadataBuilder { - - val TopicsPerRow = 7 - - /* - * rows = min(MAX_NUM_ROWS, # topics / TOPICS_PER_ROW) - * where TOPICS_PER_ROW = 7 - */ - def getCarouselRowCount(topicsCount: Int, maxCarouselRows: Int): Int = - Math.min(maxCarouselRows, (topicsCount / TopicsPerRow) + 1) -} - -case class TopicsToFollowModuleMetadataBuilder(maxCarouselRowsParam: Param[Int]) - extends BaseModuleMetadataBuilder[PipelineQuery, UniversalNoun[Any]] { - - import TopicsToFollowModuleMetadataBuilder._ - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ModuleMetadata = { - val rowCount = getCarouselRowCount(candidates.size, query.params(maxCarouselRowsParam)) - ModuleMetadata( - adsMetadata = None, - conversationMetadata = None, - gridCarouselMetadata = Some(GridCarouselMetadata(numRows = Some(rowCount))) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala deleted file mode 100644 index 04d6fae7b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/metadata/WhoToFollowFeedbackActionInfoBuilder.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.metadata - -import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.Str -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.Frown -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SeeFewer -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stringcenter.client.ExternalStringRegistry -import com.twitter.stringcenter.client.StringCenter - -case class WhoToFollowFeedbackActionInfoBuilder[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any] -]( - externalStringRegistry: ExternalStringRegistry, - stringCenter: StringCenter, - encodedFeedbackRequest: Option[String]) - extends BaseFeedbackActionInfoBuilder[Query, Candidate] { - - private val seeLessOftenFeedback = - externalStringRegistry.createProdString("Feedback.seeLessOften") - private val seeLessOftenConfirmationFeedback = - externalStringRegistry.createProdString("Feedback.seeLessOftenConfirmation") - - override def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[FeedbackActionInfo] = Some( - FeedbackActionInfo( - feedbackActions = Seq( - FeedbackAction( - feedbackType = SeeFewer, - prompt = Some( - Str(seeLessOftenFeedback, stringCenter, None) - .apply(query, candidate, candidateFeatures)), - confirmation = Some( - Str(seeLessOftenConfirmationFeedback, stringCenter, None) - .apply(query, candidate, candidateFeatures)), - childFeedbackActions = None, - feedbackUrl = None, - confirmationDisplayType = None, - clientEventInfo = None, - richBehavior = None, - subprompt = None, - icon = Some(Frown), // ignored by unsupported clients - hasUndoAction = Some(true), - encodedFeedbackRequest = encodedFeedbackRequest - ) - ), - feedbackMetadata = None, - displayContext = None, - clientEventInfo = None - ) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala deleted file mode 100644 index 6cc1ad677..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/operation/CursorCandidateUrtOperationBuilder.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.operation - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.CandidateUrtEntryBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorDisplayTreatment -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class CursorCandidateUrtOperationBuilder[-Query <: PipelineQuery]( - cursorType: CursorType, - displayTreatment: Option[CursorDisplayTreatment] = None, - idToReplace: Option[Long] = None) - extends CandidateUrtEntryBuilder[Query, CursorCandidate, CursorOperation] { - - override def apply( - query: Query, - cursorCandidate: CursorCandidate, - candidateFeatures: FeatureMap - ): CursorOperation = CursorOperation( - id = cursorCandidate.id, - sortIndex = None, // Sort indexes are automatically set in the domain marshaller phase - value = cursorCandidate.value, - cursorType = cursorType, - displayTreatment = displayTreatment, - idToReplace = idToReplace - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala deleted file mode 100644 index 6edc3b593..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/promoted/FeaturePromotedMetadataBuilder.scala +++ /dev/null @@ -1,106 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.promoted - -import com.twitter.ads.adserver.{thriftscala => ads} -import com.twitter.ads.common.base.{thriftscala => ac} -import com.twitter.adserver.{thriftscala => ad} -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted.BasePromotedMetadataBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.util.AdMetadataContainerSerializer - -case class FeaturePromotedMetadataBuilder(adImpressionFeature: Feature[_, Option[ad.AdImpression]]) - extends BasePromotedMetadataBuilder[PipelineQuery, UniversalNoun[Any]] { - - def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): Option[PromotedMetadata] = { - candidateFeatures.getOrElse(adImpressionFeature, None).map { impression => - PromotedMetadata( - advertiserId = impression.advertiserId, - disclosureType = impression.disclosureType.map(convertDisclosureType), - experimentValues = impression.experimentValues.map(_.toMap), - promotedTrendId = impression.promotedTrendId.map(_.toLong), - promotedTrendName = impression.promotedTrendName, - promotedTrendQueryTerm = impression.promotedTrendQueryTerm, - adMetadataContainer = - impression.serializedAdMetadataContainer.flatMap(convertAdMetadataContainer), - promotedTrendDescription = impression.promotedTrendDescription, - impressionString = impression.impressionString, - clickTrackingInfo = impression.clickTrackingInfo.map(convertClickTrackingInfo), - ) - } - } - - private def convertAdMetadataContainer( - serializedAdMetadataContainer: ac.SerializedThrift - ): Option[AdMetadataContainer] = - AdMetadataContainerSerializer.deserialize(serializedAdMetadataContainer).map { container => - AdMetadataContainer( - removePromotedAttributionForPreroll = container.removePromotedAttributionForPreroll, - sponsorshipCandidate = container.sponsorshipCandidate, - sponsorshipOrganization = container.sponsorshipOrganization, - sponsorshipOrganizationWebsite = container.sponsorshipOrganizationWebsite, - sponsorshipType = container.sponsorshipType.map(convertSponsorshipType), - disclaimerType = container.disclaimerType.map(convertDisclaimerType), - skAdNetworkDataList = container.skAdNetworkDataList.map(convertSkAdNetworkDataList), - unifiedCardOverride = container.unifiedCardOverride - ) - } - - private def convertDisclosureType(disclosureType: ad.DisclosureType): DisclosureType = - disclosureType match { - case ad.DisclosureType.None => NoDisclosure - case ad.DisclosureType.Political => Political - case ad.DisclosureType.Earned => Earned - case ad.DisclosureType.Issue => Issue - case _ => throw new UnsupportedOperationException(s"Unsupported: $disclosureType") - } - - private def convertSponsorshipType(sponsorshipType: ads.SponsorshipType): SponsorshipType = - sponsorshipType match { - case ads.SponsorshipType.Direct => DirectSponsorshipType - case ads.SponsorshipType.Indirect => IndirectSponsorshipType - case ads.SponsorshipType.NoSponsorship => NoSponsorshipSponsorshipType - case _ => throw new UnsupportedOperationException(s"Unsupported: $sponsorshipType") - } - - private def convertDisclaimerType(disclaimerType: ads.DisclaimerType): DisclaimerType = - disclaimerType match { - case ads.DisclaimerType.Political => DisclaimerPolitical - case ads.DisclaimerType.Issue => DisclaimerIssue - case _ => throw new UnsupportedOperationException(s"Unsupported: $disclaimerType") - } - - private def convertSkAdNetworkDataList( - skAdNetworkDataList: Seq[ads.SkAdNetworkData] - ): Seq[SkAdNetworkData] = skAdNetworkDataList.map { sdAdNetwork => - SkAdNetworkData( - version = sdAdNetwork.version, - srcAppId = sdAdNetwork.srcAppId, - dstAppId = sdAdNetwork.dstAppId, - adNetworkId = sdAdNetwork.adNetworkId, - campaignId = sdAdNetwork.campaignId, - impressionTimeInMillis = sdAdNetwork.impressionTimeInMillis, - nonce = sdAdNetwork.nonce, - signature = sdAdNetwork.signature, - fidelityType = sdAdNetwork.fidelityType - ) - } - - private def convertClickTrackingInfo(clickTracking: ad.ClickTrackingInfo): ClickTrackingInfo = - ClickTrackingInfo( - urlParams = clickTracking.urlParams.getOrElse(Map.empty), - urlOverride = clickTracking.urlOverride, - urlOverrideType = clickTracking.urlOverrideType.map { - case ad.UrlOverrideType.Unknown => UnknownUrlOverrideType - case ad.UrlOverrideType.Dcm => DcmUrlOverrideType - case ad.UrlOverrideType.EnumUnknownUrlOverrideType(value) => - throw new UnsupportedOperationException(s"Unsupported: $value") - } - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala deleted file mode 100644 index cb5ff66df..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextBuilder.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class RichTextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - textBuilder: BaseStr[Query, Candidate], - linkMap: Map[String, String], - rtl: Option[Boolean], - alignment: Option[RichTextAlignment], - linkTypeMap: Map[String, UrlType] = Map.empty) - extends BaseRichTextBuilder[Query, Candidate] { - - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): RichText = { - RichTextMarkupUtil.richTextFromMarkup( - text = textBuilder(query, candidate, candidateFeatures), - linkMap = linkMap, - rtl = rtl, - alignment = alignment, - linkTypeMap = linkTypeMap) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala deleted file mode 100644 index dacb72b90..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextMarkupUtil.scala +++ /dev/null @@ -1,135 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong - -/* - * RichTextMarkupUtil facilitates building a Product Mixer URT RichText object out of - * a string with inline XML markup. - * - * This allows us to use a string like "Our system Product Mixer is the best". Using - * inline markup like this is advantageous since the string can go through translation/localization and the - * translators will move the tags around in each language as appropriate. - * - * This class is derived from the OCF (onboarding/serve)'s RichTextUtil, but they diverge because: - * - We generate ProMix URT structures, not OCF URT structures - * - The OCF supports some internal OCF tags, like - * - The OCF has additional legacy support and processing that we don't need - */ - -object RichTextMarkupUtil { - - // Matches a anchor element, extracting the 'a' tag and the display text. - // First group is the tag - // Second group is the display text - // Allows any character in the display text, but matches reluctantly - private val LinkAnchorRegex = """(?i)(?s)(.*?)""".r - - // Matches a bold text section - private val BoldRegex = """(?i)(?s)(.*?)""".r - - def richTextFromMarkup( - text: String, - linkMap: Map[String, String], - rtl: Option[Boolean] = None, - alignment: Option[RichTextAlignment] = None, - linkTypeMap: Map[String, UrlType] = Map.empty - ): RichText = { - - // Mutable! - var currentText = text - val entities = scala.collection.mutable.ArrayBuffer.empty[RichTextEntity] - - // Using a while loop since we want to execute the regex after each iteration, so our indexes remain consistent - - // Handle Links - var matchOpt = LinkAnchorRegex.findFirstMatchIn(currentText) - while (matchOpt.isDefined) { - matchOpt.foreach { linkMatch => - val tag = linkMatch.group(1) - val displayText = linkMatch.group(2) - - currentText = currentText.substring(0, linkMatch.start) + displayText + currentText - .substring(linkMatch.end) - - adjustEntities( - entities, - linkMatch.start, - linkMatch.end - (linkMatch.start + displayText.length)) - - entities.append( - RichTextEntity( - fromIndex = linkMatch.start, - toIndex = linkMatch.start + displayText.length, - ref = linkMap.get(tag).map { url => - Url( - urlType = linkTypeMap.getOrElse(tag, ExternalUrl), - url = url - ) - }, - format = None - ) - ) - } - matchOpt = LinkAnchorRegex.findFirstMatchIn(currentText) - } - - // Handle Bold - matchOpt = BoldRegex.findFirstMatchIn(currentText) - while (matchOpt.isDefined) { - matchOpt.foreach { boldMatch => - val text = boldMatch.group(1) - - currentText = - currentText.substring(0, boldMatch.start) + text + currentText.substring(boldMatch.end) - - adjustEntities(entities, boldMatch.start, boldMatch.end - (boldMatch.start + text.length)) - - entities.append( - RichTextEntity( - fromIndex = boldMatch.start, - toIndex = boldMatch.start + text.length, - ref = None, - format = Some(Strong), - ) - ) - } - - matchOpt = BoldRegex.findFirstMatchIn(currentText) - } - - RichText( - currentText, - entities.sortBy(_.fromIndex).toList, // always return immutable copies! - rtl, - alignment - ) - } - - /* When we create a new entity, we need to adjust - * any already existing entities that have been moved. - * Entities cannot overlap, so we can just compare start positions. - */ - private def adjustEntities( - entities: scala.collection.mutable.ArrayBuffer[RichTextEntity], - start: Int, - length: Int - ): Unit = { - for (i <- entities.indices) { - if (entities(i).fromIndex > start) { - val old = entities(i) - entities.update( - i, - entities(i).copy( - fromIndex = old.fromIndex - length, - toIndex = old.toIndex - length - )) - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala deleted file mode 100644 index 503f0841c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextReferenceObjectBuilder.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject -import com.twitter.twittertext.Extractor - -trait RichTextReferenceObjectBuilder { - def apply(entity: Extractor.Entity): Option[ReferenceObject] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala deleted file mode 100644 index 6fc39d5a4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/RichTextRtlOptionBuilder.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext - -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait RichTextRtlOptionBuilder[-Query <: PipelineQuery] { - def apply(query: Query): Option[Boolean] -} - -case class StaticRichTextRtlOptionBuilder[-Query <: PipelineQuery](rtlOption: Option[Boolean]) - extends RichTextRtlOptionBuilder[Query] { - override def apply(query: Query): Option[Boolean] = rtlOption -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala deleted file mode 100644 index 64054559a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/StaticRichTextBuilder.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticRichTextBuilder(richText: RichText) - extends BaseRichTextBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): RichText = richText -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala deleted file mode 100644 index ca27c7e14..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextEntityProcessor.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text - -import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.RichTextReferenceObjectBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text.TwitterTextEntityProcessor.DefaultReferenceObjectBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextCashtag -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextHashtag -import com.twitter.twittertext.Extractor -import scala.collection.convert.ImplicitConversions._ - -object TwitterTextEntityProcessor { - object DefaultReferenceObjectBuilder extends RichTextReferenceObjectBuilder { - def apply(twitterEntity: Extractor.Entity): Option[ReferenceObject] = { - twitterEntity.getType match { - case Extractor.Entity.Type.URL => - Some(Url(ExternalUrl, twitterEntity.getValue)) - case Extractor.Entity.Type.HASHTAG => - Some(RichTextHashtag(twitterEntity.getValue)) - case Extractor.Entity.Type.CASHTAG => - Some(RichTextCashtag(twitterEntity.getValue)) - case _ => None - } - } - } -} - -/** - * Add the corresponding [[RichTextEntity]] extraction logic into [[TwitterTextRenderer]]. - * The [[TwitterTextRenderer]] after being processed will extract the defined entities. - */ -case class TwitterTextEntityProcessor( - twitterTextReferenceObjectBuilder: RichTextReferenceObjectBuilder = DefaultReferenceObjectBuilder) - extends TwitterTextRendererProcessor { - - private[this] val extractor = new Extractor() - - def process( - twitterTextRenderer: TwitterTextRenderer - ): TwitterTextRenderer = { - val twitterEntities = extractor.extractEntitiesWithIndices(twitterTextRenderer.text) - - twitterEntities.foreach { twitterEntity => - twitterTextReferenceObjectBuilder(twitterEntity).foreach { refObject => - twitterTextRenderer.setRefObject(twitterEntity.getStart, twitterEntity.getEnd, refObject) - } - } - twitterTextRenderer - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala deleted file mode 100644 index cf36eecc6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextFormatProcessor.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong -import scala.collection.mutable - -object TwitterTextFormatProcessor { - lazy val defaultFormatProcessor = TwitterTextFormatProcessor() -} - -/** - * Add the corresponding [[RichTextFormat]] extraction logic into [[TwitterTextRenderer]]. - * The [[TwitterTextRenderer]] after being processed will extract the defined entities. - */ -case class TwitterTextFormatProcessor( - formats: Set[RichTextFormat] = Set(Plain, Strong), -) extends TwitterTextRendererProcessor { - - private val formatMap = formats.map { format => format.name.toLowerCase -> format }.toMap - - private[this] val formatMatcher = { - val formatNames = formatMap.keys.toSet - s"<(/?)(${formatNames.mkString("|")})>".r - } - - def renderText(text: String): RichText = { - process(TwitterTextRenderer(text)).build - } - - def process(richTextBuilder: TwitterTextRenderer): TwitterTextRenderer = { - val text = richTextBuilder.text - val nodeStack = mutable.ArrayStack[(RichTextFormat, Int)]() - var offset = 0 - - formatMatcher.findAllMatchIn(text).foreach { m => - formatMap.get(m.group(2)) match { - case Some(format) => { - if (m.group(1).nonEmpty) { - if (!nodeStack.headOption.exists { - case (formatFromStack, _) => formatFromStack == format - }) { - throw UnmatchedFormatTag(format) - } - val (_, startIndex) = nodeStack.pop - richTextBuilder.mergeFormat(startIndex, m.start + offset, format) - } else { - nodeStack.push((format, m.start + offset)) - } - richTextBuilder.remove(m.start + offset, m.end + offset) - offset -= m.end - m.start - } - case _ => // if format is not found, skip this format - } - } - - if (nodeStack.nonEmpty) { - throw UnmatchedFormatTag(nodeStack.head._1) - } - - richTextBuilder - } -} - -case class UnmatchedFormatTag(format: RichTextFormat) - extends Exception(s"Unmatched format start and end tags for $format") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala deleted file mode 100644 index 53a534255..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRenderer.scala +++ /dev/null @@ -1,390 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat -import scala.annotation.tailrec -import scala.collection.mutable - -object TwitterTextRenderer { - - /** - * Creates a new [[TwitterTextRenderer]] instance. - * @param text The initial text representation - * @param rtl Defines whether this text is in an RTL language - * @param alignment Assigns the [[RichTextAlignment]] of the given text for display - * @return A new [[TwitterTextRenderer]] instance - */ - def apply( - text: String, - rtl: Option[Boolean] = None, - alignment: Option[RichTextAlignment] = None - ): TwitterTextRenderer = { - TwitterTextRenderer(rtl, alignment).append(text) - } - - /** - * Creates a new [[TwitterTextRenderer]] instance from a product-mixer [[RichText]] object. - * Converts Unicode entity indexes into JVM String indexes. - * @param richText The product-mixer [[RichText]] representation - * @return A new [[TwitterTextRenderer]] instance - */ - def fromRichText(richText: RichText): TwitterTextRenderer = { - val builder = TwitterTextRenderer(richText.text, richText.rtl, richText.alignment) - richText.entities.foreach { e => - val startIndex = richText.text.offsetByCodePoints(0, e.fromIndex) - val endIndex = richText.text.offsetByCodePoints(0, e.toIndex) - e.format.foreach { f => - builder.setFormat(startIndex, endIndex, f) - } - e.ref.foreach { r => - builder.setRefObject(startIndex, endIndex, r) - } - } - builder - } - - private def buildRichTextEntity( - text: String, - entity: TwitterTextRendererEntity[_] - ): RichTextEntity = { - val fromIndex = text.codePointCount(0, entity.startIndex) - val toIndex = text.codePointCount(0, entity.endIndex) - - entity.value match { - case format: RichTextFormat => - RichTextEntity(fromIndex, toIndex, ref = None, format = Some(format)) - case ref: ReferenceObject => - RichTextEntity(fromIndex, toIndex, ref = Some(ref), format = None) - } - } -} - -case class TwitterTextRenderer( - rtl: Option[Boolean], - alignment: Option[RichTextAlignment], -) { - private[this] val textBuilder = new mutable.StringBuilder() - - private[richtext] val formatBuffer = - mutable.ArrayBuffer[TwitterTextRendererEntity[RichTextFormat]]() - private[richtext] val refObjectBuffer = - mutable.ArrayBuffer[TwitterTextRendererEntity[ReferenceObject]]() - - /** - * Appends a string with attached [[RichTextFormat]] and [[ReferenceObject]] information. - * @param string The text to append to the end of the existing text - * @param format The [[RichTextFormat]] assigned to the new text - * @param refObject The [[ReferenceObject]] assigned to the new text - * @return this - */ - def append( - string: String, - format: Option[RichTextFormat] = None, - refObject: Option[ReferenceObject] = None - ): TwitterTextRenderer = { - if (string.nonEmpty) { - val start = textBuilder.length - val end = start + string.length - format.foreach { f => - formatBuffer.append(TwitterTextRendererEntity(start, end, f)) - } - refObject.foreach { r => - refObjectBuffer.append(TwitterTextRendererEntity(start, end, r)) - } - textBuilder.append(string) - } - this - } - - /** - * Builds a new [[RichText]] thrift instance with Unicode entity ranges. - */ - def build: RichText = { - val richTextString = this.text - val richTextEntities = this.entities - .map { e => - TwitterTextRenderer.buildRichTextEntity(richTextString, e) - } - - RichText( - text = richTextString, - rtl = rtl, - alignment = alignment, - entities = richTextEntities.toList - ) - } - - /** - * Modifies the TwitterTextRenderer with the provided [[TwitterTextRendererProcessor]] - */ - def transform(twitterTextProcessor: TwitterTextRendererProcessor): TwitterTextRenderer = { - twitterTextProcessor.process(this) - } - - /** - * Builds and returns a sorted list of [[TwitterTextRendererEntity]] with JVM String index entity ranges. - */ - def entities: Seq[TwitterTextRendererEntity[_]] = { - buildEntities(formatBuffer.toList, refObjectBuffer.toList) - } - - /** - * Assigns a [[RichTextFormat]] to the given range while keeping existing formatting information. - * New formatting will only be assigned to unformatted text ranges. - * @param start Start index to apply formatting (inclusive) - * @param end End index to apply formatting (exclusive) - * @param format The format to assign - * @return this - */ - def mergeFormat(start: Int, end: Int, format: RichTextFormat): TwitterTextRenderer = { - validateRange(start, end) - var injectionIndex: Option[Int] = None - var entity = TwitterTextRendererEntity(start, end, format) - - val buffer = mutable.ArrayBuffer[TwitterTextRendererEntity[RichTextFormat]]() - val iterator = formatBuffer.zipWithIndex.reverseIterator - - while (iterator.hasNext && injectionIndex.isEmpty) { - iterator.next match { - case (e, i) if e.startIndex >= end => - buffer.append(e) - - case (e, i) if e.enclosedIn(entity.startIndex, entity.endIndex) => - val endEntity = entity.copy(startIndex = e.endIndex) - if (endEntity.nonEmpty) { buffer.append(endEntity) } - buffer.append(e) - entity = entity.copy(endIndex = e.startIndex) - - case (e, i) if e.encloses(entity.startIndex, entity.endIndex) => - buffer.append(e.copy(startIndex = entity.endIndex)) - buffer.append(e.copy(endIndex = entity.startIndex)) - injectionIndex = Some(i + 1) - - case (e, i) if e.startsBetween(entity.startIndex, entity.endIndex) => - buffer.append(e) - entity = entity.copy(endIndex = e.startIndex) - - case (e, i) if e.endsBetween(entity.startIndex, entity.endIndex) => - buffer.append(e) - entity = entity.copy(startIndex = e.endIndex) - injectionIndex = Some(i + 1) - - case (e, i) if e.endIndex <= entity.startIndex => - buffer.append(e) - injectionIndex = Some(i + 1) - - case _ => // do nothing - } - } - - val index = injectionIndex.map(_ - 1).getOrElse(0) - formatBuffer.remove(index, formatBuffer.length - index) - formatBuffer.appendAll(buffer.reverse) - - if (entity.nonEmpty) { - formatBuffer.insert(injectionIndex.getOrElse(0), entity) - } - - this - } - - /** - * Removes text, formatting, and refObject information from the given range. - * @param start Start index to apply formatting (inclusive) - * @param end End index to apply formatting (exclusive) - * @return this - */ - def remove(start: Int, end: Int): TwitterTextRenderer = replace(start, end, "") - - /** - * Replaces text, formatting, and refObject information in the given range. - * @param start Start index to apply formatting (inclusive) - * @param end End index to apply formatting (exclusive) - * @param string The new text to insert - * @param format The [[RichTextFormat]] assigned to the new text - * @param refObject The [[ReferenceObject]] assigned to the new text - * @return this - */ - def replace( - start: Int, - end: Int, - string: String, - format: Option[RichTextFormat] = None, - refObject: Option[ReferenceObject] = None - ): TwitterTextRenderer = { - validateRange(start, end) - - val newEnd = start + string.length - val formatInjectIndex = removeAndOffsetFormats(start, end, string.length) - val refObjectInjectIndex = removeAndOffsetRefObjects(start, end, string.length) - format.foreach { f => - formatBuffer.insert(formatInjectIndex, TwitterTextRendererEntity(start, newEnd, f)) - } - refObject.foreach { r => - refObjectBuffer.insert(refObjectInjectIndex, TwitterTextRendererEntity(start, newEnd, r)) - } - textBuilder.replace(start, end, string) - - this - } - - /** - * Assigns a [[RichTextFormat]] to the given range. Trims existing format ranges that overlap the - * new format range. Removes format ranges that fall within the new range. - * @param start Start index to apply formatting (inclusive) - * @param end End index to apply formatting (exclusive) - * @param format The format to assign - * @return this - */ - def setFormat(start: Int, end: Int, format: RichTextFormat): TwitterTextRenderer = { - validateRange(start, end) - val bufferIndex = removeAndOffsetFormats(start, end, end - start) - formatBuffer.insert(bufferIndex, TwitterTextRendererEntity(start, end, format)) - - this - } - - private[this] def removeAndOffsetFormats(start: Int, end: Int, newSize: Int): Int = { - val newEnd = start + newSize - val offset = newEnd - end - var injectionIndex: Option[Int] = None - - val buffer = mutable.ArrayBuffer[TwitterTextRendererEntity[RichTextFormat]]() - val iterator = formatBuffer.zipWithIndex.reverseIterator - - while (iterator.hasNext && injectionIndex.isEmpty) { - iterator.next match { - case (e, i) if e.startIndex >= end => - buffer.append(e.offset(offset)) - case (e, i) if e.encloses(start, end) => - buffer.append(e.copy(startIndex = newEnd, endIndex = e.endIndex + offset)) - buffer.append(e.copy(endIndex = e.endIndex + offset)) - injectionIndex = Some(i + 1) - case (e, i) if e.endsBetween(start, end) => - buffer.append(e.copy(endIndex = start)) - injectionIndex = Some(i + 1) - case (e, i) if e.startsBetween(start, end) => - buffer.append(e.copy(startIndex = newEnd, endIndex = e.endIndex + offset)) - case (e, i) if e.endIndex <= start => - buffer.append(e) - injectionIndex = Some(i + 1) - case _ => // do nothing - } - } - val index = injectionIndex.map(_ - 1).getOrElse(0) - formatBuffer.remove(index, formatBuffer.length - index) - formatBuffer.appendAll(buffer.reverse) - - injectionIndex.getOrElse(0) - } - - private[this] def validateRange(start: Int, end: Int): Unit = { - require( - start >= 0 && start < textBuilder.length && end > start && end <= textBuilder.length, - s"The start ($start) and end ($end) indexes must be within the text range (0..${textBuilder.length})" - ) - } - - /** - * Assigns a [[ReferenceObject]] to the given range. Since it makes little sense to trim object - * ranges, existing intersecting or overlapping ranges are removed entirely. - * @param start Start index to apply formatting (inclusive) - * @param end End index to apply formatting (exclusive) - * @param refObject The [[ReferenceObject]] to assign - * @return this - */ - def setRefObject(start: Int, end: Int, refObject: ReferenceObject): TwitterTextRenderer = { - validateRange(start, end) - val bufferIndex = removeAndOffsetRefObjects(start, end, end - start) - refObjectBuffer.insert(bufferIndex, TwitterTextRendererEntity(start, end, refObject)) - - this - } - - private[this] def removeAndOffsetRefObjects(start: Int, end: Int, newSize: Int): Int = { - val newEnd = start + newSize - val offset = newEnd - end - var injectionIndex: Option[Int] = None - - val buffer = mutable.ArrayBuffer[TwitterTextRendererEntity[ReferenceObject]]() - val iterator = refObjectBuffer.zipWithIndex.reverseIterator - - while (iterator.hasNext && injectionIndex.isEmpty) { - iterator.next match { - case (e, i) if e.startIndex >= end => buffer.append(e.offset(offset)) - case (e, i) if e.endIndex <= start => injectionIndex = Some(i + 1) - case _ => // do nothing - } - } - val index = injectionIndex.getOrElse(0) - refObjectBuffer.remove(index, refObjectBuffer.length - index) - refObjectBuffer.appendAll(buffer.reverse) - - index - } - - /** - * Builds and returns the full TwitterTextRenderer text with any changes applied to the builder instance. - */ - def text: String = { - textBuilder.mkString - } - - @tailrec - private def buildEntities( - formats: List[TwitterTextRendererEntity[RichTextFormat]], - refs: List[TwitterTextRendererEntity[ReferenceObject]], - acc: List[TwitterTextRendererEntity[_]] = List() - ): Seq[TwitterTextRendererEntity[_]] = { - (formats, refs) match { - case (Nil, Nil) => acc - case (remainingFormats, Nil) => acc ++ remainingFormats - case (Nil, remainingRefs) => acc ++ remainingRefs - - case (format +: remainingFormats, ref +: remainingRefs) - if format.startIndex < ref.startIndex || (format.startIndex == ref.startIndex && format.endIndex < ref.endIndex) => - buildEntities(remainingFormats, refs, acc :+ format) - - case (format +: remainingFormats, ref +: remainingRefs) - if format.startIndex == ref.startIndex && format.endIndex == ref.endIndex => - buildEntities(remainingFormats, remainingRefs, acc :+ format :+ ref) - - case (_, ref +: remainingRefs) => - buildEntities(formats, remainingRefs, acc :+ ref) - } - } -} - -case class TwitterTextRendererEntity[+T] private[richtext] ( - startIndex: Int, - endIndex: Int, - value: T) { - require(startIndex <= endIndex, "startIndex must be <= than endIndex") - - def nonEmpty: Boolean = !isEmpty - - def isEmpty: Boolean = startIndex == endIndex - - private[richtext] def enclosedIn(start: Int, end: Int): Boolean = { - start <= startIndex && endIndex <= end - } - - private[richtext] def encloses(start: Int, end: Int): Boolean = { - startIndex < start && end < endIndex - } - - private[richtext] def endsBetween(start: Int, end: Int): Boolean = { - start < endIndex && endIndex <= end && startIndex < start - } - - private[richtext] def offset(num: Int): TwitterTextRendererEntity[T] = { - copy(startIndex = startIndex + num, endIndex = endIndex + num) - } - - private[richtext] def startsBetween(start: Int, end: Int): Boolean = { - startIndex >= start && startIndex < end && endIndex > end - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala deleted file mode 100644 index 5e5f45659..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRendererProcessor.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text - -trait TwitterTextRendererProcessor { - def process(twitterTextRichTextBuilder: TwitterTextRenderer): TwitterTextRenderer -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala deleted file mode 100644 index 50422a335..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/richtext/twitter_text/TwitterTextRichTextBuilder.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text - -import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.RichTextReferenceObjectBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.RichTextRtlOptionBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.StaticRichTextRtlOptionBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.richtext.twitter_text.TwitterTextEntityProcessor.DefaultReferenceObjectBuilder -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext.BaseRichTextBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class TwitterTextRichTextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - stringBuilder: BaseStr[Query, Candidate], - alignment: Option[RichTextAlignment] = None, - formats: Set[RichTextFormat] = Set(Plain, Strong), - twitterTextRtlOptionBuilder: RichTextRtlOptionBuilder[Query] = - StaticRichTextRtlOptionBuilder[Query](None), - twitterTextReferenceObjectBuilder: RichTextReferenceObjectBuilder = DefaultReferenceObjectBuilder) - extends BaseRichTextBuilder[Query, Candidate] { - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): RichText = { - val twitterTextRenderer = TwitterTextRenderer( - text = stringBuilder(query, candidate, candidateFeatures), - rtl = twitterTextRtlOptionBuilder(query), - alignment = alignment) - - twitterTextRenderer - .transform(TwitterTextFormatProcessor(formats)) - .transform(TwitterTextEntityProcessor(twitterTextReferenceObjectBuilder)) - .build - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala deleted file mode 100644 index d96551bc6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/FeatureSocialContextBuilder.scala +++ /dev/null @@ -1,101 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.service.{thriftscala => t} - -/** - * Use this Builder to create Product Mixer [[SocialContext]] objects when you have a - * Timeline Service Thrift [[SocialContext]] feature that you want to convert - */ -case class FeatureSocialContextBuilder( - socialContextFeature: Feature[_, Option[t.SocialContext]]) - extends BaseSocialContextBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): Option[SocialContext] = { - candidateFeatures.getOrElse(socialContextFeature, None).map { - case t.SocialContext.GeneralContext(context) => - val contextType = context.contextType match { - case t.ContextType.Like => LikeGeneralContextType - case t.ContextType.Follow => FollowGeneralContextType - case t.ContextType.Moment => MomentGeneralContextType - case t.ContextType.Reply => ReplyGeneralContextType - case t.ContextType.Conversation => ConversationGeneralContextType - case t.ContextType.Pin => PinGeneralContextType - case t.ContextType.TextOnly => TextOnlyGeneralContextType - case t.ContextType.Facepile => FacePileGeneralContextType - case t.ContextType.Megaphone => MegaPhoneGeneralContextType - case t.ContextType.Bird => BirdGeneralContextType - case t.ContextType.Feedback => FeedbackGeneralContextType - case t.ContextType.Topic => TopicGeneralContextType - case t.ContextType.List => ListGeneralContextType - case t.ContextType.Retweet => RetweetGeneralContextType - case t.ContextType.Location => LocationGeneralContextType - case t.ContextType.Community => CommunityGeneralContextType - case t.ContextType.SmartBlockExpiration => SmartblockExpirationGeneralContextType - case t.ContextType.Trending => TrendingGeneralContextType - case t.ContextType.Sparkle => SparkleGeneralContextType - case t.ContextType.Spaces => SpacesGeneralContextType - case t.ContextType.ReplyPin => ReplyPinGeneralContextType - case t.ContextType.NewUser => NewUserGeneralContextType - case t.ContextType.EnumUnknownContextType(field) => - throw new UnsupportedOperationException(s"Unknown context type: $field") - } - - val landingUrl = context.landingUrl.map { url => - val endpointOptions = url.urtEndpointOptions.map { options => - UrtEndpointOptions( - requestParams = options.requestParams.map(_.toMap), - title = options.title, - cacheId = options.cacheId, - subtitle = options.subtitle - ) - } - - val urlType = url.urlType match { - case t.UrlType.ExternalUrl => ExternalUrl - case t.UrlType.DeepLink => DeepLink - case t.UrlType.UrtEndpoint => UrtEndpoint - case t.UrlType.EnumUnknownUrlType(field) => - throw new UnsupportedOperationException(s"Unknown url type: $field") - } - - Url(urlType = urlType, url = url.url, urtEndpointOptions = endpointOptions) - } - - GeneralContext( - text = context.text, - contextType = contextType, - url = context.url, - contextImageUrls = context.contextImageUrls.map(_.toList), - landingUrl = landingUrl - ) - case t.SocialContext.TopicContext(context) => - val functionalityType = context.functionalityType match { - case t.TopicContextFunctionalityType.Basic => - BasicTopicContextFunctionalityType - case t.TopicContextFunctionalityType.Recommendation => - RecommendationTopicContextFunctionalityType - case t.TopicContextFunctionalityType.RecWithEducation => - RecWithEducationTopicContextFunctionalityType - case t.TopicContextFunctionalityType.EnumUnknownTopicContextFunctionalityType(field) => - throw new UnsupportedOperationException(s"Unknown functionality type: $field") - } - - TopicContext( - topicId = context.topicId, - functionalityType = Some(functionalityType) - ) - case t.SocialContext.UnknownUnionField(field) => - throw new UnsupportedOperationException(s"Unknown social context: $field") - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala deleted file mode 100644 index c3e9e9919..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralModuleSocialContextBuilder.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseModuleStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseModuleSocialContextBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContextType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * This class works the same as [[GeneralSocialContextBuilder]] but passes a list of candidates - * into [[BaseModuleStr]] when rendering the string. - */ -case class GeneralModuleSocialContextBuilder[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any] -]( - textBuilder: BaseModuleStr[Query, Candidate], - contextType: GeneralContextType, - url: Option[String] = None, - contextImageUrls: Option[List[String]] = None, - landingUrl: Option[Url] = None) - extends BaseModuleSocialContextBuilder[Query, Candidate] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[GeneralContext] = - Some( - GeneralContext( - text = textBuilder(query, candidates), - contextType = contextType, - url = url, - contextImageUrls = contextImageUrls, - landingUrl = landingUrl)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala deleted file mode 100644 index ef2221468..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/GeneralSocialContextBuilder.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContextType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class GeneralSocialContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - textBuilder: BaseStr[Query, Candidate], - contextType: GeneralContextType, - url: Option[String] = None, - contextImageUrls: Option[List[String]] = None, - landingUrl: Option[Url] = None) - extends BaseSocialContextBuilder[Query, Candidate] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[GeneralContext] = - Some( - GeneralContext( - text = textBuilder(query, candidate, candidateFeatures), - contextType = contextType, - url = url, - contextImageUrls = contextImageUrls, - landingUrl = landingUrl)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala deleted file mode 100644 index edcc07fcd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/social_context/WhoToFollowSocialContextBuilder.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.social_context - -import com.twitter.hermit.{thriftscala => h} -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseSocialContextBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FollowGeneralContextType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContextType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.LocationGeneralContextType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.NewUserGeneralContextType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class WhoToFollowSocialContextBuilder( - socialTextFeature: Feature[_, Option[String]], - contextTypeFeature: Feature[_, Option[h.ContextType]]) - extends BaseSocialContextBuilder[PipelineQuery, UserCandidate] { - - def apply( - query: PipelineQuery, - candidate: UserCandidate, - candidateFeatures: FeatureMap - ): Option[GeneralContext] = { - val socialTextOpt = candidateFeatures.getOrElse(socialTextFeature, None) - val contextTypeOpt = convertContextType(candidateFeatures.getOrElse(contextTypeFeature, None)) - - (socialTextOpt, contextTypeOpt) match { - case (Some(socialText), Some(contextType)) if socialText.nonEmpty => - Some( - GeneralContext( - text = socialText, - contextType = contextType, - url = None, - contextImageUrls = None, - landingUrl = None)) - case _ => None - } - } - - private def convertContextType(contextType: Option[h.ContextType]): Option[GeneralContextType] = - contextType match { - case Some(h.ContextType.Geo) => Some(LocationGeneralContextType) - case Some(h.ContextType.Social) => Some(FollowGeneralContextType) - case Some(h.ContextType.NewUser) => Some(NewUserGeneralContextType) - case _ => None - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala deleted file mode 100644 index 0abb2ec63..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/ModuleStr.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseModuleStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter.BaseModuleStringCenterPlaceholderBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stringcenter.client.StringCenter -import com.twitter.stringcenter.client.core.ExternalString - -/** - * This class works the same as [[Str]] but passes in a list of candidates to the - * [[BaseModuleStringCenterPlaceholderBuilder]] when building the placeholders. - */ -case class ModuleStr[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - text: ExternalString, - stringCenter: StringCenter, - stringCenterPlaceholderBuilder: Option[ - BaseModuleStringCenterPlaceholderBuilder[Query, Candidate] - ] = None) - extends BaseModuleStr[Query, Candidate] { - - def apply(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): String = { - val placeholderMapOpt = - stringCenterPlaceholderBuilder.map(_.apply(query, candidates)) - stringCenter.prepare( - externalString = text, - placeholders = placeholderMapOpt.getOrElse(Map.empty[String, Any]) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala deleted file mode 100644 index 6f5a6c3b3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/stringcenter/Str.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter.BaseStringCenterPlaceholderBuilder -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stringcenter.client.StringCenter -import com.twitter.stringcenter.client.core.ExternalString - -case class StrStatic( - text: String) - extends BaseStr[PipelineQuery, UniversalNoun[Any]] { - def apply( - query: PipelineQuery, - candidate: UniversalNoun[Any], - candidateFeatures: FeatureMap - ): String = text -} - -case class Str[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - text: ExternalString, - stringCenter: StringCenter, - stringCenterPlaceholderBuilder: Option[BaseStringCenterPlaceholderBuilder[Query, Candidate]] = - None) - extends BaseStr[Query, Candidate] { - - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): String = { - val placeholderMapOpt = - stringCenterPlaceholderBuilder.map(_.apply(query, candidate, candidateFeatures)) - stringCenter.prepare( - externalString = text, - placeholders = placeholderMapOpt.getOrElse(Map.empty[String, Any]) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala deleted file mode 100644 index bc9632e5a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/FeatureModuleDisplayTypeBuilder.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalConversation -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class FeatureModuleDisplayTypeBuilder( - displayTypeFeature: Feature[_, Option[ModuleDisplayType]], - defaultDisplayType: ModuleDisplayType = VerticalConversation) - extends BaseModuleDisplayTypeBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ModuleDisplayType = candidates.headOption - .flatMap(_.features.getOrElse(displayTypeFeature, None)) - .getOrElse(defaultDisplayType) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala deleted file mode 100644 index fd234de7c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleDynamicShowMoreBehaviorRevealByCountBuilder.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleShowMoreBehaviorBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ModuleDynamicShowMoreBehaviorRevealByCountBuilder( - initialItemsCount: Int, - showMoreItemsCount: Int) - extends BaseModuleShowMoreBehaviorBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidate: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ModuleShowMoreBehavior = ModuleShowMoreBehaviorRevealByCount( - initialItemsCount = initialItemsCount, - showMoreItemsCount = showMoreItemsCount - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala deleted file mode 100644 index 886825f2d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleFooterBuilder.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseUrlBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleFooterBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures - -case class ModuleFooterBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - textBuilder: BaseStr[Query, Candidate], - urlBuilder: Option[BaseUrlBuilder[Query, Candidate]]) - extends BaseModuleFooterBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[ModuleFooter] = { - candidates.headOption.map { candidate => - ModuleFooter( - text = textBuilder(query, candidate.candidate, candidate.features), - landingUrl = urlBuilder.map(_.apply(query, candidate.candidate, candidate.features)) - ) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala deleted file mode 100644 index fbe256d69..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderBuilder.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.icon.BaseHorizonIconBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseStr -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context.BaseModuleSocialContextBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderDisplayTypeBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ModuleHeaderBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - textBuilder: BaseStr[Query, Candidate], - isSticky: Option[Boolean] = None, - moduleHeaderIconBuilder: Option[BaseHorizonIconBuilder[Query, Candidate]] = None, - customIcon: Option[ImageVariant] = None, - moduleSocialContextBuilder: Option[BaseModuleSocialContextBuilder[Query, Candidate]] = None, - moduleHeaderDisplayTypeBuilder: BaseModuleHeaderDisplayTypeBuilder[Query, Candidate] = - ModuleHeaderDisplayTypeBuilder(Classic)) - extends BaseModuleHeaderBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[ModuleHeader] = { - val firstCandidate = candidates.head - Some( - ModuleHeader( - text = textBuilder(query, firstCandidate.candidate, firstCandidate.features), - sticky = isSticky, - customIcon = customIcon, - socialContext = moduleSocialContextBuilder.flatMap(_.apply(query, candidates)), - icon = moduleHeaderIconBuilder.flatMap(_.apply(query, candidates)), - moduleHeaderDisplayType = moduleHeaderDisplayTypeBuilder(query, candidates), - ) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala deleted file mode 100644 index bc0fffa8c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleHeaderDisplayTypeBuilder.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderDisplayTypeBuilder -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeaderDisplayType -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ModuleHeaderDisplayTypeBuilder[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any] -]( - moduleHeaderDisplayType: ModuleHeaderDisplayType = Classic) - extends BaseModuleHeaderDisplayTypeBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): ModuleHeaderDisplayType = moduleHeaderDisplayType - -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala deleted file mode 100644 index a885632e0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleIdGeneration.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -/** - * This trait is used for Module ID generation. Clients are safe to ignore this code unless they - * have a specific use case that requires hard-coded, specific, module ids. In that scenario, - * they can use the [[ManualModuleId]] case class. - */ -sealed trait ModuleIdGeneration { - val moduleId: Long -} - -object ModuleIdGeneration { - def apply(moduleId: Long): ModuleIdGeneration = moduleId match { - case moduleId if AutomaticUniqueModuleId.isAutomaticUniqueModuleId(moduleId) => - AutomaticUniqueModuleId(moduleId) - case moduleId => ManualModuleId(moduleId) - } -} - -/** - * Generate unique Ids for each module, which results in unique URT entryIds - * for each module even if they share the same entryNamespace. - * This is the default and recommended use case. - * Note that the module Id value is just a placeholder - */ -case class AutomaticUniqueModuleId private (moduleId: Long = 0L) extends ModuleIdGeneration { - def withOffset(offset: Long): AutomaticUniqueModuleId = copy( - AutomaticUniqueModuleId.idRange.min + offset) -} - -object AutomaticUniqueModuleId { - // We use a specific numeric range to track whether IDs should be automatically generated. - val idRange: Range = Range(-10000, -1000) - - def apply(): AutomaticUniqueModuleId = AutomaticUniqueModuleId(idRange.min) - - def isAutomaticUniqueModuleId(moduleId: Long): Boolean = idRange.contains(moduleId) -} - -/** - * ManualModuleId should normally not be required, but is helpful if the - * entryId of the module must be controlled. A scenario where this may be - * required is if a single candidate source returns multiple modules, and - * each module has the same presentation (e.g. Header, Footer). By setting - * different IDs, we signal to the platform that each module should be separate - * by using a different manual Id. - */ -case class ManualModuleId(override val moduleId: Long) extends ModuleIdGeneration { - // Negative module IDs are reserved for internal usage - if (moduleId < 0) throw new IllegalArgumentException("moduleId must be a positive number") -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala deleted file mode 100644 index 19bce376a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ModuleShowMoreBehaviorRevealByCountBuilder.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleShowMoreBehaviorBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.timelines.configapi.Param - -case class ModuleShowMoreBehaviorRevealByCountBuilder( - initialItemsCountParam: Param[Int], - showMoreItemsCountParam: Param[Int]) - extends BaseModuleShowMoreBehaviorBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidate: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ModuleShowMoreBehavior = { - ModuleShowMoreBehaviorRevealByCount( - initialItemsCount = query.params(initialItemsCountParam), - showMoreItemsCount = query.params(showMoreItemsCountParam) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala deleted file mode 100644 index 36654335a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleFooterBuilder.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleFooterBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -case class ParamGatedModuleFooterBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - enableParam: Param[Boolean], - enabledBuilder: BaseModuleFooterBuilder[Query, Candidate], - defaultBuilder: Option[BaseModuleFooterBuilder[Query, Candidate]] = None) - extends BaseModuleFooterBuilder[Query, Candidate] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[ModuleFooter] = { - if (query.params(enableParam)) { - enabledBuilder(query, candidates) - } else { - defaultBuilder.flatMap(_.apply(query, candidates)) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala deleted file mode 100644 index 44598b093..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamGatedModuleHeaderBuilder.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -case class ParamGatedModuleHeaderBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - enableParam: Param[Boolean], - enabledBuilder: BaseModuleHeaderBuilder[Query, Candidate], - defaultBuilder: Option[BaseModuleHeaderBuilder[Query, Candidate]] = None) - extends BaseModuleHeaderBuilder[Query, Candidate] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[ModuleHeader] = { - if (query.params(enableParam)) { - enabledBuilder(query, candidates) - } else { - defaultBuilder.flatMap(_.apply(query, candidates)) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala deleted file mode 100644 index 1e83a032e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/ParamWhoToFollowModuleDisplayTypeBuilder.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.configapi.StaticParam -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Carousel -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.CompactCarousel -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ConversationTree -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarousel -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Vertical -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalConversation -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalGrid -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalWithContextLine -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -object WhoToFollowModuleDisplayType extends Enumeration { - type ModuleDisplayType = Value - - val Carousel = Value - val CompactCarousel = Value - val ConversationTree = Value - val GridCarousel = Value - val Vertical = Value - val VerticalConversation = Value - val VerticalGrid = Value - val VerticalWithContextLine = Value -} - -case class ParamWhoToFollowModuleDisplayTypeBuilder( - displayTypeParam: Param[WhoToFollowModuleDisplayType.Value] = - StaticParam(WhoToFollowModuleDisplayType.Vertical)) - extends BaseModuleDisplayTypeBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ModuleDisplayType = { - val displayType = query.params(displayTypeParam) - displayType match { - case WhoToFollowModuleDisplayType.Carousel => Carousel - case WhoToFollowModuleDisplayType.CompactCarousel => CompactCarousel - case WhoToFollowModuleDisplayType.ConversationTree => ConversationTree - case WhoToFollowModuleDisplayType.GridCarousel => GridCarousel - case WhoToFollowModuleDisplayType.Vertical => Vertical - case WhoToFollowModuleDisplayType.VerticalConversation => VerticalConversation - case WhoToFollowModuleDisplayType.VerticalGrid => VerticalGrid - case WhoToFollowModuleDisplayType.VerticalWithContextLine => VerticalWithContextLine - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala deleted file mode 100644 index a7f9c647f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/StaticModuleDisplayTypeBuilder.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticModuleDisplayTypeBuilder(displayType: ModuleDisplayType) - extends BaseModuleDisplayTypeBuilder[PipelineQuery, UniversalNoun[Any]] { - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ModuleDisplayType = displayType -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala deleted file mode 100644 index 38f1a7657..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt/builder/timeline_module/TimelineModuleBuilder.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleFooterBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleHeaderBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleMetadataBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleShowMoreBehaviorBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseTimelineModuleBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures - -case class TimelineModuleBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - entryNamespace: EntryNamespace, - displayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, Candidate], - clientEventInfoBuilder: BaseClientEventInfoBuilder[Query, Candidate], - moduleIdGeneration: ModuleIdGeneration = AutomaticUniqueModuleId(), - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, Candidate] - ] = None, - headerBuilder: Option[BaseModuleHeaderBuilder[Query, Candidate]] = None, - footerBuilder: Option[BaseModuleFooterBuilder[Query, Candidate]] = None, - metadataBuilder: Option[BaseModuleMetadataBuilder[Query, Candidate]] = None, - showMoreBehaviorBuilder: Option[BaseModuleShowMoreBehaviorBuilder[Query, Candidate]] = None) - extends BaseTimelineModuleBuilder[Query, Candidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): TimelineModule = { - val firstCandidate = candidates.head - TimelineModule( - id = moduleIdGeneration.moduleId, - // Sort indexes are automatically set in the domain marshaller phase - sortIndex = None, - entryNamespace = entryNamespace, - // Modules should not need an element by default; only items should - clientEventInfo = - clientEventInfoBuilder(query, firstCandidate.candidate, firstCandidate.features, None), - feedbackActionInfo = feedbackActionInfoBuilder.flatMap( - _.apply(query, firstCandidate.candidate, firstCandidate.features)), - isPinned = None, - // Items are automatically set in the domain marshaller phase - items = Seq.empty, - displayType = displayTypeBuilder(query, candidates), - header = headerBuilder.flatMap(_.apply(query, candidates)), - footer = footerBuilder.flatMap(_.apply(query, candidates)), - metadata = metadataBuilder.map(_.apply(query, candidates)), - showMoreBehavior = showMoreBehaviorBuilder.map(_.apply(query, candidates)) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD deleted file mode 100644 index 56c339994..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/BUILD +++ /dev/null @@ -1,11 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/github/scopt", - "util/util-core/src/main/java/com/twitter/io", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala deleted file mode 100644 index 5c2a45856..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricDefinitions.scala +++ /dev/null @@ -1,116 +0,0 @@ -package com.twitter.product_mixer.component_library.experiments.metrics - -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try - -object MetricDefinition { - val SingleQuote = """"""" - val DoubleQuote = """""""" -} - -/** - * Base class for all metric definitions - */ -sealed trait MetricDefinition { - def toCsvField: Seq[String] - val metricDefinitionType: String -} - -/** - * Pattern Metric Definition - * @param pattern the regex pattern for this metric - */ -case class NamedPatternMetricDefinition( - pattern: Seq[String]) - extends MetricDefinition { - override def toCsvField: Seq[String] = pattern - override val metricDefinitionType: String = "NAMED_PATTERN" -} - -/** - * Strainer Metric Definition - * @param strainerExpression a filter on top of client events - */ -case class StrainerMetricDefinition( - strainerExpression: String) - extends MetricDefinition { - import MetricDefinition._ - override def toCsvField: Seq[String] = { - Seq(strainerExpression.replaceAll(SingleQuote, DoubleQuote)) - } - override val metricDefinitionType: String = "STRAINER" -} - -/** - * Lambda Metric Definition - * @param lambdaExpression a scala function mapping client events to a double - */ -case class LambdaMetricDefinition( - lambdaExpression: String) - extends MetricDefinition { - import MetricDefinition._ - override def toCsvField: Seq[String] = { - Seq(lambdaExpression.replaceAll(SingleQuote, DoubleQuote)) - } - override val metricDefinitionType: String = "LAMBDA" -} - -case class BucketRatioMetricDefinition( - numerator: String, - denominator: String) - extends MetricDefinition { - override def toCsvField: Seq[String] = { - Seq(s"(${numerator}) / (${denominator})") - } - override val metricDefinitionType: String = "BUCKET_RATIO" -} - -object Metric { - val bucketRatioPattern = "[(]+(.+)[)]+ / [(]+(.+)[)]+".r - - /** - * Creates a new Metric given a template line. - * @param line semicolon separated line string - * ignore line with comment, represented by hashtag at the beginning of the line - * @throws RuntimeException if the line is invalid - */ - def fromLine(line: String): Metric = { - val splits = line.split(";") - // at least two parts separated by semicolon (third part is optional) - if (splits.lengthCompare(2) >= 0) { - val metricExpression = splits(0) - val metricName = splits(1) - val metricDefinition = Try(splits(2)) match { - case Return("NAMED_PATTERN") => NamedPatternMetricDefinition(Seq(metricExpression)) - case Return("STRAINER") => StrainerMetricDefinition(metricExpression) - case Return("LAMBDA") => LambdaMetricDefinition(metricExpression) - case Return("BUCKET_RATIO") => - metricExpression match { - case bucketRatioPattern(numerator, denominator) => - BucketRatioMetricDefinition(numerator, denominator) - case _ => - throw new RuntimeException( - s"Invalid metric definition for Bucket Ratio. Expected format (numerator)/(denominator) but found $metricExpression") - } - case Return(other) => - throw new RuntimeException(s"Invalid metric definition in line in template file: $line") - // default to named pattern - case Throw(_) => NamedPatternMetricDefinition(List(metricExpression)) - } - - Metric(metricName, metricDefinition) - } else { - throw new RuntimeException(s"Invalid line in template file: $line") - } - } -} - -/** - * - * @param name globally unique metric name (current DDG limitation) - * @param definition the metric definition for this metric - */ -case class Metric( - name: String, - definition: MetricDefinition) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala deleted file mode 100644 index ccd238cd8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricGroup.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.experiments.metrics - -import scala.collection.immutable.ListSet - -/** - * - * @param id optional metric group id. If id is None, this means the group - * is being newly created and the id is not provisioned by go/ddg. Otherwise, the metric - * group is present in DDG and has a corresponding id. - * @param name metric group name - * @param description metric group description - * @param metrics set of metrics that belong to this metric group - */ -case class MetricGroup( - id: Option[Long], - name: String, - description: String, - metrics: ListSet[Metric]) { - - /* - * Returns a CSV representation of this metric group that can be imported via DDG's bulk import tool - * The bulk import tool consumes CSV data with the following columns: - * 1. group name - * 2. group description - * 3. metric name - * 4. metric description - * 5. metric pattern - * 6. group id -- numeric id - * 7. (optional) metric type -- `NAMED_PATTERN`, `STRAINER`, or `LAMBDA`. - */ - def toCsv: String = { - val metricCsvLines: ListSet[String] = for { - metric <- metrics - definition <- metric.definition.toCsvField - } yield { - Seq( - name, - description, - metric.name, - metric.name, - // wrap in single quotes so that DDG bulk import tool correctly parses - s""""$definition"""", - id.map(_.toString).getOrElse(""), - metric.definition.metricDefinitionType - ).mkString(",") - } - println(s"Generated metrics in CSV count: ${metricCsvLines.size}") - metricCsvLines.mkString("\n") - } - - // Unique metric names based on globally unique metric name - def uniqueMetricNames: Set[String] = - metrics.groupBy(_.name).keys.toSet -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala deleted file mode 100644 index b01af3cc2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplateCLIRunner.scala +++ /dev/null @@ -1,101 +0,0 @@ -package com.twitter.product_mixer.component_library.experiments.metrics - -import com.twitter.product_mixer.component_library.experiments.metrics.PlaceholderConfig.PlaceholdersMap -import java.io.File -import java.io.PrintWriter -import scala.collection.immutable.ListSet -import scala.io.Source -import scopt.OptionParser - -private case class MetricTemplateCLIConfig( - // default values required for OptionParser - templateFileName: String = null, - outputFileName: String = null, - metricGroupName: String = null, - metricGroupDesc: String = null, - metricGroupId: Option[Long] = None, - absolutePath: Option[String] = None) - -trait MetricTemplateCLIRunner { - def templateDir: String - def placeholders: PlaceholdersMap - private val ProgramName = "Metric Template CLI" - private val VersionNumber = "1.0" - - private def mkPath(fileName: String, absolutePath: Option[String]): String = { - val relativeDir = s"$templateDir/$fileName" - absolutePath match { - case Some(path) => s"$path/$relativeDir" - case _ => relativeDir - } - } - - def main(args: Array[String]): Unit = { - val parser = new OptionParser[MetricTemplateCLIConfig](ProgramName) { - head(ProgramName, VersionNumber) - // option invoked by -o or --output - opt[String]('o', "output") - .required() - .valueName("") - .action((value, config) => config.copy(outputFileName = value)) - .text("output CSV file with interpolated lines") - // option invoked by -t or --template - opt[String]('t', "template") - .required() - .valueName("") - .action((value, config) => config.copy(templateFileName = value)) - .text( - s"input template file (see README.md for template format). Path is relative to $templateDir.") - // option invoked by -n or --name - opt[String]('n', "name") - .required() - .valueName("") - .action((value, config) => config.copy(metricGroupName = value)) - .text("metric group name") - // option invoked by -d or --description - opt[String]('d', "description") - .required() - .valueName("") - .action((value, config) => config.copy(metricGroupDesc = value)) - .text("metric group description") - // option invoked by --id - opt[Long]("id") - .optional() - .valueName("") - .action((value, config) => config.copy(metricGroupId = Some(value))) - .text("metric group ID (metric MUST be created in go/ddg)") - // option invoked by -p or --path - opt[String]('p', "path") - .optional() - .valueName("") - .action((value, config) => config.copy(absolutePath = Some(value))) - .text(s"absolute path pointing to the $templateDir. Required by bazel") - } - - parser.parse(args, MetricTemplateCLIConfig()) match { - case Some(config) => - val templateLines = - Source.fromFile(mkPath(config.templateFileName, config.absolutePath)).getLines.toList - val interpolatedLines = templateLines - .filter(!_.startsWith("#")).flatMap(MetricTemplates.interpolate(_, placeholders)) - val writer = new PrintWriter(new File(mkPath(config.outputFileName, config.absolutePath))) - val metrics = interpolatedLines.map(Metric.fromLine) - println(s"${metrics.size} metric definitions found in template file.") - val dupMetrics = metrics.groupBy(identity).collect { - case (dup, lst) if lst.lengthCompare(1) > 0 => dup - } - println(s"\nWARNING: ${dupMetrics.size} Duplicate metric definition(s)\n$dupMetrics\n") - val metricGroup = MetricGroup( - config.metricGroupId, - config.metricGroupName, - config.metricGroupDesc, - metrics.to[ListSet]) - println(s"${metricGroup.uniqueMetricNames.size} unique DDG metrics with " + - s"${metricGroup.metrics.size} metric definitions in '${metricGroup.name}' metric group.") - writer.write(metricGroup.toCsv) - writer.close() - case _ => - // arguments are bad, error message will have been displayed - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala deleted file mode 100644 index 9640b1d8b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/MetricTemplates.scala +++ /dev/null @@ -1,123 +0,0 @@ -package com.twitter.product_mixer.component_library.experiments.metrics - -import com.twitter.product_mixer.component_library.experiments.metrics.PlaceholderConfig.PlaceholdersMap -import reflect.ClassTag -import scala.reflect.runtime.universe._ -import scala.util.matching.Regex - -case class MatchedPlaceholder(outerKey: String, innerKey: Option[String] = None) - -object MetricTemplates { - // Matches "${placeholder}" where `placeholder` is in a matched group - val PlaceholderPattern: Regex = "\\$\\{([^\\}]+)\\}".r.unanchored - // Matches "${placeholder[index]}" where `placeholder` and `index` are in different matched groups - val IndexedPlaceholderPattern: Regex = "\\$\\{([^\\[]+)\\[([^\\]]+)\\]\\}".r.unanchored - val DefaultFieldName = "name" - - def interpolate(inputTemplate: String, placeholders: PlaceholdersMap): Seq[String] = { - val matchedPlaceholders = getMatchedPlaceholders(inputTemplate) - val groupedPlaceholders = matchedPlaceholders.groupBy(_.outerKey) - val placeholderKeyValues = getPlaceholderKeyValues(groupedPlaceholders, placeholders) - val (keys, values) = (placeholderKeyValues.map(_._1), placeholderKeyValues.map(_._2)) - val cross: Seq[List[Named]] = crossProduct(values) - val mirror = runtimeMirror(getClass.getClassLoader) // necessary for reflection - for { - interpolatables <- cross - } yield { - assert( - keys.length == interpolatables.length, - s"Unexpected length mismatch between $keys and $interpolatables") - var replacementStr = inputTemplate - keys.zip(interpolatables).foreach { - case (key, interpolatable) => - val accessors = caseAccessors(mirror, interpolatable) - groupedPlaceholders(key).foreach { placeholder: MatchedPlaceholder => - val templateKey = generateTemplateKey(placeholder) - val fieldName = placeholder.innerKey.getOrElse(DefaultFieldName) - val fieldValue = getFieldValue(mirror, interpolatable, accessors, fieldName) - replacementStr = replacementStr.replaceAll(templateKey, fieldValue) - } - } - replacementStr - } - } - - def getMatchedPlaceholders(inputTemplate: String): Seq[MatchedPlaceholder] = { - for { - matched <- PlaceholderPattern.findAllIn(inputTemplate).toSeq - } yield { - val matchedWithIndexOpt = IndexedPlaceholderPattern.findFirstMatchIn(matched) - val (outer, inner) = matchedWithIndexOpt - .map { matchedWithIndex => - (matchedWithIndex.group(1), Some(matchedWithIndex.group(2))) - }.getOrElse((matched, None)) - val outerKey = unwrap(outer) - val innerKey = inner.map(unwrap(_)) - MatchedPlaceholder(outerKey, innerKey) - } - } - - def unwrap(str: String): String = - str.stripPrefix("${").stripSuffix("}") - - def wrap(str: String): String = - "\\$\\{" + str + "\\}" - - def getPlaceholderKeyValues( - groupedPlaceholders: Map[String, Seq[MatchedPlaceholder]], - placeholders: PlaceholdersMap - ): Seq[(String, Seq[Named])] = { - groupedPlaceholders.toSeq - .map { - case (outerKey, _) => - val placeholderValues = placeholders.getOrElse( - outerKey, - throw new RuntimeException(s"Failed to find values of $outerKey in placeholders")) - outerKey -> placeholderValues - } - } - - def crossProduct[T](seqOfSeqOfItems: Seq[Seq[T]]): Seq[List[T]] = { - if (seqOfSeqOfItems.isEmpty) { - List(Nil) - } else { - for { - // for every item in the head list - item <- seqOfSeqOfItems.head - // for every result (List) based on the cross-product of tail - resultList <- crossProduct(seqOfSeqOfItems.tail) - } yield { - item :: resultList - } - } - } - - def generateTemplateKey(matched: MatchedPlaceholder): String = { - matched.innerKey match { - case None => wrap(matched.outerKey) - case Some(innerKeyString) => wrap(matched.outerKey + "\\[" + innerKeyString + "\\]") - } - } - - // Given an instance and a field name, use reflection to get its value. - def getFieldValue[T: ClassTag]( - mirror: Mirror, - cls: T, - accessors: Map[String, MethodSymbol], - fieldName: String - ): String = { - val instance: InstanceMirror = mirror.reflect(cls) - val accessor = accessors.getOrElse( - fieldName, - throw new RuntimeException(s"Failed to find value of $fieldName for $cls")) - instance.reflectField(accessor).get.toString // .get is safe due to check above - } - - // Given an instance, use reflection to get a mapping for field name -> symbol - def caseAccessors[T: ClassTag](mirror: Mirror, cls: T): Map[String, MethodSymbol] = { - val classSymbol = mirror.classSymbol(cls.getClass) - classSymbol.toType.members.collect { - case m: MethodSymbol if m.isCaseAccessor => (m.name.toString -> m) - }.toMap - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala deleted file mode 100644 index 5a81073cc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/experiments/metrics/PlaceholderConfig.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.experiments.metrics - -// Base trait for all placeholder values -sealed trait Named { - def name: String -} - -case class Const(override val name: String) extends Named - -// contains only client event patterns -case class CEPattern( - override val name: String, - client: String = "", - page: String = "", - section: String = "", - component: String = "", - element: String = "", - action: String = "", - strainer: String = "") - extends Named { - - override def toString: String = { - "\"" + client + ":" + page + ":" + section + ":" + component + ":" + element + ":" + action + "\"" - } - -} - -case class Topic( - override val name: String, - topicId: String = "") - extends Named - -object PlaceholderConfig { - type PlaceholderKey = String - type Placeholder = Seq[Named] - type PlaceholdersMap = Map[PlaceholderKey, Placeholder] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD deleted file mode 100644 index 7da3b156c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala deleted file mode 100644 index 299d9515f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdFeature.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.component_library.feature.featurestorev1 - -import com.twitter.ml.api.transform.FeatureRenameTransform -import com.twitter.ml.featurestore.catalog.entities -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.UserId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.core.feature.featurestorev1._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import scala.reflect.ClassTag -object FeatureStoreV1QueryUserIdFeature { - def apply[Query <: PipelineQuery, Value]( - feature: FSv1Feature[UserId, Value], - legacyName: Option[String] = None, - defaultValue: Option[Value] = None, - enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1Feature[Query, Query, _ <: EntityId, Value] - with FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value] = - FeatureStoreV1QueryFeature(feature, QueryUserIdEntity, legacyName, defaultValue, enabledParam) -} - -object FeatureStoreV1QueryUserIdAggregateFeature { - def apply[Query <: PipelineQuery]( - featureGroup: TimelinesAggregationFrameworkFeatureGroup[UserId], - enabledParam: Option[FSParam[Boolean]] = None, - keepLegacyNames: Boolean = false, - featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId] = - FeatureStoreV1QueryFeatureGroup( - featureGroup, - QueryUserIdEntity, - enabledParam, - keepLegacyNames, - featureNameTransform)((implicitly[ClassTag[UserId]])) -} - -object QueryUserIdEntity extends FeatureStoreV1QueryEntity[PipelineQuery, UserId] { - override val entity: Entity[UserId] = entities.core.User - - override def entityWithId(query: PipelineQuery): EntityWithId[UserId] = - entity.withId(UserId(query.getUserIdLoggedOutSupport)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala deleted file mode 100644 index bd026c60d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature.scala +++ /dev/null @@ -1,68 +0,0 @@ -package com.twitter.product_mixer.component_library.feature.featurestorev1 - -import com.twitter.ml.api.transform.FeatureRenameTransform -import com.twitter.ml.featurestore.catalog.entities -import com.twitter.ml.featurestore.lib.EdgeEntityId -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.UserId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import scala.reflect.ClassTag - -object FeatureStoreV1QueryUserIdTweetCandidateAuthorIdFeature { - def apply[Query <: PipelineQuery, Value]( - feature: FSv1Feature[EdgeEntityId[UserId, UserId], Value], - legacyName: Option[String] = None, - defaultValue: Option[Value] = None, - enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1CandidateFeature[Query, TweetCandidate, _ <: EntityId, Value] = - FeatureStoreV1CandidateFeature( - feature, - QueryUserIdTweetCandidateAuthorIdEntity, - legacyName, - defaultValue, - enabledParam) -} - -object FeatureStoreV1QueryUserIdTweetCandidateAuthorIdAggregateFeature { - def apply[Query <: PipelineQuery]( - featureGroup: TimelinesAggregationFrameworkFeatureGroup[EdgeEntityId[UserId, UserId]], - enabledParam: Option[FSParam[Boolean]] = None, - keepLegacyNames: Boolean = false, - featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1CandidateFeatureGroup[Query, TweetCandidate, _ <: EntityId] = - FeatureStoreV1CandidateFeatureGroup( - featureGroup, - QueryUserIdTweetCandidateAuthorIdEntity, - enabledParam, - keepLegacyNames, - featureNameTransform - )(implicitly[ClassTag[EdgeEntityId[UserId, UserId]]]) -} - -object QueryUserIdTweetCandidateAuthorIdEntity - extends FeatureStoreV1CandidateEntity[ - PipelineQuery, - TweetCandidate, - EdgeEntityId[UserId, UserId] - ] { - override val entity: Entity[EdgeEntityId[UserId, UserId]] = entities.core.UserAuthor - - override def entityWithId( - query: PipelineQuery, - tweet: TweetCandidate, - existingFeatures: FeatureMap - ): EntityWithId[EdgeEntityId[UserId, UserId]] = - entity.withId( - EdgeEntityId( - UserId(query.getUserIdLoggedOutSupport), - UserId(existingFeatures.get(TweetAuthorIdFeature)))) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala deleted file mode 100644 index 9031e88be..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.component_library.feature.featurestorev1 - -import com.twitter.ml.api.transform.FeatureRenameTransform -import com.twitter.ml.featurestore.catalog.entities -import com.twitter.ml.featurestore.lib.EdgeEntityId -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.TweetId -import com.twitter.ml.featurestore.lib.UserId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import scala.reflect.ClassTag - -object FeatureStoreV1QueryUserIdTweetCandidateTweetIdFeature { - def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate, Value]( - feature: FSv1Feature[EdgeEntityId[UserId, TweetId], Value], - legacyName: Option[String] = None, - defaultValue: Option[Value] = None, - enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] = - FeatureStoreV1CandidateFeature( - feature, - QueryUserIdTweetCandidateTweetIdEntity, - legacyName, - defaultValue, - enabledParam) -} - -object FeatureStoreV1QueryUserIdTweetCandidateTweetIdAggregateFeature { - def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate]( - featureGroup: TimelinesAggregationFrameworkFeatureGroup[EdgeEntityId[UserId, TweetId]], - enabledParam: Option[FSParam[Boolean]] = None, - keepLegacyNames: Boolean = false, - featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1CandidateFeatureGroup[Query, TweetCandidate, _ <: EntityId] = - FeatureStoreV1CandidateFeatureGroup( - featureGroup, - QueryUserIdTweetCandidateTweetIdEntity, - enabledParam, - keepLegacyNames, - featureNameTransform - )(implicitly[ClassTag[EdgeEntityId[UserId, TweetId]]]) -} - -object QueryUserIdTweetCandidateTweetIdEntity - extends FeatureStoreV1CandidateEntity[ - PipelineQuery, - BaseTweetCandidate, - EdgeEntityId[UserId, TweetId] - ] { - override val entity: Entity[EdgeEntityId[UserId, TweetId]] = entities.core.UserTweet - - override def entityWithId( - query: PipelineQuery, - tweet: BaseTweetCandidate, - existingFeatures: FeatureMap - ): EntityWithId[EdgeEntityId[UserId, TweetId]] = - entity.withId(EdgeEntityId(UserId(query.getUserIdLoggedOutSupport), TweetId(tweet.id))) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala deleted file mode 100644 index b78c9569a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateAuthorIdFeature.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.component_library.feature.featurestorev1 - -import com.twitter.ml.api.transform.FeatureRenameTransform -import com.twitter.ml.featurestore.catalog.entities -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.UserId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import scala.reflect.ClassTag - -object FeatureStoreV1TweetCandidateAuthorIdFeature { - def apply[Query <: PipelineQuery, Value]( - feature: FSv1Feature[UserId, Value], - legacyName: Option[String] = None, - defaultValue: Option[Value] = None, - enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1CandidateFeature[Query, TweetCandidate, _ <: EntityId, Value] = - FeatureStoreV1CandidateFeature( - feature, - TweetCandidateAuthorIdEntity, - legacyName, - defaultValue, - enabledParam) -} - -object FeatureStoreV1TweetCandidateAuthorIdAggregateFeature { - def apply[Query <: PipelineQuery]( - featureGroup: TimelinesAggregationFrameworkFeatureGroup[UserId], - enabledParam: Option[FSParam[Boolean]] = None, - keepLegacyNames: Boolean = false, - featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1CandidateFeatureGroup[Query, TweetCandidate, _ <: EntityId] = - FeatureStoreV1CandidateFeatureGroup( - featureGroup, - TweetCandidateAuthorIdEntity, - enabledParam, - keepLegacyNames, - featureNameTransform - )(implicitly[ClassTag[UserId]]) -} - -object TweetCandidateAuthorIdEntity - extends FeatureStoreV1CandidateEntity[PipelineQuery, TweetCandidate, UserId] { - override val entity: Entity[UserId] = entities.core.Author - - override def entityWithId( - query: PipelineQuery, - tweet: TweetCandidate, - existingFeatures: FeatureMap - ): EntityWithId[UserId] = - entity.withId(UserId(existingFeatures.get(TweetAuthorIdFeature))) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala deleted file mode 100644 index c75bf21ac..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1TweetCandidateTweetIdFeature.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.feature.featurestorev1 - -import com.twitter.ml.api.transform.FeatureRenameTransform -import com.twitter.ml.featurestore.catalog.entities -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.TweetId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam - -object FeatureStoreV1TweetCandidateTweetIdFeature { - def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate, Value]( - feature: FSv1Feature[TweetId, Value], - legacyName: Option[String] = None, - defaultValue: Option[Value] = None, - enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] = - FeatureStoreV1CandidateFeature( - feature, - TweetCandidateTweetIdEntity, - legacyName, - defaultValue, - enabledParam) -} - -object FeatureStoreV1TweetCandidateTweetIdAggregateFeature { - def apply[Query <: PipelineQuery, Candidate <: BaseTweetCandidate]( - featureGroup: TimelinesAggregationFrameworkFeatureGroup[TweetId], - enabledParam: Option[FSParam[Boolean]] = None, - keepLegacyNames: Boolean = false, - featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId] = - FeatureStoreV1CandidateFeatureGroup( - featureGroup, - TweetCandidateTweetIdEntity, - enabledParam, - keepLegacyNames, - featureNameTransform - ) -} - -object TweetCandidateTweetIdEntity - extends FeatureStoreV1CandidateEntity[PipelineQuery, BaseTweetCandidate, TweetId] { - override val entity: Entity[TweetId] = entities.core.Tweet - - override def entityWithId( - query: PipelineQuery, - tweet: BaseTweetCandidate, - existingFeatures: FeatureMap - ): EntityWithId[TweetId] = - entity.withId(TweetId(tweet.id)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala deleted file mode 100644 index a0947b995..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature/featurestorev1/FeatureStoreV1UserCandidateUserIdFeature.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.feature.featurestorev1 - -import com.twitter.ml.featurestore.catalog.entities -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.UserId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam - -object FeatureStoreV1UserCandidateUserIdFeature { - def apply[Query <: PipelineQuery, Candidate <: BaseUserCandidate, Value]( - feature: FSv1Feature[UserId, Value], - legacyName: Option[String] = None, - defaultValue: Option[Value] = None, - enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] = - FeatureStoreV1CandidateFeature( - feature, - UserCandidateUserIdEntity, - legacyName, - defaultValue, - enabledParam) -} - -object UserCandidateUserIdEntity - extends FeatureStoreV1CandidateEntity[PipelineQuery, BaseUserCandidate, UserId] { - override val entity: Entity[UserId] = entities.core.User - - override def entityWithId( - query: PipelineQuery, - user: BaseUserCandidate, - existingFeatures: FeatureMap - ): EntityWithId[UserId] = - entity.withId(UserId(user.id)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD deleted file mode 100644 index 78840577d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/src/jvm/com/twitter/storehaus:core", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/src/jvm/com/twitter/storehaus:core", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala deleted file mode 100644 index 107f04fff..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/AdvertiserBrandSafetySettingsFeatureHydrator.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.ads - -import com.twitter.adserver.{thriftscala => ad} -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.storehaus.ReadableStore -import com.twitter.util.Future - -import javax.inject.Inject -import javax.inject.Singleton - -object AdvertiserBrandSafetySettingsFeature - extends FeatureWithDefaultOnFailure[AdsCandidate, Option[ad.AdvertiserBrandSafetySettings]] { - override val defaultValue = None -} - -@Singleton -case class AdvertiserBrandSafetySettingsFeatureHydrator[ - Query <: PipelineQuery with AdsQuery, - Candidate <: AdsCandidate] @Inject() ( - advertiserBrandSafetySettingsStore: ReadableStore[Long, ad.AdvertiserBrandSafetySettings]) - extends CandidateFeatureHydrator[Query, Candidate] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "AdvertiserBrandSafetySettings") - - override val features: Set[Feature[_, _]] = Set(AdvertiserBrandSafetySettingsFeature) - - override def apply( - query: Query, - candidate: Candidate, - existingFeatures: FeatureMap - ): Stitch[FeatureMap] = { - - val featureMapFuture: Future[FeatureMap] = advertiserBrandSafetySettingsStore - .get(candidate.adImpression.advertiserId) - .map { advertiserBrandSafetySettingsOpt => - FeatureMapBuilder() - .add(AdvertiserBrandSafetySettingsFeature, advertiserBrandSafetySettingsOpt).build() - } - - Stitch.callFuture(featureMapFuture) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD deleted file mode 100644 index 4c66c4346..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/ads/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/storehaus:core", - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "src/thrift/com/twitter/ads/adserver:ads_shared_types-scala", - ], - exports = [ - "3rdparty/jvm/com/twitter/storehaus:core", - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "src/thrift/com/twitter/ads/adserver:ads_shared_types-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel deleted file mode 100644 index 3759377bd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/BUILD.bazel +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "snowflake/src/main/scala/com/twitter/snowflake/id", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala deleted file mode 100644 index 4f0d99e82..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/decay/DecayCandidateFeatureHydrator.scala +++ /dev/null @@ -1,65 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.decay - -import com.twitter.conversions.DurationOps._ -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.configapi.StaticParam -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.snowflake.id.SnowflakeId -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param -import com.twitter.util.Duration - -object DecayScore extends Feature[UniversalNoun[Long], Double] - -/** - * Hydrates snowflake ID candidates with a decay score: - * - * It is using exponential decay formula to calculate the score - * exp(k * age) - * where k = ln(0.5) / half-life - * - * Here is an example for half-life = 1 day - * For the brand new tweet it will be exp((ln(0.5)/1)*0) = 1 - * For the tweet which was created 1 day ago it will be exp((ln(0.5)/1)*1) = 0.5 - * For the tweet which was created 10 day ago it will be exp((ln(0.5)/1)*10) = 0.00097 - * - * Reference: https://www.cuemath.com/exponential-decay-formula/ - * - * @note This penalizes but does not filter out the candidate, so "stale" candidates can still appear. - */ -case class DecayCandidateFeatureHydrator[Candidate <: UniversalNoun[Long]]( - halfLife: Param[Duration] = StaticParam[Duration](2.days), - resultFeature: Feature[UniversalNoun[Long], Double] = DecayScore) - extends CandidateFeatureHydrator[PipelineQuery, Candidate] { - - override val features: Set[Feature[_, _]] = Set(resultFeature) - - override val identifier: FeatureHydratorIdentifier = - FeatureHydratorIdentifier("Decay") - - override def apply( - query: PipelineQuery, - candidate: Candidate, - existingFeatures: FeatureMap - ): Stitch[FeatureMap] = { - val halfLifeInMillis = query.params(halfLife).inMillis - - val creationTime = SnowflakeId.timeFromId(candidate.id) - val ageInMillis = creationTime.untilNow.inMilliseconds - - // it is using a exponential decay formula: e^(k * tweetAge) - // where k = ln(0.5) / half-life - val k = math.log(0.5D) / halfLifeInMillis - val decayScore = math.exp(k * ageInMillis) - - Stitch.value( - FeatureMapBuilder() - .add(resultFeature, decayScore) - .build()) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD deleted file mode 100644 index a9e2c7cc4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala deleted file mode 100644 index 621eed2e9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedBulkCandidateFeatureHydrator.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated - -import com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedBulkCandidateFeatureHydrator.IdentifierPrefix -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BulkCandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[BulkCandidateFeatureHydrator]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this [[BulkCandidateFeatureHydrator]] on and off - * @param bulkCandidateFeatureHydrator the underlying [[BulkCandidateFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class ParamGatedBulkCandidateFeatureHydrator[ - -Query <: PipelineQuery, - Result <: UniversalNoun[Any] -]( - enabledParam: Param[Boolean], - bulkCandidateFeatureHydrator: BulkCandidateFeatureHydrator[Query, Result]) - extends BulkCandidateFeatureHydrator[Query, Result] - with Conditionally[Query] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - IdentifierPrefix + bulkCandidateFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = bulkCandidateFeatureHydrator.alerts - - override val features: Set[Feature[_, _]] = bulkCandidateFeatureHydrator.features - - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, bulkCandidateFeatureHydrator, query.params(enabledParam)) - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Result]] - ): Stitch[Seq[FeatureMap]] = bulkCandidateFeatureHydrator(query, candidates) -} - -object ParamGatedBulkCandidateFeatureHydrator { - val IdentifierPrefix = "ParamGated" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala deleted file mode 100644 index 6409145e5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/ParamGatedCandidateFeatureHydrator.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated - -import com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedCandidateFeatureHydrator.IdentifierPrefix -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[CandidateFeatureHydrator]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this [[CandidateFeatureHydrator]] on and off - * @param candidateFeatureHydrator the underlying [[CandidateFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class ParamGatedCandidateFeatureHydrator[ - -Query <: PipelineQuery, - -Result <: UniversalNoun[Any] -]( - enabledParam: Param[Boolean], - candidateFeatureHydrator: CandidateFeatureHydrator[Query, Result]) - extends CandidateFeatureHydrator[Query, Result] - with Conditionally[Query] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - IdentifierPrefix + candidateFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = candidateFeatureHydrator.alerts - - override val features: Set[Feature[_, _]] = candidateFeatureHydrator.features - - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, candidateFeatureHydrator, query.params(enabledParam)) - - override def apply( - query: Query, - candidate: Result, - existingFeatures: FeatureMap - ): Stitch[FeatureMap] = candidateFeatureHydrator.apply(query, candidate, existingFeatures) -} - -object ParamGatedCandidateFeatureHydrator { - val IdentifierPrefix = "ParamGated" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD deleted file mode 100644 index 7b18d7b06..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala deleted file mode 100644 index d151c4374..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/param_gated/featurestorev1/ParamGatedFeatureStoreV1CandidateFeatureHydrator.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.featurestorev1.ParamGatedFeatureStoreV1CandidateFeatureHydrator.IdentifierPrefix -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1CandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[FeatureStoreV1CandidateFeatureHydrator]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this [[FeatureStoreV1CandidateFeatureHydrator]] on and off - * @param candidateFeatureHydrator the underlying [[FeatureStoreV1CandidateFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Candidate The type of the candidates - */ -case class ParamGatedFeatureStoreV1CandidateFeatureHydrator[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] -]( - enabledParam: Param[Boolean], - candidateFeatureHydrator: FeatureStoreV1CandidateFeatureHydrator[Query, Candidate]) - extends FeatureStoreV1CandidateFeatureHydrator[Query, Candidate] - with Conditionally[Query] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - IdentifierPrefix + candidateFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = candidateFeatureHydrator.alerts - - override val features: Set[ - BaseFeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, _] - ] = candidateFeatureHydrator.features - - override val clientBuilder: FeatureStoreV1DynamicClientBuilder = - candidateFeatureHydrator.clientBuilder - - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, candidateFeatureHydrator, query.params(enabledParam)) - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] = candidateFeatureHydrator(query, candidates) -} - -object ParamGatedFeatureStoreV1CandidateFeatureHydrator { - val IdentifierPrefix = "ParamGated" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel deleted file mode 100644 index 579f420ee..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala deleted file mode 100644 index e9d74826c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/qualityfactor_gated/QualityFactorGatedCandidateFeatureHydrator.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.qualityfactor_gated - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -object QualityFactorGatedCandidateFeatureHydrator { - val IdentifierPrefix = "QfGated" -} - -/** - * A [[CandidateFeatureHydrator]] with [[Conditionally]] based on a qualityFactor threshold. - * @param pipelineIdentifier identifier of the pipeline that associated with observed quality factor - * @param qualityFactorInclusiveThreshold the inclusive threshold of quality factor that value below it results in - * the underlying hydrator being turned off - * @param candidateFeatureHydrator the underlying [[CandidateFeatureHydrator]] to run when quality factor value - * is above the given inclusive threshold - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class QualityFactorGatedCandidateFeatureHydrator[ - -Query <: PipelineQuery with HasQualityFactorStatus, - Result <: UniversalNoun[Any] -]( - pipelineIdentifier: ComponentIdentifier, - qualityFactorInclusiveThreshold: Param[Double], - candidateFeatureHydrator: CandidateFeatureHydrator[Query, Result]) - extends CandidateFeatureHydrator[Query, Result] - with Conditionally[Query] { - import QualityFactorGatedCandidateFeatureHydrator._ - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - IdentifierPrefix + candidateFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = candidateFeatureHydrator.alerts - - override val features: Set[Feature[_, _]] = candidateFeatureHydrator.features - - override def onlyIf(query: Query): Boolean = Conditionally.and( - query, - candidateFeatureHydrator, - query.getQualityFactorCurrentValue(pipelineIdentifier) >= query.params( - qualityFactorInclusiveThreshold)) - - override def apply( - query: Query, - candidate: Result, - existingFeatures: FeatureMap - ): Stitch[FeatureMap] = candidateFeatureHydrator.apply(query, candidate, existingFeatures) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD deleted file mode 100644 index 3a2b817bf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/src/jvm/com/twitter/storehaus:core", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/src/jvm/com/twitter/storehaus:core", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala deleted file mode 100644 index 651f0f4b0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_is_nsfw/TweetIsNsfwCandidateFeatureHydrator.scala +++ /dev/null @@ -1,109 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_is_nsfw - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BulkCandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient} -import com.twitter.tweetypie.{thriftscala => t} -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try -import com.twitter.util.logging.Logging - -// The VF NsfwHighPrecisionLabel that powers the NSFW determination here has been deprecated and is no longer written to. -@deprecated("Prefer VisibilityReason") -object IsNsfw extends FeatureWithDefaultOnFailure[TweetCandidate, Option[Boolean]] { - - /** - * Generic Logic to evaluate whether a tweet is nsfw - * @param hasNsfwHighPrecisionLabel flag for tweetypieTweet nsfwHighPrecision label - * @param isNsfwUser flag for tweetypieTweet coreData nsfwUser flag - * @param isNsfwAdmin flag for tweetypieTweet coreData nsfwAdmin flag - * @return isNsfw to true if any of the three flags is true - */ - def apply( - hasNsfwHighPrecisionLabel: Option[Boolean], - isNsfwUser: Option[Boolean], - isNsfwAdmin: Option[Boolean] - ): Boolean = { - hasNsfwHighPrecisionLabel - .getOrElse(false) || (isNsfwUser.getOrElse(false) || isNsfwAdmin.getOrElse(false)) - } - - override val defaultValue = None -} - -// The VF NsfwHighPrecisionLabel that powers the NSFW determination here has been deprecated and is no longer written to. -// TODO: Remove after all dependencies have migrated to using TweetCandidateVisibilityReasonFeatureHydrator. -@deprecated("Prefer TweetCandidateVisibilityReasonFeatureHydrator") -case class TweetIsNsfwCandidateFeatureHydrator( - tweetypieStitchClient: TweetypieStitchClient, - tweetVisibilityPolicy: t.TweetVisibilityPolicy) - extends BulkCandidateFeatureHydrator[PipelineQuery, BaseTweetCandidate] - with Logging { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier("TweetIsNsfw") - - override def features: Set[Feature[_, _]] = Set(IsNsfw) - - private val NsfwLabelFields: Set[t.TweetInclude] = Set[t.TweetInclude]( - // Tweet fields containing NSFW related attributes, in addition to what exists in coreData. - t.TweetInclude.TweetFieldId(t.Tweet.NsfwHighPrecisionLabelField.id), - t.TweetInclude.TweetFieldId(t.Tweet.CoreDataField.id) - ) - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[BaseTweetCandidate]] - ): Stitch[Seq[FeatureMap]] = { - Stitch - .traverse(candidates.map(_.candidate.id)) { tweetId => - tweetypieStitchClient - .getTweetFields( - tweetId = tweetId, - options = t.GetTweetFieldsOptions( - forUserId = query.getOptionalUserId, - tweetIncludes = NsfwLabelFields, - doNotCache = true, - visibilityPolicy = tweetVisibilityPolicy, - safetyLevel = None, - ) - ).liftToTry - }.map { getTweetFieldsResults: Seq[Try[t.GetTweetFieldsResult]] => - val tweets: Seq[Try[t.Tweet]] = getTweetFieldsResults.map { - case Return(t.GetTweetFieldsResult(_, t.TweetFieldsResultState.Found(found), _, _)) => - Return(found.tweet) - case Return(t.GetTweetFieldsResult(_, resultState, _, _)) => - Throw(IsNsfwFeatureHydrationFailure(s"Unexpected tweet result state: ${resultState}")) - case Throw(e) => - Throw(e) - } - - candidates.zip(tweets).map { - case (candidateWithFeatures, tweetTry) => - val isNsfwFeature = tweetTry.map { tweet => - IsNsfw( - hasNsfwHighPrecisionLabel = Some(tweet.nsfwHighPrecisionLabel.isDefined), - isNsfwUser = tweet.coreData.map(_.nsfwUser), - isNsfwAdmin = tweet.coreData.map(_.nsfwAdmin) - ) - } - - FeatureMapBuilder() - .add(IsNsfw, isNsfwFeature.map(Some(_))) - .build() - } - } - } -} - -case class IsNsfwFeatureHydrationFailure(message: String) - extends Exception(s"IsNsfwFeatureHydrationFailure(${message})") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel deleted file mode 100644 index 9d9d9a421..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/BUILD.bazel +++ /dev/null @@ -1,42 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala", - "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-strato", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "strato/config/columns/ml/featureStore:featureStore-strato-client", - "strato/src/main/scala/com/twitter/strato/client", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala", - "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-strato", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "stitch/stitch-core", - "strato/config/columns/ml/featureStore:featureStore-strato-client", - "strato/src/main/scala/com/twitter/strato/client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala deleted file mode 100644 index ee985d9c4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tlx/TweetTLXScoreCandidateFeatureHydrator.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx - -import com.twitter.ml.featurestore.timelines.thriftscala.TimelineScorerScoreView -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.component_library.scorer.tweet_tlx.TLXScore -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.strato.generated.client.ml.featureStore.TimelineScorerTweetScoresV1ClientColumn -import com.twitter.timelinescorer.thriftscala.v1 -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Hydrate Tweet Scores via Timeline Scorer (TLX) - * - * Note that this is the [[CandidateFeatureHydrator]] version of - * [[com.twitter.product_mixer.component_library.scorer.tweet_tlx.TweetTLXStratoScorer]] - */ -@Singleton -class TweetTLXScoreCandidateFeatureHydrator @Inject() ( - column: TimelineScorerTweetScoresV1ClientColumn) - extends CandidateFeatureHydrator[PipelineQuery, TweetCandidate] { - - override val identifier: FeatureHydratorIdentifier = - FeatureHydratorIdentifier("TweetTLXScore") - - override val features: Set[Feature[_, _]] = Set(TLXScore) - - private val NoScoreMap = FeatureMapBuilder() - .add(TLXScore, None) - .build() - - override def apply( - query: PipelineQuery, - candidate: TweetCandidate, - existingFeatures: FeatureMap - ): Stitch[FeatureMap] = { - query.getOptionalUserId match { - case Some(userId) => - column.fetcher - .fetch(candidate.id, TimelineScorerScoreView(Some(userId))) - .map(scoredTweet => - scoredTweet.v match { - case Some(v1.ScoredTweet(Some(_), score, _, _)) => - FeatureMapBuilder() - .add(TLXScore, score) - .build() - case _ => throw new Exception(s"Invalid response from TLX: ${scoredTweet.v}") - }) - case _ => - Stitch.value(NoScoreMap) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD deleted file mode 100644 index 298c869f3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala deleted file mode 100644 index 5f20598b5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.scala +++ /dev/null @@ -1,241 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tweetypie - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.spam.rtf.thriftscala.SafetyLevel -import com.twitter.stitch.Stitch -import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient} -import com.twitter.tweetypie.thriftscala.TweetVisibilityPolicy -import com.twitter.tweetypie.{thriftscala => TP} - -// Candidate Features -object IsCommunityTweetFeature extends Feature[TweetCandidate, Boolean] - -// Tweetypie VF Features -object HasTakedownFeature extends Feature[TweetCandidate, Boolean] -object HasTakedownForLocaleFeature extends Feature[TweetCandidate, Boolean] -object IsHydratedFeature extends Feature[TweetCandidate, Boolean] -object IsNarrowcastFeature extends Feature[TweetCandidate, Boolean] -object IsNsfwAdminFeature extends Feature[TweetCandidate, Boolean] -object IsNsfwFeature extends Feature[TweetCandidate, Boolean] -object IsNsfwUserFeature extends Feature[TweetCandidate, Boolean] -object IsNullcastFeature extends Feature[TweetCandidate, Boolean] -object QuotedTweetDroppedFeature extends Feature[TweetCandidate, Boolean] -object QuotedTweetHasTakedownFeature extends Feature[TweetCandidate, Boolean] -object QuotedTweetHasTakedownForLocaleFeature extends Feature[TweetCandidate, Boolean] -object QuotedTweetIdFeature extends Feature[TweetCandidate, Option[Long]] -object SourceTweetHasTakedownFeature extends Feature[TweetCandidate, Boolean] -object SourceTweetHasTakedownForLocaleFeature extends Feature[TweetCandidate, Boolean] -object TakedownCountryCodesFeature extends Feature[TweetCandidate, Set[String]] -object IsReplyFeature extends Feature[TweetCandidate, Boolean] -object InReplyToFeature extends Feature[TweetCandidate, Option[Long]] -object IsRetweetFeature extends Feature[TweetCandidate, Boolean] - -object TweetTweetypieCandidateFeatureHydrator { - val CoreTweetFields: Set[TP.TweetInclude] = Set[TP.TweetInclude]( - TP.TweetInclude.TweetFieldId(TP.Tweet.IdField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.CoreDataField.id) - ) - - val NsfwLabelFields: Set[TP.TweetInclude] = Set[TP.TweetInclude]( - // Tweet fields containing NSFW related attributes, in addition to what exists in coreData. - TP.TweetInclude.TweetFieldId(TP.Tweet.NsfwHighRecallLabelField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.NsfwHighPrecisionLabelField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.NsfaHighRecallLabelField.id) - ) - - val SafetyLabelFields: Set[TP.TweetInclude] = Set[TP.TweetInclude]( - // Tweet fields containing RTF labels for abuse and spam. - TP.TweetInclude.TweetFieldId(TP.Tweet.SpamLabelField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.AbusiveLabelField.id) - ) - - val OrganicTweetTPHydrationFields: Set[TP.TweetInclude] = CoreTweetFields ++ - NsfwLabelFields ++ - SafetyLabelFields ++ - Set( - TP.TweetInclude.TweetFieldId(TP.Tweet.TakedownCountryCodesField.id), - // QTs imply a TweetyPie -> SGS request dependency - TP.TweetInclude.TweetFieldId(TP.Tweet.QuotedTweetField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.EscherbirdEntityAnnotationsField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.CommunitiesField.id), - // Field required for determining if a Tweet was created via News Camera. - TP.TweetInclude.TweetFieldId(TP.Tweet.ComposerSourceField.id) - ) - - val InjectedTweetTPHydrationFields: Set[TP.TweetInclude] = - OrganicTweetTPHydrationFields ++ Set( - // Mentions imply a TweetyPie -> Gizmoduck request dependency - TP.TweetInclude.TweetFieldId(TP.Tweet.MentionsField.id), - TP.TweetInclude.TweetFieldId(TP.Tweet.HashtagsField.id) - ) - - val DefaultFeatureMap = FeatureMapBuilder() - .add(IsNsfwAdminFeature, false) - .add(IsNsfwUserFeature, false) - .add(IsNsfwFeature, false) - .add(IsNullcastFeature, false) - .add(IsNarrowcastFeature, false) - .add(HasTakedownFeature, false) - .add(IsCommunityTweetFeature, false) - .add(TakedownCountryCodesFeature, Set.empty: Set[String]) - .add(IsHydratedFeature, false) - .add(HasTakedownForLocaleFeature, false) - .add(QuotedTweetDroppedFeature, false) - .add(SourceTweetHasTakedownFeature, false) - .add(QuotedTweetHasTakedownFeature, false) - .add(SourceTweetHasTakedownForLocaleFeature, false) - .add(QuotedTweetHasTakedownForLocaleFeature, false) - .add(IsReplyFeature, false) - .add(InReplyToFeature, None) - .add(IsRetweetFeature, false) - .build() -} - -class TweetTweetypieCandidateFeatureHydrator( - tweetypieStitchClient: TweetypieStitchClient, - safetyLevelPredicate: PipelineQuery => SafetyLevel) - extends CandidateFeatureHydrator[PipelineQuery, BaseTweetCandidate] { - - import TweetTweetypieCandidateFeatureHydrator._ - - override val features: Set[Feature[_, _]] = - Set( - IsNsfwFeature, - IsNsfwAdminFeature, - IsNsfwUserFeature, - IsNullcastFeature, - IsNarrowcastFeature, - HasTakedownFeature, - IsCommunityTweetFeature, - TakedownCountryCodesFeature, - IsHydratedFeature, - HasTakedownForLocaleFeature, - QuotedTweetDroppedFeature, - SourceTweetHasTakedownFeature, - QuotedTweetHasTakedownFeature, - SourceTweetHasTakedownForLocaleFeature, - QuotedTweetHasTakedownForLocaleFeature, - IsReplyFeature, - InReplyToFeature, - IsRetweetFeature - ) - - override val identifier: FeatureHydratorIdentifier = - FeatureHydratorIdentifier("TweetTweetypie") - - override def apply( - query: PipelineQuery, - candidate: BaseTweetCandidate, - existingFeatures: FeatureMap - ): Stitch[FeatureMap] = { - val countryCode = query.getCountryCode.getOrElse("") - - tweetypieStitchClient - .getTweetFields( - tweetId = candidate.id, - options = TP.GetTweetFieldsOptions( - tweetIncludes = OrganicTweetTPHydrationFields, - includeRetweetedTweet = true, - includeQuotedTweet = true, - visibilityPolicy = TweetVisibilityPolicy.UserVisible, - safetyLevel = Some(safetyLevelPredicate(query)) - ) - ).map { - case TP.GetTweetFieldsResult(_, TP.TweetFieldsResultState.Found(found), quoteOpt, _) => - val coreData = found.tweet.coreData - val isNsfwAdmin = coreData.exists(_.nsfwAdmin) - val isNsfwUser = coreData.exists(_.nsfwUser) - val hasTakedown = coreData.exists(_.hasTakedown) - val isReply = coreData.exists(_.reply.nonEmpty) - val ancestorId = coreData.flatMap(_.reply).flatMap(_.inReplyToStatusId) - val isRetweet = coreData.exists(_.share.nonEmpty) - val takedownCountryCodes = - found.tweet.takedownCountryCodes.getOrElse(Seq.empty).map(_.toLowerCase).toSet - - val quotedTweetDropped = quoteOpt.exists { - case _: TP.TweetFieldsResultState.Filtered => - true - case _: TP.TweetFieldsResultState.NotFound => - true - case _ => false - } - val quotedTweetIsNsfw = quoteOpt.exists { - case quoteTweet: TP.TweetFieldsResultState.Found => - quoteTweet.found.tweet.coreData.exists(data => data.nsfwAdmin || data.nsfwUser) - case _ => false - } - val quotedTweetHasTakedown = quoteOpt.exists { - case quoteTweet: TP.TweetFieldsResultState.Found => - quoteTweet.found.tweet.coreData.exists(_.hasTakedown) - case _ => false - } - val quotedTweetTakedownCountryCodes = quoteOpt - .collect { - case quoteTweet: TP.TweetFieldsResultState.Found => - quoteTweet.found.tweet.takedownCountryCodes - .getOrElse(Seq.empty).map(_.toLowerCase).toSet - }.getOrElse(Set.empty[String]) - - val sourceTweetIsNsfw = - found.retweetedTweet.exists(_.coreData.exists(data => data.nsfwAdmin || data.nsfwUser)) - val sourceTweetHasTakedown = - found.retweetedTweet.exists(_.coreData.exists(_.hasTakedown)) - val sourceTweetTakedownCountryCodes = found.retweetedTweet - .map { sourceTweet: TP.Tweet => - sourceTweet.takedownCountryCodes.getOrElse(Seq.empty).map(_.toLowerCase).toSet - }.getOrElse(Set.empty) - - FeatureMapBuilder() - .add(IsNsfwAdminFeature, isNsfwAdmin) - .add(IsNsfwUserFeature, isNsfwUser) - .add(IsNsfwFeature, isNsfwAdmin || isNsfwUser || sourceTweetIsNsfw || quotedTweetIsNsfw) - .add(IsNullcastFeature, coreData.exists(_.nullcast)) - .add(IsNarrowcastFeature, coreData.exists(_.narrowcast.nonEmpty)) - .add(HasTakedownFeature, hasTakedown) - .add( - HasTakedownForLocaleFeature, - hasTakedownForLocale(hasTakedown, countryCode, takedownCountryCodes)) - .add(QuotedTweetDroppedFeature, quotedTweetDropped) - .add(SourceTweetHasTakedownFeature, sourceTweetHasTakedown) - .add(QuotedTweetHasTakedownFeature, quotedTweetHasTakedown) - .add( - SourceTweetHasTakedownForLocaleFeature, - hasTakedownForLocale( - sourceTweetHasTakedown, - countryCode, - sourceTweetTakedownCountryCodes)) - .add( - QuotedTweetHasTakedownForLocaleFeature, - hasTakedownForLocale( - quotedTweetHasTakedown, - countryCode, - quotedTweetTakedownCountryCodes)) - .add(IsCommunityTweetFeature, found.tweet.communities.exists(_.communityIds.nonEmpty)) - .add( - TakedownCountryCodesFeature, - found.tweet.takedownCountryCodes.getOrElse(Seq.empty).map(_.toLowerCase).toSet) - .add(IsHydratedFeature, true) - .add(IsReplyFeature, isReply) - .add(InReplyToFeature, ancestorId) - .add(IsRetweetFeature, isRetweet) - .build() - - // If no tweet result found, return default features - case _ => - DefaultFeatureMap - } - } - - private def hasTakedownForLocale( - hasTakedown: Boolean, - countryCode: String, - takedownCountryCodes: Set[String] - ) = hasTakedown && takedownCountryCodes.contains(countryCode) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD deleted file mode 100644 index 592cfa5b6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - "util/util-slf4j-api", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/spam/rtf:safety-result-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - "util/util-slf4j-api", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala deleted file mode 100644 index 1014e5865..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.scala +++ /dev/null @@ -1,98 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_visibility_reason - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BulkCandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.spam.rtf.{thriftscala => SPAM} -import com.twitter.stitch.Stitch -import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient} -import com.twitter.tweetypie.{thriftscala => TP} -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try -import com.twitter.util.logging.Logging -import javax.inject.Inject -import javax.inject.Singleton - -object VisibilityReason - extends FeatureWithDefaultOnFailure[TweetCandidate, Option[SPAM.FilteredReason]] { - override val defaultValue = None -} - -/** - * A [[BulkCandidateFeatureHydrator]] that hydrates TweetCandidates with VisibilityReason features - * by [[SPAM.SafetyLevel]] when present. The [[VisibilityReason]] feature represents a VisibilityFiltering - * [[SPAM.FilteredReason]], which contains safety filtering verdict information including action (e.g. - * Drop, Avoid) and reason (e.g. Misinformation, Abuse). This feature can inform downstream services' - * handling and presentation of Tweets (e.g. ad avoidance). - * - * @param tweetypieStitchClient used to retrieve Tweet fields for BaseTweetCandidates - * @param safetyLevel specifies VisibilityFiltering SafetyLabel - */ - -@Singleton -case class TweetVisibilityReasonBulkCandidateFeatureHydrator @Inject() ( - tweetypieStitchClient: TweetypieStitchClient, - safetyLevel: SPAM.SafetyLevel) - extends BulkCandidateFeatureHydrator[PipelineQuery, BaseTweetCandidate] - with Logging { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "TweetVisibilityReason") - - override def features: Set[Feature[_, _]] = Set(VisibilityReason) - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[BaseTweetCandidate]] - ): Stitch[Seq[FeatureMap]] = { - Stitch - .traverse(candidates.map(_.candidate.id)) { tweetId => - tweetypieStitchClient - .getTweetFields( - tweetId = tweetId, - options = TP.GetTweetFieldsOptions( - forUserId = query.getOptionalUserId, - tweetIncludes = Set.empty, - doNotCache = true, - visibilityPolicy = TP.TweetVisibilityPolicy.UserVisible, - safetyLevel = Some(safetyLevel) - ) - ).liftToTry - }.map { getTweetFieldsResults: Seq[Try[TP.GetTweetFieldsResult]] => - val tweetFields: Seq[Try[TP.TweetFieldsResultFound]] = getTweetFieldsResults.map { - case Return(TP.GetTweetFieldsResult(_, TP.TweetFieldsResultState.Found(found), _, _)) => - Return(found) - case Return(TP.GetTweetFieldsResult(_, resultState, _, _)) => - Throw( - VisibilityReasonFeatureHydrationFailure( - s"Unexpected tweet result state: ${resultState}")) - case Throw(e) => - Throw(e) - } - - tweetFields.map { tweetFieldTry => - val tweetFilteredReason = tweetFieldTry.map { tweetField => - tweetField.suppressReason match { - case Some(suppressReason) => Some(suppressReason) - case _ => None - } - } - - FeatureMapBuilder() - .add(VisibilityReason, tweetFilteredReason) - .build() - } - } - } -} - -case class VisibilityReasonFeatureHydrationFailure(message: String) - extends Exception(s"VisibilityReasonFeatureHydrationFailure($message)") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala deleted file mode 100644 index 44a187725..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.scala +++ /dev/null @@ -1,97 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.async - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A [[QueryFeatureHydrator]] with [[AsyncQueryFeatureHydrator]] that hydrated asynchronously for features - * to be before the step identified in [[hydrateBefore]] - * - * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before. - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously - * @tparam Query The domain model for the query or request - */ -case class AsyncQueryFeatureHydrator[-Query <: PipelineQuery] private[async] ( - override val hydrateBefore: PipelineStepIdentifier, - queryFeatureHydrator: QueryFeatureHydrator[Query]) - extends QueryFeatureHydrator[Query] - with AsyncHydrator { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "Async" + queryFeatureHydrator.identifier.name) - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - override val features: Set[Feature[_, _]] = queryFeatureHydrator.features - - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} - -/** - * A [[FeatureStoreV1QueryFeatureHydrator]] with [[AsyncHydrator]] that hydrated asynchronously for features - * to be before the step identified in [[hydrateBefore]]. We need a standalone class for feature store, - * different from the above as FStore hydrators are exempt from validations at run time. - * - * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before. - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously - * @tparam Query The domain model for the query or request - */ -case class AsyncFeatureStoreV1QueryFeatureHydrator[Query <: PipelineQuery] private[async] ( - override val hydrateBefore: PipelineStepIdentifier, - featureStoreV1QueryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query]) - extends FeatureStoreV1QueryFeatureHydrator[ - Query - ] - with AsyncHydrator { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "Async" + featureStoreV1QueryFeatureHydrator.identifier.name) - override val alerts: Seq[Alert] = featureStoreV1QueryFeatureHydrator.alerts - - override val features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] = - featureStoreV1QueryFeatureHydrator.features - - override val clientBuilder: FeatureStoreV1DynamicClientBuilder = - featureStoreV1QueryFeatureHydrator.clientBuilder -} - -object AsyncQueryFeatureHydrator { - - /** - * A [[QueryFeatureHydrator]] with [[AsyncQueryFeatureHydrator]] that hydrated asynchronously for features - * to be before the step identified in [[hydrateBefore]] - * - * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before. - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously - * @tparam Query The domain model for the query or request - */ - def apply[Query <: PipelineQuery]( - hydrateBefore: PipelineStepIdentifier, - queryFeatureHydrator: QueryFeatureHydrator[Query] - ): AsyncQueryFeatureHydrator[Query] = - new AsyncQueryFeatureHydrator(hydrateBefore, queryFeatureHydrator) - - /** - * A [[FeatureStoreV1QueryFeatureHydrator]] with [[AsyncHydrator]] that hydrated asynchronously for features - * to be before the step identified in [[hydrateBefore]]. We need a standalone class for feature store, - * different from the above as FStore hydrators are exempt from validations at run time. - * - * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before. - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run asynchronously - * @tparam Query The domain model for the query or request - */ - def apply[Query <: PipelineQuery]( - hydrateBefore: PipelineStepIdentifier, - featureStoreV1QueryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query] - ): AsyncFeatureStoreV1QueryFeatureHydrator[Query] = - new AsyncFeatureStoreV1QueryFeatureHydrator(hydrateBefore, featureStoreV1QueryFeatureHydrator) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD deleted file mode 100644 index 6bd8f5e31..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel deleted file mode 100644 index f81495371..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.bazel +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "cr-ml-ranker/thrift/src/main/thrift:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "stitch/stitch-core", - ], - exports = [ - "cr-ml-ranker/thrift/src/main/thrift:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala deleted file mode 100644 index 547f14999..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker - -import com.twitter.cr_ml_ranker.{thriftscala => t} -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object CrMlRankerCommonFeatures extends Feature[PipelineQuery, t.CommonFeatures] -object CrMlRankerRankingConfig extends Feature[PipelineQuery, t.RankingConfig] - -private[cr_ml_ranker] class CrMlRankerCommonQueryFeatureHydrator( - crMlRanker: t.CrMLRanker.MethodPerEndpoint, - rankingConfigSelector: RankingConfigBuilder) - extends QueryFeatureHydrator[PipelineQuery] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier("CrMlRanker") - - override val features: Set[Feature[_, _]] = - Set(CrMlRankerCommonFeatures, CrMlRankerRankingConfig) - - override def hydrate(query: PipelineQuery): Stitch[FeatureMap] = { - val rankingConfig = rankingConfigSelector.apply(query) - Stitch - .callFuture( - crMlRanker.getCommonFeatures( - t.RankingRequestContext(query.getRequiredUserId, rankingConfig))).map { commonFeatures => - FeatureMapBuilder() - .add(CrMlRankerRankingConfig, rankingConfig) - .add(CrMlRankerCommonFeatures, commonFeatures) - .build() - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala deleted file mode 100644 index 2a5d41d49..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker - -import com.twitter.cr_ml_ranker.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Builds a query hydrator that hydrates Common Features for the given Query from CR ML Ranker - * to be later used to call CR ML Ranker for scoring using the desired [[RankingConfigBuilder]] - * for building the ranking config. - */ -@Singleton -class CrMlRankerCommonQueryFeatureHydratorBuilder @Inject() ( - crMlRanker: t.CrMLRanker.MethodPerEndpoint) { - - def build(rankingConfigSelector: RankingConfigBuilder): CrMlRankerCommonQueryFeatureHydrator = - new CrMlRankerCommonQueryFeatureHydrator(crMlRanker, rankingConfigSelector) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala deleted file mode 100644 index 2f17683e7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker - -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.cr_ml_ranker.{thriftscala => t} - -/** - * Builder for constructing a ranking config from a query - */ -trait RankingConfigBuilder { - def apply(query: PipelineQuery): t.RankingConfig -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD deleted file mode 100644 index fdedd2d2b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/src/jvm/com/twitter/storehaus:core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/timelines/impression_store:thrift-scala", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/src/jvm/com/twitter/storehaus:core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "src/thrift/com/twitter/timelines/impression_store:thrift-scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala deleted file mode 100644 index 0d90eed29..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.impressed_tweets - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.storehaus.ReadableStore -import com.twitter.timelines.impressionstore.thriftscala.ImpressionList -import com.twitter.util.Future -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Query Feature to store ids of the tweets impressed by the user. - */ -case object ImpressedTweets extends FeatureWithDefaultOnFailure[PipelineQuery, Seq[Long]] { - override val defaultValue: Seq[Long] = Seq.empty -} - -/** - * Enrich the query with a list of tweet ids that the user has already seen. - */ -@Singleton -case class ImpressedTweetsQueryFeatureHydrator @Inject() ( - tweetImpressionStore: ReadableStore[Long, ImpressionList]) - extends QueryFeatureHydrator[PipelineQuery] { - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier("TweetsToExclude") - - override val features: Set[Feature[_, _]] = Set(ImpressedTweets) - - override def hydrate(query: PipelineQuery): Stitch[FeatureMap] = { - query.getOptionalUserId match { - case Some(userId) => - val featureMapResult: Future[FeatureMap] = tweetImpressionStore - .get(userId).map { impressionListOpt => - val tweetIdsOpt = for { - impressionList <- impressionListOpt - impressions <- impressionList.impressions - } yield { - impressions.map(_.tweetId) - } - val tweetIds = tweetIdsOpt.getOrElse(Seq.empty) - FeatureMapBuilder().add(ImpressedTweets, tweetIds).build() - } - Stitch.callFuture(featureMapResult) - // Non-logged-in users do not have userId, returns empty feature - - case None => - val featureMapResult = FeatureMapBuilder().add(ImpressedTweets, Seq.empty).build() - Stitch.value(featureMapResult) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD deleted file mode 100644 index a9e2c7cc4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala deleted file mode 100644 index 11d149bd8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.logged_in_only - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A [[QueryFeatureHydrator]] with [[Conditionally]] to run only for logged in users - * - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when query.isLoggedOut is false - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class LoggedInOnlyQueryFeatureHydrator[-Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - queryFeatureHydrator: QueryFeatureHydrator[Query]) - extends QueryFeatureHydrator[Query] - with Conditionally[Query] { - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "LoggedInOnly" + queryFeatureHydrator.identifier.name) - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - override val features: Set[Feature[_, _]] = queryFeatureHydrator.features - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, queryFeatureHydrator, !query.isLoggedOut) - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala deleted file mode 100644 index 60a322e43..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]] that hydrates asynchronously for features - * to be before the step identified in [[hydrateBefore]] - * - * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off - * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before. - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class AsyncParamGatedQueryFeatureHydrator[ - -Query <: PipelineQuery, - Result <: UniversalNoun[Any] -]( - enabledParam: Param[Boolean], - override val hydrateBefore: PipelineStepIdentifier, - queryFeatureHydrator: QueryFeatureHydrator[Query]) - extends QueryFeatureHydrator[Query] - with Conditionally[Query] - with AsyncHydrator { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "AsyncParamGated" + queryFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - - override val features: Set[Feature[_, _]] = queryFeatureHydrator.features - - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam)) - - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD deleted file mode 100644 index a9e2c7cc4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala deleted file mode 100644 index 70b8baeed..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class ParamGatedQueryFeatureHydrator[-Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - enabledParam: Param[Boolean], - queryFeatureHydrator: QueryFeatureHydrator[Query]) - extends QueryFeatureHydrator[Query] - with Conditionally[Query] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "ParamGated" + queryFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - - override val features: Set[Feature[_, _]] = queryFeatureHydrator.features - - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam)) - - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala deleted file mode 100644 index 825b0ed4a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]] that hydrates asynchronously for features - * to be before the step identified in [[hydrateBefore]] - * - * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off - * @param hydrateBefore the [[PipelineStepIdentifier]] step to make sure this feature is hydrated before. - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class AsyncParamGatedFeatureStoreV1QueryFeatureHydrator[ - Query <: PipelineQuery, - Result <: UniversalNoun[Any] -]( - enabledParam: Param[Boolean], - override val hydrateBefore: PipelineStepIdentifier, - queryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query]) - extends FeatureStoreV1QueryFeatureHydrator[Query] - with Conditionally[Query] - with AsyncHydrator { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "AsyncParamGated" + queryFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - - override val features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] = - queryFeatureHydrator.features - - override val clientBuilder: FeatureStoreV1DynamicClientBuilder = - queryFeatureHydrator.clientBuilder - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam)) - - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD deleted file mode 100644 index 7b18d7b06..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala deleted file mode 100644 index 9fce95a7a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1DynamicClientBuilder -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this [[QueryFeatureHydrator]] on and off - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class ParamGatedFeatureStoreV1QueryFeatureHydrator[ - Query <: PipelineQuery, - Result <: UniversalNoun[Any] -]( - enabledParam: Param[Boolean], - queryFeatureHydrator: FeatureStoreV1QueryFeatureHydrator[Query]) - extends FeatureStoreV1QueryFeatureHydrator[Query] - with Conditionally[Query] { - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - "ParamGated" + queryFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - - override val features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] = - queryFeatureHydrator.features - - override val clientBuilder: FeatureStoreV1DynamicClientBuilder = - queryFeatureHydrator.clientBuilder - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, queryFeatureHydrator, query.params(enabledParam)) - - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel deleted file mode 100644 index 579f420ee..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala deleted file mode 100644 index ac490d174..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.feature_hydrator.query.qualityfactor_gated - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -object QualityFactorGatedQueryFeatureHydrator { - val IdentifierPrefix = "QfGated" -} - -/** - * A [[QueryFeatureHydrator]] with [[Conditionally]] based on a qualityFactor threshold. - * @param pipelineIdentifier identifier of the pipeline that associated with observed quality factor - * @param qualityFactorInclusiveThreshold the threshold of the quality factor that results in the hydrator being turned off - * @param queryFeatureHydrator the underlying [[QueryFeatureHydrator]] to run when quality factor value - * is above the given inclusive threshold - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class QualityFactorGatedQueryFeatureHydrator[ - -Query <: PipelineQuery with HasQualityFactorStatus, - Result <: UniversalNoun[Any] -]( - pipelineIdentifier: ComponentIdentifier, - qualityFactorInclusiveThreshold: Param[Double], - queryFeatureHydrator: QueryFeatureHydrator[Query]) - extends QueryFeatureHydrator[Query] - with Conditionally[Query] { - import QualityFactorGatedQueryFeatureHydrator._ - - override val identifier: FeatureHydratorIdentifier = FeatureHydratorIdentifier( - IdentifierPrefix + queryFeatureHydrator.identifier.name) - - override val alerts: Seq[Alert] = queryFeatureHydrator.alerts - - override val features: Set[Feature[_, _]] = queryFeatureHydrator.features - - override def onlyIf(query: Query): Boolean = Conditionally.and( - query, - queryFeatureHydrator, - query.getQualityFactorCurrentValue(pipelineIdentifier) >= query.params( - qualityFactorInclusiveThreshold)) - - override def hydrate(query: Query): Stitch[FeatureMap] = queryFeatureHydrator.hydrate(query) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala deleted file mode 100644 index f0a77ae69..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilter - -trait GetAdaptiveLongIntBloomFilter[Query <: PipelineQuery] { - def apply(query: Query): Option[AdaptiveLongIntBloomFilter] -} - -case class AdaptiveLongIntBloomFilterDedupFilter[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Long] -]( - getBloomFilter: GetAdaptiveLongIntBloomFilter[Query]) - extends Filter[Query, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier( - "AdaptiveLongIntBloomFilterDedupFilter") - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - val filterResult = getBloomFilter(query) - .map { bloomFilter => - val (kept, removed) = - candidates.map(_.candidate).partition(candidate => !bloomFilter.contains(candidate.id)) - FilterResult(kept, removed) - }.getOrElse(FilterResult(candidates.map(_.candidate), Seq.empty)) - - Stitch.value(filterResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD deleted file mode 100644 index 371cb91b9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-core/src/main/scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/java/com/twitter/search/common/util/bloomfilter", - "src/thrift/com/twitter/tweetypie:service-scala", - "src/thrift/com/twitter/tweetypie:tweet-scala", - "stitch/stitch-core", - "stitch/stitch-tweetypie", - "stitch/stitch-tweetypie/src/main/scala", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "snowflake/src/main/scala/com/twitter/snowflake/id", - "src/java/com/twitter/search/common/util/bloomfilter", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala deleted file mode 100644 index d43f2380f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.model.marshalling.request.HasExcludedIds -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -case class ExcludedIdsFilter[ - Query <: PipelineQuery with HasExcludedIds, - Candidate <: UniversalNoun[Long] -]() extends Filter[Query, Candidate] { - override val identifier: FilterIdentifier = FilterIdentifier("ExcludedIds") - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val (kept, removed) = - candidates.map(_.candidate).partition(candidate => !query.excludedIds.contains(candidate.id)) - - val filterResult = FilterResult(kept = kept, removed = removed) - Stitch.value(filterResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala deleted file mode 100644 index 9b1933bab..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object FeatureFilter { - - /** - * Builds a Filter using the Feature name as the FilterIdentifier - * - * @see [[FeatureFilter.fromFeature(identifier, feature)]] - */ - def fromFeature[Candidate <: UniversalNoun[Any]]( - feature: Feature[Candidate, Boolean] - ): Filter[PipelineQuery, Candidate] = - FeatureFilter.fromFeature(FilterIdentifier(feature.toString), feature) - - /** - * Builds a Filter that keeps candidates when the provided Boolean Feature is present and True. - * If the Feature is missing or False, the candidate is removed. - * - * {{{ - * Filter.fromFeature( - * FilterIdentifier("SomeFilter"), - * feature = SomeFeature - * ) - * }}} - * - * @param identifier A FilterIdentifier for the new filter - * @param feature A feature of [Candidate, Boolean] type used to determine whether Candidates will be kept - * when this feature is present and true otherwise they will be removed. - */ - def fromFeature[Candidate <: UniversalNoun[Any]]( - identifier: FilterIdentifier, - feature: Feature[Candidate, Boolean] - ): Filter[PipelineQuery, Candidate] = { - val i = identifier - - new Filter[PipelineQuery, Candidate] { - override val identifier: FilterIdentifier = i - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val (keptCandidates, removedCandidates) = candidates.partition { filterCandidate => - filterCandidate.features.getOrElse(feature, false) - } - - Stitch.value( - FilterResult( - kept = keptCandidates.map(_.candidate), - removed = removedCandidates.map(_.candidate))) - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala deleted file mode 100644 index 552da4b2f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.filter.FeatureConditionalFilter.IdentifierInfix -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Predicate to apply to candidate feature, to determine whether to apply filter. - * True indicates we will apply the filter. False indicates to keep candidate and not apply filter. - * @tparam FeatureValue - */ -trait ShouldApplyFilter[FeatureValue] { - def apply(feature: FeatureValue): Boolean -} - -/** - * A filter that applies the [[filter]] for candidates for which [[shouldApplyFilter]] is true, and keeps the others - * @param feature feature to determine whether to apply underyling filter - * @param shouldApplyFilter function to determine whether to apply filter - * @param filter the actual filter to apply if shouldApplyFilter is True - * @tparam Query The domain model for the query or request - * @tparam Candidate The type of the candidates - * @tparam FeatureValueType - */ -case class FeatureValueConditionalFilter[ - -Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - FeatureValueType -]( - feature: Feature[Candidate, FeatureValueType], - shouldApplyFilter: ShouldApplyFilter[FeatureValueType], - filter: Filter[Query, Candidate]) - extends Filter[Query, Candidate] { - override val identifier: FilterIdentifier = FilterIdentifier( - feature.toString + IdentifierInfix + filter.identifier.name - ) - - override val alerts: Seq[Alert] = filter.alerts - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val (candidatesToFilter, candidatesToKeep) = candidates.partition { candidate => - shouldApplyFilter(candidate.features.get(feature)) - } - filter.apply(query, candidatesToFilter).map { filterResult => - FilterResult( - kept = filterResult.kept ++ candidatesToKeep.map(_.candidate), - removed = filterResult.removed) - } - } -} - -object FeatureConditionalFilter { - val IdentifierInfix = "FeatureConditional" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala deleted file mode 100644 index a6248f99e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A filter that checks for presence of a successfully hydrated [[TweetAuthorIdFeature]] - */ -case class HasAuthorIdFeatureFilter[Candidate <: TweetCandidate]() - extends Filter[PipelineQuery, Candidate] { - - override val identifier = FilterIdentifier("HasAuthorIdFeature") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val (kept, removed) = candidates.partition(_.features.getTry(TweetAuthorIdFeature).isReturn) - Stitch.value(FilterResult(kept.map(_.candidate), removed.map(_.candidate))) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala deleted file mode 100644 index aa3a4e72f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.filter.ParamGatedFilter.IdentifierPrefix -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[Filter]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this filter on and off - * @param filter the underlying filter to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Candidate The type of the candidates - */ -case class ParamGatedFilter[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - enabledParam: Param[Boolean], - filter: Filter[Query, Candidate]) - extends Filter[Query, Candidate] - with Filter.Conditionally[Query, Candidate] { - override val identifier: FilterIdentifier = FilterIdentifier( - IdentifierPrefix + filter.identifier.name) - override val alerts: Seq[Alert] = filter.alerts - override def onlyIf(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): Boolean = - Conditionally.and(Filter.Input(query, candidates), filter, query.params(enabledParam)) - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = filter.apply(query, candidates) -} - -object ParamGatedFilter { - val IdentifierPrefix = "ParamGated" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala deleted file mode 100644 index 158cc636e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Predicate which will be applied to each candidate. True indicates that the candidate will be - * @tparam Candidate - the type of the candidate - */ -trait ShouldKeepCandidate[Candidate] { - def apply(candidate: Candidate): Boolean -} - -object PredicateFilter { - - /** - * Builds a simple Filter out of a predicate function from the candidate to a boolean. For clarity, - * we recommend including the name of the shouldKeepCandidate parameter. - * - * {{{ - * Filter.fromPredicate( - * FilterIdentifier("SomeFilter"), - * shouldKeepCandidate = { candidate: UserCandidate => candidate.id % 2 == 0L } - * ) - * }}} - * - * @param identifier A FilterIdentifier for the new filter - * @param shouldKeepCandidate A predicate function from the candidate. Candidates will be kept - * when this function returns True. - */ - def fromPredicate[Candidate <: UniversalNoun[Any]]( - identifier: FilterIdentifier, - shouldKeepCandidate: ShouldKeepCandidate[Candidate] - ): Filter[PipelineQuery, Candidate] = { - val i = identifier - - new Filter[PipelineQuery, Candidate] { - override val identifier: FilterIdentifier = i - - /** - * Filter the list of candidates - * - * @return a FilterResult including both the list of kept candidate and the list of removed candidates - */ - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val (keptCandidates, removedCandidates) = candidates.map(_.candidate).partition { - filterCandidate => - shouldKeepCandidate(filterCandidate) - } - - Stitch.value(FilterResult(kept = keptCandidates, removed = removedCandidates)) - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala deleted file mode 100644 index 940521c7a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.snowflake.id.SnowflakeId -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param -import com.twitter.util.Duration - -/** - * @param maxAgeParam Feature Switch configurable for convenience - * @tparam Candidate The type of the candidates - */ -case class SnowflakeIdAgeFilter[Candidate <: UniversalNoun[Long]]( - maxAgeParam: Param[Duration]) - extends Filter[PipelineQuery, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier("SnowflakeIdAge") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val maxAge = query.params(maxAgeParam) - - val (keptCandidates, removedCandidates) = candidates - .map(_.candidate) - .partition { filterCandidate => - SnowflakeId.timeFromIdOpt(filterCandidate.id) match { - case Some(creationTime) => - query.queryTime.since(creationTime) <= maxAge - case _ => false - } - } - - Stitch.value(FilterResult(kept = keptCandidates, removed = removedCandidates)) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala deleted file mode 100644 index ee83408d9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A [[filter]] that filters candidates based on a country code feature - * - * @param countryCodeFeature the feature to filter candidates on - */ -case class TweetAuthorCountryFilter[Candidate <: BaseTweetCandidate]( - countryCodeFeature: Feature[Candidate, Option[String]]) - extends Filter[PipelineQuery, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier("TweetAuthorCountry") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - val userCountry = query.getCountryCode - - val (keptCandidates, removedCandidates) = candidates.partition { filteredCandidate => - val authorCountry = filteredCandidate.features.get(countryCodeFeature) - - (authorCountry, userCountry) match { - case (Some(authorCountryCode), Some(userCountryCode)) => - authorCountryCode.equalsIgnoreCase(userCountryCode) - case _ => true - } - } - - Stitch.value( - FilterResult( - kept = keptCandidates.map(_.candidate), - removed = removedCandidates.map(_.candidate) - ) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala deleted file mode 100644 index 5f87e9080..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.TweetAuthorIdFeature -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A [[filter]] that filters based on whether query user is the author of the tweet. This will NOT filter empty user ids - * @note It is recommended to apply [[HasAuthorIdFeatureFilter]] before this, as this will FAIL if feature is unavailable - * - * @tparam Candidate The type of the candidates - */ -case class TweetAuthorIsSelfFilter[Candidate <: BaseTweetCandidate]() - extends Filter[PipelineQuery, Candidate] { - override val identifier: FilterIdentifier = FilterIdentifier("TweetAuthorIsSelf") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - val (kept, removed) = candidates.partition { candidate => - val authorId = candidate.features.get(TweetAuthorIdFeature) - !query.getOptionalUserId.contains(authorId) - } - - val filterResult = FilterResult( - kept = kept.map(_.candidate), - removed = removed.map(_.candidate) - ) - Stitch.value(filterResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala deleted file mode 100644 index 88cc82890..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.component_library.filter -import com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tweetypie.IsReplyFeature -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Filters out tweets that is a reply to a tweet - */ -case class TweetIsNotReplyFilter[Candidate <: BaseTweetCandidate]() - extends Filter[PipelineQuery, Candidate] { - override val identifier: FilterIdentifier = FilterIdentifier("TweetIsNotReply") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - val (kept, removed) = candidates - .partition { candidate => - !candidate.features.get(IsReplyFeature) - } - - val filterResult = FilterResult( - kept = kept.map(_.candidate), - removed = removed.map(_.candidate) - ) - - Stitch.value(filterResult) - } - -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala deleted file mode 100644 index 12013df9d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -case class TweetLanguageFilter[Candidate <: BaseTweetCandidate]( - languageCodeFeature: Feature[Candidate, Option[String]]) - extends Filter[PipelineQuery, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier("TweetLanguage") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - val userAppLanguage = query.getLanguageCode - - val (keptCandidates, removedCandidates) = candidates.partition { filterCandidate => - val tweetLanguage = filterCandidate.features.get(languageCodeFeature) - - (tweetLanguage, userAppLanguage) match { - case (Some(tweetLanguageCode), Some(userAppLanguageCode)) => - tweetLanguageCode.equalsIgnoreCase(userAppLanguageCode) - case _ => true - } - } - - Stitch.value( - FilterResult( - kept = keptCandidates.map(_.candidate), - removed = removedCandidates.map(_.candidate))) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala deleted file mode 100644 index 0f105e679..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.scala +++ /dev/null @@ -1,71 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.util.logging.Logging -import com.twitter.product_mixer.component_library.filter.TweetVisibilityFilter._ -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.spam.rtf.thriftscala.SafetyLevel -import com.twitter.stitch.Stitch -import com.twitter.stitch.tweetypie.{TweetyPie => TweetypieStitchClient} -import com.twitter.tweetypie.{thriftscala => TP} -import com.twitter.util.Return -import com.twitter.util.Try - -object TweetVisibilityFilter { - val DefaultTweetIncludes = Set(TP.TweetInclude.TweetFieldId(TP.Tweet.IdField.id)) - private final val getTweetFieldsFailureMessage = "TweetyPie.getTweetFields failed: " -} - -case class TweetVisibilityFilter[Candidate <: BaseTweetCandidate]( - tweetypieStitchClient: TweetypieStitchClient, - tweetVisibilityPolicy: TP.TweetVisibilityPolicy, - safetyLevel: SafetyLevel, - tweetIncludes: Set[TP.TweetInclude.TweetFieldId] = DefaultTweetIncludes) - extends Filter[PipelineQuery, Candidate] - with Logging { - - override val identifier: FilterIdentifier = FilterIdentifier("TweetVisibility") - - def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - Stitch - .traverse(candidates.map(_.candidate.id)) { tweetId => - tweetypieStitchClient - .getTweetFields(tweetId, getTweetFieldsOptions(query.getOptionalUserId)) - .liftToTry - } - .map { getTweetFieldsResults: Seq[Try[TP.GetTweetFieldsResult]] => - val (checkedSucceeded, checkFailed) = getTweetFieldsResults.partition(_.isReturn) - checkFailed.foreach(e => warn(() => getTweetFieldsFailureMessage, e.throwable)) - if (checkFailed.nonEmpty) { - warn(() => - s"TweetVisibilityFilter dropped ${checkFailed.size} candidates due to tweetypie failure.") - } - - val allowedTweets = checkedSucceeded.collect { - case Return(TP.GetTweetFieldsResult(_, TP.TweetFieldsResultState.Found(found), _, _)) => - found.tweet.id - }.toSet - - val (kept, removed) = - candidates.map(_.candidate).partition(candidate => allowedTweets.contains(candidate.id)) - - FilterResult(kept = kept, removed = removed) - } - } - - private def getTweetFieldsOptions(userId: Option[Long]) = - TP.GetTweetFieldsOptions( - forUserId = userId, - tweetIncludes = tweetIncludes.toSet, - doNotCache = true, - visibilityPolicy = tweetVisibilityPolicy, - safetyLevel = Some(safetyLevel) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala deleted file mode 100644 index fe664e7fe..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.component_library.filter - -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -case class UrtUnorderedExcludeIdsCursorFilter[ - Candidate <: UniversalNoun[Long], - Query <: PipelineQuery with HasPipelineCursor[UrtUnorderedExcludeIdsCursor] -]() extends Filter[Query, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier("UnorderedExcludeIdsCursor") - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - val excludeIds = query.pipelineCursor.map(_.excludedIds.toSet).getOrElse(Set.empty) - val (kept, removed) = - candidates.map(_.candidate).partition(candidate => !excludeIds.contains(candidate.id)) - - val filterResult = FilterResult(kept = kept, removed = removed) - Stitch.value(filterResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel deleted file mode 100644 index deb6081bf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.bazel +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "src/thrift/com/twitter/socialgraph:thrift-scala", - "strato/config/columns/lists/reads:core-strato-client", - "strato/src/main/scala/com/twitter/strato/client", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "strato/config/columns/lists/reads:core-strato-client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala deleted file mode 100644 index a3a08af32..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.filter.list_visibility - -import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.socialgraph.thriftscala.SocialgraphList -import com.twitter.stitch.Stitch -import com.twitter.strato.catalog.Fetch -import com.twitter.strato.generated.client.lists.reads.CoreOnListClientColumn - -/* This Filter queries the core.List.strato column - * on Strato, and filters out any lists that are not - * returned. core.List.strato performs an authorization - * check, and does not return lists the viewer is not authorized - * to have access to. */ -class ListVisibilityFilter[Candidate <: UniversalNoun[Long]]( - listsColumn: CoreOnListClientColumn) - extends Filter[PipelineQuery, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier("ListVisibility") - - def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - val listCandidates = candidates.collect { - case CandidateWithFeatures(candidate: TwitterListCandidate, _) => candidate - } - - Stitch - .traverse( - listCandidates.map(_.id) - ) { listId => - listsColumn.fetcher.fetch(listId) - }.map { fetchResults => - fetchResults.collect { - case Fetch.Result(Some(list: SocialgraphList), _) => list.id - } - }.map { allowedListIds => - val (kept, excluded) = candidates.map(_.candidate).partition { - case candidate: TwitterListCandidate => allowedListIds.contains(candidate.id) - case _ => true - } - FilterResult(kept, excluded) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel deleted file mode 100644 index afd5204bd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.bazel +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala deleted file mode 100644 index dd8cee2bf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.filter.tweet_impression - -import com.twitter.product_mixer.component_library.feature_hydrator.query.impressed_tweets.ImpressedTweets -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Filters out tweets that the user has seen - */ -case class TweetImpressionFilter[Candidate <: BaseTweetCandidate]( -) extends Filter[PipelineQuery, Candidate] { - - override val identifier: FilterIdentifier = FilterIdentifier("TweetImpression") - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] = { - - // Set of Tweets that have impressed the user - val impressedTweetsSet: Set[Long] = query.features match { - case Some(featureMap) => featureMap.getOrElse(ImpressedTweets, Seq.empty).toSet - case None => Set.empty - } - - val (keptCandidates, removedCandidates) = candidates.partition { filteredCandidate => - !impressedTweetsSet.contains(filteredCandidate.candidate.id) - } - - Stitch.value(FilterResult(keptCandidates.map(_.candidate), removedCandidates.map(_.candidate))) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD deleted file mode 100644 index 35e791b9b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "src/scala/com/twitter/ml/featurestore/lib", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala deleted file mode 100644 index 7fc6fd501..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object DefinedCountryCodeGate extends Gate[PipelineQuery] { - override val identifier: GateIdentifier = GateIdentifier("DefinedCountryCode") - - override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = - Stitch.value(query.getCountryCode.isDefined) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala deleted file mode 100644 index 8530e4b7b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.scala +++ /dev/null @@ -1,83 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.MissingFeatureException -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.gate.GateResult -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch -import com.twitter.util.Return -import com.twitter.util.Throw - -trait ShouldContinue[Value] { - - /** Given the [[Feature]] value, returns whether the execution should continue */ - def apply(featureValue: Value): Boolean - - /** If the [[Feature]] is a failure, use this value */ - def onFailedFeature(t: Throwable): GateResult = GateResult.Stop - - /** - * If the [[Feature]], or [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]], - * is missing use this value - */ - def onMissingFeature: GateResult = GateResult.Stop -} - -object FeatureGate { - - def fromFeature( - feature: Feature[_, Boolean] - ): FeatureGate[Boolean] = - FeatureGate.fromFeature(GateIdentifier(feature.toString), feature) - - def fromNegatedFeature( - feature: Feature[_, Boolean] - ): FeatureGate[Boolean] = - FeatureGate.fromNegatedFeature(GateIdentifier(feature.toString), feature) - - def fromFeature( - gateIdentifier: GateIdentifier, - feature: Feature[_, Boolean] - ): FeatureGate[Boolean] = - FeatureGate[Boolean](gateIdentifier, feature, identity) - - def fromNegatedFeature( - gateIdentifier: GateIdentifier, - feature: Feature[_, Boolean] - ): FeatureGate[Boolean] = - FeatureGate[Boolean](gateIdentifier, feature, !identity(_)) - -} - -/** - * A [[Gate]] that is actuated based upon the value of the provided feature - */ -case class FeatureGate[Value]( - gateIdentifier: GateIdentifier, - feature: Feature[_, Value], - continue: ShouldContinue[Value]) - extends Gate[PipelineQuery] { - - override val identifier: GateIdentifier = gateIdentifier - - override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = { - Stitch - .value( - query.features.map(_.getTry(feature)) match { - case Some(Return(value)) => continue(value) - case Some(Throw(_: MissingFeatureException)) => continue.onMissingFeature.continue - case Some(Throw(t)) => continue.onFailedFeature(t).continue - case None => - throw PipelineFailure( - MisconfiguredFeatureMapFailure, - "Expected a FeatureMap to be present but none was found, ensure that your" + - "PipelineQuery has a FeatureMap configured before gating on Feature values" - ) - } - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala deleted file mode 100644 index ef2d485ac..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Gate used in first page. Use request cursor to determine if the gate should be open or closed. - */ -object FirstPageGate extends Gate[PipelineQuery with HasPipelineCursor[_]] { - - override val identifier: GateIdentifier = GateIdentifier("FirstPage") - - // If cursor is first page, then gate should return continue, otherwise return stop - override def shouldContinue(query: PipelineQuery with HasPipelineCursor[_]): Stitch[Boolean] = - Stitch.value(query.isFirstPage) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala deleted file mode 100644 index db3406edf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.gate.QueryAndCandidateGate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A Gate that only continues if the previously returned candidates are empty. This is useful - * for gating dependent candidate pipelines that are intedned to be used as a backfill when there - * are no candidates available. - */ -case class NoCandidatesGate(scope: CandidateScope) extends QueryAndCandidateGate[PipelineQuery] { - override val identifier: GateIdentifier = GateIdentifier("NoCandidates") - override def shouldContinue( - query: PipelineQuery, - candidates: Seq[CandidateWithDetails] - ): Stitch[Boolean] = Stitch.value(scope.partition(candidates).candidatesInScope.isEmpty) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala deleted file mode 100644 index 303fe3d13..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object NonEmptyAdsQueryStringGate extends Gate[PipelineQuery with AdsQuery] { - override val identifier: GateIdentifier = GateIdentifier("NonEmptyAdsQueryString") - - override def shouldContinue(query: PipelineQuery with AdsQuery): Stitch[Boolean] = { - val queryString = query.searchRequestContext.flatMap(_.queryString) - Stitch.value(queryString.exists(_.trim.nonEmpty)) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala deleted file mode 100644 index cdc6fe13d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.gate.QueryAndCandidateGate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A Gate that only continues if the previously returned candidates are not empty. This is useful - * for gating dependent candidate pipelines that are intended to only be used if a previous pipeline - * completed successfully. - */ -case class NonEmptyCandidatesGate(scope: CandidateScope) - extends QueryAndCandidateGate[PipelineQuery] { - override val identifier: GateIdentifier = GateIdentifier("NonEmptyCandidates") - override def shouldContinue( - query: PipelineQuery, - candidates: Seq[CandidateWithDetails] - ): Stitch[Boolean] = Stitch.value(scope.partition(candidates).candidatesInScope.nonEmpty) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala deleted file mode 100644 index e0fc5e4b6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.component_library.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.stitch.Stitch - -/** - * A Gate that only continues if the quality factor value of the pipeline is above the given - * threshold. This is useful for disabling an expensive function when the pipeline is under pressure - * (quality factor is low). - */ -case class QualityFactorGate(pipelineIdentifier: ComponentIdentifier, threshold: Double) - extends Gate[PipelineQuery with HasQualityFactorStatus] { - - override val identifier: GateIdentifier = GateIdentifier( - s"${pipelineIdentifier.name}QualityFactor") - - override def shouldContinue( - query: PipelineQuery with HasQualityFactorStatus - ): Stitch[Boolean] = - Stitch.value(query.getQualityFactorCurrentValue(pipelineIdentifier) >= threshold) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala deleted file mode 100644 index 3e859549d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.component_library.gate.any_candidates_without_feature - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.gate.QueryAndCandidateGate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * A gate that enables a component only if any candidates are missing a specific feature. - * You can restrict which candidates to check with the scope parameter. - * This is most commonly used to do backfill scoring, where you can have one Scoring Pipeline that - * might return a score feature "FeatureA" and another sequential pipeline that you only want to run - * if the previous scoring pipeline fails to hydrate for all candidates. - * @param identifier Unique identifier for this gate. Typically, AnyCandidatesWithout{YourFeature}. - * @param scope A [[CandidateScope]] to specify which candidates to check. - * @param missingFeature The feature that should be missing for any of the candidates for this gate to continue - */ -case class AnyCandidatesWithoutFeatureGate( - override val identifier: GateIdentifier, - scope: CandidateScope, - missingFeature: Feature[_, _]) - extends QueryAndCandidateGate[PipelineQuery] { - - override def shouldContinue( - query: PipelineQuery, - candidates: Seq[CandidateWithDetails] - ): Stitch[Boolean] = - Stitch.value(scope.partition(candidates).candidatesInScope.exists { candidateWithDetails => - !candidateWithDetails.features.getSuccessfulFeatures.contains(missingFeature) - }) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel deleted file mode 100644 index 7d26d6370..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala deleted file mode 100644 index 650307acd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.scala +++ /dev/null @@ -1,77 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -trait BaseArticleCandidate extends UniversalNoun[Int] - -/** - * Canonical ArticleCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class ArticleCandidate private ( - override val id: Int) - extends BaseArticleCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[ArticleCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: ArticleCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object ArticleCandidate { - def apply(id: Int): ArticleCandidate = new ArticleCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala deleted file mode 100644 index 9c17dc647..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical AudioSpaceCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class AudioSpaceCandidate private ( - override val id: String) - extends UniversalNoun[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[AudioSpaceCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: AudioSpaceCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object AudioSpaceCandidate { - def apply(id: String): AudioSpaceCandidate = new AudioSpaceCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD deleted file mode 100644 index e92b67378..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala deleted file mode 100644 index 3c7980de1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical CardCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class CardCandidate private ( - override val id: String) - extends UniversalNoun[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CardCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CardCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object CardCandidate { - def apply(id: String): CardCandidate = new CardCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala deleted file mode 100644 index 8970e7840..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.scala +++ /dev/null @@ -1,160 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical CommerceProductCandidate model which encapsulates information about a specific Product. - * Always prefer this version over all other variants. For example, iPhone 14, 128 GB, White. When a - * user clicks on a CommerceProduct, they will be taken to the specific product page. - * - * @note Both CommerceProduct and CommerceProductGroups (below) can be shown in the same - * TimelineModule (i.e Carousel) - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class CommerceProductCandidate private ( - override val id: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CommerceProductCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CommerceProductCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object CommerceProductCandidate { - def apply(id: Long): CommerceProductCandidate = new CommerceProductCandidate(id) -} - -/** - * Canonical CommerceProductGroupCandidate model which encapsulates information about a Single - * Product Type and its corresponding versions. Always prefer this version over all other variants. - * For example: - * iPhone 14 - * - 128 GB, White - * - 128 GB, Blue - * - 1TB, Grey - * When a user clicks on a Product Group, they will be shown information about all of the possible - * versions of the top level product. - * - * @note Both CommerceProduct (above) and CommerceProductGroups can be shown in the same - * TimelineModule (i.e Carousel) - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class CommerceProductGroupCandidate private ( - override val id: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CommerceProductGroupCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CommerceProductGroupCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object CommerceProductGroupCandidate { - def apply(id: Long): CommerceProductGroupCandidate = new CommerceProductGroupCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala deleted file mode 100644 index fd9c82cd9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.scala +++ /dev/null @@ -1,87 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -sealed trait CursorType -case object PreviousCursor extends CursorType -case object NextCursor extends CursorType - -/** - * Canonical CursorCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class CursorCandidate private ( - override val id: Long, - val value: String, - val cursorType: CursorType) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CursorCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CursorCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && value == candidate.value && cursorType == candidate.cursorType)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - 31 * ( - id.## - ) + value.## - ) + cursorType.## -} - -object CursorCandidate { - def apply(id: Long, value: String, cursorType: CursorType): CursorCandidate = - new CursorCandidate(id, value, cursorType) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala deleted file mode 100644 index 594fe96b5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.scala +++ /dev/null @@ -1,160 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -trait BaseDMConvoCandidate extends UniversalNoun[String] { - def lastReadableEventId: Option[Long] -} - -/** - * Canonical DMConvoCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class DMConvoCandidate private ( - override val id: String, - override val lastReadableEventId: Option[Long]) - extends BaseDMConvoCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[DMConvoCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: DMConvoCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && lastReadableEventId == candidate.lastReadableEventId)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + lastReadableEventId.## -} - -object DMConvoCandidate { - def apply(id: String, lastReadableEventId: Option[Long]): DMConvoCandidate = - new DMConvoCandidate(id, lastReadableEventId) -} - -/** - * Canonical DMConvoSearchCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class DMConvoSearchCandidate private ( - override val id: String, - override val lastReadableEventId: Option[Long]) - extends BaseDMConvoCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[DMConvoSearchCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: DMConvoSearchCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && lastReadableEventId == candidate.lastReadableEventId)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + lastReadableEventId.## -} - -object DMConvoSearchCandidate { - def apply(id: String, lastReadableEventId: Option[Long]): DMConvoSearchCandidate = - new DMConvoSearchCandidate(id, lastReadableEventId) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala deleted file mode 100644 index 370b31933..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.scala +++ /dev/null @@ -1,152 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical DM Events such as Message Create, Conversation Create, Join conversation, etc model. - * Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class DMEventCandidate private ( - override val id: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[DMEventCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: DMEventCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object DMEventCandidate { - def apply(id: Long): DMEventCandidate = new DMEventCandidate(id) -} - -/** - * Represent DM Events such as Message Create, Conversation Create, Join conversation, etc. - * - * @note historically this was used to represent events from Elastic - * Search rather than Strato. Now deprecated in favor of DMEvent. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - * - */ -@deprecated("Prefer DMEvent") -final class DMMessageSearchCandidate private ( - override val id: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[DMMessageSearchCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: DMMessageSearchCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object DMMessageSearchCandidate { - def apply(id: Long): DMMessageSearchCandidate = new DMMessageSearchCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala deleted file mode 100644 index 3a884f8cd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical GenericSummaryCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class GenericSummaryCandidate private ( - override val id: String) - extends UniversalNoun[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[GenericSummaryCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: GenericSummaryCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object GenericSummaryCandidate { - def apply(id: String): GenericSummaryCandidate = new GenericSummaryCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala deleted file mode 100644 index 444fb82f0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.scala +++ /dev/null @@ -1,72 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical LabelCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class LabelCandidate private ( - override val id: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[LabelCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: LabelCandidate => - ((this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object LabelCandidate { - def apply(id: Long): LabelCandidate = new LabelCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala deleted file mode 100644 index 77464823f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical MomentAnnotationCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class MomentAnnotationCandidate private ( - override val id: Long, - val text: Option[String], - val header: Option[String]) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[MomentAnnotationCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: MomentAnnotationCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && text == candidate.text && header == candidate.header)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - 31 * ( - id.## - ) + text.## - ) + header.## -} - -object MomentAnnotationCandidate { - def apply( - id: Long, - text: Option[String], - header: Option[String] - ): MomentAnnotationCandidate = new MomentAnnotationCandidate(id, text, header) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala deleted file mode 100644 index 5ebaf0d93..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.scala +++ /dev/null @@ -1,433 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -sealed trait BasePromptCandidate[+T] extends UniversalNoun[T] - -/** - * Canonical InlinePromptCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class InlinePromptCandidate private ( - override val id: String) - extends BasePromptCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[InlinePromptCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: InlinePromptCandidate => - ((this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object InlinePromptCandidate { - def apply(id: String): InlinePromptCandidate = new InlinePromptCandidate(id) -} - -/** - * Canonical CompactPromptCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class CompactPromptCandidate private ( - override val id: Long) - extends BasePromptCandidate[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CompactPromptCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CompactPromptCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object CompactPromptCandidate { - def apply(id: Long): CompactPromptCandidate = new CompactPromptCandidate(id) -} - -/** - * Canonical FullCoverPromptCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class FullCoverPromptCandidate private ( - override val id: String) - extends BasePromptCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[FullCoverPromptCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: FullCoverPromptCandidate => - ((this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object FullCoverPromptCandidate { - def apply(id: String): FullCoverPromptCandidate = new FullCoverPromptCandidate(id) -} - -/** - * Canonical HalfCoverPromptCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class HalfCoverPromptCandidate private ( - override val id: String) - extends BasePromptCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[HalfCoverPromptCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: HalfCoverPromptCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object HalfCoverPromptCandidate { - def apply(id: String): HalfCoverPromptCandidate = new HalfCoverPromptCandidate(id) -} - -/** - * Canonical PromptCarouselTileCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class PromptCarouselTileCandidate private ( - override val id: Long) - extends BasePromptCandidate[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[PromptCarouselTileCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: PromptCarouselTileCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object PromptCarouselTileCandidate { - def apply(id: Long): PromptCarouselTileCandidate = new PromptCarouselTileCandidate(id) -} - -/** - * Canonical RelevancePromptCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class RelevancePromptCandidate private ( - override val id: String, - val position: Option[Int]) - extends BasePromptCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[RelevancePromptCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: RelevancePromptCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && position == candidate.position)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + position.## -} - -object RelevancePromptCandidate { - def apply( - id: String, - position: Option[Int] = None - ): RelevancePromptCandidate = - new RelevancePromptCandidate(id, position) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala deleted file mode 100644 index 7c5e1b8ad..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.scala +++ /dev/null @@ -1,80 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical ShowAlertCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class ShowAlertCandidate private ( - override val id: String, - val userIds: Seq[Long]) - extends UniversalNoun[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[ShowAlertCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: ShowAlertCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && userIds == candidate.userIds)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + userIds.## -} - -object ShowAlertCandidate { - def apply(id: String, userIds: Seq[Long]): ShowAlertCandidate = - new ShowAlertCandidate(id, userIds) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala deleted file mode 100644 index 53844c419..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.scala +++ /dev/null @@ -1,159 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -trait BaseTopicCandidate extends UniversalNoun[Long] - -/** - * Canonical TopicCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class TopicCandidate private ( - override val id: Long) - extends BaseTopicCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TopicCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: TopicCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object TopicCandidate { - def apply(id: Long): TopicCandidate = new TopicCandidate(id) -} - -/** - * Canonical CategorizedTopicCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -@deprecated("Prefer TopicCandidate") -final class CategorizedTopicCandidate private ( - override val id: Long, - val categoryId: Option[Long], - val categoryName: Option[String]) - extends BaseTopicCandidate { - - override def canEqual(that: Any): Boolean = that.isInstanceOf[CategorizedTopicCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CategorizedTopicCandidate => - ( - (this eq candidate) - || ( - (hashCode == candidate.hashCode) - && (id == candidate.id && categoryId == candidate.categoryId && categoryName == candidate.categoryName) - ) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - 31 * ( - id.## - ) + categoryId.## - ) + categoryName.## -} - -object CategorizedTopicCandidate { - def apply( - id: Long, - categoryId: Option[Long] = None, - categoryName: Option[String] = None - ): CategorizedTopicCandidate = - new CategorizedTopicCandidate(id, categoryId, categoryName) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala deleted file mode 100644 index bea57aa51..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.scala +++ /dev/null @@ -1,93 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.fasterxml.jackson.annotation.JsonTypeName -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.UniversalNoun - -// JSON type annotations are needed for identifying renderable entities to Turntable, most candidates -// do not need them. -@JsonTypeName("tweet") -trait BaseTweetCandidate extends UniversalNoun[Long] - -/** - * Canonical TweetCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class TweetCandidate private ( - override val id: Long) - extends BaseTweetCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TweetCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: TweetCandidate => - ((this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object TweetCandidate { - def apply(id: Long): TweetCandidate = new TweetCandidate(id) -} - -/** - * Tweet Author User ID of a given Tweet Candidate. This is typically needed when hydrating tweet - * author extended features in Feature Store (e.g, [[TweetCandidateAuthorIdEntity]]). This feature - * is typically extracted by hydrating it from Tweetypie, or extracting it in your candidate source - * if it returns the Author ID alongside Tweet ID using a [[CandidatePipelineResultsTransformer]] - */ -object TweetAuthorIdFeature extends Feature[TweetCandidate, Long] - -/** - * Whether the tweet should be pinned when marshalled to URT or not. - * See [[com.twitter.product_mixer.component_library.decorator.urt.builder.item.tweet.TweetCandidateUrtItemBuilder]] - */ -object IsPinnedFeature extends Feature[TweetCandidate, Boolean] diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala deleted file mode 100644 index b9befe9f6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical TwitterListCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class TwitterListCandidate private ( - override val id: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TwitterListCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: TwitterListCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object TwitterListCandidate { - def apply(id: Long): TwitterListCandidate = new TwitterListCandidate(id) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala deleted file mode 100644 index 9e34e5054..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.scala +++ /dev/null @@ -1,87 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate - -import com.fasterxml.jackson.annotation.JsonTypeName -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.UniversalNoun - -// JSON type annotations are needed for identifying renderable entities to Turntable, most candidates -// do not need them. -@JsonTypeName("user") -trait BaseUserCandidate extends UniversalNoun[Long] - -/** - * Canonical UserCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class UserCandidate private ( - override val id: Long) - extends BaseUserCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[UserCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: UserCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object UserCandidate { - def apply(id: Long): UserCandidate = new UserCandidate(id) -} - -/** - * Feature to indicate whether a rendered user candidate should be marked unread in URT. Used in - * [[UserCandidateUrtItemBuilder]] when decorating the candidate.r - */ -object IsMarkUnreadFeature extends Feature[BaseUserCandidate, Boolean] diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala deleted file mode 100644 index b00f4505f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.scala +++ /dev/null @@ -1,95 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.ads - -import com.twitter.adserver.{thriftscala => adsthrift} -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * An [[AdsCandidate]] represents a piece of promoted content. - * - * This candidate class stores a reference to the adImpression, which is the common thrift structure - * used by the Ads team to represent an ad. - * - * Goldfinch, the ads-injection library, consumes the [[AdImpression]]. - */ -sealed trait AdsCandidate extends UniversalNoun[Any] { - val adImpression: adsthrift.AdImpression -} - -/** - * Canonical AdsTweetCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class AdsTweetCandidate private ( - override val id: Long, - override val adImpression: adsthrift.AdImpression) - extends AdsCandidate - with BaseTweetCandidate { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[AdsTweetCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: AdsTweetCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && adImpression == candidate.adImpression)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + adImpression.## -} - -object AdsTweetCandidate { - def apply(id: Long, adImpression: adsthrift.AdImpression): AdsTweetCandidate = - new AdsTweetCandidate(id, adImpression) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD deleted file mode 100644 index 3627c158e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model/promoted", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - ], - exports = [ - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/model/promoted", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "src/thrift/com/twitter/ads/adserver:adserver_common-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala deleted file mode 100644 index 42622b6c4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.scala +++ /dev/null @@ -1,91 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.hubble - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.slice.AdType - -/** - * Canonical AdCreativeCandidate model which describes an Ad Creative from an ad management - * perspective. It can be a tweet, or account, and has a 1:n relationship with ad units. Always - * prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class AdCreativeCandidate private ( - // This is the creativeId, but needs to be named ID to confirm to UniversalNoun - override val id: Long, - val adType: AdType, - val adAccountId: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[AdCreativeCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: AdCreativeCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && adType == candidate.adType && adAccountId == candidate.adAccountId)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - 31 * ( - id.## - ) + adType.## - ) + adAccountId.## -} - -object AdCreativeCandidate { - def apply( - id: Long, - adType: AdType, - adAccountId: Long - ): AdCreativeCandidate = - new AdCreativeCandidate(id, adType, adAccountId) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala deleted file mode 100644 index 60f726dac..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.hubble - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical AdGroupCandidate model which describes an "Ad Group" from the the Ad Management - * perspective. It is based on the LineItem table in Ads DB, and provides an ad group for - * advertisers to manage and report different line items belonging to a single ad. Always prefer - * this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class AdGroupCandidate private ( - override val id: Long, // This is the ad_group_id, renamed to ID to conform to UniversalNoun - val adAccountId: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[AdGroupCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: AdGroupCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && adAccountId == candidate.adAccountId)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + adAccountId.## -} - -object AdGroupCandidate { - def apply( - id: Long, - adAccountId: Long - ): AdGroupCandidate = - new AdGroupCandidate(id, adAccountId) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala deleted file mode 100644 index 1a96ff212..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.hubble - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical AdUnitCandidate model which describes an "Ad" from the Ad Management perspective. It is - * based on the AdUnit table in Ads DB, and provides a candidate for advertisers to manage and - * report on their advertising configurations.Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class AdUnitCandidate private ( - // This is the adUnitId, but needs to be named ID to confirm to UniversalNoun - override val id: Long, - val adAccountId: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[AdUnitCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: AdUnitCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && adAccountId == candidate.adAccountId)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + adAccountId.## -} - -object AdUnitCandidate { - def apply( - id: Long, - adAccountId: Long - ): AdUnitCandidate = - new AdUnitCandidate(id, adAccountId) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD deleted file mode 100644 index d9e52eeb9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala deleted file mode 100644 index 7a7ea3481..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.scala +++ /dev/null @@ -1,76 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.hubble - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical CampaignCandidate model which describes a "Campaign" from the Ads Management - * perspective. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class CampaignCandidate private ( - // This is the campaignId, but needs to be named id to conform to UniversalNoun - override val id: Long, - val adAccountId: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CampaignCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: CampaignCandidate => - ((this eq candidate) - || ((hashCode == candidate.hashCode) && (id == candidate.id))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = id.## -} - -object CampaignCandidate { - def apply(id: Long, adAccountId: Long): CampaignCandidate = - new CampaignCandidate(id, adAccountId) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala deleted file mode 100644 index c119280a0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.scala +++ /dev/null @@ -1,83 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.hubble - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** - * Canonical FundingSourceCandidate model which describes a "Funding Instrument" from the the Ad - * Management perspective. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class FundingSourceCandidate private ( - override val id: Long, - val adAccountId: Long) - extends UniversalNoun[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[FundingSourceCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: FundingSourceCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && adAccountId == candidate.adAccountId)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + adAccountId.## -} - -object FundingSourceCandidate { - def apply( - id: Long, - adAccountId: Long - ): FundingSourceCandidate = new FundingSourceCandidate(id, adAccountId) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD deleted file mode 100644 index 2f373e3e1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala deleted file mode 100644 index 4c6cd70ad..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.scala +++ /dev/null @@ -1,296 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.suggestion - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.slice.TypeaheadMetadata - -/** - * Represents a query suggestion in typeahead - */ -sealed trait BaseQuerySuggestionCandidate[+T] extends UniversalNoun[T] - -/** - * Canonical QuerySuggestionCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class QuerySuggestionCandidate private ( - override val id: String, - val metadata: Option[TypeaheadMetadata]) - extends BaseQuerySuggestionCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[QuerySuggestionCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: QuerySuggestionCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && metadata == candidate.metadata)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + metadata.## -} - -object QuerySuggestionCandidate { - def apply( - id: String, - metadata: Option[TypeaheadMetadata] = None - ): QuerySuggestionCandidate = new QuerySuggestionCandidate(id, metadata) -} - -/** - * Canonical TypeaheadQueryCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - * - */ -final class TypeaheadQueryCandidate( - override val id: String, - val score: Option[Double]) - extends BaseQuerySuggestionCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TypeaheadQueryCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: TypeaheadQueryCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && score == candidate.score)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + score.## -} - -object TypeaheadQueryCandidate { - def apply(id: String, score: Option[Double]): TypeaheadQueryCandidate = - new TypeaheadQueryCandidate(id, score) -} - -final class TypeaheadEventCandidate private ( - override val id: Long, - val metadata: Option[TypeaheadMetadata]) - extends BaseQuerySuggestionCandidate[Long] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TypeaheadQueryCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: TypeaheadEventCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && metadata == candidate.metadata)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + metadata.## -} - -object TypeaheadEventCandidate { - def apply( - id: Long, - metadata: Option[TypeaheadMetadata] = None - ): TypeaheadEventCandidate = new TypeaheadEventCandidate(id, metadata) -} - -/** - * Canonical TweetAnnotationQueryCandidate model. Always prefer this version over all other variants. - * - * TODO Remove score from the candidate and use a Feature instead - */ -final class TweetAnnotationQueryCandidate private ( - override val id: String, - val score: Option[Double]) - extends BaseQuerySuggestionCandidate[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TweetAnnotationQueryCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: TweetAnnotationQueryCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && score == candidate.score)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - id.## - ) + score.## -} - -object TweetAnnotationQueryCandidate { - def apply(id: String, score: Option[Double]): TweetAnnotationQueryCandidate = - new TweetAnnotationQueryCandidate(id, score) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala deleted file mode 100644 index c946d29c3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.scala +++ /dev/null @@ -1,93 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.suggestion - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingActionType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.TextResult - -/** - * Canonical SpellingSuggestionCandidate model. Always prefer this version over all other variants. - * - * @note Any additional fields should be added as a [[com.twitter.product_mixer.core.feature.Feature]] - * on the candidate's [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. If the - * features come from the candidate source itself (as opposed to hydrated via a - * [[com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator]]), - * then [[com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig.featuresFromCandidateSourceTransformers]] - * can be used to extract features from the candidate source response. - * - * @note This class should always remain `final`. If for any reason the `final` modifier is removed, - * the equals() implementation must be updated in order to handle class inheritor equality - * (see note on the equals method below) - */ -final class SpellingSuggestionCandidate private ( - override val id: String, - val textResult: TextResult, - val spellingActionType: Option[SpellingActionType], - val originalQuery: Option[String]) - extends UniversalNoun[String] { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[SpellingSuggestionCandidate] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case candidate: SpellingSuggestionCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id && textResult == candidate.textResult && spellingActionType == candidate.spellingActionType && originalQuery == candidate.originalQuery)) - ) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated candidate - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = - 31 * ( - 31 * ( - 31 * ( - id.## - ) + textResult.## - ) + spellingActionType.## - ) + originalQuery.## -} - -object SpellingSuggestionCandidate { - def apply( - id: String, - textResult: TextResult, - spellingActionType: Option[SpellingActionType], - originalQuery: Option[String] - ): SpellingSuggestionCandidate = - new SpellingSuggestionCandidate(id, textResult, spellingActionType, originalQuery) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD deleted file mode 100644 index 9574c702e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala deleted file mode 100644 index acb0c351c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.scala +++ /dev/null @@ -1,119 +0,0 @@ -package com.twitter.product_mixer.component_library.model.candidate.trends_events - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.GroupedTrend -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclosureType - -/** - * An [[UnifiedTrendEventCandidate]] represents a piece of Event or Trend content. - * The Event and Trend candidate are represented by different types of keys that Event has a Long - * eventId while Trend has a String trendName. - */ -sealed trait UnifiedTrendEventCandidate[+T] extends UniversalNoun[T] - -final class UnifiedEventCandidate private ( - override val id: Long) - extends UnifiedTrendEventCandidate[Long] { - - override def canEqual(that: Any): Boolean = this.isInstanceOf[UnifiedEventCandidate] - - override def equals(that: Any): Boolean = { - that match { - case candidate: UnifiedEventCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => false - } - } - - override val hashCode: Int = id.## -} - -object UnifiedEventCandidate { - def apply(id: Long): UnifiedEventCandidate = new UnifiedEventCandidate(id) -} - -/** - * Text description of an Event. Usually this is extracted from curated Event metadata - */ -object EventTitleFeature extends Feature[UnifiedEventCandidate, String] - -/** - * Display type of an Event. This will be used for client to differentiate if this Event will be - * displayed as a normal cell, a hero, etc. - */ -object EventDisplayType extends Feature[UnifiedEventCandidate, EventSummaryDisplayType] - -/** - * URL that servces as the landing page of an Event - */ -object EventUrl extends Feature[UnifiedEventCandidate, Url] - -/** - * Use to render an Event cell's editorial image - */ -object EventImage extends Feature[UnifiedEventCandidate, Option[ImageVariant]] - -/** - * Localized time string like "LIVE" or "Last Night" that is used to render the Event cell - */ -object EventTimeString extends Feature[UnifiedEventCandidate, Option[String]] - -final class UnifiedTrendCandidate private ( - override val id: String) - extends UnifiedTrendEventCandidate[String] { - - override def canEqual(that: Any): Boolean = this.isInstanceOf[UnifiedTrendCandidate] - - override def equals(that: Any): Boolean = { - that match { - case candidate: UnifiedTrendCandidate => - ( - (this eq candidate) - || ((hashCode == candidate.hashCode) - && (id == candidate.id)) - ) - case _ => false - } - } - - override val hashCode: Int = id.## -} - -object UnifiedTrendCandidate { - def apply(id: String): UnifiedTrendCandidate = new UnifiedTrendCandidate(id) -} - -object TrendNormalizedTrendName extends Feature[UnifiedTrendCandidate, String] - -object TrendTrendName extends Feature[UnifiedTrendCandidate, String] - -object TrendUrl extends Feature[UnifiedTrendCandidate, Url] - -object TrendDescription extends Feature[UnifiedTrendCandidate, Option[String]] - -object TrendTweetCount extends Feature[UnifiedTrendCandidate, Option[Int]] - -object TrendDomainContext extends Feature[UnifiedTrendCandidate, Option[String]] - -object TrendGroupedTrends extends Feature[UnifiedTrendCandidate, Option[Seq[GroupedTrend]]] - -object PromotedTrendNameFeature extends Feature[UnifiedTrendCandidate, Option[String]] - -object PromotedTrendDescriptionFeature extends Feature[UnifiedTrendCandidate, Option[String]] - -object PromotedTrendAdvertiserNameFeature extends Feature[UnifiedTrendCandidate, Option[String]] - -object PromotedTrendIdFeature extends Feature[UnifiedTrendCandidate, Option[Long]] - -object PromotedTrendDisclosureTypeFeature - extends Feature[UnifiedTrendCandidate, Option[DisclosureType]] - -object PromotedTrendImpressionIdFeature extends Feature[UnifiedTrendCandidate, Option[String]] diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD deleted file mode 100644 index beb7ae2a9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/scala/com/twitter/search/common/util/bloomfilter", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/scala/com/twitter/search/common/util/bloomfilter", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala deleted file mode 100644 index 647250ba0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.component_library.model.cursor - -import com.twitter.product_mixer.core.pipeline.PipelineCursor -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.{ - CursorType => UrtCursorType -} - -/** - * Cursor model that may be used when cursoring over an ordered candidate source. - * - * @param initialSortIndex See [[UrtPipelineCursor]] - * @param id represents the ID of the element, typically the top element for a top cursor or the - * bottom element for a bottom cursor, in an ordered candidate list - * @param gapBoundaryId represents the ID of the gap boundary element, which in gap cursors is the - * opposite bound of the gap to be filled with the cursor - */ -case class UrtOrderedCursor( - override val initialSortIndex: Long, - id: Option[Long], - cursorType: Option[UrtCursorType], - gapBoundaryId: Option[Long] = None) - extends UrtPipelineCursor - -case class OrderedCursor( - id: Option[Long], - cursorType: Option[CursorType], - gapBoundaryId: Option[Long] = None) - extends PipelineCursor diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala deleted file mode 100644 index 4b6c9bec2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.component_library.model.cursor - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.{ - CursorType => UrtCursorType -} - -case object PreviousCursorFeature - extends Feature[PipelineQuery with HasPipelineCursor[UrtPassThroughCursor], String] - -case object NextCursorFeature - extends Feature[PipelineQuery with HasPipelineCursor[UrtPassThroughCursor], String] - -/** - * Cursor model that may be used when we want to pass through the cursor value from and back to - * a downstream as-is. - * - * @param initialSortIndex See [[UrtPipelineCursor]] - * @param cursorValue the pass through cursor - */ -case class UrtPassThroughCursor( - override val initialSortIndex: Long, - cursorValue: String, - cursorType: Option[UrtCursorType] = None) - extends UrtPipelineCursor - -case class PassThroughCursor( - cursorValue: String, - cursorType: Option[CursorType] = None) - extends PipelineCursor diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala deleted file mode 100644 index 1b988256c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.component_library.model.cursor - -import com.twitter.product_mixer.core.pipeline.PipelineCursor -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor -import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilter - -/** - * Cursor model that may be used when cursoring over a unordered candidate source. On each server - * round-trip, the server will add the IDs of the candidates into a space efficient bloom filter. - * Then on subsequent requests the client will return the cursor, and the bloom filter can be sent to - * the downstream's bloom filter parameter in serialized form, or exclude candidates locally via a - * filter on the candidate source pipeline. - * - * @param initialSortIndex See [[UrtPipelineCursor]] - * @param longIntBloomFilter the bloom filter to use to dedup candidate from the candidate list - */ -case class UrtUnorderedBloomFilterCursor( - override val initialSortIndex: Long, - // space-efficient and mutable variant of the BloomFilter class used for storing long integers. - longIntBloomFilter: AdaptiveLongIntBloomFilter) - extends UrtPipelineCursor - -case class UnorderedBloomFilterCursor( - longIntBloomFilter: AdaptiveLongIntBloomFilter) - extends PipelineCursor diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala deleted file mode 100644 index bc3c4b83e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.component_library.model.cursor - -import com.twitter.product_mixer.core.pipeline.PipelineCursor -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor - -/** - * URT Cursor model that may be used when cursoring over a unordered candidate source. On each server - * round-trip, the server will append the IDs of the elements in the response to the cursor. Then - * on subsequent requests the client will return the cursor, and the excludedIds list can be sent to - * the downstream's excludeIds parameter, or excluded locally via a filter on the candidate source - * pipeline. - * - * Note that the cursor is bounded, as the excludedIds list cannot be appended to indefinitely due - * to payload size constraints. As such, this strategy is typically used for bounded (limited page - * size) products, or for unbounded (unlimited page size) products in conjunction with an - * impression store. In the latter case, the cursor excludedIds list would be limited to a max size - * via a circular buffer implementation, which would be unioned with the impression store IDs when - * filtering. This usage allows the impression store to "catch up", as there is often latency - * between when an impression client event is sent by the client and storage in the impression - * store. - * - * @param initialSortIndex See [[UrtPipelineCursor]] - * @param excludedIds the list of IDs to exclude from the candidate list - */ -case class UrtUnorderedExcludeIdsCursor( - override val initialSortIndex: Long, - excludedIds: Seq[Long]) - extends UrtPipelineCursor - -case class UnorderedExcludeIdsCursor(excludedIds: Seq[Long]) extends PipelineCursor diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala deleted file mode 100644 index aeb23de72..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.component_library.model.cursor - -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor - -/** - * Cursor model that may be used when we just need a placeholder but no real cursor value. Since URT - * requires that top and bottom cursors are always present, placeholders are often used when up - * scrolling (PTR) is not supported on a timeline. While placeholder cursors generally should not be - * submitted back by the client, they sometimes are like in the case of client-side background - * auto-refresh. If submitted, the backend will treat any request with a placeholder cursor like no - * cursor was submitted, which will behave the same way as an initial page load. - */ -case class UrtPlaceholderCursor() extends UrtPipelineCursor { - // This value is unused, in that it is not serialized into the final cursor value - override def initialSortIndex: Long = throw new UnsupportedOperationException( - "initialSortIndex is not defined for placeholder cursors") -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel deleted file mode 100644 index 728bad076..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "strato/config/columns/ml/featureStore:featureStore-strato-client", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "strato/config/columns/ml/featureStore:featureStore-strato-client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD deleted file mode 100644 index 54b01577e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala deleted file mode 100644 index f2128529b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.component_library.model.presentation.slice - -import com.twitter.product_mixer.core.model.common.presentation.slice.BaseSliceItemPresentation -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem - -case class SliceItemPresentation(override val sliceItem: SliceItem) - extends BaseSliceItemPresentation diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD deleted file mode 100644 index 062428d76..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala deleted file mode 100644 index 732c7273e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.component_library.model.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtItemPresentation -import com.twitter.product_mixer.core.model.common.presentation.urt.IsDispensable -import com.twitter.product_mixer.core.model.common.presentation.urt.WithItemTreeDisplay - -trait ConversationModuleItem - extends BaseUrtItemPresentation - with IsDispensable - with WithItemTreeDisplay diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala deleted file mode 100644 index 9286ce4dd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.component_library.model.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtItemPresentation -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtModulePresentation -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -case class UrtItemPresentation( - override val timelineItem: TimelineItem, - override val modulePresentation: Option[BaseUrtModulePresentation] = None) - extends BaseUrtItemPresentation diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala deleted file mode 100644 index 5471d8a55..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.component_library.model.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtModulePresentation -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule - -final case class UrtModulePresentation( - override val timelineModule: TimelineModule) - extends BaseUrtModulePresentation diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala deleted file mode 100644 index cbfef0cb2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.component_library.model.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtOperationPresentation -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation - -final case class UrtOperationPresentation( - override val timelineOperation: TimelineOperation) - extends BaseUrtOperationPresentation diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala deleted file mode 100644 index 5525d984a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.component_library.model.query.ads - -import com.twitter.adserver.{thriftscala => ads} -import com.twitter.dspbidder.commons.{thriftscala => dsp} - -/** - * AdsQuery holds request-time fields required by our ads candidate pipelines - */ -trait AdsQuery { - - /** - * Timelines-specific context. - * - * @note used in Home Timelines - */ - def timelineRequestParams: Option[ads.TimelineRequestParams] = None - - /** - * Navigation action trigger-type - * - * @note used in Home Timelines - */ - def requestTriggerType: Option[ads.RequestTriggerType] = None - - /** - * Autoplay setting - * - * @note used in Home Timelines - */ - def autoplayEnabled: Option[Boolean] = None - - /** - * Disable NSFW avoidance for ads mixing - * - * @note used in Home Timelines - */ - def disableNsfwAvoidance: Option[Boolean] = None - - /** - * DSP context for adwords - * - * @note used in Home Timelines - */ - def dspClientContext: Option[dsp.DspClientContext] = None - - /** - * User ID for the User Profile being viewed. - * - * @note used in Profile Timelines - */ - def userProfileViewedUserId: Option[Long] = None - - /** - * Search-specific context. - * - * @note used in Search Timelines - */ - def searchRequestContext: Option[ads.SearchRequestContext] = None -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD deleted file mode 100644 index eb9b9d5d0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "dspbidder/thrift/src/main/thrift/com/twitter/dspbidder/commons:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala", - ], - exports = [ - "dspbidder/thrift/src/main/thrift/com/twitter/dspbidder/commons:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ads/adserver:adserver_rpc-scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala deleted file mode 100644 index db100f9ed..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.annotations.Flags -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.account_recommendations_mixer.thriftscala.AccountRecommendationsMixer -import com.twitter.util.Duration - -/** - * Implementation with reasonable defaults for an idempotent Account Recommendations Mixer Thrift client. - * - * Note that the per request and total timeouts configured in this module are meant to represent a - * reasonable starting point only. These were selected based on common practice, and should not be - * assumed to be optimal for any particular use case. If you are interested in further tuning the - * settings in this module, it is recommended to create local copy for your service. - */ -object AccountRecommendationsMixerModule - extends ThriftMethodBuilderClientModule[ - AccountRecommendationsMixer.ServicePerEndpoint, - AccountRecommendationsMixer.MethodPerEndpoint - ] - with MtlsClient { - final val AccountRecommendationsMixerTimeoutPerRequest = - "account_recommendations_mixer.timeout_per_request" - final val AccountRecommendationsMixerTimeoutTotal = "account_recommendations_mixer.timeout_total" - - flag[Duration]( - name = AccountRecommendationsMixerTimeoutPerRequest, - default = 800.milliseconds, - help = "Timeout per request for AccountRecommendationsMixer") - - flag[Duration]( - name = AccountRecommendationsMixerTimeoutTotal, - default = 1200.milliseconds, - help = "Timeout total for AccountRecommendationsMixer") - - override val label: String = "account-recs-mixer" - - override val dest: String = "/s/account-recs-mixer/account-recs-mixer:thrift" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - val timeOutPerRequest: Duration = injector - .instance[Duration](Flags.named(AccountRecommendationsMixerTimeoutPerRequest)) - val timeOutTotal: Duration = - injector.instance[Duration](Flags.named(AccountRecommendationsMixerTimeoutTotal)) - methodBuilder - .withTimeoutPerRequest(timeOutPerRequest) - .withTimeoutTotal(timeOutTotal) - .idempotent(5.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD deleted file mode 100644 index 020a0cc52..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD +++ /dev/null @@ -1,72 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/src/jvm/com/twitter/storehaus:core", - "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala", - "content-recommender/thrift/src/main/thrift:thrift-scala", - "cr-mixer/thrift/src/main/thrift:thrift-scala", - "decider/src/main/scala", - "explore/explore-ranker/thrift/src/main/thrift:thrift-scala", - "finagle/finagle-memcached/src/main/scala", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-thrift-client/src/main/scala", - "finatra/utils/src/main/java/com/twitter/finatra/annotations", - "follow-recommendations-service/thrift/src/main/thrift:thrift-scala", - "home-scorer/thrift/src/main/thrift:thrift-scala", - "interests_discovery/thrift/src/main/thrift:service-thrift-scala", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "people-discovery/api/thrift/src/main/thrift:thrift-scala", - "src/scala/com/twitter/summingbird_internal/runner/store_config", - "src/thrift/com/twitter/gizmoduck:thrift-scala", - "src/thrift/com/twitter/search:earlybird-scala", - "src/thrift/com/twitter/socialgraph:thrift-scala", - "src/thrift/com/twitter/timelinemixer:thrift-scala", - "src/thrift/com/twitter/timelineranker:thrift-scala", - "src/thrift/com/twitter/timelines/impression_store:thrift-scala", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelineservice:thrift-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "stitch/stitch-gizmoduck", - "stitch/stitch-socialgraph", - "stitch/stitch-timelineservice/src/main/scala", - "stitch/stitch-tweetypie", - "timelines/src/main/scala/com/twitter/timelines/impressionstore/store", - "tweetconvosvc/client/src/main/scala/com/twitter/tweetconvosvc/client/builder", - "user_session_store/src/main/scala/com/twitter/user_session_store/config", - "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readonly", - "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readwrite", - ], - exports = [ - "3rdparty/src/jvm/com/twitter/storehaus:core", - "account-recommendations-mixer/thrift/src/main/thrift:thrift-scala", - "content-recommender/thrift/src/main/thrift:thrift-scala", - "finagle/finagle-memcached/src/main/scala", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-thrift-client/src/main/scala", - "finatra/utils/src/main/java/com/twitter/finatra/annotations", - "follow-recommendations-service/thrift/src/main/thrift:thrift-scala", - "interests_discovery/thrift/src/main/thrift:service-thrift-scala", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "src/scala/com/twitter/summingbird_internal/runner/store_config", - "src/thrift/com/twitter/gizmoduck:thrift-scala", - "src/thrift/com/twitter/socialgraph:thrift-scala", - "src/thrift/com/twitter/timelineranker:thrift-scala", - "src/thrift/com/twitter/timelines/impression_store:thrift-scala", - "src/thrift/com/twitter/tweetypie:service-scala", - "stitch/stitch-gizmoduck", - "stitch/stitch-socialgraph", - "stitch/stitch-tweetypie", - "timelines/src/main/scala/com/twitter/timelines/impressionstore/store", - "user_session_store/src/main/scala/com/twitter/user_session_store/config", - "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readonly", - "user_session_store/src/main/scala/com/twitter/user_session_store/impl/manhattan/readwrite", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala deleted file mode 100644 index dcba0279b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.ThriftMux -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.tweetconvosvc.thriftscala.ConversationService -import com.twitter.util.Duration -import org.apache.thrift.protocol.TCompactProtocol - -object ConversationServiceModule - extends ThriftMethodBuilderClientModule[ - ConversationService.ServicePerEndpoint, - ConversationService.MethodPerEndpoint - ] - with MtlsClient { - - override val label: String = "tweetconvosvc" - override val dest: String = "/s/tweetconvosvc/tweetconvosvc" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = - methodBuilder - .withTimeoutTotal(200.milliseconds) - .withTimeoutPerRequest(100.milliseconds) - .idempotent(1.percent) - - override def configureThriftMuxClient( - injector: Injector, - client: ThriftMux.Client - ): ThriftMux.Client = - super - .configureThriftMuxClient(injector, client) - .withProtocolFactory(new TCompactProtocol.Factory()) - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala deleted file mode 100644 index 8c09804bd..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.cr_mixer.{thriftscala => t} -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.util.Duration - -object CrMixerClientModule - extends ThriftMethodBuilderClientModule[ - t.CrMixer.ServicePerEndpoint, - t.CrMixer.MethodPerEndpoint - ] - with MtlsClient { - - override val label = "cr-mixer" - override val dest = "/s/cr-mixer/cr-mixer" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(500.millis) - .withTimeoutTotal(750.millis) - .idempotent(1.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala deleted file mode 100644 index 94b446232..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.decider.Decider -import com.twitter.decider.RandomRecipient -import com.twitter.finagle.thrift.ClientId -import com.twitter.finagle.thrift.service.Filterable -import com.twitter.finagle.thrift.service.ReqRepServicePerEndpointBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.annotations.Flags -import com.twitter.inject.thrift.modules.ReqRepDarkTrafficFilterModule -import scala.reflect.ClassTag - -class DarkTrafficFilterModule[MethodIface <: Filterable[MethodIface]: ClassTag]( - implicit serviceBuilder: ReqRepServicePerEndpointBuilder[MethodIface]) - extends ReqRepDarkTrafficFilterModule - with MtlsClient { - - override protected def enableSampling(injector: Injector): Any => Boolean = _ => { - val decider = injector.instance[Decider] - val deciderKey = - injector.instance[String](Flags.named("thrift.dark.traffic.filter.decider_key")) - val fromProxy = ClientId.current - .map(_.name).exists(name => name.contains("diffy") || name.contains("darktraffic")) - !fromProxy && decider.isAvailable(deciderKey, recipient = Some(RandomRecipient)) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala deleted file mode 100644 index 0be558201..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.ThriftMux -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.annotations.Flags -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.search.earlybird.{thriftscala => t} -import com.twitter.util.Duration -import org.apache.thrift.protocol.TCompactProtocol - -object EarlybirdModule - extends ThriftMethodBuilderClientModule[ - t.EarlybirdService.ServicePerEndpoint, - t.EarlybirdService.MethodPerEndpoint - ] - with MtlsClient { - final val EarlybirdTimeoutPerRequest = "earlybird.timeout_per_request" - final val EarlybirdTimeoutTotal = "earlybird.timeout_total" - - flag[Duration]( - name = EarlybirdTimeoutPerRequest, - default = 200.milliseconds, - help = "Timeout per request for Earlybird") - - flag[Duration]( - name = EarlybirdTimeoutTotal, - default = 400.milliseconds, - help = "Timeout total for Earlybird") - - override val dest = "/s/earlybird-root-superroot/root-superroot" - override val label = "earlybird" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - val timeOutPerRequest: Duration = injector - .instance[Duration](Flags.named(EarlybirdTimeoutPerRequest)) - val timeOutTotal: Duration = injector.instance[Duration](Flags.named(EarlybirdTimeoutTotal)) - methodBuilder - // See TL-14313 for load testing details that led to 200ms being selected as request timeout - .withTimeoutPerRequest(timeOutPerRequest) - .withTimeoutTotal(timeOutTotal) - .idempotent(5.percent) - } - - override def configureThriftMuxClient( - injector: Injector, - client: ThriftMux.Client - ): ThriftMux.Client = - super - .configureThriftMuxClient(injector, client) - .withProtocolFactory(new TCompactProtocol.Factory()) - - override protected def sessionAcquisitionTimeout: Duration = 1.seconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala deleted file mode 100644 index b339eddce..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.explore_ranker.thriftscala.ExploreRanker -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.annotations.Flags -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.util.Duration - -object ExploreRankerClientModule - extends ThriftMethodBuilderClientModule[ - ExploreRanker.ServicePerEndpoint, - ExploreRanker.MethodPerEndpoint - ] - with MtlsClient { - - override val label: String = "explore-ranker" - override val dest: String = "/s/explore-ranker/explore-ranker" - - private final val ExploreRankerTimeoutTotal = "explore_ranker.timeout_total" - - flag[Duration]( - name = ExploreRankerTimeoutTotal, - default = 800.milliseconds, - help = "Timeout total for ExploreRanker") - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - val timeoutTotal: Duration = injector.instance[Duration](Flags.named(ExploreRankerTimeoutTotal)) - methodBuilder - .withTimeoutTotal(timeoutTotal) - .nonIdempotent - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala deleted file mode 100644 index d394290b7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.follow_recommendations.thriftscala.FollowRecommendationsThriftService -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.util.Duration - -object FollowRecommenderServiceModule - extends ThriftMethodBuilderClientModule[ - FollowRecommendationsThriftService.ServicePerEndpoint, - FollowRecommendationsThriftService.MethodPerEndpoint - ] - with MtlsClient { - - override val label: String = "follow-recommendations-service" - - override val dest: String = "/s/follow-recommendations/follow-recos-service" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(400.millis) - .withTimeoutTotal(800.millis) - .idempotent(5.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala deleted file mode 100644 index dc4e4afb8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.gizmoduck.thriftscala.UserService -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.stitch.gizmoduck.Gizmoduck -import com.twitter.util.Duration -import javax.inject.Singleton - -/** - * Implementation with reasonable defaults for an idempotent Gizmoduck Thrift and Stitch client. - * - * Note that the per request and total timeouts configured in this module are meant to represent a - * reasonable starting point only. These were selected based on common practice, and should not be - * assumed to be optimal for any particular use case. If you are interested in further tuning the - * settings in this module, it is recommended to create local copy for your service. - */ -object GizmoduckClientModule - extends ThriftMethodBuilderClientModule[ - UserService.ServicePerEndpoint, - UserService.MethodPerEndpoint - ] - with MtlsClient { - override val label: String = "gizmoduck" - override val dest: String = "/s/gizmoduck/gizmoduck" - - @Singleton - @Provides - def provideGizmoduckStitchClient(userService: UserService.MethodPerEndpoint): Gizmoduck = - new Gizmoduck(userService) - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = - methodBuilder - .withTimeoutPerRequest(200.milliseconds) - .withTimeoutTotal(400.milliseconds) - .idempotent(1.percent) - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala deleted file mode 100644 index 16823deb6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.home_scorer.{thriftscala => t} -import com.twitter.util.Duration - -object HomeScorerClientModule - extends ThriftMethodBuilderClientModule[ - t.HomeScorer.ServicePerEndpoint, - t.HomeScorer.MethodPerEndpoint - ] - with MtlsClient { - - override val label = "home-scorer" - override val dest = "/s/home-scorer/home-scorer" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(1200.millis) - .withTimeoutTotal(2400.millis) - .idempotent(1.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala deleted file mode 100644 index f4a5d211d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.interests_discovery.thriftscala.InterestsDiscoveryService -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.util.Duration - -object InterestsDiscoveryServiceModule - extends ThriftMethodBuilderClientModule[ - InterestsDiscoveryService.ServicePerEndpoint, - InterestsDiscoveryService.MethodPerEndpoint - ] - with MtlsClient { - - override val label: String = "interests-discovery-service" - - override val dest: String = "/s/interests_discovery/interests_discovery" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(500.millis) - .withTimeoutTotal(1000.millis) - .idempotent(5.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala deleted file mode 100644 index fd564eb9f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.onboarding.task.service.thriftscala.TaskService -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.util.Duration -import com.twitter.conversions.DurationOps._ - -object OnboardingTaskServiceModule - extends ThriftMethodBuilderClientModule[ - TaskService.ServicePerEndpoint, - TaskService.MethodPerEndpoint - ] - with MtlsClient { - override val label: String = "onboarding-task-service" - override val dest: String = "/s/onboarding-task-service/onboarding-task-service" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(500.millis) - .withTimeoutTotal(1000.millis) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala deleted file mode 100644 index c9c1ab7a7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.peoplediscovery.api.thriftscala.ThriftPeopleDiscoveryService -import com.twitter.util.Duration - -/** - * Implementation with reasonable defaults for an idempotent People Discovery Thrift client. - * - * Note that the per request and total timeouts configured in this module are meant to represent a - * reasonable starting point only. These were selected based on common practice, and should not be - * assumed to be optimal for any particular use case. If you are interested in further tuning the - * settings in this module, it is recommended to create local copy for your service. - */ -object PeopleDiscoveryServiceModule - extends ThriftMethodBuilderClientModule[ - ThriftPeopleDiscoveryService.ServicePerEndpoint, - ThriftPeopleDiscoveryService.MethodPerEndpoint - ] - with MtlsClient { - - override val label: String = "people-discovery-api" - - override val dest: String = "/s/people-discovery-api/people-discovery-api:thrift" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(800.millis) - .withTimeoutTotal(1200.millis) - .idempotent(5.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala deleted file mode 100644 index a37531260..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.socialgraph.thriftscala.SocialGraphService -import com.twitter.stitch.socialgraph.SocialGraph -import javax.inject.Singleton - -object SocialGraphServiceModule - extends ThriftMethodBuilderClientModule[ - SocialGraphService.ServicePerEndpoint, - SocialGraphService.MethodPerEndpoint - ] - with MtlsClient { - - val label: String = "socialgraphservice" - val dest: String = "/s/socialgraph/socialgraph" - - @Singleton - @Provides - def provideGizmoduckStitchClient( - socialGraphService: SocialGraphService.MethodPerEndpoint - ): SocialGraph = - new SocialGraph(socialGraphService) - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder.withTimeoutPerRequest(400.millis) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala deleted file mode 100644 index d36d2dfd7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.timelinemixer.{thriftscala => t} -import com.twitter.util.Duration - -object TimelineMixerClientModule - extends ThriftMethodBuilderClientModule[ - t.TimelineMixer.ServicePerEndpoint, - t.TimelineMixer.MethodPerEndpoint - ] - with MtlsClient { - - override val label = "timeline-mixer" - override val dest = "/s/timelinemixer/timelinemixer" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(2000.millis) - .withTimeoutTotal(4000.millis) - .idempotent(1.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala deleted file mode 100644 index 3a28cb3d1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.ThriftMux -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.mtls.client.MtlsStackClient._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.timelineranker.{thriftscala => t} -import com.twitter.util.Duration -import org.apache.thrift.protocol.TCompactProtocol - -object TimelineRankerClientModule - extends ThriftMethodBuilderClientModule[ - t.TimelineRanker.ServicePerEndpoint, - t.TimelineRanker.MethodPerEndpoint - ] - with MtlsClient { - - override val label = "timeline-ranker" - override val dest = "/s/timelineranker/timelineranker:compactthrift" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(750.millis) - .withTimeoutTotal(750.millis) - } - - override def configureThriftMuxClient( - injector: Injector, - client: ThriftMux.Client - ): ThriftMux.Client = { - val serviceIdentifier = injector.instance[ServiceIdentifier] - super - .configureThriftMuxClient(injector, client) - .withProtocolFactory(new TCompactProtocol.Factory()) - .withMutualTls(serviceIdentifier) - .withPerEndpointStats - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala deleted file mode 100644 index 32310303b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.timelinescorer.{thriftscala => t} -import com.twitter.util.Duration - -object TimelineScorerClientModule - extends ThriftMethodBuilderClientModule[ - t.TimelineScorer.ServicePerEndpoint, - t.TimelineScorer.MethodPerEndpoint - ] - with MtlsClient { - - override val label = "timeline-scorer" - override val dest = "/s/timelinescorer/timelinescorer" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(2000.millis) - .withTimeoutTotal(4000.millis) - .idempotent(1.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala deleted file mode 100644 index 115136fdb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.stitch.timelineservice.TimelineService -import com.twitter.timelineservice.{thriftscala => t} -import com.twitter.util.Duration -import javax.inject.Singleton - -object TimelineServiceClientModule - extends ThriftMethodBuilderClientModule[ - t.TimelineService.ServicePerEndpoint, - t.TimelineService.MethodPerEndpoint - ] - with MtlsClient { - - override val label = "timelineservice" - override val dest = "/s/timelineservice/timelineservice" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutPerRequest(1200.millis) - .withTimeoutTotal(2400.millis) - .idempotent(1.percent) - } - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds - - @Singleton - @Provides - def providesTimelineServiceStitchClient( - client: t.TimelineService.MethodPerEndpoint - ): TimelineService = { - new TimelineService(client) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala deleted file mode 100644 index 3929a1437..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.Memcached -import com.twitter.finagle.Resolver -import com.twitter.finagle.memcached.protocol.Command -import com.twitter.finagle.memcached.protocol.Response -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.mtls.client.MtlsStackClient._ -import com.twitter.finagle.param.HighResTimer -import com.twitter.finagle.service.RetryExceptionsFilter -import com.twitter.finagle.service.RetryPolicy -import com.twitter.finagle.service.StatsFilter -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.storehaus.ReadableStore -import com.twitter.timelines.impressionstore.store.TweetImpressionsStore -import com.twitter.timelines.impressionstore.thriftscala.ImpressionList -import javax.inject.Singleton - -object TweetImpressionStoreModule extends TwitterModule { - private val TweetImpressionMemcacheWilyPath = "/s/cache/timelines_impressionstore:twemcaches" - private val tweetImpressionLabel = "timelinesTweetImpressions" - - @Provides - @Singleton - def provideTimelineTweetImpressionStore( - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver - ): ReadableStore[Long, ImpressionList] = { - val scopedStatsReceiver = statsReceiver.scope("timelinesTweetImpressions") - - // the below values for configuring the Memcached client - // are set to be the same as Home timeline's read path to the impression store. - val acquisitionTimeoutMillis = 200.milliseconds - val requestTimeoutMillis = 300.milliseconds - val numTries = 2 - - val statsFilter = new StatsFilter[Command, Response](scopedStatsReceiver) - val retryFilter = new RetryExceptionsFilter[Command, Response]( - retryPolicy = RetryPolicy.tries( - numTries, - RetryPolicy.TimeoutAndWriteExceptionsOnly - .orElse(RetryPolicy.ChannelClosedExceptionsOnly) - ), - timer = HighResTimer.Default, - statsReceiver = scopedStatsReceiver - ) - - val client = Memcached.client - .withMutualTls(serviceIdentifier) - .withSession - .acquisitionTimeout(acquisitionTimeoutMillis) - .withRequestTimeout(requestTimeoutMillis) - .withStatsReceiver(scopedStatsReceiver) - .filtered(statsFilter.andThen(retryFilter)) - .newRichClient( - dest = Resolver.eval(TweetImpressionMemcacheWilyPath), - label = tweetImpressionLabel - ) - - TweetImpressionsStore.tweetImpressionsStore(client) - } - -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala deleted file mode 100644 index f2d2a59c0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.PercentOps._ -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.thrift.ClientId -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.stitch.tweetypie.TweetyPie -import com.twitter.tweetypie.thriftscala.TweetService -import com.twitter.util.Duration -import javax.inject.Singleton - -/** - * Implementation with reasonable defaults for an idempotent TweetyPie Thrift and Stitch client. - * - * Note that the per request and total timeouts are meant to represent a reasonable starting point - * only. These were selected based on common practice, and should not be assumed to be optimal for - * any particular use case. If you are interested in further tuning the settings in this module, - * it is recommended to create local copy for your service. - */ -object TweetyPieClientModule - extends ThriftMethodBuilderClientModule[ - TweetService.ServicePerEndpoint, - TweetService.MethodPerEndpoint - ] - with MtlsClient { - override val label: String = "tweetypie" - override val dest: String = "/s/tweetypie/tweetypie" - - @Singleton - @Provides - def providesTweetypieStitchClient(tweetService: TweetService.MethodPerEndpoint): TweetyPie = - new TweetyPie(tweetService) - - /** - * TweetyPie client id must be in the form of {service.env} or it will not be treated as an - * unauthorized client - */ - override protected def clientId(injector: Injector): ClientId = { - val serviceIdentifier = injector.instance[ServiceIdentifier] - ClientId(s"${serviceIdentifier.service}.${serviceIdentifier.environment}") - } - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = - methodBuilder - .withTimeoutPerRequest(200.milliseconds) - .withTimeoutTotal(400.milliseconds) - .idempotent(1.percent) - - override protected def sessionAcquisitionTimeout: Duration = 500.milliseconds -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala deleted file mode 100644 index 4c1d983ca..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.component_library.module - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.user_session_store.ReadOnlyUserSessionStore -import com.twitter.user_session_store.ReadWriteUserSessionStore -import com.twitter.user_session_store.UserSessionDataset -import com.twitter.user_session_store.UserSessionDataset.UserSessionDataset -import com.twitter.user_session_store.config.manhattan.UserSessionStoreManhattanConfig -import com.twitter.user_session_store.impl.manhattan.readonly.ReadOnlyManhattanUserSessionStoreBuilder -import com.twitter.user_session_store.impl.manhattan.readwrite.ReadWriteManhattanUserSessionStoreBuilder - -import javax.inject.Singleton - -object UserSessionStoreModule extends TwitterModule { - private val ReadWriteAppId = "timelineservice_user_session_store" - private val ReadWriteStagingDataset = "tls_user_session_store_nonprod" - private val ReadWriteProdDataset = "tls_user_session_store" - private val ReadOnlyAppId = "user_session_store" - private val ReadOnlyDataset = "user_session_fields" - - @Provides - @Singleton - def providesReadWriteUserSessionStore( - injectedServiceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver - ): ReadWriteUserSessionStore = { - val scopedStatsReceiver = statsReceiver.scope(injectedServiceIdentifier.service) - - val dataset = injectedServiceIdentifier.environment.toLowerCase match { - case "prod" => ReadWriteProdDataset - case _ => ReadWriteStagingDataset - } - - val clientReadWriteConfig = new UserSessionStoreManhattanConfig.Prod.ReadWrite.Omega { - override val appId = ReadWriteAppId - override val defaultMaxTimeout = 400.milliseconds - override val maxRetryCount = 1 - override val serviceIdentifier = injectedServiceIdentifier - override val datasetNamesById = Map[UserSessionDataset, String]( - UserSessionDataset.ActiveDaysInfo -> dataset, - UserSessionDataset.NonPollingTimes -> dataset - ) - } - - ReadWriteManhattanUserSessionStoreBuilder - .buildReadWriteUserSessionStore(clientReadWriteConfig, statsReceiver, scopedStatsReceiver) - } - - @Provides - @Singleton - def providesReadOnlyUserSessionStore( - injectedServiceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver - ): ReadOnlyUserSessionStore = { - val scopedStatsReceiver = statsReceiver.scope(injectedServiceIdentifier.service) - - val clientReadOnlyConfig = new UserSessionStoreManhattanConfig.Prod.ReadOnly.Athena { - override val appId = ReadOnlyAppId - override val defaultMaxTimeout = 400.milliseconds - override val maxRetryCount = 1 - override val serviceIdentifier = injectedServiceIdentifier - override val datasetNamesById = Map[UserSessionDataset, String]( - UserSessionDataset.UserHealth -> ReadOnlyDataset - ) - } - - ReadOnlyManhattanUserSessionStoreBuilder - .buildReadOnlyUserSessionStore(clientReadOnlyConfig, statsReceiver, scopedStatsReceiver) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel deleted file mode 100644 index 16d3773f0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "cr-ml-ranker/thrift/src/main/thrift:thrift-scala", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala deleted file mode 100644 index 8c18d31b4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.module.cr_ml_ranker - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.cr_ml_ranker.thriftscala.CrMLRanker -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.finatra.mtls.thriftmux.modules.MtlsClient -import com.twitter.inject.Injector -import com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule -import com.twitter.product_mixer.component_library.scorer.cr_ml_ranker.CrMlRankerScoreStitchClient -import com.twitter.util.Duration -import javax.inject.Singleton - -case class CrMLRankerModule(totalTimeout: Duration = 100.milliseconds, batchSize: Int = 50) - extends ThriftMethodBuilderClientModule[ - CrMLRanker.ServicePerEndpoint, - CrMLRanker.MethodPerEndpoint - ] - with MtlsClient { - override val label = "cr-ml-ranker" - override val dest = "/s/cr-ml-ranker/cr-ml-ranker" - - override protected def configureMethodBuilder( - injector: Injector, - methodBuilder: MethodBuilder - ): MethodBuilder = { - methodBuilder - .withTimeoutTotal(totalTimeout) - } - - @Provides - @Singleton - def providesStitchClient( - crMlRankerThriftClient: CrMLRanker.MethodPerEndpoint - ): CrMlRankerScoreStitchClient = new CrMlRankerScoreStitchClient( - crMlRankerThriftClient, - maxBatchSize = batchSize - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD deleted file mode 100644 index 2f6ec6310..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/http-client/src/main/scala", - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client", - "util/util-core:scala", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - "util/util-security/src/main/scala/com/twitter/util/security", - ], - exports = [ - "finagle/finagle-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/http-client/src/main/scala", - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client", - "util/util-core:scala", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - "util/util-security/src/main/scala/com/twitter/util/security", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala deleted file mode 100644 index 1f75ec99a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.scala +++ /dev/null @@ -1,69 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.Http -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientBuilder.buildFinagleHttpClientMutualTls -import com.twitter.util.Duration -import javax.inject.Named -import javax.inject.Singleton - -object FinagleHttpClientModule extends TwitterModule { - - final val HttpClientRequestTimeout = "http_client.request_timeout" - final val HttpClientConnectTimeout = "http_client.connect_timeout" - final val HttpClientAcquisitionTimeout = "http_client.acquisition_timeout" - - flag[Duration]( - name = HttpClientRequestTimeout, - default = 200.milliseconds, - help = "HTTP client request timeout") - - flag[Duration]( - name = HttpClientConnectTimeout, - default = 500.milliseconds, - help = "HTTP client transport connect timeout") - - flag[Duration]( - name = HttpClientAcquisitionTimeout, - default = 500.milliseconds, - help = "HTTP client session acquisition timeout") - - final val FinagleHttpClientModule = "FinagleHttpClientModule" - - /** - * Provides a Finagle HTTP client with S2S Auth / Mutual TLS - * - * Note that the timeouts configured in this module are meant to be a reasonable starting point - * only. To further tuning the settings, either override the flags or create local copy of the module. - * - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param serviceIdentifier Service ID used to S2S Auth - * @param statsReceiver Stats - * - * @return Finagle HTTP Client with S2S Auth / Mutual TLS - */ - @Provides - @Singleton - @Named(FinagleHttpClientModule) - def providesFinagleHttpClient( - @Flag(HttpClientRequestTimeout) requestTimeout: Duration, - @Flag(HttpClientConnectTimeout) connectTimeout: Duration, - @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration, - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver - ): Http.Client = - buildFinagleHttpClientMutualTls( - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - serviceIdentifier = serviceIdentifier, - statsReceiver = statsReceiver - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala deleted file mode 100644 index 9ea2a7bb7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.finagle.Http -import com.twitter.finagle.http.ProxyCredentials -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemoteHost -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemotePort -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterHost -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterPort -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithCredentialProxy -import com.twitter.product_mixer.shared_library.http_client.HttpHostPort -import com.twitter.util.Duration -import javax.inject.Named -import javax.inject.Singleton - -object FinagleHttpClientWithCredentialProxyModule extends TwitterModule { - - final val FinagleHttpClientWithCredentialProxy = "FinagleHttpClientWithCredentialProxy" - - /** - * Provide a Finagle HTTP client with Egress Proxy support using Credentials - * - * Note that the timeouts configured in this module are meant to be a reasonable starting point - * only. To further tuning the settings, either override the flags or create local copy of the module. - * - * @param proxyTwitterHost Twitter egress proxy host - * @param proxyTwitterPort Twitter egress proxy port - * @param proxyRemoteHost Remote proxy host - * @param proxyRemotePort Remote proxy port - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param isServiceLocal If this is a Local deployment for testing - * @param proxyCredentials Proxy credentials - * @param statsReceiver Stats - * - * @return Finagle HTTP client with Egress Proxy support using Credentials - */ - @Provides - @Singleton - @Named(FinagleHttpClientWithCredentialProxy) - def providesFinagleHttpClientWithCredentialProxy( - @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String, - @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int, - @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String, - @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int, - @Flag(HttpClientRequestTimeout) requestTimeout: Duration, - @Flag(HttpClientConnectTimeout) connectTimeout: Duration, - @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration, - @Flag(ServiceLocal) isServiceLocal: Boolean, - proxyCredentials: ProxyCredentials, - statsReceiver: StatsReceiver - ): Http.Client = { - - val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort) - val remoteProxyHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort) - - buildFinagleHttpClientWithCredentialProxy( - twitterProxyHostPort = twitterProxyHostPort, - remoteProxyHostPort = remoteProxyHostPort, - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - proxyCredentials = proxyCredentials, - statsReceiver = statsReceiver - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala deleted file mode 100644 index c169d7fed..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.scala +++ /dev/null @@ -1,81 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.finagle.Http -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithProxy -import com.twitter.product_mixer.shared_library.http_client.HttpHostPort -import com.twitter.util.Duration -import javax.inject.Named -import javax.inject.Singleton - -object FinagleHttpClientWithProxyModule extends TwitterModule { - final val HttpClientWithProxyTwitterHost = "http_client.proxy.twitter_host" - final val HttpClientWithProxyTwitterPort = "http_client.proxy.twitter_port" - final val HttpClientWithProxyRemoteHost = "http_client.proxy.remote_host" - final val HttpClientWithProxyRemotePort = "http_client.proxy.remote_port" - - flag[String]( - HttpClientWithProxyTwitterHost, - "httpproxy.local.twitter.com", - "Twitter egress proxy host") - - flag[Int](HttpClientWithProxyTwitterPort, 3128, "Twitter egress proxy port") - - flag[String](HttpClientWithProxyRemoteHost, "Host that the proxy will connect to") - - flag[Int](HttpClientWithProxyRemotePort, 443, "Port that the proxy will connect to") - - final val FinagleHttpClientWithProxy = "FinagleHttpClientWithProxy" - - /** - * Provide a Finagle HTTP client with Egress Proxy support - * - * Note that the timeouts configured in this module are meant to be a reasonable starting point - * only. To further tuning the settings, either override the flags or create local copy of the module. - * - * @param proxyTwitterHost Twitter egress proxy host - * @param proxyTwitterPort Twitter egress proxy port - * @param proxyRemoteHost Remote proxy host - * @param proxyRemotePort Remote proxy port - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param isServiceLocal If this is a Local deployment for testing - * @param statsReceiver Stats - * - * @return Finagle HTTP client with Egress Proxy support - */ - @Provides - @Singleton - @Named(FinagleHttpClientWithProxy) - def providesFinagleHttpClientWithProxy( - @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String, - @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int, - @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String, - @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int, - @Flag(HttpClientRequestTimeout) requestTimeout: Duration, - @Flag(HttpClientConnectTimeout) connectTimeout: Duration, - @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration, - @Flag(ServiceLocal) isServiceLocal: Boolean, - statsReceiver: StatsReceiver - ): Http.Client = { - val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort) - val remoteProxyHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort) - - buildFinagleHttpClientWithProxy( - twitterProxyHostPort = twitterProxyHostPort, - remoteProxyHostPort = remoteProxyHostPort, - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - statsReceiver = statsReceiver - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala deleted file mode 100644 index 3e68b0477..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finatra.httpclient.HttpClient -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientBuilder.buildFinagleHttpClientMutualTls -import com.twitter.product_mixer.shared_library.http_client.HttpHostPort -import com.twitter.util.Duration -import com.twitter.util.jackson.ScalaObjectMapper -import javax.inject.Named -import javax.inject.Singleton - -object FinatraHttpClientModule extends TwitterModule { - - final val HttpClientHost = "http_client.host" - final val HttpClientPort = "http_client.port" - - flag[String](HttpClientHost, "Host that the client will connect to") - - flag[Int](HttpClientPort, 443, "Port that the client will connect to") - - final val FinatraHttpClient = "FinatraHttpClient" - - /** - * Build a Finatra HTTP client for a host. The Finatra HTTP client can be helpful (as opposed to - * the base Finagle HTTP Client), as it provides built-in JSON response parsing and other - * convenience methods - * - * Note that the timeouts configured in this module are meant to be a reasonable starting point - * only. To further tuning the settings, either override the flags or create local copy of the module. - * - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param host Host to build Finatra client - * @param port Port to build Finatra client - * @param scalaObjectMapper Object mapper used by the built-in JSON response parsing - * @param serviceIdentifier Service ID used to S2S Auth - * @param statsReceiver Stats - * - * @return Finatra HTTP client - */ - @Provides - @Singleton - @Named(FinatraHttpClient) - def providesFinatraHttpClient( - @Flag(HttpClientRequestTimeout) requestTimeout: Duration, - @Flag(HttpClientConnectTimeout) connectTimeout: Duration, - @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration, - @Flag(HttpClientHost) host: String, - @Flag(HttpClientPort) port: Int, - scalaObjectMapper: ScalaObjectMapper, - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver - ): HttpClient = { - val finagleHttpClient = buildFinagleHttpClientMutualTls( - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - serviceIdentifier = serviceIdentifier, - statsReceiver = statsReceiver - ) - - val hostPort = HttpHostPort(host, port) - val finagleHttpService = finagleHttpClient.newService(hostPort.toString) - - new HttpClient( - hostname = hostPort.host, - httpService = finagleHttpService, - mapper = scalaObjectMapper - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala deleted file mode 100644 index d3d2a7576..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.scala +++ /dev/null @@ -1,93 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.finagle.http.ProxyCredentials -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finatra.httpclient.HttpClient -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemoteHost -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemotePort -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterHost -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterPort -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithCredentialProxy -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpServiceWithProxy -import com.twitter.product_mixer.shared_library.http_client.HttpHostPort -import com.twitter.util.Duration -import com.twitter.util.jackson.ScalaObjectMapper -import javax.inject.Named -import javax.inject.Singleton - -object FinatraHttpClientWithCredentialProxyModule extends TwitterModule { - - final val FinatraHttpClientWithCredentialProxy = "FinagleHttpClientWithCredentialProxy" - - /** - * Build a Finatra HTTP client with Egress Proxy support with Credentials for a host. The Finatra - * HTTP client can be helpful (as opposed to the base Finagle HTTP Client), as it provides - * built-in JSON response zparsing and other convenience methods - * - * Note that the timeouts configured in this module are meant to be a reasonable starting point - * only. To further tuning the settings, either override the flags or create local copy of the module. - * - * @param proxyTwitterHost Twitter egress proxy host - * @param proxyTwitterPort Twitter egress proxy port - * @param proxyRemoteHost Remote proxy host - * @param proxyRemotePort Remote proxy port - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param isServiceLocal Local deployment for testing - * @param proxyCredentials Proxy credentials - * @param scalaObjectMapper Object mapper used by the built-in JSON response parsing - * @param statsReceiver Stats - * - * @return Finatra HTTP client with Egress Proxy support for a host - */ - @Provides - @Singleton - @Named(FinatraHttpClientWithCredentialProxy) - def providesFinatraHttpClientWithCredentialProxy( - @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String, - @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int, - @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String, - @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int, - @Flag(HttpClientRequestTimeout) requestTimeout: Duration, - @Flag(HttpClientConnectTimeout) connectTimeout: Duration, - @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration, - @Flag(ServiceLocal) isServiceLocal: Boolean, - proxyCredentials: ProxyCredentials, - scalaObjectMapper: ScalaObjectMapper, - statsReceiver: StatsReceiver - ): HttpClient = { - val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort) - val proxyRemoteHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort) - - val finagleHttpClientWithCredentialProxy = - buildFinagleHttpClientWithCredentialProxy( - twitterProxyHostPort = twitterProxyHostPort, - remoteProxyHostPort = proxyRemoteHostPort, - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - proxyCredentials = proxyCredentials, - statsReceiver = statsReceiver - ) - - val finagleHttpServiceWithCredentialProxy = - buildFinagleHttpServiceWithProxy( - finagleHttpClientWithProxy = finagleHttpClientWithCredentialProxy, - twitterProxyHostPort = twitterProxyHostPort - ) - - new HttpClient( - hostname = twitterProxyHostPort.host, - httpService = finagleHttpServiceWithCredentialProxy, - mapper = scalaObjectMapper - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala deleted file mode 100644 index 1876acc88..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.scala +++ /dev/null @@ -1,89 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finatra.httpclient.HttpClient -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientAcquisitionTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientConnectTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.HttpClientRequestTimeout -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemoteHost -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyRemotePort -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterHost -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientWithProxyModule.HttpClientWithProxyTwitterPort -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpClientWithProxy -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientWithProxyBuilder.buildFinagleHttpServiceWithProxy -import com.twitter.product_mixer.shared_library.http_client.HttpHostPort -import com.twitter.util.Duration -import com.twitter.util.jackson.ScalaObjectMapper -import javax.inject.Named -import javax.inject.Singleton - -object FinatraHttpClientWithProxyModule extends TwitterModule { - - final val FinatraHttpClientWithProxy = "FinagleHttpClientWithProxy" - - /** - * Build a Finatra HTTP client with Egress Proxy support for a host. The Finatra HTTP client can - * be helpful (as opposed to the base Finagle HTTP Client), as it provides built-in JSON response - * parsing and other convenience methods - * - * Note that the timeouts configured in this module are meant to be a reasonable starting point - * only. To further tuning the settings, either override the flags or create local copy of the module. - * - * @param proxyTwitterHost Twitter egress proxy host - * @param proxyTwitterPort Twitter egress proxy port - * @param proxyRemoteHost Remote proxy host - * @param proxyRemotePort Remote proxy port - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param isServiceLocal Local deployment for testing - * @param scalaObjectMapper Object mapper used by the built-in JSON response parsing - * @param statsReceiver Stats - * - * @return Finatra HTTP client with Egress Proxy support for a host - */ - @Provides - @Singleton - @Named(FinatraHttpClientWithProxy) - def providesFinatraHttpClientWithProxy( - @Flag(HttpClientWithProxyTwitterHost) proxyTwitterHost: String, - @Flag(HttpClientWithProxyTwitterPort) proxyTwitterPort: Int, - @Flag(HttpClientWithProxyRemoteHost) proxyRemoteHost: String, - @Flag(HttpClientWithProxyRemotePort) proxyRemotePort: Int, - @Flag(HttpClientRequestTimeout) requestTimeout: Duration, - @Flag(HttpClientConnectTimeout) connectTimeout: Duration, - @Flag(HttpClientAcquisitionTimeout) acquisitionTimeout: Duration, - @Flag(ServiceLocal) isServiceLocal: Boolean, - scalaObjectMapper: ScalaObjectMapper, - statsReceiver: StatsReceiver - ): HttpClient = { - val twitterProxyHostPort = HttpHostPort(proxyTwitterHost, proxyTwitterPort) - val proxyRemoteHostPort = HttpHostPort(proxyRemoteHost, proxyRemotePort) - - val finagleHttpClientWithProxy = - buildFinagleHttpClientWithProxy( - twitterProxyHostPort = twitterProxyHostPort, - remoteProxyHostPort = proxyRemoteHostPort, - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - statsReceiver = statsReceiver - ) - - val finagleHttpServiceWithProxy = - buildFinagleHttpServiceWithProxy( - finagleHttpClientWithProxy = finagleHttpClientWithProxy, - twitterProxyHostPort = twitterProxyHostPort - ) - - new HttpClient( - hostname = twitterProxyHostPort.host, - httpService = finagleHttpServiceWithProxy, - mapper = scalaObjectMapper - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala deleted file mode 100644 index 88cb81ce6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.component_library.module.http - -import com.google.inject.Provides -import com.twitter.finagle.http.ProxyCredentials -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.util.security.{Credentials => CredentialsUtil} -import java.io.File -import javax.inject.Singleton - -object ProxyCredentialsModule extends TwitterModule { - final val HttpClientWithProxyCredentialsPath = "http_client.proxy.proxy_credentials_path" - - flag[String](HttpClientWithProxyCredentialsPath, "", "Path the load the proxy credentials") - - @Provides - @Singleton - def providesProxyCredentials( - @Flag(HttpClientWithProxyCredentialsPath) proxyCredentialsPath: String, - ): ProxyCredentials = { - val credentialsFile = new File(proxyCredentialsPath) - ProxyCredentials(CredentialsUtil(credentialsFile)) - .getOrElse(throw MissingProxyCredentialsException) - } - - object MissingProxyCredentialsException extends Exception("Proxy Credentials not found") -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala deleted file mode 100644 index d38bdff77..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.{thriftscala => ads} -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject - -class AdsCandidatePipelineConfig[Query <: PipelineQuery with AdsQuery] @Inject() ( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - override val gates: Seq[Gate[Query]], - override val candidateSource: CandidateSource[ - ads.AdRequestParams, - ads.AdImpression - ], - override val filters: Seq[Filter[Query, AdsCandidate]], - override val postFilterFeatureHydration: Seq[ - BaseCandidateFeatureHydrator[Query, AdsCandidate, _] - ], - override val decorator: Option[CandidateDecorator[Query, AdsCandidate]], - override val alerts: Seq[Alert], - adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query], - estimateNumOrganicItems: EstimateNumOrganicItems[Query], - urtRequest: Option[Boolean], -) extends CandidatePipelineConfig[ - Query, - ads.AdRequestParams, - ads.AdImpression, - AdsCandidate - ] { - - override val queryTransformer: CandidatePipelineQueryTransformer[Query, ads.AdRequestParams] = - AdsCandidatePipelineQueryTransformer( - adsDisplayLocationBuilder = adsDisplayLocationBuilder, - estimatedNumOrganicItems = estimateNumOrganicItems, - urtRequest = urtRequest) - - override val resultTransformer: CandidatePipelineResultsTransformer[ - ads.AdImpression, - AdsCandidate - ] = AdsCandidatePipelineResultsTransformer -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala deleted file mode 100644 index c4a1ee6a3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.thriftscala.AdImpression -import com.twitter.adserver.thriftscala.AdRequestParams -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.ad.AdsCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdsCandidatePipelineConfigBuilder @Inject() () { - - def build[Query <: PipelineQuery with AdsQuery]( - adsCandidateSource: CandidateSource[AdRequestParams, AdImpression], - adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query], - estimateNumOrganicItems: EstimateNumOrganicItems[Query], - identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("Ads"), - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - gates: Seq[Gate[Query]] = Seq.empty, - filters: Seq[Filter[Query, AdsCandidate]] = Seq.empty, - postFilterFeatureHydration: Seq[BaseCandidateFeatureHydrator[Query, AdsCandidate, _]] = - Seq.empty, - decorator: Option[CandidateDecorator[Query, AdsCandidate]] = - Some(UrtItemCandidateDecorator(AdsCandidateUrtItemBuilder())), - alerts: Seq[Alert] = Seq.empty, - urtRequest: Option[Boolean] = None, - ): AdsCandidatePipelineConfig[Query] = { - new AdsCandidatePipelineConfig( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - gates = gates, - candidateSource = adsCandidateSource, - filters = filters, - postFilterFeatureHydration = postFilterFeatureHydration, - decorator = decorator, - alerts = alerts, - adsDisplayLocationBuilder = adsDisplayLocationBuilder, - estimateNumOrganicItems = estimateNumOrganicItems, - urtRequest = urtRequest, - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala deleted file mode 100644 index 4669a6d0a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.{thriftscala => ads} -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.component_library.pipeline.candidate.ads.AdsCandidatePipelineQueryTransformer.buildAdRequestParams -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Transform a PipelineQuery with AdsQuery into an AdsRequestParams - * - * @param adsDisplayLocationBuilder Builder that determines the display location for the ads - * @param estimatedNumOrganicItems Estimate for the number of organic items that will be served - * alongside inorganic items such as ads. - */ -case class AdsCandidatePipelineQueryTransformer[Query <: PipelineQuery with AdsQuery]( - adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query], - estimatedNumOrganicItems: EstimateNumOrganicItems[Query], - urtRequest: Option[Boolean], -) extends CandidatePipelineQueryTransformer[Query, ads.AdRequestParams] { - - override def transform(query: Query): ads.AdRequestParams = - buildAdRequestParams( - query = query, - adsDisplayLocation = adsDisplayLocationBuilder(query), - organicItemIds = None, - numOrganicItems = Some(estimatedNumOrganicItems(query)), - urtRequest = urtRequest - ) -} - -object AdsCandidatePipelineQueryTransformer { - - def buildAdRequestParams( - query: PipelineQuery with AdsQuery, - adsDisplayLocation: ads.DisplayLocation, - organicItemIds: Option[Seq[Long]], - numOrganicItems: Option[Short], - urtRequest: Option[Boolean], - ): ads.AdRequestParams = { - val searchRequestContext = query.searchRequestContext - val queryString = query.searchRequestContext.flatMap(_.queryString) - - val adRequest = ads.AdRequest( - queryString = queryString, - displayLocation = adsDisplayLocation, - searchRequestContext = searchRequestContext, - organicItemIds = organicItemIds, - numOrganicItems = numOrganicItems, - profileUserId = query.userProfileViewedUserId, - isDebug = Some(false), - isTest = Some(false), - requestTriggerType = query.requestTriggerType, - disableNsfwAvoidance = query.disableNsfwAvoidance, - timelineRequestParams = query.timelineRequestParams, - ) - - val context = query.clientContext - - val clientInfo = ads.ClientInfo( - clientId = context.appId.map(_.toInt), - userId64 = context.userId, - userIp = context.ipAddress, - guestId = context.guestIdAds, - userAgent = context.userAgent, - deviceId = context.deviceId, - languageCode = context.languageCode, - countryCode = context.countryCode, - mobileDeviceId = context.mobileDeviceId, - mobileDeviceAdId = context.mobileDeviceAdId, - limitAdTracking = context.limitAdTracking, - autoplayEnabled = query.autoplayEnabled, - urtRequest = urtRequest, - dspClientContext = query.dspClientContext - ) - - ads.AdRequestParams(adRequest, clientInfo) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala deleted file mode 100644 index ea693f800..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.thriftscala.AdImpression -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsTweetCandidate -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult - -object AdsCandidatePipelineResultsTransformer - extends CandidatePipelineResultsTransformer[AdImpression, AdsCandidate] { - - override def transform(sourceResult: AdImpression): AdsCandidate = - (sourceResult.nativeRtbCreative, sourceResult.promotedTweetId) match { - case (None, Some(promotedTweetId)) => - AdsTweetCandidate( - id = promotedTweetId, - adImpression = sourceResult - ) - case (Some(_), None) => - throw unsupportedAdImpressionPipelineFailure( - impression = sourceResult, - reason = "Received ad impression with rtbCreative") - case (Some(_), Some(_)) => - throw unsupportedAdImpressionPipelineFailure( - impression = sourceResult, - reason = "Received ad impression with both rtbCreative and promoted tweetId") - case (None, None) => - throw unsupportedAdImpressionPipelineFailure( - impression = sourceResult, - reason = "Received ad impression with neither rtbCreative nor promoted tweetId") - } - - private def unsupportedAdImpressionPipelineFailure(impression: AdImpression, reason: String) = - PipelineFailure( - UnexpectedCandidateResult, - reason = - s"Unsupported AdImpression ($reason). impressionString: ${impression.impressionString}") -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala deleted file mode 100644 index 2df599613..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.{thriftscala => ads} -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.functional_component.transformer.DependentCandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam - -class AdsDependentCandidatePipelineConfig[Query <: PipelineQuery with AdsQuery]( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - override val gates: Seq[BaseGate[Query]], - override val candidateSource: CandidateSource[ - ads.AdRequestParams, - ads.AdImpression - ], - override val filters: Seq[Filter[Query, AdsCandidate]], - override val postFilterFeatureHydration: Seq[ - BaseCandidateFeatureHydrator[Query, AdsCandidate, _] - ], - override val decorator: Option[CandidateDecorator[Query, AdsCandidate]], - override val alerts: Seq[Alert], - adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query], - urtRequest: Option[Boolean], - getOrganicItemIds: GetOrganicItemIds, - countNumOrganicItems: CountNumOrganicItems[Query], -) extends DependentCandidatePipelineConfig[ - Query, - ads.AdRequestParams, - ads.AdImpression, - AdsCandidate - ] { - - override def queryTransformer: DependentCandidatePipelineQueryTransformer[ - Query, - ads.AdRequestParams - ] = AdsDependentCandidatePipelineQueryTransformer( - adsDisplayLocationBuilder = adsDisplayLocationBuilder, - getOrganicItemIds = getOrganicItemIds, - countNumOrganicItems = countNumOrganicItems, - urtRequest = urtRequest - ) - - override val resultTransformer: CandidatePipelineResultsTransformer[ - ads.AdImpression, - AdsCandidate - ] = AdsCandidatePipelineResultsTransformer -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala deleted file mode 100644 index 6cdf573c8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.thriftscala.AdImpression -import com.twitter.adserver.thriftscala.AdRequestParams -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.ad.AdsCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdsDependentCandidatePipelineConfigBuilder @Inject() () { - - /** - * Build a AdsDependentCandidatePipelineConfig - */ - def build[Query <: PipelineQuery with AdsQuery]( - adsCandidateSource: CandidateSource[AdRequestParams, AdImpression], - identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("Ads"), - adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query], - getOrganicItemIds: GetOrganicItemIds = EmptyOrganicItemIds, - countNumOrganicItems: CountNumOrganicItems[Query] = CountAllCandidates, - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - gates: Seq[BaseGate[Query]] = Seq.empty, - filters: Seq[Filter[Query, AdsCandidate]] = Seq.empty, - postFilterFeatureHydration: Seq[BaseCandidateFeatureHydrator[Query, AdsCandidate, _]] = - Seq.empty, - decorator: Option[CandidateDecorator[Query, AdsCandidate]] = - Some(UrtItemCandidateDecorator(AdsCandidateUrtItemBuilder())), - alerts: Seq[Alert] = Seq.empty, - urtRequest: Option[Boolean] = None, - ): AdsDependentCandidatePipelineConfig[Query] = new AdsDependentCandidatePipelineConfig[Query]( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - gates = gates, - candidateSource = adsCandidateSource, - filters = filters, - postFilterFeatureHydration = postFilterFeatureHydration, - decorator = decorator, - alerts = alerts, - adsDisplayLocationBuilder = adsDisplayLocationBuilder, - getOrganicItemIds = getOrganicItemIds, - countNumOrganicItems = countNumOrganicItems, - urtRequest = urtRequest) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala deleted file mode 100644 index 2dc5a1628..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.{thriftscala => ads} -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.component_library.pipeline.candidate.ads.AdsCandidatePipelineQueryTransformer.buildAdRequestParams -import com.twitter.product_mixer.core.functional_component.transformer.DependentCandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Transform a PipelineQuery with AdsQuery into an AdsRequestParams - * - * @param adsDisplayLocationBuilder Builder that determines the display location for the ads - * @param countNumOrganicItems Count organic items from the response - */ -case class AdsDependentCandidatePipelineQueryTransformer[Query <: PipelineQuery with AdsQuery]( - adsDisplayLocationBuilder: AdsDisplayLocationBuilder[Query], - getOrganicItemIds: GetOrganicItemIds, - countNumOrganicItems: CountNumOrganicItems[Query], - urtRequest: Option[Boolean], -) extends DependentCandidatePipelineQueryTransformer[Query, ads.AdRequestParams] { - - override def transform( - query: Query, - previousCandidates: Seq[CandidateWithDetails] - ): ads.AdRequestParams = buildAdRequestParams( - query = query, - adsDisplayLocation = adsDisplayLocationBuilder(query), - organicItemIds = getOrganicItemIds.apply(previousCandidates), - numOrganicItems = Some(countNumOrganicItems.apply(query, previousCandidates)), - urtRequest = urtRequest - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala deleted file mode 100644 index e10ce6a12..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.adserver.{thriftscala => ads} -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait AdsDisplayLocationBuilder[-Query <: PipelineQuery with AdsQuery] { - - def apply(query: Query): ads.DisplayLocation -} - -case class StaticAdsDisplayLocationBuilder(displayLocation: ads.DisplayLocation) - extends AdsDisplayLocationBuilder[PipelineQuery with AdsQuery] { - - def apply(query: PipelineQuery with AdsQuery): ads.DisplayLocation = displayLocation -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD deleted file mode 100644 index c459215e5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala deleted file mode 100644 index c42abfa7b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.product_mixer.component_library.model.query.ads.AdsQuery -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Derive an estimate of the number of organic items from the query. If you need a more precise number, - * consider switching to [[AdsDependentCandidatePipelineConfig]] - */ -trait EstimateNumOrganicItems[Query <: PipelineQuery with AdsQuery] { - - def apply(query: Query): Short -} - -/** - * Compute the number of organic items from the query and set of previous candidates. - * - * @note the key difference between [[CountNumOrganicItems]] and [[EstimateNumOrganicItems]] is - * that for [[EstimateNumOrganicItems]] we don't have any candidates returned yet, so we can - * only guess as to the number of organic items in the result set. In contrast, - * [[CountNumOrganicItems]] is used on dependant candidate pipelines where we can scan over - * the candidate pipelines result set to count the number of organic items. - */ -trait CountNumOrganicItems[-Query <: PipelineQuery with AdsQuery] { - - def apply(query: Query, previousCandidates: Seq[CandidateWithDetails]): Short -} - -/** - * Treat all previously retrieved candidates as organic - */ -case object CountAllCandidates extends CountNumOrganicItems[PipelineQuery with AdsQuery] { - - def apply( - query: PipelineQuery with AdsQuery, - previousCandidates: Seq[CandidateWithDetails] - ): Short = - previousCandidates.length.toShort -} - -/** - * Only count candidates from a specific subset of pipelines as organic - */ -case class CountCandidatesFromPipelines(pipelines: CandidateScope) - extends CountNumOrganicItems[PipelineQuery with AdsQuery] { - - def apply( - query: PipelineQuery with AdsQuery, - previousCandidates: Seq[CandidateWithDetails] - ): Short = - previousCandidates.count(pipelines.contains).toShort -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala deleted file mode 100644 index 9682ad5c9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -/** - * Get organic item candidates from the set of previous candidates - */ -trait GetOrganicItemIds { - - def apply(previousCandidates: Seq[CandidateWithDetails]): Option[Seq[Long]] -} - -/** - * Get organic items from specified pipelines - */ -case class PipelineScopedOrganicItemIds(pipelines: CandidateScope) extends GetOrganicItemIds { - - def apply(previousCandidates: Seq[CandidateWithDetails]): Option[Seq[Long]] = - Some(previousCandidates.filter(pipelines.contains).map(_.candidateIdLong)) -} - -/** - * Get an empty list of organic item candidates - */ -case object EmptyOrganicItemIds extends GetOrganicItemIds { - - def apply(previousCandidates: Seq[CandidateWithDetails]): Option[Seq[Long]] = None -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala deleted file mode 100644 index ef323aa6a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsTweetCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -case class PromotedTweetsOnlyFilter[Query <: PipelineQuery]( - underlyingFilter: Filter[Query, AdsTweetCandidate]) - extends Filter[Query, AdsCandidate] { - - override val identifier: FilterIdentifier = - FilterIdentifier(s"PromotedTweets${underlyingFilter.identifier.name}") - - override def apply( - query: Query, - candidatesWithFeatures: Seq[CandidateWithFeatures[AdsCandidate]] - ): Stitch[FilterResult[AdsCandidate]] = { - - val adsTweetCandidates: Seq[CandidateWithFeatures[AdsTweetCandidate]] = - candidatesWithFeatures.flatMap { - case tweetCandidateWithFeatures @ CandidateWithFeatures(_: AdsTweetCandidate, _) => - Some(tweetCandidateWithFeatures.asInstanceOf[CandidateWithFeatures[AdsTweetCandidate]]) - case _ => None - } - - underlyingFilter - .apply(query, adsTweetCandidates) - .map { filterResult => - val removedSet = filterResult.removed.toSet[AdsCandidate] - val (removed, kept) = candidatesWithFeatures.map(_.candidate).partition(removedSet.contains) - FilterResult(kept, removed) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala deleted file mode 100644 index 4064a69cc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.ads - -import com.twitter.product_mixer.component_library.model.candidate.ads.AdsCandidate -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.filter.FilterResult -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object ValidAdImpressionIdFilter extends Filter[PipelineQuery, AdsCandidate] { - override val identifier: FilterIdentifier = FilterIdentifier("ValidAdImpressionId") - - override def apply( - query: PipelineQuery, - candidatesWithFeatures: Seq[CandidateWithFeatures[AdsCandidate]] - ): Stitch[FilterResult[AdsCandidate]] = { - val (kept, removed) = candidatesWithFeatures - .map(_.candidate) - .partition(candidate => candidate.adImpression.impressionString.exists(_.nonEmpty)) - - Stitch.value(FilterResult(kept, removed)) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel deleted file mode 100644 index ef2575873..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala deleted file mode 100644 index 88d522175..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline - -import com.twitter.onboarding.task.service.thriftscala.GetInjectionsRequest -import com.twitter.onboarding.task.service.{thriftscala => servicethrift} -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator -import com.twitter.product_mixer.component_library.decorator.urt.UrtMultipleModulesDecorator -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptModuleGrouping -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptUrtModuleBuilder -import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipCandidateFeatureTransformer -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipQueryTransformer -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.PromptResultsTransformer -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam - -/** - * A candidate pipeline for Flexible Injection Pipeline Candidates. - * Fetches prompts from FLIP (inside onboarding-task-service). - */ -class FlipPromptCandidatePipelineConfig[Query <: PipelineQuery with HasFlipInjectionParams]( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - promptCandidateSource: PromptCandidateSource) - extends CandidatePipelineConfig[ - Query, - servicethrift.GetInjectionsRequest, - IntermediatePrompt, - BasePromptCandidate[Any] - ] { - - override val candidateSource: CandidateSource[GetInjectionsRequest, IntermediatePrompt] = - promptCandidateSource - - override val queryTransformer: CandidatePipelineQueryTransformer[Query, GetInjectionsRequest] = - FlipQueryTransformer - - override val resultTransformer: CandidatePipelineResultsTransformer[ - IntermediatePrompt, - BasePromptCandidate[Any] - ] = PromptResultsTransformer - - override val decorator: Option[ - CandidateDecorator[Query, BasePromptCandidate[Any]] - ] = Some( - UrtMultipleModulesDecorator( - urtItemCandidateDecorator = UrtItemCandidateDecorator(FlipPromptCandidateUrtItemBuilder()), - moduleBuilder = FlipPromptUrtModuleBuilder(), - groupByKey = FlipPromptModuleGrouping - )) - - override val featuresFromCandidateSourceTransformers: Seq[ - CandidateFeatureTransformer[IntermediatePrompt] - ] = Seq(FlipCandidateFeatureTransformer) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala deleted file mode 100644 index 199eb73f2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline - -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FlipPromptCandidatePipelineConfigBuilder @Inject() ( - promptCandidateSource: PromptCandidateSource) { - - /** - * Build a FlipPromptCandidatePipelineConfig - * - * @note If injected classes are needed to populate parameters in this method, consider creating a - * ProductFlipPromptCandidatePipelineConfigBuilder with a single `def build()` method. - * That product-specific builder class can then inject everything it needs (including this - * class), and delegate to this class's build() method within its own build() method. - */ - def build[Query <: PipelineQuery with HasFlipInjectionParams]( - identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("FlipPrompt"), - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - ): FlipPromptCandidatePipelineConfig[Query] = { - new FlipPromptCandidatePipelineConfig( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - promptCandidateSource = promptCandidateSource) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala deleted file mode 100644 index 537c91639..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.scala +++ /dev/null @@ -1,69 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline - -import com.twitter.onboarding.task.service.thriftscala.GetInjectionsRequest -import com.twitter.onboarding.task.service.{thriftscala => servicethrift} -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator -import com.twitter.product_mixer.component_library.decorator.urt.UrtMultipleModulesDecorator -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptModuleGrouping -import com.twitter.product_mixer.component_library.decorator.urt.builder.flexible_injection_pipeline.FlipPromptUrtModuleBuilder -import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipCandidateFeatureTransformer -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.FlipQueryTransformer -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.PromptResultsTransformer -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam - -/** - * A dependent candidate pipeline for Flexible Injection Pipeline Candidates. - * Fetches prompts from FLIP (inside onboarding-task-service). - */ -class FlipPromptDependentCandidatePipelineConfig[ - Query <: PipelineQuery with HasFlipInjectionParams -]( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - promptCandidateSource: PromptCandidateSource) - extends DependentCandidatePipelineConfig[ - Query, - servicethrift.GetInjectionsRequest, - IntermediatePrompt, - BasePromptCandidate[Any] - ] { - - override val candidateSource: CandidateSource[GetInjectionsRequest, IntermediatePrompt] = - promptCandidateSource - - override val queryTransformer: CandidatePipelineQueryTransformer[Query, GetInjectionsRequest] = - FlipQueryTransformer - - override val resultTransformer: CandidatePipelineResultsTransformer[ - IntermediatePrompt, - BasePromptCandidate[Any] - ] = PromptResultsTransformer - - override val decorator: Option[ - CandidateDecorator[Query, BasePromptCandidate[Any]] - ] = Some( - UrtMultipleModulesDecorator( - urtItemCandidateDecorator = UrtItemCandidateDecorator(FlipPromptCandidateUrtItemBuilder()), - moduleBuilder = FlipPromptUrtModuleBuilder(), - groupByKey = FlipPromptModuleGrouping - )) - - override val featuresFromCandidateSourceTransformers: Seq[ - CandidateFeatureTransformer[IntermediatePrompt] - ] = Seq(FlipCandidateFeatureTransformer) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala deleted file mode 100644 index 87c5e080c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline - -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.PromptCandidateSource -import com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer.HasFlipInjectionParams -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FlipPromptDependentCandidatePipelineConfigBuilder @Inject() ( - promptCandidateSource: PromptCandidateSource) { - - /** - * Build a FlipPromptDependentCandidatePipelineConfig - * - * @note If injected classes are needed to populate parameters in this method, consider creating a - * ProductFlipPromptDependentCandidatePipelineConfigBuilder with a single `def build()` method. - * That product-specific builder class can then inject everything it needs (including this - * class), and delegate to this class's build() method within its own build() method. - */ - def build[Query <: PipelineQuery with HasFlipInjectionParams]( - identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("FlipPrompt"), - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - ): FlipPromptDependentCandidatePipelineConfig[Query] = { - new FlipPromptDependentCandidatePipelineConfig( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - promptCandidateSource = promptCandidateSource) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD deleted file mode 100644 index 5b4460cec..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "onboarding/service/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/flexible_injection_pipeline", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala deleted file mode 100644 index 78d0fa58a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer - -import com.twitter.onboarding.injections.{thriftscala => onboardingthrift} -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt -import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate -import com.twitter.product_mixer.component_library.model.candidate.PromptCarouselTileCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -case object FlipPromptCarouselTileFeature - extends Feature[PromptCarouselTileCandidate, Option[onboardingthrift.Tile]] - -case object FlipPromptInjectionsFeature - extends Feature[BasePromptCandidate[String], onboardingthrift.Injection] - -case object FlipPromptOffsetInModuleFeature - extends Feature[PromptCarouselTileCandidate, Option[Int]] - -object FlipCandidateFeatureTransformer extends CandidateFeatureTransformer[IntermediatePrompt] { - - override val identifier: TransformerIdentifier = TransformerIdentifier("FlipCandidateFeature") - - override val features: Set[Feature[_, _]] = - Set(FlipPromptInjectionsFeature, FlipPromptOffsetInModuleFeature, FlipPromptCarouselTileFeature) - - /** Hydrates a [[FeatureMap]] for a given [[Inputs]] */ - override def transform(input: IntermediatePrompt): FeatureMap = { - FeatureMapBuilder() - .add(FlipPromptInjectionsFeature, input.injection) - .add(FlipPromptOffsetInModuleFeature, input.offsetInModule) - .add(FlipPromptCarouselTileFeature, input.carouselTile) - .build() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala deleted file mode 100644 index bcb84f375..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer - -import com.twitter.onboarding.task.service.{thriftscala => flip} - -trait HasFlipInjectionParams { - def displayLocation: flip.DisplayLocation - def rankingDisablerWithLatestControlsAvailable: Option[Boolean] - def isEmptyState: Option[Boolean] - def isFirstRequestAfterSignup: Option[Boolean] - def isEndOfTimeline: Option[Boolean] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala deleted file mode 100644 index e80cfe2aa..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer - -import com.twitter.onboarding.task.service.thriftscala.PromptType -import com.twitter.onboarding.task.service.{thriftscala => flip} -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object FlipQueryTransformer - extends CandidatePipelineQueryTransformer[ - PipelineQuery with HasFlipInjectionParams, - flip.GetInjectionsRequest - ] { - - val SUPPORTED_PROMPT_TYPES: Set[PromptType] = Set( - PromptType.InlinePrompt, - PromptType.FullCover, - PromptType.HalfCover, - PromptType.TileCarousel, - PromptType.RelevancePrompt) - - override def transform( - query: PipelineQuery with HasFlipInjectionParams - ): flip.GetInjectionsRequest = { - val clientContext = flip.ClientContext( - userId = query.clientContext.userId, - guestId = query.clientContext.guestId, - clientApplicationId = query.clientContext.appId, - deviceId = query.clientContext.deviceId, - countryCode = query.clientContext.countryCode, - languageCode = query.clientContext.languageCode, - userAgent = query.clientContext.userAgent, - guestIdMarketing = query.clientContext.guestIdMarketing, - guestIdAds = query.clientContext.guestIdAds, - isInternalOrTwoffice = query.clientContext.isTwoffice, - ipAddress = query.clientContext.ipAddress - ) - val displayContext: flip.DisplayContext = - flip.DisplayContext( - displayLocation = query.displayLocation, - timelineId = query.clientContext.userId - ) - - val requestTargetingContext: flip.RequestTargetingContext = - flip.RequestTargetingContext( - rankingDisablerWithLatestControlsAvaliable = - query.rankingDisablerWithLatestControlsAvailable, - reactivePromptContext = None, - isEmptyState = query.isEmptyState, - isFirstRequestAfterSignup = query.isFirstRequestAfterSignup, - isEndOfTimeline = query.isEndOfTimeline - ) - - flip.GetInjectionsRequest( - clientContext = clientContext, - displayContext = displayContext, - requestTargetingContext = Some(requestTargetingContext), - userRoles = query.clientContext.userRoles, - timelineContext = None, - supportedPromptTypes = Some(SUPPORTED_PROMPT_TYPES) - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala deleted file mode 100644 index d195aa0f8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.flexible_injection_pipeline.transformer - -import com.twitter.onboarding.injections.{thriftscala => flipinjection} -import com.twitter.product_mixer.component_library.candidate_source.flexible_injection_pipeline.IntermediatePrompt -import com.twitter.product_mixer.component_library.model.candidate.BasePromptCandidate -import com.twitter.product_mixer.component_library.model.candidate.FullCoverPromptCandidate -import com.twitter.product_mixer.component_library.model.candidate.HalfCoverPromptCandidate -import com.twitter.product_mixer.component_library.model.candidate.InlinePromptCandidate -import com.twitter.product_mixer.component_library.model.candidate.PromptCarouselTileCandidate -import com.twitter.product_mixer.component_library.model.candidate.RelevancePromptCandidate -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller - -object PromptResultsTransformer - extends CandidatePipelineResultsTransformer[ - IntermediatePrompt, - BasePromptCandidate[Any] - ] { - - /** - * Transforms a Flip Injection to a Product Mixer domain object deriving from BasePromptCandidate. - * Supported injection types have to match those declared in com.twitter.product_mixer.component_library.transformer.flexible_injection_pipeline.FlipQueryTransformer#supportedPromptFormats - */ - override def transform(input: IntermediatePrompt): BasePromptCandidate[Any] = - input.injection match { - case inlinePrompt: flipinjection.Injection.InlinePrompt => - InlinePromptCandidate(id = inlinePrompt.inlinePrompt.injectionIdentifier - .getOrElse(throw new MissingInjectionId(input.injection))) - case _: flipinjection.Injection.FullCover => - FullCoverPromptCandidate(id = "0") - case _: flipinjection.Injection.HalfCover => - HalfCoverPromptCandidate(id = "0") - case _: flipinjection.Injection.TilesCarousel => - PromptCarouselTileCandidate(id = - input.offsetInModule.getOrElse(throw FlipPromptOffsetInModuleMissing)) - case relevancePrompt: flipinjection.Injection.RelevancePrompt => - RelevancePromptCandidate( - id = relevancePrompt.relevancePrompt.injectionIdentifier, - position = relevancePrompt.relevancePrompt.requestedPosition.map(_.toInt)) - case injection => throw new UnsupportedInjectionType(injection) - } -} - -class MissingInjectionId(injection: flipinjection.Injection) - extends IllegalArgumentException( - s"Injection identifier is missing ${TransportMarshaller.getSimpleName(injection.getClass)}") - -class UnsupportedInjectionType(injection: flipinjection.Injection) - extends UnsupportedOperationException( - s"Unsupported FLIP injection Type : ${TransportMarshaller.getSimpleName(injection.getClass)}") - -object FlipPromptOffsetInModuleMissing - extends NoSuchElementException( - "FlipPromptOffsetInModuleFeature must be set for the TilesCarousel FLIP injection in PromptCandidateSource") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel deleted file mode 100644 index 0146a3493..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.bazel +++ /dev/null @@ -1,20 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/account_recommendations_mixer", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/candidate_source/people_discovery", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "servo/repo/src/main/scala", - "src/thrift/com/twitter/hermit/internal:hermit-internal-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala deleted file mode 100644 index 8763389af..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.scala +++ /dev/null @@ -1,82 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.WhoToFollowModuleFooterFeature -import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.WhoToFollowModuleHeaderFeature -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemInModuleDecorator -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.user.UserCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.ClientEventInfoBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.StaticUrlBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.promoted.FeaturePromotedMetadataBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.social_context.WhoToFollowSocialContextBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.StrStatic -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleFooterBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleHeaderBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.TimelineModuleBuilder -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object WhoToFollowArmCandidateDecorator { - val ClientEventComponent = "suggest_who_to_follow" - val EntryNamespaceString = "who-to-follow" -} - -case class WhoToFollowArmCandidateDecorator[-Query <: PipelineQuery]( - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, UserCandidate] - ]) extends CandidateDecorator[Query, UserCandidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[UserCandidate]] - ): Stitch[Seq[Decoration]] = { - val clientEventDetailsBuilder = WhoToFollowClientEventDetailsBuilder(TrackingTokenFeature) - val clientEventInfoBuilder = ClientEventInfoBuilder[Query, UserCandidate]( - WhoToFollowArmCandidateDecorator.ClientEventComponent, - Some(clientEventDetailsBuilder)) - val promotedMetadataBuilder = FeaturePromotedMetadataBuilder(AdImpressionFeature) - val socialContextBuilder = - WhoToFollowSocialContextBuilder(SocialTextFeature, HermitContextTypeFeature) - val userItemBuilder = UserCandidateUrtItemBuilder( - clientEventInfoBuilder = clientEventInfoBuilder, - promotedMetadataBuilder = Some(promotedMetadataBuilder), - socialContextBuilder = Some(socialContextBuilder)) - val userItemDecorator = UrtItemCandidateDecorator(userItemBuilder) - - val whoToFollowModuleBuilder = { - val whoToFollowHeaderOpt = query.features.map(_.get(WhoToFollowModuleHeaderFeature)) - val whoToFollowFooterOpt = query.features.flatMap(_.get(WhoToFollowModuleFooterFeature)) - val whoToFollowModuleHeaderBuilder = whoToFollowHeaderOpt.flatMap(_.title).map { title => - ModuleHeaderBuilder(textBuilder = StrStatic(title), isSticky = Some(true)) - } - val whoToFollowModuleFooterBuilder = whoToFollowFooterOpt.flatMap(_.action).map { action => - ModuleFooterBuilder( - textBuilder = StrStatic(action.title), - urlBuilder = Some(StaticUrlBuilder(action.actionUrl, DeepLink))) - } - - TimelineModuleBuilder( - entryNamespace = EntryNamespace(WhoToFollowArmCandidateDecorator.EntryNamespaceString), - clientEventInfoBuilder = clientEventInfoBuilder, - displayTypeBuilder = moduleDisplayTypeBuilder, - headerBuilder = whoToFollowModuleHeaderBuilder, - footerBuilder = whoToFollowModuleFooterBuilder, - feedbackActionInfoBuilder = feedbackActionInfoBuilder, - ) - } - - UrtItemInModuleDecorator( - userItemDecorator, - whoToFollowModuleBuilder - ).apply(query, candidates) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala deleted file mode 100644 index d72241fd2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier - -object WhoToFollowArmCandidatePipelineConfig { - val MinCandidatesSize = 3 - val MaxCandidatesSize = 20 - - val identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("WhoToFollowArm") -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala deleted file mode 100644 index bfcf877ce..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.scala +++ /dev/null @@ -1,72 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.account_recommendations_mixer.{thriftscala => t} -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.marshaller.request.ClientContextMarshaller -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest -import com.twitter.timelines.configapi.Param - -object WhoToFollowArmCandidatePipelineQueryTransformer { - val HomeDisplayLocation = "timeline" - val HomeReverseChronDisplayLocation = "timeline_reverse_chron" - val ProfileDisplayLocation = "profile_timeline" -} - -case class WhoToFollowArmCandidatePipelineQueryTransformer[-Query <: PipelineQuery]( - displayLocationParam: Param[String], - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]], - profileUserIdFeature: Option[Feature[PipelineQuery, Long]]) - extends CandidatePipelineQueryTransformer[Query, t.AccountRecommendationsMixerRequest] { - - override def transform(input: Query): t.AccountRecommendationsMixerRequest = { - input.params(displayLocationParam) match { - case WhoToFollowArmCandidatePipelineQueryTransformer.HomeReverseChronDisplayLocation => - t.AccountRecommendationsMixerRequest( - clientContext = ClientContextMarshaller(input.clientContext), - product = t.Product.HomeReverseChronWhoToFollow, - productContext = Some( - t.ProductContext.HomeReverseChronWhoToFollowProductContext( - t.HomeReverseChronWhoToFollowProductContext( - wtfReactiveContext = Some(getWhoToFollowReactiveContext(input)) - ))) - ) - case WhoToFollowArmCandidatePipelineQueryTransformer.HomeDisplayLocation => - t.AccountRecommendationsMixerRequest( - clientContext = ClientContextMarshaller(input.clientContext), - product = t.Product.HomeWhoToFollow, - productContext = Some( - t.ProductContext.HomeWhoToFollowProductContext( - t.HomeWhoToFollowProductContext( - wtfReactiveContext = Some(getWhoToFollowReactiveContext(input)) - ))) - ) - case WhoToFollowArmCandidatePipelineQueryTransformer.ProfileDisplayLocation => - t.AccountRecommendationsMixerRequest( - clientContext = ClientContextMarshaller(input.clientContext), - product = t.Product.ProfileWhoToFollow, - productContext = Some( - t.ProductContext.ProfileWhoToFollowProductContext(t.ProfileWhoToFollowProductContext( - wtfReactiveContext = Some(getWhoToFollowReactiveContext(input)), - profileUserId = profileUserIdFeature - .flatMap(feature => input.features.map(_.get(feature))) - .getOrElse(throw PipelineFailure(BadRequest, "profileUserId not provided")), - ))) - ) - case displayLocation => - throw PipelineFailure(BadRequest, s"display location $displayLocation not supported") - } - } - - private def getWhoToFollowReactiveContext( - input: Query - ): t.WhoToFollowReactiveContext = { - t.WhoToFollowReactiveContext( - excludedUserIds = excludedUserIdsFeature.flatMap(feature => - input.features - .map(_.get(feature))), - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala deleted file mode 100644 index f1e7b3ca7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.scala +++ /dev/null @@ -1,76 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.account_recommendations_mixer.{thriftscala => t} -import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.AccountRecommendationsMixerCandidateSource -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.decider.DeciderParam - -class WhoToFollowArmDependentCandidatePipelineConfig[Query <: PipelineQuery]( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - override val alerts: Seq[Alert], - override val gates: Seq[BaseGate[Query]], - accountRecommendationsMixerCandidateSource: AccountRecommendationsMixerCandidateSource, - override val filters: Seq[Filter[Query, UserCandidate]], - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[PipelineQuery, UserCandidate] - ], - displayLocationParam: Param[String], - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]], - profileUserIdFeature: Option[Feature[PipelineQuery, Long]]) - extends DependentCandidatePipelineConfig[ - Query, - t.AccountRecommendationsMixerRequest, - t.RecommendedUser, - UserCandidate - ] { - - override val candidateSource: BaseCandidateSource[ - t.AccountRecommendationsMixerRequest, - t.RecommendedUser - ] = - accountRecommendationsMixerCandidateSource - - override val queryTransformer: CandidatePipelineQueryTransformer[ - PipelineQuery, - t.AccountRecommendationsMixerRequest - ] = WhoToFollowArmCandidatePipelineQueryTransformer( - displayLocationParam = displayLocationParam, - excludedUserIdsFeature = excludedUserIdsFeature, - profileUserIdFeature = profileUserIdFeature - ) - - override val featuresFromCandidateSourceTransformers: Seq[ - CandidateFeatureTransformer[t.RecommendedUser] - ] = Seq(WhoToFollowArmResponseFeatureTransformer) - - override val resultTransformer: CandidatePipelineResultsTransformer[ - t.RecommendedUser, - UserCandidate - ] = { user => UserCandidate(user.userId) } - - override val decorator: Option[CandidateDecorator[Query, UserCandidate]] = - Some( - WhoToFollowArmCandidateDecorator( - moduleDisplayTypeBuilder, - feedbackActionInfoBuilder - )) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala deleted file mode 100644 index 91eb9b1bf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.product_mixer.component_library.candidate_source.account_recommendations_mixer.AccountRecommendationsMixerCandidateSource -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.configapi.StaticParam -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class WhoToFollowArmDependentCandidatePipelineConfigBuilder @Inject() ( - accountRecommendationsMixerCandidateSource: AccountRecommendationsMixerCandidateSource) { - - /** - * Build a WhoToFollowArmDependentCandidatePipelineConfig - * - * - * To create a regular CandidatePipelineConfig instead see [[WhoToFollowArmCandidatePipelineConfigBuilder]]. - * - * @note If injected classes are needed to populate parameters in this method, consider creating a - * ProductWhoToFollowCandidatePipelineConfigBuilder with a single `def build()` method. That - * product-specific builder class can then inject everything it needs (including this class), - * and delegate to this class's build() method within its own build() method. - */ - def build[Query <: PipelineQuery]( - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - identifier: CandidatePipelineIdentifier = WhoToFollowArmCandidatePipelineConfig.identifier, - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - alerts: Seq[Alert] = Seq.empty, - gates: Seq[BaseGate[Query]] = Seq.empty, - filters: Seq[Filter[Query, UserCandidate]] = Seq.empty, - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[ - PipelineQuery, - UserCandidate - ]] = None, - displayLocationParam: Param[String] = - StaticParam(WhoToFollowArmCandidatePipelineQueryTransformer.HomeDisplayLocation), - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]], - profileUserIdFeature: Option[Feature[PipelineQuery, Long]] - ): WhoToFollowArmDependentCandidatePipelineConfig[Query] = - new WhoToFollowArmDependentCandidatePipelineConfig( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - alerts = alerts, - gates = gates, - accountRecommendationsMixerCandidateSource = accountRecommendationsMixerCandidateSource, - filters = filters, - moduleDisplayTypeBuilder = moduleDisplayTypeBuilder, - feedbackActionInfoBuilder = feedbackActionInfoBuilder, - displayLocationParam = displayLocationParam, - excludedUserIdsFeature = excludedUserIdsFeature, - profileUserIdFeature = profileUserIdFeature - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala deleted file mode 100644 index 4ee90a4bf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.hermit.{thriftscala => h} -import com.twitter.account_recommendations_mixer.{thriftscala => t} -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -object ContextTypeFeature extends Feature[UserCandidate, Option[t.ContextType]] - -object WhoToFollowArmResponseFeatureTransformer - extends CandidateFeatureTransformer[t.RecommendedUser] { - - override val identifier: TransformerIdentifier = TransformerIdentifier("WhoToFollowArmResponse") - - override val features: Set[Feature[_, _]] = - Set( - AdImpressionFeature, - ContextTypeFeature, - HermitContextTypeFeature, - SocialTextFeature, - TrackingTokenFeature, - ScoreFeature) - - override def transform(input: t.RecommendedUser): FeatureMap = FeatureMapBuilder() - .add(AdImpressionFeature, input.adImpression) - .add(ContextTypeFeature, input.contextType) - .add( - HermitContextTypeFeature, - input.contextType.map(contextType => h.ContextType(contextType.value))) - .add(SocialTextFeature, input.socialText) - .add(TrackingTokenFeature, input.trackingToken) - .add(ScoreFeature, input.mlPredictionScore) - .build() -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala deleted file mode 100644 index 763c860d0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.scala +++ /dev/null @@ -1,89 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.product_mixer.component_library.candidate_source.people_discovery.WhoToFollowModuleHeaderFeature -import com.twitter.product_mixer.component_library.candidate_source.people_discovery.WhoToFollowModuleShowMoreFeature -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemCandidateDecorator -import com.twitter.product_mixer.component_library.decorator.urt.UrtItemInModuleDecorator -import com.twitter.product_mixer.component_library.decorator.urt.builder.item.user.UserCandidateUrtItemBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.ClientEventInfoBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.metadata.StaticUrlBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.promoted.FeaturePromotedMetadataBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.social_context.WhoToFollowSocialContextBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.stringcenter.StrStatic -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleDynamicShowMoreBehaviorRevealByCountBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleFooterBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleHeaderBuilder -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.TimelineModuleBuilder -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -object WhoToFollowCandidateDecorator { - val ClientEventComponent = "suggest_who_to_follow" - val EntryNamespaceString = "who-to-follow" -} - -case class WhoToFollowCandidateDecorator[-Query <: PipelineQuery]( - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[Query, UserCandidate] - ]) extends CandidateDecorator[Query, UserCandidate] { - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[UserCandidate]] - ): Stitch[Seq[Decoration]] = { - val clientEventDetailsBuilder = WhoToFollowClientEventDetailsBuilder(TrackingTokenFeature) - val clientEventInfoBuilder = ClientEventInfoBuilder[Query, UserCandidate]( - WhoToFollowCandidateDecorator.ClientEventComponent, - Some(clientEventDetailsBuilder)) - val promotedMetadataBuilder = FeaturePromotedMetadataBuilder(AdImpressionFeature) - val socialContextBuilder = - WhoToFollowSocialContextBuilder(SocialTextFeature, HermitContextTypeFeature) - val userItemBuilder = UserCandidateUrtItemBuilder( - clientEventInfoBuilder = clientEventInfoBuilder, - promotedMetadataBuilder = Some(promotedMetadataBuilder), - socialContextBuilder = Some(socialContextBuilder)) - val userItemDecorator = UrtItemCandidateDecorator(userItemBuilder) - - val whoToFollowModuleBuilder = { - val whoToFollowHeaderOpt = query.features.map(_.get(WhoToFollowModuleHeaderFeature)) - val whoToFollowModuleHeaderBuilder = whoToFollowHeaderOpt.flatMap(_.title).map { title => - ModuleHeaderBuilder(textBuilder = StrStatic(title.text), isSticky = Some(true)) - } - val whoToFollowModuleFooterBuilder = whoToFollowHeaderOpt.flatMap(_.action).map { action => - ModuleFooterBuilder( - textBuilder = StrStatic(action.title), - urlBuilder = Some(StaticUrlBuilder(action.actionUrl, DeepLink))) - } - val showMoreBehaviorBuilder = - query.features.flatMap(_.get(WhoToFollowModuleShowMoreFeature)).map { showMore => - ModuleDynamicShowMoreBehaviorRevealByCountBuilder( - showMore.initialToShow, - showMore.extraToShow) - } - - TimelineModuleBuilder( - entryNamespace = EntryNamespace(WhoToFollowCandidateDecorator.EntryNamespaceString), - clientEventInfoBuilder = clientEventInfoBuilder, - displayTypeBuilder = moduleDisplayTypeBuilder, - headerBuilder = whoToFollowModuleHeaderBuilder, - footerBuilder = whoToFollowModuleFooterBuilder, - feedbackActionInfoBuilder = feedbackActionInfoBuilder, - showMoreBehaviorBuilder = showMoreBehaviorBuilder - ) - } - - UrtItemInModuleDecorator( - userItemDecorator, - whoToFollowModuleBuilder - ).apply(query, candidates) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala deleted file mode 100644 index 55888e38d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.scala +++ /dev/null @@ -1,77 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.peoplediscovery.api.{thriftscala => t} -import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.decider.DeciderParam - -object WhoToFollowCandidatePipelineConfig { - val MinCandidatesSize = 3 - val MaxCandidatesSize = 20 - - val identifier: CandidatePipelineIdentifier = CandidatePipelineIdentifier("WhoToFollow") -} - -class WhoToFollowCandidatePipelineConfig[Query <: PipelineQuery]( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - override val alerts: Seq[Alert], - override val gates: Seq[Gate[Query]], - whoToFollowCandidateSource: PeopleDiscoveryCandidateSource, - override val filters: Seq[Filter[Query, UserCandidate]], - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[PipelineQuery, UserCandidate] - ], - displayLocationParam: Param[String], - supportedLayoutsParam: Param[Seq[String]], - layoutVersionParam: Param[Int], - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]], -) extends CandidatePipelineConfig[ - Query, - t.GetModuleRequest, - t.RecommendedUser, - UserCandidate - ] { - - override val candidateSource: BaseCandidateSource[t.GetModuleRequest, t.RecommendedUser] = - whoToFollowCandidateSource - - override val queryTransformer: CandidatePipelineQueryTransformer[ - PipelineQuery, - t.GetModuleRequest - ] = WhoToFollowCandidatePipelineQueryTransformer( - displayLocationParam, - supportedLayoutsParam, - layoutVersionParam, - excludedUserIdsFeature) - - override val featuresFromCandidateSourceTransformers: Seq[ - CandidateFeatureTransformer[t.RecommendedUser] - ] = Seq(WhoToFollowResponseFeatureTransformer) - - override val resultTransformer: CandidatePipelineResultsTransformer[ - t.RecommendedUser, - UserCandidate - ] = { user => UserCandidate(user.userId) } - - override val decorator: Option[CandidateDecorator[Query, UserCandidate]] = - Some(WhoToFollowCandidateDecorator(moduleDisplayTypeBuilder, feedbackActionInfoBuilder)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala deleted file mode 100644 index 5c50bbb85..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,69 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.configapi.StaticParam -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class WhoToFollowCandidatePipelineConfigBuilder @Inject() ( - whoToFollowCandidateSource: PeopleDiscoveryCandidateSource) { - - /** - * Build a WhoToFollowCandidatePipelineConfig - * - * To create a DependentCandidatePipelineConfig instead see [[WhoToFollowDependentCandidatePipelineConfigBuilder]]. - * - * @note If injected classes are needed to populate parameters in this method, consider creating a - * ProductWhoToFollowCandidatePipelineConfigBuilder with a single `def build()` method. That - * product-specific builder class can then inject everything it needs (including this class), - * and delegate to this class's build() method within its own build() method. - */ - def build[Query <: PipelineQuery]( - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - identifier: CandidatePipelineIdentifier = WhoToFollowCandidatePipelineConfig.identifier, - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - alerts: Seq[Alert] = Seq.empty, - gates: Seq[Gate[Query]] = Seq.empty, - filters: Seq[Filter[Query, UserCandidate]] = Seq.empty, - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[ - PipelineQuery, - UserCandidate - ]] = None, - displayLocationParam: Param[String] = - StaticParam(WhoToFollowCandidatePipelineQueryTransformer.DisplayLocation), - supportedLayoutsParam: Param[Seq[String]] = - StaticParam(WhoToFollowCandidatePipelineQueryTransformer.SupportedLayouts), - layoutVersionParam: Param[Int] = - StaticParam(WhoToFollowCandidatePipelineQueryTransformer.LayoutVersion), - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]] = None, - ): WhoToFollowCandidatePipelineConfig[Query] = - new WhoToFollowCandidatePipelineConfig( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - alerts = alerts, - gates = gates, - moduleDisplayTypeBuilder = moduleDisplayTypeBuilder, - whoToFollowCandidateSource = whoToFollowCandidateSource, - filters = filters, - feedbackActionInfoBuilder = feedbackActionInfoBuilder, - displayLocationParam = displayLocationParam, - supportedLayoutsParam = supportedLayoutsParam, - layoutVersionParam = layoutVersionParam, - excludedUserIdsFeature = excludedUserIdsFeature - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala deleted file mode 100644 index f4ba0558f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.peoplediscovery.api.thriftscala.ClientContext -import com.twitter.peoplediscovery.api.thriftscala.GetModuleRequest -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -object WhoToFollowCandidatePipelineQueryTransformer { - val DisplayLocation = "timeline" - val SupportedLayouts = Seq("user-bio-list") - val LayoutVersion = 2 -} - -case class WhoToFollowCandidatePipelineQueryTransformer[-Query <: PipelineQuery]( - displayLocationParam: Param[String], - supportedLayoutsParam: Param[Seq[String]], - layoutVersionParam: Param[Int], - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]], -) extends CandidatePipelineQueryTransformer[Query, GetModuleRequest] { - - override def transform(input: Query): GetModuleRequest = - GetModuleRequest( - clientContext = ClientContext( - userId = input.getRequiredUserId, - deviceId = input.clientContext.deviceId, - userAgent = input.clientContext.userAgent, - countryCode = input.clientContext.countryCode, - languageCode = input.clientContext.languageCode, - ), - displayLocation = input.params(displayLocationParam), - supportedLayouts = input.params(supportedLayoutsParam), - layoutVersion = input.params(layoutVersionParam), - excludedUserIds = - excludedUserIdsFeature.flatMap(feature => input.features.map(_.get(feature))), - includePromoted = Some(true), - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala deleted file mode 100644 index a8c673a57..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.bijection.scrooge.BinaryScalaCodec -import com.twitter.bijection.Base64String -import com.twitter.bijection.{Injection => Serializer} -import com.twitter.hermit.internal.thriftscala.HermitTrackingToken -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseClientEventDetailsBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails -import com.twitter.servo.cache.ThriftSerializer -import com.twitter.suggests.controller_data.thriftscala.ControllerData -import com.twitter.util.Try -import org.apache.thrift.protocol.TBinaryProtocol - -object WhoToFollowClientEventDetailsBuilder { - - val InjectionType = "WhoToFollow" - - private implicit val ByteSerializer: Serializer[ControllerData, Array[Byte]] = - BinaryScalaCodec(ControllerData) - - private val TrackingTokenSerializer = - new ThriftSerializer[HermitTrackingToken](HermitTrackingToken, new TBinaryProtocol.Factory()) - - val ControllerDataSerializer: Serializer[ControllerData, String] = - Serializer.connect[ControllerData, Array[Byte], Base64String, String] - - def deserializeTrackingToken(token: Option[String]): Option[HermitTrackingToken] = - token.flatMap(t => Try(TrackingTokenSerializer.fromString(t)).toOption) - - def serializeControllerData(cd: ControllerData): String = ControllerDataSerializer(cd) -} - -case class WhoToFollowClientEventDetailsBuilder[-Query <: PipelineQuery]( - trackingTokenFeature: Feature[_, Option[String]], -) extends BaseClientEventDetailsBuilder[Query, UserCandidate] { - - override def apply( - query: Query, - candidate: UserCandidate, - candidateFeatures: FeatureMap - ): Option[ClientEventDetails] = { - val serializedTrackingToken = candidateFeatures.getOrElse(trackingTokenFeature, None) - - val controllerData = WhoToFollowClientEventDetailsBuilder - .deserializeTrackingToken(serializedTrackingToken) - .flatMap(_.controllerData) - .map(WhoToFollowClientEventDetailsBuilder.serializeControllerData) - - Some( - ClientEventDetails( - conversationDetails = None, - timelinesDetails = Some( - TimelinesDetails( - injectionType = Some(WhoToFollowClientEventDetailsBuilder.InjectionType), - controllerData = controllerData, - sourceData = serializedTrackingToken)), - articleDetails = None, - liveEventDetails = None, - commerceDetails = None - )) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala deleted file mode 100644 index 26915ceca..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.peoplediscovery.api.{thriftscala => t} -import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.decider.DeciderParam - -class WhoToFollowDependentCandidatePipelineConfig[Query <: PipelineQuery]( - override val identifier: CandidatePipelineIdentifier, - override val enabledDeciderParam: Option[DeciderParam[Boolean]], - override val supportedClientParam: Option[FSParam[Boolean]], - override val alerts: Seq[Alert], - override val gates: Seq[BaseGate[Query]], - whoToFollowCandidateSource: PeopleDiscoveryCandidateSource, - override val filters: Seq[Filter[Query, UserCandidate]], - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - feedbackActionInfoBuilder: Option[ - BaseFeedbackActionInfoBuilder[PipelineQuery, UserCandidate] - ], - displayLocationParam: Param[String], - supportedLayoutsParam: Param[Seq[String]], - layoutVersionParam: Param[Int], - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]]) - extends DependentCandidatePipelineConfig[ - Query, - t.GetModuleRequest, - t.RecommendedUser, - UserCandidate - ] { - - override val candidateSource: BaseCandidateSource[t.GetModuleRequest, t.RecommendedUser] = - whoToFollowCandidateSource - - override val queryTransformer: CandidatePipelineQueryTransformer[ - PipelineQuery, - t.GetModuleRequest - ] = WhoToFollowCandidatePipelineQueryTransformer( - displayLocationParam = displayLocationParam, - supportedLayoutsParam = supportedLayoutsParam, - layoutVersionParam = layoutVersionParam, - excludedUserIdsFeature = excludedUserIdsFeature - ) - - override val featuresFromCandidateSourceTransformers: Seq[ - CandidateFeatureTransformer[t.RecommendedUser] - ] = Seq(WhoToFollowResponseFeatureTransformer) - - override val resultTransformer: CandidatePipelineResultsTransformer[ - t.RecommendedUser, - UserCandidate - ] = { user => UserCandidate(user.userId) } - - override val decorator: Option[CandidateDecorator[Query, UserCandidate]] = - Some( - WhoToFollowCandidateDecorator( - moduleDisplayTypeBuilder, - feedbackActionInfoBuilder - )) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala deleted file mode 100644 index 8d95bb14b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.product_mixer.component_library.candidate_source.people_discovery.PeopleDiscoveryCandidateSource -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.configapi.StaticParam -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata.BaseFeedbackActionInfoBuilder -import com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module.BaseModuleDisplayTypeBuilder -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.Param -import com.twitter.timelines.configapi.decider.DeciderParam -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class WhoToFollowDependentCandidatePipelineConfigBuilder @Inject() ( - whoToFollowCandidateSource: PeopleDiscoveryCandidateSource) { - - /** - * Build a WhoToFollowDependentCandidatePipelineConfig - * - * - * To create a regular CandidatePipelineConfig instead see [[WhoToFollowCandidatePipelineConfigBuilder]]. - * - * @note If injected classes are needed to populate parameters in this method, consider creating a - * ProductWhoToFollowCandidatePipelineConfigBuilder with a single `def build()` method. That - * product-specific builder class can then inject everything it needs (including this class), - * and delegate to this class's build() method within its own build() method. - */ - def build[Query <: PipelineQuery]( - moduleDisplayTypeBuilder: BaseModuleDisplayTypeBuilder[Query, UserCandidate], - identifier: CandidatePipelineIdentifier = WhoToFollowCandidatePipelineConfig.identifier, - enabledDeciderParam: Option[DeciderParam[Boolean]] = None, - supportedClientParam: Option[FSParam[Boolean]] = None, - alerts: Seq[Alert] = Seq.empty, - gates: Seq[BaseGate[Query]] = Seq.empty, - filters: Seq[Filter[Query, UserCandidate]] = Seq.empty, - feedbackActionInfoBuilder: Option[BaseFeedbackActionInfoBuilder[ - PipelineQuery, - UserCandidate - ]] = None, - displayLocationParam: Param[String] = - StaticParam(WhoToFollowCandidatePipelineQueryTransformer.DisplayLocation), - supportedLayoutsParam: Param[Seq[String]] = - StaticParam(WhoToFollowCandidatePipelineQueryTransformer.SupportedLayouts), - layoutVersionParam: Param[Int] = - StaticParam(WhoToFollowCandidatePipelineQueryTransformer.LayoutVersion), - excludedUserIdsFeature: Option[Feature[PipelineQuery, Seq[Long]]] = None, - ): WhoToFollowDependentCandidatePipelineConfig[Query] = - new WhoToFollowDependentCandidatePipelineConfig( - identifier = identifier, - enabledDeciderParam = enabledDeciderParam, - supportedClientParam = supportedClientParam, - alerts = alerts, - gates = gates, - whoToFollowCandidateSource = whoToFollowCandidateSource, - filters = filters, - moduleDisplayTypeBuilder = moduleDisplayTypeBuilder, - feedbackActionInfoBuilder = feedbackActionInfoBuilder, - displayLocationParam = displayLocationParam, - supportedLayoutsParam = supportedLayoutsParam, - layoutVersionParam = layoutVersionParam, - excludedUserIdsFeature = excludedUserIdsFeature - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala deleted file mode 100644 index 96cb68f1a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.pipeline.candidate.who_to_follow_module - -import com.twitter.adserver.{thriftscala => ad} -import com.twitter.hermit.{thriftscala => h} -import com.twitter.peoplediscovery.api.{thriftscala => t} -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -object AdImpressionFeature extends Feature[UserCandidate, Option[ad.AdImpression]] -object HermitContextTypeFeature extends Feature[UserCandidate, Option[h.ContextType]] -object SocialTextFeature extends Feature[UserCandidate, Option[String]] -object TrackingTokenFeature extends Feature[UserCandidate, Option[String]] -object ScoreFeature extends Feature[UserCandidate, Option[Double]] - -object WhoToFollowResponseFeatureTransformer - extends CandidateFeatureTransformer[t.RecommendedUser] { - - override val identifier: TransformerIdentifier = TransformerIdentifier("WhoToFollowResponse") - - override val features: Set[Feature[_, _]] = - Set( - AdImpressionFeature, - HermitContextTypeFeature, - SocialTextFeature, - TrackingTokenFeature, - ScoreFeature) - - override def transform(input: t.RecommendedUser): FeatureMap = FeatureMapBuilder() - .add(AdImpressionFeature, input.adImpression) - .add(HermitContextTypeFeature, input.reason.flatMap(_.contextType)) - .add(SocialTextFeature, input.socialText) - .add(TrackingTokenFeature, input.trackingToken) - .add(ScoreFeature, input.mlPredictionScore) - .build() -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD deleted file mode 100644 index f2f85ac92..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "scrooge/scrooge-serializer/src/main/scala", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "scrooge/scrooge-serializer/src/main/scala", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala deleted file mode 100644 index d8906520a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.scala +++ /dev/null @@ -1,149 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.cursor - -import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor -import com.twitter.product_mixer.component_library.model.cursor.PassThroughCursor -import com.twitter.product_mixer.component_library.model.cursor.UnorderedBloomFilterCursor -import com.twitter.product_mixer.component_library.model.cursor.UnorderedExcludeIdsCursor -import com.twitter.product_mixer.component_library.{thriftscala => t} -import com.twitter.product_mixer.core.pipeline.PipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MalformedCursor -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.scrooge.BinaryThriftStructSerializer -import com.twitter.scrooge.ThriftStructCodec -import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilterSerializer -import com.twitter.util.Base64UrlSafeStringEncoder -import com.twitter.util.StringEncoder -import com.twitter.product_mixer.core.functional_component.marshaller.response.slice.CursorTypeMarshaller - -/** - * Handles serialization and deserialization for all supported generic cursors. Note that generic - * cursors may be used for Slices or any bespoke marshalling format. - */ -object CursorSerializer extends PipelineCursorSerializer[PipelineCursor] { - - private[cursor] val CursorThriftSerializer: BinaryThriftStructSerializer[ - t.ProductMixerRequestCursor - ] = - new BinaryThriftStructSerializer[t.ProductMixerRequestCursor] { - override def codec: ThriftStructCodec[t.ProductMixerRequestCursor] = - t.ProductMixerRequestCursor - override def encoder: StringEncoder = Base64UrlSafeStringEncoder - } - - override def serializeCursor(cursor: PipelineCursor): String = - cursor match { - case OrderedCursor(id, cursorType, gapBoundaryId) => - val cursorTypeMarshaller = new CursorTypeMarshaller() - val thriftCursor = t.ProductMixerRequestCursor.OrderedCursor( - t.OrderedCursor( - id = id, - cursorType = cursorType.map(cursorTypeMarshaller.apply), - gapBoundaryId)) - - CursorThriftSerializer.toString(thriftCursor) - case UnorderedExcludeIdsCursor(excludedIds) => - val thriftCursor = t.ProductMixerRequestCursor.UnorderedExcludeIdsCursor( - t.UnorderedExcludeIdsCursor(excludedIds = Some(excludedIds))) - - CursorThriftSerializer.toString(thriftCursor) - case UnorderedBloomFilterCursor(longIntBloomFilter) => - val thriftCursor = t.ProductMixerRequestCursor.UnorderedBloomFilterCursor( - t.UnorderedBloomFilterCursor( - serializedLongIntBloomFilter = - AdaptiveLongIntBloomFilterSerializer.serialize(longIntBloomFilter) - )) - - CursorThriftSerializer.toString(thriftCursor) - case PassThroughCursor(cursorValue, cursorType) => - val cursorTypeMarshaller = new CursorTypeMarshaller() - val thriftCursor = t.ProductMixerRequestCursor.PassThroughCursor( - t.PassThroughCursor( - cursorValue = cursorValue, - cursorType = cursorType.map(cursorTypeMarshaller.apply) - )) - - CursorThriftSerializer.toString(thriftCursor) - case _ => - throw PipelineFailure(IllegalStateFailure, "Unknown cursor type") - } - - def deserializeOrderedCursor(cursorString: String): Option[OrderedCursor] = - deserializeCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor - .OrderedCursor(t.OrderedCursor(id, cursorType, gapBoundaryId))) => - val cursorTypeMarshaller = new CursorTypeMarshaller() - Some( - OrderedCursor( - id = id, - cursorType = cursorType.map(cursorTypeMarshaller.unmarshall), - gapBoundaryId)) - } - ) - - def deserializeUnorderedExcludeIdsCursor( - cursorString: String - ): Option[UnorderedExcludeIdsCursor] = { - deserializeCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor - .UnorderedExcludeIdsCursor(t.UnorderedExcludeIdsCursor(excludedIdsOpt))) => - Some(UnorderedExcludeIdsCursor(excludedIds = excludedIdsOpt.getOrElse(Seq.empty))) - } - ) - } - - def deserializeUnorderedBloomFilterCursor( - cursorString: String - ): Option[UnorderedBloomFilterCursor] = - deserializeCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor.UnorderedBloomFilterCursor( - t.UnorderedBloomFilterCursor(serializedLongIntBloomFilter))) => - val bloomFilter = AdaptiveLongIntBloomFilterSerializer - .deserialize(serializedLongIntBloomFilter).getOrElse( - throw PipelineFailure( - MalformedCursor, - s"Failed to deserialize UnorderedBloomFilterCursor from cursor string: $cursorString") - ) - - Some(UnorderedBloomFilterCursor(longIntBloomFilter = bloomFilter)) - } - ) - - def deserializePassThroughCursor(cursorString: String): Option[PassThroughCursor] = - deserializeCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor - .PassThroughCursor(t.PassThroughCursor(cursorValue, cursorType))) => - val cursorTypeMarshaller = new CursorTypeMarshaller() - Some( - PassThroughCursor( - cursorValue = cursorValue, - cursorType = cursorType.map(cursorTypeMarshaller.unmarshall))) - } - ) - - // Note that the "A" type of the PartialFunction cannot be inferred due to the thrift type not - // being present on the PipelineCursorSerializer trait. By using this private def with the - // deserializePf type declared, it can be inferred. - private def deserializeCursor[Cursor <: PipelineCursor]( - cursorString: String, - deserializePf: PartialFunction[Option[t.ProductMixerRequestCursor], Option[Cursor]] - ): Option[Cursor] = - PipelineCursorSerializer.deserializeCursor( - cursorString, - CursorThriftSerializer, - deserializePf - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala deleted file mode 100644 index 18c9f48a5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.scala +++ /dev/null @@ -1,161 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.cursor - -import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor -import com.twitter.product_mixer.component_library.model.cursor.UrtPassThroughCursor -import com.twitter.product_mixer.component_library.model.cursor.UrtPlaceholderCursor -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedBloomFilterCursor -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer.CursorThriftSerializer -import com.twitter.product_mixer.component_library.{thriftscala => t} -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer.deserializeCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MalformedCursor -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilterSerializer -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorTypeMarshaller - -/** - * Handles serialization and deserialization for all supported URT cursors - */ -object UrtCursorSerializer extends PipelineCursorSerializer[UrtPipelineCursor] { - - val SerializedUrtPlaceholderCursor = CursorThriftSerializer.toString( - t.ProductMixerRequestCursor.UrtPlaceholderCursor(t.UrtPlaceholderCursor())) - - val cursorTypeMarshaller = new CursorTypeMarshaller() - - override def serializeCursor(cursor: UrtPipelineCursor): String = - cursor match { - case UrtOrderedCursor(initialSortIndex, id, cursorType, gapBoundaryId) => - val thriftCursor = t.ProductMixerRequestCursor.UrtOrderedCursor( - t.UrtOrderedCursor( - initialSortIndex = initialSortIndex, - id = id, - cursorType.map(cursorTypeMarshaller.apply), - gapBoundaryId = gapBoundaryId)) - - CursorThriftSerializer.toString(thriftCursor) - case UrtUnorderedExcludeIdsCursor(initialSortIndex, excludedIds) => - val thriftCursor = t.ProductMixerRequestCursor.UrtUnorderedExcludeIdsCursor( - t.UrtUnorderedExcludeIdsCursor( - initialSortIndex = initialSortIndex, - excludedIds = Some(excludedIds))) - - CursorThriftSerializer.toString(thriftCursor) - case UrtUnorderedBloomFilterCursor(initialSortIndex, longIntBloomFilter) => - val thriftCursor = t.ProductMixerRequestCursor.UrtUnorderedBloomFilterCursor( - t.UrtUnorderedBloomFilterCursor( - initialSortIndex = initialSortIndex, - serializedLongIntBloomFilter = - AdaptiveLongIntBloomFilterSerializer.serialize(longIntBloomFilter) - )) - - CursorThriftSerializer.toString(thriftCursor) - case UrtPassThroughCursor(initialSortIndex, cursorValue, cursorType) => - val thriftCursor = t.ProductMixerRequestCursor.UrtPassThroughCursor( - t.UrtPassThroughCursor( - initialSortIndex = initialSortIndex, - cursorValue = cursorValue, - cursorType = cursorType.map(cursorTypeMarshaller.apply) - )) - - CursorThriftSerializer.toString(thriftCursor) - case UrtPlaceholderCursor() => - SerializedUrtPlaceholderCursor - case _ => - throw PipelineFailure(IllegalStateFailure, "Unknown cursor type") - } - - def deserializeOrderedCursor(cursorString: String): Option[UrtOrderedCursor] = { - deserializeUrtCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor.UrtOrderedCursor( - t.UrtOrderedCursor(initialSortIndex, id, cursorType, gapBoundaryId))) => - Some( - UrtOrderedCursor( - initialSortIndex = initialSortIndex, - id = id, - cursorType = cursorType.map(cursorTypeMarshaller.unmarshall), - gapBoundaryId)) - } - ) - } - - def deserializeUnorderedExcludeIdsCursor( - cursorString: String - ): Option[UrtUnorderedExcludeIdsCursor] = { - deserializeUrtCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor.UrtUnorderedExcludeIdsCursor( - t.UrtUnorderedExcludeIdsCursor(initialSortIndex, excludedIdsOpt))) => - Some( - UrtUnorderedExcludeIdsCursor( - initialSortIndex = initialSortIndex, - excludedIds = excludedIdsOpt.getOrElse(Seq.empty))) - } - ) - } - - def deserializeUnorderedBloomFilterCursor( - cursorString: String - ): Option[UrtUnorderedBloomFilterCursor] = { - deserializeUrtCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor.UrtUnorderedBloomFilterCursor( - t.UrtUnorderedBloomFilterCursor(initialSortIndex, serializedLongIntBloomFilter))) => - val longIntBloomFilter = AdaptiveLongIntBloomFilterSerializer - .deserialize(serializedLongIntBloomFilter).getOrElse( - throw PipelineFailure( - MalformedCursor, - s"Failed to deserialize UrtUnorderedBloomFilterCursor from cursor string: $cursorString") - ) - - Some( - UrtUnorderedBloomFilterCursor( - initialSortIndex = initialSortIndex, - longIntBloomFilter = longIntBloomFilter)) - } - ) - } - - def deserializePassThroughCursor(cursorString: String): Option[UrtPassThroughCursor] = { - deserializeUrtCursor( - cursorString, - { - case Some( - t.ProductMixerRequestCursor - .UrtPassThroughCursor( - t.UrtPassThroughCursor(initialSortIndex, cursorValue, cursorType))) => - Some( - UrtPassThroughCursor( - initialSortIndex = initialSortIndex, - cursorValue = cursorValue, - cursorType = cursorType.map(cursorTypeMarshaller.unmarshall))) - } - ) - } - - private def deserializeUrtCursor[Cursor <: PipelineCursor]( - cursorString: String, - deserializePf: PartialFunction[Option[t.ProductMixerRequestCursor], Option[Cursor]] - ): Option[Cursor] = { - deserializeCursor[t.ProductMixerRequestCursor, Cursor]( - cursorString, - CursorThriftSerializer, - deserializePf orElse { - case Some(t.ProductMixerRequestCursor.UrtPlaceholderCursor(t.UrtPlaceholderCursor())) => - // Treat submitted placeholder cursor like an initial page load - None - }, - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD deleted file mode 100644 index 87f51350d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala deleted file mode 100644 index a53f410b2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.scala +++ /dev/null @@ -1,96 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice - -import com.twitter.product_mixer.component_library.model.candidate._ -import com.twitter.product_mixer.component_library.model.candidate.hubble.AdCreativeCandidate -import com.twitter.product_mixer.component_library.model.candidate.hubble.AdGroupCandidate -import com.twitter.product_mixer.component_library.model.candidate.hubble.AdUnitCandidate -import com.twitter.product_mixer.component_library.model.candidate.hubble.CampaignCandidate -import com.twitter.product_mixer.component_library.model.candidate.hubble.FundingSourceCandidate -import com.twitter.product_mixer.component_library.model.candidate.suggestion.QuerySuggestionCandidate -import com.twitter.product_mixer.component_library.model.candidate.suggestion.TypeaheadEventCandidate -import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceBuilder -import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceCursorBuilder -import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceCursorUpdater -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.premarshaller.UndecoratedCandidateDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedCandidateDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedModuleDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedPresentationDomainMarshallerException -import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.slice.BaseSliceItemPresentation -import com.twitter.product_mixer.core.model.marshalling.response.slice._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Domain marshaller that generates Slices automatically for most candidates but a different - * presentation can be provided by decorators that implement [[BaseSliceItemPresentation]]. This will - * only be necessary in the rare case that a candidate contains more than an id. For example, - * cursors require a value/type rather than an id. - */ -case class SliceDomainMarshaller[-Query <: PipelineQuery]( - override val cursorBuilders: Seq[SliceCursorBuilder[Query]] = Seq.empty, - override val cursorUpdaters: Seq[SliceCursorUpdater[Query]] = Seq.empty, - override val identifier: DomainMarshallerIdentifier = DomainMarshallerIdentifier("Slice")) - extends DomainMarshaller[Query, Slice] - with SliceBuilder[Query] { - - override def apply( - query: Query, - selections: Seq[CandidateWithDetails] - ): Slice = { - val entries = selections.map { - case ItemCandidateWithDetails(_, Some(presentation: BaseSliceItemPresentation), _) => - presentation.sliceItem - case candidateWithDetails @ ItemCandidateWithDetails(candidate, None, _) => - val source = candidateWithDetails.source - candidate match { - case candidate: BaseTopicCandidate => TopicItem(candidate.id) - case candidate: BaseTweetCandidate => TweetItem(candidate.id) - case candidate: BaseUserCandidate => UserItem(candidate.id) - case candidate: TwitterListCandidate => TwitterListItem(candidate.id) - case candidate: DMConvoSearchCandidate => - DMConvoSearchItem(candidate.id, candidate.lastReadableEventId) - case candidate: DMEventCandidate => - DMEventItem(candidate.id) - case candidate: DMConvoCandidate => - DMConvoItem(candidate.id, candidate.lastReadableEventId) - case candidate: DMMessageSearchCandidate => DMMessageSearchItem(candidate.id) - case candidate: QuerySuggestionCandidate => - TypeaheadQuerySuggestionItem(candidate.id, candidate.metadata) - case candidate: TypeaheadEventCandidate => - TypeaheadEventItem(candidate.id, candidate.metadata) - case candidate: AdUnitCandidate => - AdItem(candidate.id, candidate.adAccountId) - case candidate: AdCreativeCandidate => - AdCreativeItem(candidate.id, candidate.adType, candidate.adAccountId) - case candidate: AdGroupCandidate => - AdGroupItem(candidate.id, candidate.adAccountId) - case candidate: CampaignCandidate => - CampaignItem(candidate.id, candidate.adAccountId) - case candidate: FundingSourceCandidate => - FundingSourceItem(candidate.id, candidate.adAccountId) - case candidate: CursorCandidate => - // Cursors must contain a cursor type which is defined by the presentation. As a result, - // cursors are expected to be handled by the Some(presentation) case above, and must not - // fall into this case. - throw new UndecoratedCandidateDomainMarshallerException(candidate, source) - case candidate => - throw new UnsupportedCandidateDomainMarshallerException(candidate, source) - } - case itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, Some(presentation), _) => - throw new UnsupportedPresentationDomainMarshallerException( - candidate, - presentation, - itemCandidateWithDetails.source) - case moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, presentation, _) => - throw new UnsupportedModuleDomainMarshallerException( - presentation, - moduleCandidateWithDetails.source) - } - - buildSlice(query, entries) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD deleted file mode 100644 index bb49419b4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala deleted file mode 100644 index 0d6db99a2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Builds [[OrderedCursor]] in the Next position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param includeOperation Specifies whether to include the builder operation in the response - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedNextCursorBuilder[Query <: PipelineQuery with HasPipelineCursor[OrderedCursor]]( - idSelector: PartialFunction[SliceItem, Long], - override val includeOperation: ShouldInclude[Query] = AlwaysInclude, - serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer) - extends SliceCursorBuilder[Query] { - override val cursorType: CursorType = NextCursor - - override def cursorValue( - query: Query, - entries: Seq[SliceItem] - ): String = { - val bottomId = entries.reverseIterator.collectFirst(idSelector) - - val id = bottomId.orElse(query.pipelineCursor.flatMap(_.id)) - - val cursor = OrderedCursor(id = id, cursorType = Some(cursorType)) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala deleted file mode 100644 index fc5b509db..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Updates an [[OrderedCursor]] in the Next position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param includeOperation Specifies whether to include the builder operation in the response - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedNextCursorUpdater[Query <: PipelineQuery with HasPipelineCursor[OrderedCursor]]( - idSelector: PartialFunction[SliceItem, Long], - override val includeOperation: ShouldInclude[Query] = AlwaysInclude, - serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer) - extends SliceCursorUpdaterFromUnderlyingBuilder[Query] { - override val cursorType: CursorType = NextCursor - - override val underlying: OrderedNextCursorBuilder[Query] = - OrderedNextCursorBuilder(idSelector, includeOperation, serializer) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala deleted file mode 100644 index 1136ae5ac..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Builds [[OrderedCursor]] in the Previous position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param includeOperation Specifies whether to include the builder operation in the response - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedPreviousCursorBuilder[ - Query <: PipelineQuery with HasPipelineCursor[OrderedCursor] -]( - idSelector: PartialFunction[SliceItem, Long], - override val includeOperation: ShouldInclude[Query] = AlwaysInclude, - serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer) - extends SliceCursorBuilder[Query] { - override val cursorType: CursorType = PreviousCursor - - override def cursorValue( - query: Query, - entries: Seq[SliceItem] - ): String = { - val topId = entries.collectFirst(idSelector) - - val id = topId.orElse(query.pipelineCursor.flatMap(_.id)) - - val cursor = OrderedCursor(id = id, cursorType = Some(cursorType)) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala deleted file mode 100644 index a8f3e8573..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.component_library.model.cursor.OrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.CursorSerializer -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Updates an [[OrderedCursor]] in the Previous position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param includeOperation Specifies whether to include the builder operation in the response - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedPreviousCursorUpdater[ - Query <: PipelineQuery with HasPipelineCursor[OrderedCursor] -]( - idSelector: PartialFunction[SliceItem, Long], - override val includeOperation: ShouldInclude[Query] = AlwaysInclude, - serializer: PipelineCursorSerializer[OrderedCursor] = CursorSerializer) - extends SliceCursorUpdaterFromUnderlyingBuilder[Query] { - override val cursorType: CursorType = PreviousCursor - - override val underlying: OrderedPreviousCursorBuilder[Query] = - OrderedPreviousCursorBuilder(idSelector, includeOperation, serializer) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala deleted file mode 100644 index 7770019b2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait ShouldInclude[-Query <: PipelineQuery] { - def apply(query: Query, items: Seq[SliceItem]): Boolean -} - -object AlwaysInclude extends ShouldInclude[PipelineQuery] { - override def apply(query: PipelineQuery, entries: Seq[SliceItem]): Boolean = true -} - -object IncludeOnNonEmpty extends ShouldInclude[PipelineQuery] { - override def apply(query: PipelineQuery, entries: Seq[SliceItem]): Boolean = entries.nonEmpty -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala deleted file mode 100644 index fba16e5c4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem -import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.GapCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.Slice -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceInfo -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateInMarshaller - -trait SliceBuilder[-Query <: PipelineQuery] { - def cursorBuilders: Seq[SliceCursorBuilder[Query]] - def cursorUpdaters: Seq[SliceCursorUpdater[Query]] - - private def containsGapCursor(items: Seq[SliceItem]): Boolean = - items.collectFirst { case CursorItem(_, GapCursor) => () }.nonEmpty - - final def buildSlice(query: Query, items: Seq[SliceItem]): Slice = { - val builtCursors = cursorBuilders.flatMap(_.build(query, items)) - - // Iterate over the cursorUpdaters in the order they were defined. Note that each updater will - // be passed the items updated by the previous cursorUpdater. - val updatedItems = cursorUpdaters.foldLeft(items) { (items, cursorUpdater) => - cursorUpdater.update(query, items) - } ++ builtCursors - - val (cursors, nonCursorItems) = updatedItems.partition(_.isInstanceOf[CursorItem]) - val nextCursor = cursors.collectFirst { - case cursor @ CursorItem(_, NextCursor) => cursor.value - } - val previousCursor = cursors.collectFirst { - case cursor @ CursorItem(_, PreviousCursor) => cursor.value - } - - /** - * Identify whether a [[GapCursor]] is present and give as much detail to point to where it came from - * Since this is already a fatal error case for the request, its okay to be a little expensive to get - * the best error message possible for debug purposes. - */ - if (containsGapCursor(cursors)) { - val errorDetails = - if (containsGapCursor(builtCursors)) { - "This means one of your `cursorBuilders` returned a GapCursor." - } else if (containsGapCursor(items)) { - "This means one of your `CandidateDecorator`s decorated a Candidate with a GapCursor." - } else { - "This means one of your `cursorUpdaters` returned a GapCursor." - } - throw PipelineFailure( - UnexpectedCandidateInMarshaller, - s"SliceBuilder does not support GapCursors but one was given. $errorDetails" - ) - } - - Slice( - items = nonCursorItems, - sliceInfo = SliceInfo(previousCursor = previousCursor, nextCursor = nextCursor)) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala deleted file mode 100644 index f033b3fe8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait SliceCursorBuilder[-Query <: PipelineQuery] { - - val includeOperation: ShouldInclude[Query] = AlwaysInclude - - def cursorValue(query: Query, items: Seq[SliceItem]): String - def cursorType: CursorType - - def build(query: Query, entries: Seq[SliceItem]): Option[CursorItem] = { - if (includeOperation(query, entries)) { - Some( - CursorItem( - cursorType = cursorType, - value = cursorValue(query, entries) - )) - } else None - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala deleted file mode 100644 index c70acec39..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.slice.builder - -import com.twitter.product_mixer.component_library.premarshaller.slice.builder.SliceCursorUpdater.getCursorByType -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorItem -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object SliceCursorUpdater { - - def getCursorByType( - items: Seq[SliceItem], - cursorType: CursorType - ): Option[CursorItem] = { - items.collectFirst { - case cursor: CursorItem if cursor.cursorType == cursorType => cursor - } - } -} - -/** - * If [[SliceCursorBuilder.includeOperation]] is true and a cursor does exist in the `items`, - * this will run the the underlying [[SliceCursorBuilder]] with the full `items` - * (including all cursors which may be present) then filter out only the originally - * found [[CursorItem]] from the results). Then append the new cursor to the end of the results. - * - * If you have multiple cursors that need to be updated, you will need to have multiple updaters. - * - * If a CursorCandidate is returned by a Candidate Source, use this trait to update the Cursor - * (if necessary) and add it to the end of the candidates list. - */ -trait SliceCursorUpdater[-Query <: PipelineQuery] extends SliceCursorBuilder[Query] { self => - - def getExistingCursor(items: Seq[SliceItem]): Option[CursorItem] = { - getCursorByType(items, self.cursorType) - } - - def update(query: Query, items: Seq[SliceItem]): Seq[SliceItem] = { - if (includeOperation(query, items)) { - getExistingCursor(items) - .map { existingCursor => - // Safe get because includeOperation() is shared in this context - val newCursor = build(query, items).get - - items.filterNot(_ == existingCursor) :+ newCursor - }.getOrElse(items) - } else items - } -} - -trait SliceCursorUpdaterFromUnderlyingBuilder[-Query <: PipelineQuery] - extends SliceCursorUpdater[Query] { - def underlying: SliceCursorBuilder[Query] - override def cursorValue( - query: Query, - entries: Seq[SliceItem] - ): String = underlying.cursorValue(query, entries) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD deleted file mode 100644 index 8ac8b547e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala deleted file mode 100644 index 0a622caae..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urp - -import com.twitter.product_mixer.component_library.premarshaller.urp.builder.PageBodyBuilder -import com.twitter.product_mixer.component_library.premarshaller.urp.builder.PageHeaderBuilder -import com.twitter.product_mixer.component_library.premarshaller.urp.builder.PageNavBarBuilder -import com.twitter.product_mixer.component_library.premarshaller.urp.builder.TimelineScribeConfigBuilder -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.response.urp._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object UrpDomainMarshaller { - val PageIdSuffix = "-Page" -} - -/** - * Domain marshaller that given the builders for the body, header and navbar will generate a URP Page - * - * @param pageBodyBuilder PageBody builder that generates a PageBody with the query and selections - * @param scribeConfigBuilder Scribe Config builder that generates the configuration for scribing of the page - * @param pageHeaderBuilder PageHeader builder that generates a PageHeader with the query and selections - * @param pageNavBarBuilder PageNavBar builder that generates a PageNavBar with the query and selections - * @tparam Query The type of Query that this Marshaller operates with - */ -case class UrpDomainMarshaller[-Query <: PipelineQuery]( - pageBodyBuilder: PageBodyBuilder[Query], - pageHeaderBuilder: Option[PageHeaderBuilder[Query]] = None, - pageNavBarBuilder: Option[PageNavBarBuilder[Query]] = None, - scribeConfigBuilder: Option[TimelineScribeConfigBuilder[Query]] = None, - override val identifier: DomainMarshallerIdentifier = - DomainMarshallerIdentifier("UnifiedRichPage")) - extends DomainMarshaller[Query, Page] { - - override def apply( - query: Query, - selections: Seq[CandidateWithDetails] - ): Page = { - val pageBody = pageBodyBuilder.build(query, selections) - val pageHeader = pageHeaderBuilder.flatMap(_.build(query, selections)) - val pageNavBar = pageNavBarBuilder.flatMap(_.build(query, selections)) - val scribeConfig = scribeConfigBuilder.flatMap(_.build(query, pageBody, pageHeader, pageNavBar)) - - Page( - id = query.product.identifier.toString + UrpDomainMarshaller.PageIdSuffix, - pageBody = pageBody, - scribeConfig = scribeConfig, - pageHeader = pageHeader, - pageNavBar = pageNavBar - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD deleted file mode 100644 index d22d01bf8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stringcenter/client", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stringcenter/client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala deleted file mode 100644 index 1fed528fc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urp.builder - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Trait for our builder which given a query and selections will return a `PageBody` - * - * @tparam Query - */ -trait PageBodyBuilder[-Query <: PipelineQuery] { - - def build( - query: Query, - selections: Seq[CandidateWithDetails] - ): PageBody -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala deleted file mode 100644 index aa23f44e1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urp.builder - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Trait for our builder which given a query and selections will return an `Option[PageHeader]` - * - * @tparam Query - */ -trait PageHeaderBuilder[-Query <: PipelineQuery] { - - def build( - query: Query, - selections: Seq[CandidateWithDetails] - ): Option[PageHeader] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala deleted file mode 100644 index 76a3836ed..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urp.builder - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Trait for our builder which given a query and selections will return an `Option[PageNavBar]` - * - * @tparam Query - */ -trait PageNavBarBuilder[-Query <: PipelineQuery] { - - def build( - query: Query, - selections: Seq[CandidateWithDetails] - ): Option[PageNavBar] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala deleted file mode 100644 index c815bf58b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urp.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticTimelineScribeConfigBuilder( - timelineScribeConfig: TimelineScribeConfig) - extends TimelineScribeConfigBuilder[PipelineQuery] { - - override def build( - query: PipelineQuery, - pageBody: PageBody, - pageHeader: Option[PageHeader], - pageNavBar: Option[PageNavBar] - ): Option[TimelineScribeConfig] = Some(timelineScribeConfig) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala deleted file mode 100644 index 3860552df..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urp.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Trait for our builder which given a query and page info will return an `Option[TimelineScribeConfig]` - * - * @tparam Query - */ -trait TimelineScribeConfigBuilder[-Query <: PipelineQuery] { - - def build( - query: Query, - pageBody: PageBody, - pageHeader: Option[PageHeader], - pageNavBar: Option[PageNavBar] - ): Option[TimelineScribeConfig] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD deleted file mode 100644 index e9426b86a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/decorator/urt", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala deleted file mode 100644 index 28f5b2912..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.scala +++ /dev/null @@ -1,148 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt - -import com.twitter.product_mixer.component_library.model.candidate.ArticleCandidate -import com.twitter.product_mixer.component_library.model.candidate.AudioSpaceCandidate -import com.twitter.product_mixer.component_library.model.candidate.TopicCandidate -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.TwitterListCandidate -import com.twitter.product_mixer.component_library.model.candidate.UserCandidate -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.AddEntriesInstructionBuilder -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.BaseUrtMetadataBuilder -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtBuilder -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorUpdater -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtInstructionBuilder -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedCandidateDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedModuleDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedPresentationDomainMarshallerException -import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FollowingListSeed -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.Tweet -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.User -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Decorator that is useful for fast prototyping, as it will generate URT entries from only - * candidate IDs (no ItemPresentations or ModulePresentations from candidate pipeline decorators - * are required). - */ -case class UndecoratedUrtDomainMarshaller[Query <: PipelineQuery]( - override val instructionBuilders: Seq[UrtInstructionBuilder[Query, TimelineInstruction]] = - Seq(AddEntriesInstructionBuilder()), - override val cursorBuilders: Seq[UrtCursorBuilder[Query]] = Seq.empty, - override val cursorUpdaters: Seq[UrtCursorUpdater[Query]] = Seq.empty, - override val metadataBuilder: Option[BaseUrtMetadataBuilder[Query]] = None, - override val sortIndexStep: Int = 1, - override val identifier: DomainMarshallerIdentifier = - DomainMarshallerIdentifier("UndecoratedUnifiedRichTimeline")) - extends DomainMarshaller[Query, Timeline] - with UrtBuilder[Query, TimelineInstruction] { - - override def apply( - query: Query, - selections: Seq[CandidateWithDetails] - ): Timeline = { - val entries = selections.map { - case itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, None, _) => - candidate match { - case candidate: ArticleCandidate => - ArticleItem( - id = candidate.id, - articleSeedType = FollowingListSeed, - sortIndex = None, - clientEventInfo = None, - feedbackActionInfo = None, - displayType = None, - socialContext = None, - ) - case candidate: AudioSpaceCandidate => - AudioSpaceItem( - id = candidate.id, - sortIndex = None, - clientEventInfo = None, - feedbackActionInfo = None) - case candidate: TopicCandidate => - TopicItem( - id = candidate.id, - sortIndex = None, - clientEventInfo = None, - feedbackActionInfo = None, - topicFunctionalityType = None, - topicDisplayType = None - ) - case candidate: TweetCandidate => - TweetItem( - id = candidate.id, - entryNamespace = TweetItem.TweetEntryNamespace, - sortIndex = None, - clientEventInfo = None, - feedbackActionInfo = None, - isPinned = None, - entryIdToReplace = None, - socialContext = None, - highlights = None, - displayType = Tweet, - innerTombstoneInfo = None, - timelinesScoreInfo = None, - hasModeratedReplies = None, - forwardPivot = None, - innerForwardPivot = None, - promotedMetadata = None, - conversationAnnotation = None, - contextualTweetRef = None, - prerollMetadata = None, - replyBadge = None, - destination = None - ) - case candidate: TwitterListCandidate => - TwitterListItem( - id = candidate.id, - sortIndex = None, - clientEventInfo = None, - feedbackActionInfo = None, - displayType = None - ) - case candidate: UserCandidate => - UserItem( - id = candidate.id, - sortIndex = None, - clientEventInfo = None, - feedbackActionInfo = None, - isMarkUnread = None, - displayType = User, - promotedMetadata = None, - socialContext = None, - reactiveTriggers = None, - enableReactiveBlending = None - ) - case candidate => - throw new UnsupportedCandidateDomainMarshallerException( - candidate, - itemCandidateWithDetails.source) - } - case itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, Some(presentation), _) => - throw new UnsupportedPresentationDomainMarshallerException( - candidate, - presentation, - itemCandidateWithDetails.source) - case moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, presentation, _) => - throw new UnsupportedModuleDomainMarshallerException( - presentation, - moduleCandidateWithDetails.source) - } - - buildTimeline(query, entries) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala deleted file mode 100644 index 80708e90a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.scala +++ /dev/null @@ -1,112 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt - -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ManualModuleId -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.ModuleIdGeneration -import com.twitter.product_mixer.component_library.decorator.urt.builder.timeline_module.AutomaticUniqueModuleId -import com.twitter.product_mixer.component_library.premarshaller.urt.builder._ -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.premarshaller.UndecoratedCandidateDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UndecoratedModuleDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedModuleDomainMarshallerException -import com.twitter.product_mixer.core.functional_component.premarshaller.UnsupportedPresentationDomainMarshallerException -import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtItemPresentation -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtModulePresentation -import com.twitter.product_mixer.core.model.common.presentation.urt.BaseUrtOperationPresentation -import com.twitter.product_mixer.core.model.common.presentation.urt.IsDispensable -import com.twitter.product_mixer.core.model.common.presentation.urt.WithItemTreeDisplay -import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Domain marshaller that generates URT timelines automatically if the candidate pipeline decorators - * use item and module presentations types that implement [[BaseUrtItemPresentation]] and - * [[BaseUrtModulePresentation]], respectively to hold URT presentation data. - */ -case class UrtDomainMarshaller[-Query <: PipelineQuery]( - override val instructionBuilders: Seq[UrtInstructionBuilder[Query, TimelineInstruction]] = - Seq(AddEntriesInstructionBuilder()), - override val cursorBuilders: Seq[UrtCursorBuilder[Query]] = Seq.empty, - override val cursorUpdaters: Seq[UrtCursorUpdater[Query]] = Seq.empty, - override val metadataBuilder: Option[BaseUrtMetadataBuilder[Query]] = None, - override val sortIndexStep: Int = 1, - override val identifier: DomainMarshallerIdentifier = - DomainMarshallerIdentifier("UnifiedRichTimeline")) - extends DomainMarshaller[Query, Timeline] - with UrtBuilder[Query, TimelineInstruction] { - - override def apply( - query: Query, - selections: Seq[CandidateWithDetails] - ): Timeline = { - val initialSortIndex = getInitialSortIndex(query) - - val entries = selections.zipWithIndex.map { - case (ItemCandidateWithDetails(_, Some(presentation: BaseUrtItemPresentation), _), _) => - presentation.timelineItem - case (ItemCandidateWithDetails(_, Some(presentation: BaseUrtOperationPresentation), _), _) => - presentation.timelineOperation - case ( - ModuleCandidateWithDetails( - candidates, - Some(presentation: BaseUrtModulePresentation), - _), - index) => - val moduleItems = candidates.collect { - case ItemCandidateWithDetails(_, Some(itemPresentation: BaseUrtItemPresentation), _) => - buildModuleItem(itemPresentation) - } - - ModuleIdGeneration(presentation.timelineModule.id) match { - case _: AutomaticUniqueModuleId => - // Module IDs are unique using this method since initialSortIndex is based on time of request combined - // with each timeline module index - presentation.timelineModule.copy(id = initialSortIndex + index, items = moduleItems) - case ManualModuleId(moduleId) => - presentation.timelineModule.copy(id = moduleId, items = moduleItems) - } - case ( - itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, Some(presentation), _), - _) => - throw new UnsupportedPresentationDomainMarshallerException( - candidate, - presentation, - itemCandidateWithDetails.source) - case (itemCandidateWithDetails @ ItemCandidateWithDetails(candidate, None, _), _) => - throw new UndecoratedCandidateDomainMarshallerException( - candidate, - itemCandidateWithDetails.source) - case ( - moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, presentation @ Some(_), _), - _) => - // handles given a non `BaseUrtModulePresentation` presentation type - throw new UnsupportedModuleDomainMarshallerException( - presentation, - moduleCandidateWithDetails.source) - case (moduleCandidateWithDetails @ ModuleCandidateWithDetails(_, None, _), _) => - throw new UndecoratedModuleDomainMarshallerException(moduleCandidateWithDetails.source) - } - - buildTimeline(query, entries) - } - - private def buildModuleItem(itemPresentation: BaseUrtItemPresentation): ModuleItem = { - val isDispensable = itemPresentation match { - case isDispensable: IsDispensable => Some(isDispensable.dispensable) - case _ => None - } - val treeDisplay = itemPresentation match { - case withItemTreeDisplay: WithItemTreeDisplay => withItemTreeDisplay.treeDisplay - case _ => None - } - ModuleItem( - itemPresentation.timelineItem, - dispensable = isDispensable, - treeDisplay = treeDisplay) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala deleted file mode 100644 index eec2a50ea..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class AddEntriesInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddEntriesTimelineInstruction] = { - if (entries.nonEmpty && includeInstruction(query, entries)) - Seq(AddEntriesTimelineInstruction(entries)) - else Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala deleted file mode 100644 index 5d19b7f04..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Build the AddEntries instruction with special handling for AddToModule entries. - * - * Entries which are going to be added to a module are going to be added via - * AddToModuleInstructionBuilder, for other entries in the same response (like cursor entries) we - * still need an AddEntriesTimelineInstruction which is going to be created by this builder. - */ -case class AddEntriesWithAddToModuleInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddEntriesTimelineInstruction] = { - if (includeInstruction(query, entries)) { - val entriesToAdd = entries.filter { - case _: TimelineModule => false - case _ => true - } - if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd)) - else Seq.empty - } else - Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala deleted file mode 100644 index ff5c70196..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Iterates over all the [[TimelineEntry]] passed it and creates `addEntry` entries in the URT for - * any entries which are not pinned and not replaceable(cursors are replaceable) - * - * This is because pinned entries always show up in the `pinEntry` section, and replaceable entries - * will show up in the `replaceEntry` section. - */ -case class AddEntriesWithPinnedAndReplaceInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddEntriesTimelineInstruction] = { - if (includeInstruction(query, entries)) { - val entriesToAdd = entries - .filterNot(_.isPinned.getOrElse(false)) - .filter(_.entryIdToReplace.isEmpty) - if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd)) - else Seq.empty - } else - Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala deleted file mode 100644 index 6c2e96b72..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class AddEntriesWithReplaceAndShowAlertInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddEntriesTimelineInstruction] = { - if (includeInstruction(query, entries)) { - val entriesToAdd = entries - .filterNot(_.isInstanceOf[ShowAlert]) - .filter(_.entryIdToReplace.isEmpty) - if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd)) - else Seq.empty - } else - Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala deleted file mode 100644 index 64a03007e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Build the AddEntries instruction with special handling for replaceable entries. - * - * Entries (though almost always a single entry) with a non-empty entryIdToReplace field should be - * collected and transformed into ReplaceEntry instructions. These should be filtered out of the - * AddEntries instruction. We avoid doing this as part of the regular AddEntriesInstructionBuilder - * because replacement is rare and detecting replaceable entries takes linear time. - */ -case class AddEntriesWithReplaceInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddEntriesTimelineInstruction] = { - if (includeInstruction(query, entries)) { - val entriesToAdd = entries.filter(_.entryIdToReplace.isEmpty) - if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd)) - else Seq.empty - } else { - Seq.empty - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala deleted file mode 100644 index f6c742549..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Build AddEntries instruction with special handling for Covers. - * - * Cover Entries should be collected and transformed into ShowCover instructions. These should be - * filtered out of the AddEntries instruction. We avoid doing this as part of the regular - * AddEntriesInstructionBuilder because covers are used only used when using a Flip Pipeline and - * detecting cover entries takes linear time. - */ -case class AddEntriesWithShowCoverInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddEntriesTimelineInstruction] { - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddEntriesTimelineInstruction] = { - if (includeInstruction(query, entries)) { - val entriesToAdd = entries.filterNot(_.isInstanceOf[Cover]) - if (entriesToAdd.nonEmpty) Seq(AddEntriesTimelineInstruction(entriesToAdd)) else Seq.empty - } else - Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala deleted file mode 100644 index 72598e20f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddToModuleTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class AddToModuleInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, AddToModuleTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[AddToModuleTimelineInstruction] = { - if (includeInstruction(query, entries)) { - val moduleEntries = entries.collect { - case module: TimelineModule => module - } - if (moduleEntries.nonEmpty) { - assert(moduleEntries.size == 1, "Currently we only support appending to one module") - moduleEntries.headOption.map { moduleEntry => - AddToModuleTimelineInstruction( - moduleItems = moduleEntry.items, - moduleEntryId = moduleEntry.entryIdentifier, - // Currently configuring moduleItemEntryId and prepend fields are not supported. - moduleItemEntryId = None, - prepend = None - ) - } - }.toSeq - else Seq.empty - } else { - Seq.empty - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD deleted file mode 100644 index 13fee695d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "src/scala/com/twitter/search/common/util/bloomfilter", - "stringcenter/client", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "src/scala/com/twitter/search/common/util/bloomfilter", - "stringcenter/client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala deleted file mode 100644 index 72325d7e8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -trait BaseUnorderedExcludeIdsBottomCursorBuilder - extends UrtCursorBuilder[ - PipelineQuery with HasPipelineCursor[UrtUnorderedExcludeIdsCursor] - ] { - - def excludedIdsMaxLengthParam: Param[Int] - - def excludeEntriesCollector(entries: Seq[TimelineEntry]): Seq[Long] - - def serializer: PipelineCursorSerializer[UrtUnorderedExcludeIdsCursor] - - override val cursorType: CursorType = BottomCursor - - override def cursorValue( - query: PipelineQuery with HasPipelineCursor[UrtUnorderedExcludeIdsCursor], - entries: Seq[TimelineEntry] - ): String = { - val excludedIdsMaxLength = query.params(excludedIdsMaxLengthParam) - assert(excludedIdsMaxLength > 0, "Excluded IDs max length must be greater than zero") - - val newEntryIds = excludeEntriesCollector(entries) - assert( - newEntryIds.length < excludedIdsMaxLength, - "New entry IDs length must be smaller than excluded IDs max length") - - val excludedIds = query.pipelineCursor - .map(_.excludedIds ++ newEntryIds) - .getOrElse(newEntryIds) - .takeRight(excludedIdsMaxLength) - - val cursor = UrtUnorderedExcludeIdsCursor( - initialSortIndex = nextBottomInitialSortIndex(query, entries), - excludedIds = excludedIds - ) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala deleted file mode 100644 index 458c25ff5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ClearCacheInstructionBuilder.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ClearCacheTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ClearCacheInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, ClearCacheTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[ClearCacheTimelineInstruction] = - if (includeInstruction(query, entries)) Seq(ClearCacheTimelineInstruction()) else Seq.empty -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala deleted file mode 100644 index 368336b2e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/FeaturePassThroughCursorBuilder.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtPassThroughCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class PassThroughCursorBuilder[ - -Query <: PipelineQuery with HasPipelineCursor[UrtPassThroughCursor] -]( - cursorFeature: Feature[Query, String], - override val cursorType: CursorType) - extends UrtCursorBuilder[Query] { - - override val includeOperation: IncludeInstruction[Query] = { (query, _) => - query.features.exists(_.getOrElse(cursorFeature, "").nonEmpty) - } - - override def cursorValue( - query: Query, - entries: Seq[TimelineEntry] - ): String = - UrtCursorSerializer.serializeCursor( - UrtPassThroughCursor( - cursorSortIndex(query, entries), - query.features.map(_.get(cursorFeature)).getOrElse(""), - cursorType = Some(cursorType) - ) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala deleted file mode 100644 index e34e7b85d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/IncludeInstruction.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait IncludeInstruction[-Query <: PipelineQuery] { self => - def apply(query: Query, entries: Seq[TimelineEntry]): Boolean - - def inverse(): IncludeInstruction[Query] = new IncludeInstruction[Query] { - def apply(query: Query, entries: Seq[TimelineEntry]): Boolean = !self.apply(query, entries) - } -} - -object AlwaysInclude extends IncludeInstruction[PipelineQuery] { - override def apply(query: PipelineQuery, entries: Seq[TimelineEntry]): Boolean = true -} - -object IncludeOnFirstPage extends IncludeInstruction[PipelineQuery with HasPipelineCursor[_]] { - override def apply( - query: PipelineQuery with HasPipelineCursor[_], - entries: Seq[TimelineEntry] - ): Boolean = query.isFirstPage -} - -object IncludeAfterFirstPage extends IncludeInstruction[PipelineQuery with HasPipelineCursor[_]] { - override def apply( - query: PipelineQuery with HasPipelineCursor[_], - entries: Seq[TimelineEntry] - ): Boolean = !query.isFirstPage -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala deleted file mode 100644 index a4b8d0f5b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/MarkUnreadInstructionBuilder.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.MarkEntriesUnreadInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.MarkUnreadableEntry - -/** - * Build a MarkUnreadEntries instruction - * - * Note that this implementation currently supports top-level entries, but not module item entries. - */ -case class MarkUnreadInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, MarkEntriesUnreadInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[MarkEntriesUnreadInstruction] = { - if (includeInstruction(query, entries)) { - val filteredEntries = entries.collect { - case entry: MarkUnreadableEntry if entry.isMarkUnread.contains(true) => - entry.entryIdentifier - } - if (filteredEntries.nonEmpty) Seq(MarkEntriesUnreadInstruction(filteredEntries)) - else Seq.empty - } else { - Seq.empty - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala deleted file mode 100644 index 85b7b5e47..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedBottomCursorBuilder.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Builds [[UrtOrderedCursor]] in the Bottom position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param includeOperation Logic to determine whether or not to build the bottom cursor, which only - * applies if gap cursors are required (e.g. Home Latest). When applicable, - * this logic should always be the inverse of the logic used to decide - * whether or not to build the gap cursor via [[OrderedGapCursorBuilder]], - * since either the gap or the bottom cursor must always be returned. - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedBottomCursorBuilder[ - -Query <: PipelineQuery with HasPipelineCursor[UrtOrderedCursor] -]( - idSelector: PartialFunction[TimelineEntry, Long], - override val includeOperation: IncludeInstruction[Query] = AlwaysInclude, - serializer: PipelineCursorSerializer[UrtOrderedCursor] = UrtCursorSerializer) - extends UrtCursorBuilder[Query] { - override val cursorType: CursorType = BottomCursor - - override def cursorValue(query: Query, timelineEntries: Seq[TimelineEntry]): String = { - val bottomId = timelineEntries.reverseIterator.collectFirst(idSelector) - - val id = bottomId.orElse(query.pipelineCursor.flatMap(_.id)) - - val cursor = UrtOrderedCursor( - initialSortIndex = nextBottomInitialSortIndex(query, timelineEntries), - id = id, - cursorType = Some(cursorType) - ) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala deleted file mode 100644 index c5136c1b7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedGapCursorBuilder.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.GapCursor -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Builds [[UrtOrderedCursor]] in the Bottom position as a Gap cursor. - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param includeOperation Logic to determine whether or not to build the gap cursor, which should - * always be the inverse of the logic used to decide whether or not to build - * the bottom cursor via [[OrderedBottomCursorBuilder]], since either the - * gap or the bottom cursor must always be returned. - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedGapCursorBuilder[ - -Query <: PipelineQuery with HasPipelineCursor[UrtOrderedCursor] -]( - idSelector: PartialFunction[TimelineEntry, Long], - override val includeOperation: IncludeInstruction[Query], - serializer: PipelineCursorSerializer[UrtOrderedCursor] = UrtCursorSerializer) - extends UrtCursorBuilder[Query] { - override val cursorType: CursorType = GapCursor - - override def cursorValue( - query: Query, - timelineEntries: Seq[TimelineEntry] - ): String = { - // To determine the gap boundary, use any existing cursor gap boundary id (i.e. if submitted - // from a previous gap cursor, else use the existing cursor id (i.e. from a previous top cursor) - val gapBoundaryId = query.pipelineCursor.flatMap(_.gapBoundaryId).orElse { - query.pipelineCursor.flatMap(_.id) - } - - val bottomId = timelineEntries.reverseIterator.collectFirst(idSelector) - - val id = bottomId.orElse(gapBoundaryId) - - val cursor = UrtOrderedCursor( - initialSortIndex = nextBottomInitialSortIndex(query, timelineEntries), - id = id, - cursorType = Some(cursorType), - gapBoundaryId = gapBoundaryId - ) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala deleted file mode 100644 index 2939f8d5e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/OrderedTopCursorBuilder.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtOrderedCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.OrderedTopCursorBuilder.TopCursorOffset -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case object OrderedTopCursorBuilder { - // Ensure that the next initial sort index is at least 10000 entries away from top cursor's - // current sort index. This is to ensure that the contents of the next page can be populated - // without being assigned sort indices which conflict with that of the current page. This assumes - // that each page will have fewer than 10000 entries. - val TopCursorOffset = 10000L -} - -/** - * Builds [[UrtOrderedCursor]] in the Top position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param serializer Converts the cursor to an encoded string - */ -case class OrderedTopCursorBuilder( - idSelector: PartialFunction[UniversalNoun[_], Long], - serializer: PipelineCursorSerializer[UrtOrderedCursor] = UrtCursorSerializer) - extends UrtCursorBuilder[ - PipelineQuery with HasPipelineCursor[UrtOrderedCursor] - ] { - override val cursorType: CursorType = TopCursor - - override def cursorValue( - query: PipelineQuery with HasPipelineCursor[UrtOrderedCursor], - timelineEntries: Seq[TimelineEntry] - ): String = { - val topId = timelineEntries.collectFirst(idSelector) - - val id = topId.orElse(query.pipelineCursor.flatMap(_.id)) - - val cursor = UrtOrderedCursor( - initialSortIndex = cursorSortIndex(query, timelineEntries) + TopCursorOffset, - id = id, - cursorType = Some(cursorType) - ) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala deleted file mode 100644 index 9fc4cea24..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PinEntryInstructionBuilder.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.PinEntryTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnableEntry - -case class PinEntryInstructionBuilder() - extends UrtInstructionBuilder[PipelineQuery, PinEntryTimelineInstruction] { - - override def build( - query: PipelineQuery, - entries: Seq[TimelineEntry] - ): Seq[PinEntryTimelineInstruction] = { - // Only one entry can be pinned and the desirable behavior is to pick the entry with the highest - // sort index in the event that multiple pinned items exist. Since the entries are already - // sorted we can accomplish this by picking the first one. - entries.collectFirst { - case entry: PinnableEntry if entry.isPinned.getOrElse(false) => - PinEntryTimelineInstruction(entry) - }.toSeq - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala deleted file mode 100644 index adfe085aa..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/PlaceholderTopCursorBuilder.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtPlaceholderCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.PlaceholderTopCursorBuilder.DefaultPlaceholderCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor - -object PlaceholderTopCursorBuilder { - val DefaultPlaceholderCursor = UrtPlaceholderCursor() -} - -/** - * Top cursor builder that can be used when the Product does not support paging up. The URT spec - * requires that both bottom and top cursors always be present on each page. Therefore, if the - * product does not support paging up, then we can use a cursor value that is not deserializable. - * This way if the client submits a TopCursor, the backend will treat the the request as if no - * cursor was submitted. - */ -case class PlaceholderTopCursorBuilder( - serializer: PipelineCursorSerializer[UrtPipelineCursor] = UrtCursorSerializer) - extends UrtCursorBuilder[PipelineQuery with HasPipelineCursor[UrtPipelineCursor]] { - override val cursorType: CursorType = TopCursor - - override def cursorValue( - query: PipelineQuery with HasPipelineCursor[UrtPipelineCursor], - timelineEntries: Seq[TimelineEntry] - ): String = serializer.serializeCursor(DefaultPlaceholderCursor) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala deleted file mode 100644 index e93553780..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ReplaceEntryInstructionBuilder.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ReplaceEntryTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Selects one or more [[TimelineEntry]] instance from the input timeline entries. - * - * @tparam Query The domain model for the [[PipelineQuery]] used as input. - */ -trait EntriesToReplace[-Query <: PipelineQuery] { - def apply(query: Query, entries: Seq[TimelineEntry]): Seq[TimelineEntry] -} - -/** - * Selects all entries with a non-empty valid entryIdToReplace. - * - * @note this will result in multiple [[ReplaceEntryTimelineInstruction]]s - */ -case object ReplaceAllEntries extends EntriesToReplace[PipelineQuery] { - def apply(query: PipelineQuery, entries: Seq[TimelineEntry]): Seq[TimelineEntry] = - entries.filter(_.entryIdToReplace.isDefined) -} - -/** - * Selects a replaceable URT [[CursorOperation]] from the timeline entries, that matches the - * input cursorType. - */ -case class ReplaceUrtCursor(cursorType: CursorType) extends EntriesToReplace[PipelineQuery] { - override def apply(query: PipelineQuery, entries: Seq[TimelineEntry]): Seq[TimelineEntry] = - entries.collectFirst { - case cursorOperation: CursorOperation - if cursorOperation.cursorType == cursorType && cursorOperation.entryIdToReplace.isDefined => - cursorOperation - }.toSeq -} - -/** - * Create a ReplaceEntry instruction - * - * @param entriesToReplace each replace instruction can contain only one entry. Users specify which - * entry to replace using [[EntriesToReplace]]. If multiple entries are - * specified, multiple [[ReplaceEntryTimelineInstruction]]s will be created. - * @param includeInstruction whether the instruction should be included in the response - */ -case class ReplaceEntryInstructionBuilder[Query <: PipelineQuery]( - entriesToReplace: EntriesToReplace[Query], - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, ReplaceEntryTimelineInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[ReplaceEntryTimelineInstruction] = { - if (includeInstruction(query, entries)) - entriesToReplace(query, entries).map(ReplaceEntryTimelineInstruction) - else - Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala deleted file mode 100644 index 678904755..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowAlertInstructionBuilder.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlertInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ShowAlertInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, ShowAlertInstruction] { - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[ShowAlertInstruction] = { - if (includeInstruction(query, entries)) { - // Currently only one Alert is supported per response - entries.collectFirst { - case alertEntry: ShowAlert => ShowAlertInstruction(alertEntry) - }.toSeq - } else Seq.empty - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala deleted file mode 100644 index fe7e4364e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/ShowCoverInstructionBuilder.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowCoverInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class ShowCoverInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends UrtInstructionBuilder[Query, ShowCoverInstruction] { - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[ShowCoverInstruction] = { - if (includeInstruction(query, entries)) { - // Currently only one cover is supported per response - entries.collectFirst { - case coverEntry: Cover => ShowCoverInstruction(coverEntry) - }.toSeq - } else { - Seq.empty - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala deleted file mode 100644 index 2b374f2d0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/StaticTimelineScribeConfigBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class StaticTimelineScribeConfigBuilder( - timelineScribeConfig: TimelineScribeConfig) - extends TimelineScribeConfigBuilder[PipelineQuery] { - - def build( - query: PipelineQuery, - entries: Seq[TimelineEntry] - ): Option[TimelineScribeConfig] = Some(timelineScribeConfig) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala deleted file mode 100644 index 0e6831ca2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TerminateInstructionBuilder.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.BottomTermination -import com.twitter.product_mixer.core.model.marshalling.response.urt.TerminateTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineTerminationDirection -import com.twitter.product_mixer.core.model.marshalling.response.urt.TopAndBottomTermination -import com.twitter.product_mixer.core.model.marshalling.response.urt.TopTermination -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -sealed trait TerminateInstructionBuilder[Query <: PipelineQuery] - extends UrtInstructionBuilder[Query, TerminateTimelineInstruction] { - - def direction: TimelineTerminationDirection - - override def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[TerminateTimelineInstruction] = - if (includeInstruction(query, entries)) - Seq(TerminateTimelineInstruction(terminateTimelineDirection = direction)) - else Seq.empty -} - -case class TerminateTopInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends TerminateInstructionBuilder[Query] { - - override val direction = TopTermination -} - -case class TerminateBottomInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends TerminateInstructionBuilder[Query] { - - override val direction = BottomTermination -} - -case class TerminateTopAndBottomInstructionBuilder[Query <: PipelineQuery]( - override val includeInstruction: IncludeInstruction[Query] = AlwaysInclude) - extends TerminateInstructionBuilder[Query] { - - override val direction = TopAndBottomTermination -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala deleted file mode 100644 index 98c05ac4a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/TimelineScribeConfigBuilder.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Trait for our builder which given a query and entries will return an `Option[TimelineScribeConfig]` - * - * @tparam Query - */ -trait TimelineScribeConfigBuilder[-Query <: PipelineQuery] { - - def build( - query: Query, - entries: Seq[TimelineEntry] - ): Option[TimelineScribeConfig] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala deleted file mode 100644 index aeb333373..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedBloomFilterBottomCursorBuilder.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedBloomFilterCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.search.common.util.bloomfilter.AdaptiveLongIntBloomFilterBuilder - -/** - * Builds [[UrtUnorderedBloomFilterCursor]] in the Bottom position - * - * @param idSelector Specifies the entry from which to derive the `id` field - * @param serializer Converts the cursor to an encoded string - */ -case class UnorderedBloomFilterBottomCursorBuilder( - idSelector: PartialFunction[UniversalNoun[_], Long], - serializer: PipelineCursorSerializer[UrtUnorderedBloomFilterCursor] = UrtCursorSerializer) - extends UrtCursorBuilder[ - PipelineQuery with HasPipelineCursor[UrtUnorderedBloomFilterCursor] - ] { - - override val cursorType: CursorType = BottomCursor - - override def cursorValue( - query: PipelineQuery with HasPipelineCursor[UrtUnorderedBloomFilterCursor], - entries: Seq[TimelineEntry] - ): String = { - val bloomFilter = query.pipelineCursor.map(_.longIntBloomFilter) - val ids = entries.collect(idSelector) - - val cursor = UrtUnorderedBloomFilterCursor( - initialSortIndex = nextBottomInitialSortIndex(query, entries), - longIntBloomFilter = AdaptiveLongIntBloomFilterBuilder.build(ids, bloomFilter) - ) - - serializer.serializeCursor(cursor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala deleted file mode 100644 index 5a25da032..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsBottomCursorBuilder.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.timelines.configapi.Param - -/** - * Builds [[UrtUnorderedExcludeIdsCursor]] in the Bottom position - * - * @param excludedIdsMaxLengthParam The maximum length of the cursor - * @param excludeIdsSelector Specifies the entry Ids to populate on the `excludedIds` field - * @param serializer Converts the cursor to an encoded string - */ -case class UnorderedExcludeIdsBottomCursorBuilder( - override val excludedIdsMaxLengthParam: Param[Int], - excludeIdsSelector: PartialFunction[UniversalNoun[_], Long], - override val serializer: PipelineCursorSerializer[UrtUnorderedExcludeIdsCursor] = - UrtCursorSerializer) - extends BaseUnorderedExcludeIdsBottomCursorBuilder { - - override def excludeEntriesCollector(entries: Seq[TimelineEntry]): Seq[Long] = - entries.collect(excludeIdsSelector) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala deleted file mode 100644 index 468b5076b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UnorderedExcludeIdsSeqBottomCursorBuilder.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.model.cursor.UrtUnorderedExcludeIdsCursor -import com.twitter.product_mixer.component_library.premarshaller.cursor.UrtCursorSerializer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineCursorSerializer -import com.twitter.timelines.configapi.Param - -/** - * Builds [[UrtUnorderedExcludeIdsCursor]] in the Bottom position when we want to also exclude ids - * of items inside a module. The reason we cannot use [[UnorderedExcludeIdsBottomCursorBuilder]] in - * such case is that the excludeIdsSelector of [[UnorderedExcludeIdsBottomCursorBuilder]] is doing a - * one to one mapping between entries and excluded ids, but in case of having a module, a module - * entry can result in excluding a sequence of entries. - * - * @param excludedIdsMaxLengthParam The maximum length of the cursor - * @param excludeIdsSelector Specifies the entry Ids to populate on the `excludedIds` field - * @param serializer Converts the cursor to an encoded string - */ -case class UnorderedExcludeIdsSeqBottomCursorBuilder( - override val excludedIdsMaxLengthParam: Param[Int], - excludeIdsSelector: PartialFunction[UniversalNoun[_], Seq[Long]], - override val serializer: PipelineCursorSerializer[UrtUnorderedExcludeIdsCursor] = - UrtCursorSerializer) - extends BaseUnorderedExcludeIdsBottomCursorBuilder { - - override def excludeEntriesCollector(entries: Seq[TimelineEntry]): Seq[Long] = - entries.collect(excludeIdsSelector).flatten -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala deleted file mode 100644 index e47bf476b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtBuilder.scala +++ /dev/null @@ -1,94 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor -import com.twitter.product_mixer.core.util.SortIndexBuilder - -trait UrtBuilder[-Query <: PipelineQuery, +Instruction <: TimelineInstruction] { - private val TimelineIdSuffix = "-Timeline" - - def instructionBuilders: Seq[UrtInstructionBuilder[Query, Instruction]] - - def cursorBuilders: Seq[UrtCursorBuilder[Query]] - def cursorUpdaters: Seq[UrtCursorUpdater[Query]] - - def metadataBuilder: Option[BaseUrtMetadataBuilder[Query]] - - // Timeline entry sort indexes will count down by this value. Values higher than 1 are useful to - // leave room in the sequence for dynamically injecting content in between existing entries. - def sortIndexStep: Int = 1 - - final def buildTimeline( - query: Query, - entries: Seq[TimelineEntry] - ): Timeline = { - val initialSortIndex = getInitialSortIndex(query) - - // Set the sort indexes of the entries before we pass them to the cursor builders, since many - // cursor implementations use the sort index of the first/last entry as part of the cursor value - val sortIndexedEntries = updateSortIndexes(initialSortIndex, entries) - - // Iterate over the cursorUpdaters in the order they were defined. Note that each updater will - // be passed the timelineEntries updated by the previous cursorUpdater. - val updatedCursorEntries: Seq[TimelineEntry] = - cursorUpdaters.foldLeft(sortIndexedEntries) { (timelineEntries, cursorUpdater) => - cursorUpdater.update(query, timelineEntries) - } - - val allCursoredEntries = - updatedCursorEntries ++ cursorBuilders.flatMap(_.build(query, updatedCursorEntries)) - - val instructions: Seq[Instruction] = - instructionBuilders.flatMap(_.build(query, allCursoredEntries)) - - val metadata = metadataBuilder.map(_.build(query, allCursoredEntries)) - - Timeline( - id = query.product.identifier.toString + TimelineIdSuffix, - instructions = instructions, - metadata = metadata - ) - } - - final def getInitialSortIndex(query: Query): Long = - query match { - case cursorQuery: HasPipelineCursor[_] => - UrtPipelineCursor - .getCursorInitialSortIndex(cursorQuery) - .getOrElse(SortIndexBuilder.timeToId(query.queryTime)) - case _ => SortIndexBuilder.timeToId(query.queryTime) - } - - /** - * Updates the sort indexes in the timeline entries starting from the given initial sort index - * value and decreasing by the value defined in the sort index step field - * - * @param initialSortIndex The initial value of the sort index - * @param timelineEntries Timeline entries to update - */ - final def updateSortIndexes( - initialSortIndex: Long, - timelineEntries: Seq[TimelineEntry] - ): Seq[TimelineEntry] = { - val indexRange = - initialSortIndex to (initialSortIndex - (timelineEntries.size * sortIndexStep)) by -sortIndexStep - - // Skip any existing cursors because their sort indexes will be managed by their cursor updater. - // If the cursors are not removed first, then the remaining entries would have a gap everywhere - // an existing cursor was present. - val (cursorEntries, nonCursorEntries) = timelineEntries.partition { - case _: CursorOperation => true - case _ => false - } - - nonCursorEntries.zip(indexRange).map { - case (entry, index) => - entry.withSortIndex(index) - } ++ cursorEntries - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala deleted file mode 100644 index 9142bbd05..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorBuilder.scala +++ /dev/null @@ -1,134 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder.DefaultSortIndex -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder.NextPageTopCursorEntryOffset -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorBuilder.UrtEntryOffset -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.BottomCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.GapCursor -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.TopCursor -import com.twitter.product_mixer.core.pipeline.HasPipelineCursor -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.UrtPipelineCursor -import com.twitter.product_mixer.core.util.SortIndexBuilder - -object UrtCursorBuilder { - val NextPageTopCursorEntryOffset = 1L - val UrtEntryOffset = 1L - val DefaultSortIndex = (query: PipelineQuery) => SortIndexBuilder.timeToId(query.queryTime) -} - -trait UrtCursorBuilder[-Query <: PipelineQuery] { - - val includeOperation: IncludeInstruction[Query] = AlwaysInclude - - def cursorType: CursorType - def cursorValue(query: Query, entries: Seq[TimelineEntry]): String - - /** - * Identifier of an *existing* timeline cursor that this new cursor would replace, if this cursor - * is returned in a `ReplaceEntry` timeline instruction. - * - * Note: - * - This id is used to populate the `entryIdToReplace` field on the URT TimelineEntry - * generated. More details at [[CursorOperation.entryIdToReplace]]. - * - As a convention, we use the sortIndex of the cursor for its id/entryId fields. So the - * `idToReplace` should represent the sortIndex of the existing cursor to be replaced. - */ - def idToReplace(query: Query): Option[Long] = None - - def cursorSortIndex(query: Query, entries: Seq[TimelineEntry]): Long = - (query, cursorType) match { - case (query: PipelineQuery with HasPipelineCursor[_], TopCursor) => - topCursorSortIndex(query, entries) - case (query: PipelineQuery with HasPipelineCursor[_], BottomCursor | GapCursor) => - bottomCursorSortIndex(query, entries) - case _ => - throw new UnsupportedOperationException( - "Automatic sort index support limited to top and bottom cursors") - } - - def build(query: Query, entries: Seq[TimelineEntry]): Option[CursorOperation] = { - if (includeOperation(query, entries)) { - val sortIndex = cursorSortIndex(query, entries) - - val cursorOperation = CursorOperation( - id = sortIndex, - sortIndex = Some(sortIndex), - value = cursorValue(query, entries), - cursorType = cursorType, - displayTreatment = None, - idToReplace = idToReplace(query), - ) - - Some(cursorOperation) - } else None - } - - /** - * Build the top cursor sort index which handles the following cases: - * 1. When there is at least one non-cursor entry, use the first entry's sort index + UrtEntryOffset - * 2. When there are no non-cursor entries, and initialSortIndex is not set which indicates that - * it is the first page, use DefaultSortIndex + UrtEntryOffset - * 3. When there are no non-cursor entries, and initialSortIndex is set which indicates that it is - * not the first page, use the query.initialSortIndex from the passed-in cursor + UrtEntryOffset - */ - protected def topCursorSortIndex( - query: PipelineQuery with HasPipelineCursor[_], - entries: Seq[TimelineEntry] - ): Long = { - val nonCursorEntries = entries.filter { - case _: CursorOperation => false - case _: CursorItem => false - case _ => true - } - - lazy val initialSortIndex = - UrtPipelineCursor.getCursorInitialSortIndex(query).getOrElse(DefaultSortIndex(query)) - - nonCursorEntries.headOption.flatMap(_.sortIndex).getOrElse(initialSortIndex) + UrtEntryOffset - } - - /** - * Specifies the point at which the next page's entries' sort indices will start counting. - * - * Note that in the case of URT, the next page's entries' does not include the top cursor. As - * such, the value of initialSortIndex passed back in the cursor is typically the bottom cursor's - * sort index - 2. Subtracting 2 leaves room for the next page's top cursor, which will have a - * sort index of top entry + 1. - */ - protected def nextBottomInitialSortIndex( - query: PipelineQuery with HasPipelineCursor[_], - entries: Seq[TimelineEntry] - ): Long = { - bottomCursorSortIndex(query, entries) - NextPageTopCursorEntryOffset - UrtEntryOffset - } - - /** - * Build the bottom cursor sort index which handles the following cases: - * 1. When there is at least one non-cursor entry, use the last entry's sort index - UrtEntryOffset - * 2. When there are no non-cursor entries, and initialSortIndex is not set which indicates that - * it is the first page, use DefaultSortIndex - * 3. When there are no non-cursor entries, and initialSortIndex is set which indicates that it is - * not the first page, use the query.initialSortIndex from the passed-in cursor - */ - protected def bottomCursorSortIndex( - query: PipelineQuery with HasPipelineCursor[_], - entries: Seq[TimelineEntry] - ): Long = { - val nonCursorEntries = entries.filter { - case _: CursorOperation => false - case _: CursorItem => false - case _ => true - } - - lazy val initialSortIndex = - UrtPipelineCursor.getCursorInitialSortIndex(query).getOrElse(DefaultSortIndex(query)) - - nonCursorEntries.lastOption - .flatMap(_.sortIndex).map(_ - UrtEntryOffset).getOrElse(initialSortIndex) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala deleted file mode 100644 index 0885ff852..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtCursorUpdater.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.component_library.premarshaller.urt.builder.UrtCursorUpdater.getCursorByType -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object UrtCursorUpdater { - - def getCursorByType( - entries: Seq[TimelineEntry], - cursorType: CursorType - ): Option[CursorOperation] = { - entries.collectFirst { - case cursor: CursorOperation if cursor.cursorType == cursorType => cursor - } - } -} - -// If a CursorCandidate is returned by a Candidate Source, use this trait to update that Cursor as -// necessary (as opposed to building a new cursor which is done with the UrtCursorBuilder) -trait UrtCursorUpdater[-Query <: PipelineQuery] extends UrtCursorBuilder[Query] { self => - - def getExistingCursor(entries: Seq[TimelineEntry]): Option[CursorOperation] = { - getCursorByType(entries, self.cursorType) - } - - def update(query: Query, entries: Seq[TimelineEntry]): Seq[TimelineEntry] = { - if (includeOperation(query, entries)) { - getExistingCursor(entries) - .map { existingCursor => - // Safe .get because includeOperation() is shared in this context - // build() method creates a new CursorOperation. We copy over the `idToReplace` - // from the existing cursor. - val newCursor = - build(query, entries).get - .copy(idToReplace = existingCursor.idToReplace) - - entries.filterNot(_ == existingCursor) :+ newCursor - }.getOrElse(entries) - } else entries - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala deleted file mode 100644 index ac1b9da31..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtInstructionBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait UrtInstructionBuilder[-Query <: PipelineQuery, +Instruction <: TimelineInstruction] { - - def includeInstruction: IncludeInstruction[Query] = AlwaysInclude - - def build( - query: Query, - entries: Seq[TimelineEntry] - ): Seq[Instruction] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala deleted file mode 100644 index a59efea0c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/UrtMetadataBuilder.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.component_library.premarshaller.urt.builder - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stringcenter.client.StringCenter -import com.twitter.stringcenter.client.core.ExternalString - -trait BaseUrtMetadataBuilder[-Query <: PipelineQuery] { - def build( - query: Query, - entries: Seq[TimelineEntry] - ): TimelineMetadata -} - -case class UrtMetadataBuilder( - title: Option[String] = None, - scribeConfigBuilder: Option[TimelineScribeConfigBuilder[PipelineQuery]]) - extends BaseUrtMetadataBuilder[PipelineQuery] { - - override def build( - query: PipelineQuery, - entries: Seq[TimelineEntry] - ): TimelineMetadata = TimelineMetadata( - title = title, - scribeConfig = scribeConfigBuilder.flatMap(_.build(query, entries)) - ) -} - -case class UrtMetadataStringCenterBuilder( - titleKey: ExternalString, - scribeConfigBuilder: Option[TimelineScribeConfigBuilder[PipelineQuery]], - stringCenter: StringCenter) - extends BaseUrtMetadataBuilder[PipelineQuery] { - - override def build( - query: PipelineQuery, - entries: Seq[TimelineEntry] - ): TimelineMetadata = TimelineMetadata( - title = Some(stringCenter.prepare(titleKey)), - scribeConfig = scribeConfigBuilder.flatMap(_.build(query, entries)) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD deleted file mode 100644 index ed7e90b3f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/io/grpc:grpc-netty", - "3rdparty/jvm/io/netty:netty4-tcnative-boringssl-static", - "3rdparty/jvm/io/opil:tensorflow-serving-client", - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/jvm/triton/inference:triton-grpc", - "finagle-internal/finagle-grpc/src/main/scala", - "finagle-internal/finagle-grpc/src/test/java", - "finagle-internal/finagle-grpc/src/test/proto", - "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authentication", - "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/client", - "finagle/finagle-http/src/main/scala", - "finatra-internal/mtls/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "ml-serving/scala:kfserving-tfserving-converter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/triton/inference:triton-grpc", - "finagle/finagle-http/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala deleted file mode 100644 index ee763759c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/MLModelInferenceClient.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.common - -import com.twitter.stitch.Stitch -import inference.GrpcService.ModelInferRequest -import inference.GrpcService.ModelInferResponse - -/** - * MLModelInferenceClient for calling different Inference Service such as ManagedModelClient or NaviModelClient. - */ -trait MLModelInferenceClient { - def score(request: ModelInferRequest): Stitch[ModelInferResponse] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala deleted file mode 100644 index cd71a072a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ManagedModelClient.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.common - -import com.twitter.finagle.Http -import com.twitter.finagle.grpc.FinagleChannelBuilder -import com.twitter.finagle.grpc.FutureConverters -import com.twitter.stitch.Stitch -import inference.GRPCInferenceServiceGrpc -import inference.GrpcService.ModelInferRequest -import inference.GrpcService.ModelInferResponse -import io.grpc.ManagedChannel - -/** - * Client wrapper for calling a Cortex Managed Inference Service (go/cmis) ML Model using GRPC. - * @param httpClient Finagle HTTP Client to use for connection. - * @param modelPath Wily path to the ML Model service (e.g. /cluster/local/role/service/instance). - */ -case class ManagedModelClient( - httpClient: Http.Client, - modelPath: String) - extends MLModelInferenceClient { - - private val channel: ManagedChannel = - FinagleChannelBuilder.forTarget(modelPath).httpClient(httpClient).build() - - private val inferenceServiceStub = GRPCInferenceServiceGrpc.newFutureStub(channel) - - def score(request: ModelInferRequest): Stitch[ModelInferResponse] = { - Stitch - .callFuture( - FutureConverters - .RichListenableFuture(inferenceServiceStub.modelInfer(request)).toTwitter) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala deleted file mode 100644 index 9dfdf7415..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/ModelSelector.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.common - -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Selector for choosing which Model ID/Name to use when calling an underlying ML Model Service. - */ -trait ModelSelector[-Query <: PipelineQuery] { - def apply(query: Query): Option[String] -} - -/** - * Simple Model ID Selector that chooses model based off of a Param object. - * @param param ConfigAPI Param that decides the model id. - */ -case class ParamModelSelector[Query <: PipelineQuery](param: Param[String]) - extends ModelSelector[Query] { - override def apply(query: Query): Option[String] = Some(query.params(param)) -} - -/** - * Static Selector that chooses the same model name always - * @param modelName The model name to use. - */ -case class StaticModelSelector(modelName: String) extends ModelSelector[PipelineQuery] { - override def apply(query: PipelineQuery): Option[String] = Some(modelName) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala deleted file mode 100644 index d5a5ccb50..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common/NaviModelClient.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.common - -import com.twitter.finagle.Http -import com.twitter.finagle.grpc.FinagleChannelBuilder -import com.twitter.finagle.grpc.FutureConverters -import com.twitter.mlserving.frontend.TFServingInferenceServiceImpl -import com.twitter.stitch.Stitch -import tensorflow.serving.PredictionServiceGrpc -import inference.GrpcService.ModelInferRequest -import inference.GrpcService.ModelInferResponse -import io.grpc.ManagedChannel -import io.grpc.Status - -/** - * Client wrapper for calling a Navi Inference Service (go/navi). - * @param httpClient Finagle HTTP Client to use for connection. - * @param modelPath Wily path to the ML Model service (e.g. /s/role/service). - */ -case class NaviModelClient( - httpClient: Http.Client, - modelPath: String) - extends MLModelInferenceClient { - - private val channel: ManagedChannel = - FinagleChannelBuilder - .forTarget(modelPath) - .httpClient(httpClient) - // Navi enforces an authority name. - .overrideAuthority("rustserving") - // certain GRPC errors need to be retried. - .enableRetryForStatus(Status.UNKNOWN) - .enableRetryForStatus(Status.RESOURCE_EXHAUSTED) - // this is required at channel level as mTLS is enabled at httpClient level - .usePlaintext() - .build() - - private val inferenceServiceStub = PredictionServiceGrpc.newFutureStub(channel) - - def score(request: ModelInferRequest): Stitch[ModelInferResponse] = { - val tfServingRequest = TFServingInferenceServiceImpl.adaptModelInferRequest(request) - Stitch - .callFuture( - FutureConverters - .RichListenableFuture(inferenceServiceStub.predict(tfServingRequest)).toTwitter - .map { response => - TFServingInferenceServiceImpl.adaptModelInferResponse(response) - } - ) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD deleted file mode 100644 index 80e97e4a4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-http/src/main/scala", - "finatra-internal/mtls/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/scala/com/twitter/ml/featurestore/lib", - "src/thrift/com/twitter/ml/prediction_service:prediction_service-java", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala deleted file mode 100644 index 67c85407d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorer.scala +++ /dev/null @@ -1,137 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cortex - -import com.google.protobuf.ByteString -import com.twitter.ml.prediction_service.BatchPredictionRequest -import com.twitter.ml.prediction_service.BatchPredictionResponse -import com.twitter.product_mixer.component_library.scorer.common.ManagedModelClient -import com.twitter.product_mixer.component_library.scorer.common.ModelSelector -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.product_mixer.core.feature.datarecord.TensorDataRecordCompatible -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordConverter -import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordExtractor -import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import inference.GrpcService -import inference.GrpcService.ModelInferRequest -import inference.GrpcService.ModelInferResponse -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch -import org.apache.thrift.TDeserializer -import org.apache.thrift.TSerializer -import scala.collection.JavaConverters._ - -private[cortex] class CortexManagedDataRecordScorer[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - QueryFeatures <: BaseDataRecordFeature[Query, _], - CandidateFeatures <: BaseDataRecordFeature[Candidate, _], - ResultFeatures <: BaseDataRecordFeature[Candidate, _] with TensorDataRecordCompatible[_] -]( - override val identifier: ScorerIdentifier, - modelSignature: String, - modelSelector: ModelSelector[Query], - modelClient: ManagedModelClient, - queryFeatures: FeaturesScope[QueryFeatures], - candidateFeatures: FeaturesScope[CandidateFeatures], - resultFeatures: Set[ResultFeatures]) - extends Scorer[Query, Candidate] { - - require(resultFeatures.nonEmpty, "Result features cannot be empty") - override val features: Set[Feature[_, _]] = resultFeatures.asInstanceOf[Set[Feature[_, _]]] - - private val queryDataRecordAdapter = new DataRecordConverter(queryFeatures) - private val candidatesDataRecordAdapter = new DataRecordConverter(candidateFeatures) - private val resultDataRecordExtractor = new DataRecordExtractor(resultFeatures) - - private val localTSerializer = new ThreadLocal[TSerializer] { - override protected def initialValue: TSerializer = new TSerializer() - } - - private val localTDeserializer = new ThreadLocal[TDeserializer] { - override protected def initialValue: TDeserializer = new TDeserializer() - } - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] = { - modelClient.score(buildRequest(query, candidates)).map(buildResponse(candidates, _)) - } - - /** - * Takes candidates to be scored and converts it to a ModelInferRequest that can be passed to the - * managed ML service - */ - private def buildRequest( - query: Query, - scorerCandidates: Seq[CandidateWithFeatures[Candidate]] - ): ModelInferRequest = { - // Convert the feature maps to thrift data records and construct thrift request. - val thriftDataRecords = scorerCandidates.map { candidate => - candidatesDataRecordAdapter.toDataRecord(candidate.features) - } - val batchRequest = new BatchPredictionRequest(thriftDataRecords.asJava) - query.features.foreach { featureMap => - batchRequest.setCommonFeatures(queryDataRecordAdapter.toDataRecord(featureMap)) - } - val serializedBatchRequest = localTSerializer.get().serialize(batchRequest) - - // Build Tensor Request - val requestBuilder = ModelInferRequest - .newBuilder() - - modelSelector.apply(query).foreach { modelName => - requestBuilder.setModelName(modelName) // model name in the model config - } - - val inputTensorBuilder = ModelInferRequest.InferInputTensor - .newBuilder() - .setName("request") - .setDatatype("UINT8") - .addShape(serializedBatchRequest.length) - - val inferParameter = GrpcService.InferParameter - .newBuilder() - .setStringParam(modelSignature) // signature of exported tf function - .build() - - requestBuilder - .addInputs(inputTensorBuilder) - .addRawInputContents(ByteString.copyFrom(serializedBatchRequest)) - .putParameters("signature_name", inferParameter) - .build() - } - - private def buildResponse( - scorerCandidates: Seq[CandidateWithFeatures[Candidate]], - response: ModelInferResponse - ): Seq[FeatureMap] = { - - val responseByteString = if (response.getRawOutputContentsList.isEmpty()) { - throw PipelineFailure( - IllegalStateFailure, - "Model inference response has empty raw outputContents") - } else { - response.getRawOutputContents(0) - } - val batchPredictionResponse: BatchPredictionResponse = new BatchPredictionResponse() - localTDeserializer.get().deserialize(batchPredictionResponse, responseByteString.toByteArray) - - // get the prediction values from the batch prediction response - val resultScoreMaps = - batchPredictionResponse.predictions.asScala.map(resultDataRecordExtractor.fromDataRecord) - - if (resultScoreMaps.size != scorerCandidates.size) { - throw PipelineFailure(IllegalStateFailure, "Result Size mismatched candidates size") - } - - resultScoreMaps - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala deleted file mode 100644 index 026cfa696..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceDataRecordScorerBuilder.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cortex - -import com.twitter.finagle.Http -import com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule.FinagleHttpClientModule -import com.twitter.product_mixer.component_library.scorer.common.ManagedModelClient -import com.twitter.product_mixer.component_library.scorer.common.ModelSelector -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.product_mixer.core.feature.datarecord.TensorDataRecordCompatible -import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import javax.inject.Inject -import javax.inject.Named -import javax.inject.Singleton - -@Singleton -class CortexManagedInferenceServiceDataRecordScorerBuilder @Inject() ( - @Named(FinagleHttpClientModule) httpClient: Http.Client) { - - /** - * Builds a configurable Scorer to call into your desired DataRecord-backed Cortex Managed ML Model Service. - * - * If your service does not bind an Http.Client implementation, add - * [[com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule]] - * to your server module list - * - * @param scorerIdentifier Unique identifier for the scorer - * @param modelPath MLS path to model - * @param modelSignature Model Signature Key - * @param modelSelector [[ModelSelector]] for choosing the model name, can be an anon function. - * @param candidateFeatures Desired candidate level feature store features to pass to the model. - * @param resultFeatures Desired candidate level feature store features to extract from the model. - * Since the Cortex Managed Platform always returns tensor values, the - * feature must use a [[TensorDataRecordCompatible]]. - * @tparam Query Type of pipeline query. - * @tparam Candidate Type of candidates to score. - * @tparam QueryFeatures type of the query level features consumed by the scorer. - * @tparam CandidateFeatures type of the candidate level features consumed by the scorer. - * @tparam ResultFeatures type of the candidate level features returned by the scorer. - */ - def build[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - QueryFeatures <: BaseDataRecordFeature[Query, _], - CandidateFeatures <: BaseDataRecordFeature[Candidate, _], - ResultFeatures <: BaseDataRecordFeature[Candidate, _] with TensorDataRecordCompatible[_] - ]( - scorerIdentifier: ScorerIdentifier, - modelPath: String, - modelSignature: String, - modelSelector: ModelSelector[Query], - queryFeatures: FeaturesScope[QueryFeatures], - candidateFeatures: FeaturesScope[CandidateFeatures], - resultFeatures: Set[ResultFeatures] - ): Scorer[Query, Candidate] = - new CortexManagedDataRecordScorer( - identifier = scorerIdentifier, - modelSignature = modelSignature, - modelSelector = modelSelector, - modelClient = ManagedModelClient(httpClient, modelPath), - queryFeatures = queryFeatures, - candidateFeatures = candidateFeatures, - resultFeatures = resultFeatures - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala deleted file mode 100644 index be96e78be..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorer.scala +++ /dev/null @@ -1,97 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cortex - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.component_library.scorer.common.MLModelInferenceClient -import com.twitter.product_mixer.component_library.scorer.tensorbuilder.ModelInferRequestBuilder -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch -import com.twitter.util.logging.Logging -import inference.GrpcService.ModelInferRequest -import inference.GrpcService.ModelInferResponse.InferOutputTensor -import scala.collection.convert.ImplicitConversions.`collection AsScalaIterable` - -private[scorer] class CortexManagedInferenceServiceTensorScorer[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] -]( - override val identifier: ScorerIdentifier, - modelInferRequestBuilder: ModelInferRequestBuilder[ - Query, - Candidate - ], - resultFeatureExtractors: Seq[FeatureWithExtractor[Query, Candidate, _]], - client: MLModelInferenceClient, - statsReceiver: StatsReceiver) - extends Scorer[Query, Candidate] - with Logging { - - require(resultFeatureExtractors.nonEmpty, "Result Extractors cannot be empty") - - private val managedServiceRequestFailures = statsReceiver.counter("managedServiceRequestFailures") - override val features: Set[Feature[_, _]] = - resultFeatureExtractors.map(_.feature).toSet.asInstanceOf[Set[Feature[_, _]]] - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] = { - val batchInferRequest: ModelInferRequest = modelInferRequestBuilder(query, candidates) - - val managedServiceResponse: Stitch[Seq[InferOutputTensor]] = - client.score(batchInferRequest).map(_.getOutputsList.toSeq).onFailure { e => - error(s"request to ML Managed Service Failed: $e") - managedServiceRequestFailures.incr() - } - - managedServiceResponse.map { responses => - extractResponse(query, candidates.map(_.candidate), responses) - } - } - - def extractResponse( - query: Query, - candidates: Seq[Candidate], - tensorOutput: Seq[InferOutputTensor] - ): Seq[FeatureMap] = { - val featureMapBuilders = candidates.map { _ => FeatureMapBuilder.apply() } - // Extract the feature for each candidate from the tensor outputs - resultFeatureExtractors.foreach { - case FeatureWithExtractor(feature, extractor) => - val extractedValues = extractor.apply(query, tensorOutput) - if (candidates.size != extractedValues.size) { - throw PipelineFailure( - IllegalStateFailure, - s"Managed Service returned a different number of $feature than the number of candidates." + - s"Returned ${extractedValues.size} scores but there were ${candidates.size} candidates." - ) - } - // Go through the extracted features list one by one and update the feature map result for each candidate. - featureMapBuilders.zip(extractedValues).foreach { - case (builder, value) => - builder.add(feature, Some(value)) - } - } - - featureMapBuilders.map(_.build()) - } -} - -case class FeatureWithExtractor[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any], - ResultType -]( - feature: Feature[Candidate, Option[ResultType]], - featureExtractor: ModelFeatureExtractor[Query, ResultType]) - -class UnexpectedFeatureTypeException(feature: Feature[_, _]) - extends UnsupportedOperationException(s"Unsupported Feature type passed in $feature") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala deleted file mode 100644 index 84ef39fd7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/CortexManagedInferenceServiceTensorScorerBuilder.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cortex - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.component_library.scorer.common.MLModelInferenceClient -import com.twitter.product_mixer.component_library.scorer.tensorbuilder.ModelInferRequestBuilder -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CortexManagedInferenceServiceTensorScorerBuilder @Inject() ( - statsReceiver: StatsReceiver) { - - /** - * Builds a configurable Scorer to call into your desired Cortex Managed ML Model Service. - * - * If your service does not bind an Http.Client implementation, add - * [[com.twitter.product_mixer.component_library.module.http.FinagleHttpClientModule]] - * to your server module list - * - * @param scorerIdentifier Unique identifier for the scorer - * @param resultFeatureExtractors The result features an their tensor extractors for each candidate. - * @tparam Query Type of pipeline query. - * @tparam Candidate Type of candidates to score. - * @tparam QueryFeatures type of the query level features consumed by the scorer. - * @tparam CandidateFeatures type of the candidate level features consumed by the scorer. - */ - def build[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - scorerIdentifier: ScorerIdentifier, - modelInferRequestBuilder: ModelInferRequestBuilder[ - Query, - Candidate - ], - resultFeatureExtractors: Seq[FeatureWithExtractor[Query, Candidate, _]], - client: MLModelInferenceClient - ): Scorer[Query, Candidate] = - new CortexManagedInferenceServiceTensorScorer( - scorerIdentifier, - modelInferRequestBuilder, - resultFeatureExtractors, - client, - statsReceiver.scope(scorerIdentifier.name) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala deleted file mode 100644 index 3a44d5ceb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cortex/ModelFeatureExtractor.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cortex - -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import inference.GrpcService.ModelInferResponse.InferOutputTensor - -/** - * Extractor defining how a Scorer should go from outputted tensors to the individual results - * for each candidate being scored. - * - * @tparam Result the type of the Value being returned. - * Users can pass in an anonymous function - */ -trait ModelFeatureExtractor[-Query <: PipelineQuery, Result] { - def apply(query: Query, tensorOutput: Seq[InferOutputTensor]): Seq[Result] -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel deleted file mode 100644 index ce01a28e6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "cr-ml-ranker/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - ], - exports = [ - "cr-ml-ranker/thrift/src/main/thrift:thrift-scala", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala deleted file mode 100644 index 9bc1b6aae..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerScorer.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cr_ml_ranker - -import com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker.CrMlRankerCommonFeatures -import com.twitter.product_mixer.component_library.feature_hydrator.query.cr_ml_ranker.CrMlRankerRankingConfig -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -object CrMlRankerScore extends Feature[TweetCandidate, Double] - -/** - * Scorer that scores tweets using the Content Recommender ML Light Ranker: http://go/cr-ml-ranker - */ -@Singleton -class CrMlRankerScorer @Inject() (crMlRanker: CrMlRankerScoreStitchClient) - extends Scorer[PipelineQuery, TweetCandidate] { - - override val identifier: ScorerIdentifier = ScorerIdentifier("CrMlRanker") - - override val features: Set[Feature[_, _]] = Set(CrMlRankerScore) - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[TweetCandidate]] - ): Stitch[Seq[FeatureMap]] = { - val queryFeatureMap = query.features.getOrElse(FeatureMap.empty) - val rankingConfig = queryFeatureMap.get(CrMlRankerRankingConfig) - val commonFeatures = queryFeatureMap.get(CrMlRankerCommonFeatures) - val userId = query.getRequiredUserId - - val scoresStitch = Stitch.collect(candidates.map { candidateWithFeatures => - crMlRanker - .getScore(userId, candidateWithFeatures.candidate, rankingConfig, commonFeatures).map( - _.score) - }) - scoresStitch.map { scores => - scores.map { score => - FeatureMapBuilder() - .add(CrMlRankerScore, score) - .build() - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala deleted file mode 100644 index 15e9103f1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/cr_ml_ranker/CrMlRankerStitchClient.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.cr_ml_ranker - -import com.twitter.cr_ml_ranker.{thriftscala => t} -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.stitch.SeqGroup -import com.twitter.stitch.Stitch -import com.twitter.util.Future -import com.twitter.util.Return -import com.twitter.util.Try - -case class CrMlRankerResult( - tweetId: Long, - score: Double) - -class CrMlRankerScoreStitchClient( - crMLRanker: t.CrMLRanker.MethodPerEndpoint, - maxBatchSize: Int) { - - def getScore( - userId: Long, - tweetCandidate: BaseTweetCandidate, - rankingConfig: t.RankingConfig, - commonFeatures: t.CommonFeatures - ): Stitch[CrMlRankerResult] = { - Stitch.call( - tweetCandidate, - CrMlRankerGroup( - userId = userId, - rankingConfig = rankingConfig, - commonFeatures = commonFeatures - ) - ) - } - - private case class CrMlRankerGroup( - userId: Long, - rankingConfig: t.RankingConfig, - commonFeatures: t.CommonFeatures) - extends SeqGroup[BaseTweetCandidate, CrMlRankerResult] { - - override val maxSize: Int = maxBatchSize - - override protected def run( - tweetCandidates: Seq[BaseTweetCandidate] - ): Future[Seq[Try[CrMlRankerResult]]] = { - val crMlRankerCandidates = - tweetCandidates.map { tweetCandidate => - t.RankingCandidate( - tweetId = tweetCandidate.id, - hydrationContext = Some( - t.FeatureHydrationContext.HomeHydrationContext(t - .HomeFeatureHydrationContext(tweetAuthor = None))) - ) - } - - val thriftResults = crMLRanker.getRankedResults( - t.RankingRequest( - requestContext = t.RankingRequestContext( - userId = userId, - config = rankingConfig - ), - candidates = crMlRankerCandidates, - commonFeatures = commonFeatures.commonFeatures - ) - ) - - thriftResults.map { response => - response.scoredTweets.map { scoredTweet => - Return( - CrMlRankerResult( - tweetId = scoredTweet.tweetId, - score = scoredTweet.score - ) - ) - } - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD deleted file mode 100644 index 355427143..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "cortex-deepbird/thrift/src/main/thrift:thrift-java", - "finagle/finagle-http/src/main/scala", - "finatra-internal/mtls/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "scrooge/scrooge-serializer", - "src/java/com/twitter/ml/api:api-base", - "src/java/com/twitter/ml/common/base", - "src/java/com/twitter/ml/prediction/core", - "src/thrift/com/twitter/ml/prediction_service:prediction_service-java", - "src/thrift/com/twitter/ml/prediction_service:prediction_service-scala", - "twml/runtime/src/main/scala/com/twitter/deepbird/runtime/prediction_engine", - ], - exports = [ - "cortex-deepbird/thrift/src/main/thrift:thrift-java", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/java/com/twitter/ml/prediction/core", - "src/thrift/com/twitter/ml/prediction_service:prediction_service-java", - "twml/runtime/src/main/scala/com/twitter/deepbird/runtime/prediction_engine", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala deleted file mode 100644 index 59b1f29bf..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/BaseDeepbirdV2Scorer.scala +++ /dev/null @@ -1,91 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.deepbird - -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.ml.prediction_service.BatchPredictionRequest -import com.twitter.ml.prediction_service.BatchPredictionResponse -import com.twitter.cortex.deepbird.thriftjava.{ModelSelector => TModelSelector} -import com.twitter.ml.api.DataRecord -import com.twitter.product_mixer.component_library.scorer.common.ModelSelector -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordConverter -import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordExtractor -import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import scala.collection.JavaConverters._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch -import com.twitter.util.Future - -abstract class BaseDeepbirdV2Scorer[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - QueryFeatures <: BaseDataRecordFeature[Query, _], - CandidateFeatures <: BaseDataRecordFeature[Candidate, _], - ResultFeatures <: BaseDataRecordFeature[Candidate, _] -]( - override val identifier: ScorerIdentifier, - modelIdSelector: ModelSelector[Query], - queryFeatures: FeaturesScope[QueryFeatures], - candidateFeatures: FeaturesScope[CandidateFeatures], - resultFeatures: Set[ResultFeatures]) - extends Scorer[Query, Candidate] { - - private val queryDataRecordConverter = new DataRecordConverter(queryFeatures) - private val candidateDataRecordConverter = new DataRecordConverter(candidateFeatures) - private val resultDataRecordExtractor = new DataRecordExtractor(resultFeatures) - - require(resultFeatures.nonEmpty, "Result features cannot be empty") - override val features: Set[Feature[_, _]] = resultFeatures.asInstanceOf[Set[Feature[_, _]]] - def getBatchPredictions( - request: BatchPredictionRequest, - modelSelector: TModelSelector - ): Future[BatchPredictionResponse] - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] = { - // Convert all candidate feature maps to java datarecords then to scala datarecords. - val thriftCandidateDataRecords = candidates.map { candidate => - candidateDataRecordConverter.toDataRecord(candidate.features) - } - - val request = new BatchPredictionRequest(thriftCandidateDataRecords.asJava) - - // Convert the query feature map to data record if available. - query.features.foreach { featureMap => - request.setCommonFeatures(queryDataRecordConverter.toDataRecord(featureMap)) - } - - val modelSelector = modelIdSelector - .apply(query).map { id => - val selector = new TModelSelector() - selector.setId(id) - selector - }.orNull - - Stitch.callFuture(getBatchPredictions(request, modelSelector)).map { response => - val dataRecords = Option(response.predictions).map(_.asScala).getOrElse(Seq.empty) - buildResults(candidates, dataRecords) - } - } - - private def buildResults( - candidates: Seq[CandidateWithFeatures[Candidate]], - dataRecords: Seq[DataRecord] - ): Seq[FeatureMap] = { - if (dataRecords.size != candidates.size) { - throw PipelineFailure(IllegalStateFailure, "Result Size mismatched candidates size") - } - - dataRecords.map { resultDataRecord => - resultDataRecordExtractor.fromDataRecord(resultDataRecord) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala deleted file mode 100644 index 330706490..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/DeepbirdV2PredictionServerScorer.scala +++ /dev/null @@ -1,55 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.deepbird - -import com.twitter.cortex.deepbird.{thriftjava => t} -import com.twitter.ml.prediction_service.BatchPredictionRequest -import com.twitter.ml.prediction_service.BatchPredictionResponse -import com.twitter.product_mixer.component_library.scorer.common.ModelSelector -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.util.Future - -/** - * Configurable Scorer that calls any Deepbird Prediction Service thrift. - * @param identifier Unique identifier for the scorer - * @param predictionService The Prediction Thrift Service - * @param modelSelector Model ID Selector to decide which model to select, can also be represented - * as an anonymous function: { query: Query => Some("Ex") } - * @param queryFeatures The Query Features to convert and pass to the deepbird model. - * @param candidateFeatures The Candidate Features to convert and pass to the deepbird model. - * @param resultFeatures The Candidate features returned by the model. - * @tparam Query Type of pipeline query. - * @tparam Candidate Type of candidates to score. - * @tparam QueryFeatures type of the query level features consumed by the scorer. - * @tparam CandidateFeatures type of the candidate level features consumed by the scorer. - * @tparam ResultFeatures type of the candidate level features returned by the scorer. - */ -case class DeepbirdV2PredictionServerScorer[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - QueryFeatures <: BaseDataRecordFeature[Query, _], - CandidateFeatures <: BaseDataRecordFeature[Candidate, _], - ResultFeatures <: BaseDataRecordFeature[Candidate, _] -]( - override val identifier: ScorerIdentifier, - predictionService: t.DeepbirdPredictionService.ServiceToClient, - modelSelector: ModelSelector[Query], - queryFeatures: FeaturesScope[QueryFeatures], - candidateFeatures: FeaturesScope[CandidateFeatures], - resultFeatures: Set[ResultFeatures]) - extends BaseDeepbirdV2Scorer[ - Query, - Candidate, - QueryFeatures, - CandidateFeatures, - ResultFeatures - ](identifier, modelSelector, queryFeatures, candidateFeatures, resultFeatures) { - - override def getBatchPredictions( - request: BatchPredictionRequest, - modelSelector: t.ModelSelector - ): Future[BatchPredictionResponse] = - predictionService.batchPredictFromModel(request, modelSelector) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala deleted file mode 100644 index c60651be9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/LollyPredictionEngineScorer.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.deepbird - -import com.twitter.ml.prediction.core.PredictionEngine -import com.twitter.ml.prediction_service.PredictionRequest -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordConverter -import com.twitter.product_mixer.core.feature.featuremap.datarecord.DataRecordExtractor -import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Scorer that locally loads a Deepbird model. - * @param identifier Unique identifier for the scorer - * @param predictionEngine Prediction Engine hosting the Deepbird model. - * @param candidateFeatures The Candidate Features to convert and pass to the deepbird model. - * @param resultFeatures The Candidate features returned by the model. - * @tparam Query Type of pipeline query. - * @tparam Candidate Type of candidates to score. - * @tparam QueryFeatures type of the query level features consumed by the scorer. - * @tparam CandidateFeatures type of the candidate level features consumed by the scorer. - * @tparam ResultFeatures type of the candidate level features returned by the scorer. - */ -class LollyPredictionEngineScorer[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - QueryFeatures <: BaseDataRecordFeature[Query, _], - CandidateFeatures <: BaseDataRecordFeature[Candidate, _], - ResultFeatures <: BaseDataRecordFeature[Candidate, _] -]( - override val identifier: ScorerIdentifier, - predictionEngine: PredictionEngine, - candidateFeatures: FeaturesScope[CandidateFeatures], - resultFeatures: Set[ResultFeatures]) - extends Scorer[Query, Candidate] { - - private val dataRecordAdapter = new DataRecordConverter(candidateFeatures) - - require(resultFeatures.nonEmpty, "Result features cannot be empty") - override val features: Set[Feature[_, _]] = resultFeatures.asInstanceOf[Set[Feature[_, _]]] - - private val resultsDataRecordExtractor = new DataRecordExtractor(resultFeatures) - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] = { - val featureMaps = candidates.map { candidateWithFeatures => - val dataRecord = dataRecordAdapter.toDataRecord(candidateWithFeatures.features) - val predictionResponse = predictionEngine.apply(new PredictionRequest(dataRecord), true) - resultsDataRecordExtractor.fromDataRecord(predictionResponse.getPrediction) - } - Stitch.value(featureMaps) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala deleted file mode 100644 index 847d62c89..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/deepbird/TensorflowPredictionEngineScorer.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.deepbird - -import com.twitter.cortex.deepbird.runtime.prediction_engine.TensorflowPredictionEngine -import com.twitter.cortex.deepbird.thriftjava.ModelSelector -import com.twitter.ml.prediction_service.BatchPredictionRequest -import com.twitter.ml.prediction_service.BatchPredictionResponse -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.product_mixer.core.feature.featuremap.datarecord.FeaturesScope -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.util.Future - -/** - * Configurable Scorer that calls a TensorflowPredictionEngine. - * @param identifier Unique identifier for the scorer - * @param tensorflowPredictionEngine The TensorFlow Prediction Engine - * @param queryFeatures The Query Features to convert and pass to the deepbird model. - * @param candidateFeatures The Candidate Features to convert and pass to the deepbird model. - * @param resultFeatures The Candidate features returned by the model. - * @tparam Query Type of pipeline query. - * @tparam Candidate Type of candidates to score. - * @tparam QueryFeatures type of the query level features consumed by the scorer. - * @tparam CandidateFeatures type of the candidate level features consumed by the scorer. - * @tparam ResultFeatures type of the candidate level features returned by the scorer. - */ -class TensorflowPredictionEngineScorer[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - QueryFeatures <: BaseDataRecordFeature[Query, _], - CandidateFeatures <: BaseDataRecordFeature[Candidate, _], - ResultFeatures <: BaseDataRecordFeature[Candidate, _] -]( - override val identifier: ScorerIdentifier, - tensorflowPredictionEngine: TensorflowPredictionEngine, - queryFeatures: FeaturesScope[QueryFeatures], - candidateFeatures: FeaturesScope[CandidateFeatures], - resultFeatures: Set[ResultFeatures]) - extends BaseDeepbirdV2Scorer[ - Query, - Candidate, - QueryFeatures, - CandidateFeatures, - ResultFeatures - ]( - identifier, - { _: Query => - None - }, - queryFeatures, - candidateFeatures, - resultFeatures) { - - override def getBatchPredictions( - request: BatchPredictionRequest, - modelSelector: ModelSelector - ): Future[BatchPredictionResponse] = tensorflowPredictionEngine.getBatchPrediction(request) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD deleted file mode 100644 index af69ac038..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala deleted file mode 100644 index 3185ce019..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/param_gated/ParamGatedScorer.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.param_gated - -import com.twitter.product_mixer.component_library.scorer.param_gated.ParamGatedScorer.IdentifierPrefix -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[scorer]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this [[scorer]] on and off - * @param scorer the underlying [[scorer]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class ParamGatedScorer[-Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - enabledParam: Param[Boolean], - scorer: Scorer[Query, Result]) - extends Scorer[Query, Result] - with Conditionally[Query] { - override val identifier: ScorerIdentifier = ScorerIdentifier( - IdentifierPrefix + scorer.identifier.name) - override val alerts: Seq[Alert] = scorer.alerts - override val features: Set[Feature[_, _]] = scorer.features - override def onlyIf(query: Query): Boolean = - Conditionally.and(query, scorer, query.params(enabledParam)) - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Result]] - ): Stitch[Seq[FeatureMap]] = scorer(query, candidates) -} - -object ParamGatedScorer { - val IdentifierPrefix = "ParamGated" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD deleted file mode 100644 index af69ac038..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala deleted file mode 100644 index 3309fbdca..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/qualityfactor_gated/QualityFactorGatedScorer.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.qualityfactor_gated - -import com.twitter.product_mixer.component_library.scorer.qualityfactor_gated.QualityFactorGatedScorer.IdentifierPrefix -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[scorer]] with [[Conditionally]] based on quality factor value and threshold - * - * @param qualityFactorThreshold quliaty factor threshold that turn off the scorer - * @param pipelineIdentifier identifier of the pipeline that quality factor is based on - * @param scorer the underlying [[scorer]] to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - * @tparam Result The type of the candidates - */ -case class QualityFactorGatedScorer[ - -Query <: PipelineQuery with HasQualityFactorStatus, - Result <: UniversalNoun[Any] -]( - pipelineIdentifier: ComponentIdentifier, - qualityFactorThresholdParam: Param[Double], - scorer: Scorer[Query, Result]) - extends Scorer[Query, Result] - with Conditionally[Query] { - - override val identifier: ScorerIdentifier = ScorerIdentifier( - IdentifierPrefix + scorer.identifier.name) - - override val alerts: Seq[Alert] = scorer.alerts - - override val features: Set[Feature[_, _]] = scorer.features - - override def onlyIf(query: Query): Boolean = - Conditionally.and( - query, - scorer, - query.getQualityFactorCurrentValue(pipelineIdentifier) >= query.params( - qualityFactorThresholdParam)) - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Result]] - ): Stitch[Seq[FeatureMap]] = scorer(query, candidates) -} - -object QualityFactorGatedScorer { - val IdentifierPrefix = "QualityFactorGated" -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD deleted file mode 100644 index e18c39662..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ml/api:embedding-scala", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala deleted file mode 100644 index bbdf2b5c6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BooleanInferInputTensorBuilder.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import inference.GrpcService.ModelInferRequest.InferInputTensor - -case object BooleanInferInputTensorBuilder extends InferInputTensorBuilder[Boolean] { - def apply( - featureName: String, - featureValues: Seq[Boolean] - ): Seq[InferInputTensor] = { - val tensorShape = Seq(featureValues.size, 1) - InferInputTensorBuilder.buildBoolInferInputTensor(featureName, featureValues, tensorShape) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala deleted file mode 100644 index 8b36c514f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/BytesInferInputTensorBuilder.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import inference.GrpcService.ModelInferRequest.InferInputTensor - -case object BytesInferInputTensorBuilder extends InferInputTensorBuilder[String] { - def apply( - featureName: String, - featureValues: Seq[String] - ): Seq[InferInputTensor] = { - val tensorShape = Seq(featureValues.size, 1) - InferInputTensorBuilder.buildBytesInferInputTensor(featureName, featureValues, tensorShape) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala deleted file mode 100644 index ed7c28cdb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/CandidateInferInputTensorBuilder.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import com.twitter.ml.api.thriftscala.FloatTensor -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.ModelFeatureName -import com.twitter.product_mixer.core.feature.featuremap.featurestorev1.FeatureStoreV1FeatureMap._ -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import inference.GrpcService.ModelInferRequest.InferInputTensor - -class CandidateInferInputTensorBuilder[-Candidate <: UniversalNoun[Any], +Value]( - builder: InferInputTensorBuilder[Value], - features: Set[_ <: Feature[Candidate, _] with ModelFeatureName]) { - def apply( - candidates: Seq[CandidateWithFeatures[Candidate]], - ): Seq[InferInputTensor] = { - features.flatMap { feature => - val featureValues: Seq[Value] = feature match { - case feature: FeatureStoreV1CandidateFeature[_, Candidate, _, Value] => - candidates.map(_.features.getFeatureStoreV1CandidateFeature(feature)) - case feature: FeatureStoreV1QueryFeature[_, _, _] => - throw new UnexpectedFeatureTypeException(feature) - case feature: FeatureWithDefaultOnFailure[Candidate, Value] => - candidates.map(_.features.getTry(feature).toOption.getOrElse(feature.defaultValue)) - case feature: Feature[Candidate, Value] => - candidates.map(_.features.get(feature)) - } - builder.apply(feature.featureName, featureValues) - }.toSeq - } -} - -case class CandidateBooleanInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]]( - features: Set[_ <: Feature[Candidate, Boolean] with ModelFeatureName]) - extends CandidateInferInputTensorBuilder[Candidate, Boolean]( - BooleanInferInputTensorBuilder, - features) - -case class CandidateBytesInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]]( - features: Set[_ <: Feature[Candidate, String] with ModelFeatureName]) - extends CandidateInferInputTensorBuilder[Candidate, String]( - BytesInferInputTensorBuilder, - features) - -case class CandidateFloat32InferInputTensorBuilder[-Candidate <: UniversalNoun[Any]]( - features: Set[_ <: Feature[Candidate, _ <: AnyVal] with ModelFeatureName]) - extends CandidateInferInputTensorBuilder[Candidate, AnyVal]( - Float32InferInputTensorBuilder, - features) - -case class CandidateFloatTensorInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]]( - features: Set[_ <: Feature[Candidate, FloatTensor] with ModelFeatureName]) - extends CandidateInferInputTensorBuilder[Candidate, FloatTensor]( - FloatTensorInferInputTensorBuilder, - features) - -case class CandidateInt64InferInputTensorBuilder[-Candidate <: UniversalNoun[Any]]( - features: Set[_ <: Feature[Candidate, _ <: AnyVal] with ModelFeatureName]) - extends CandidateInferInputTensorBuilder[Candidate, AnyVal]( - Int64InferInputTensorBuilder, - features) - -case class CandidateSparseMapInferInputTensorBuilder[-Candidate <: UniversalNoun[Any]]( - features: Set[_ <: Feature[Candidate, Option[Map[Int, Double]]] with ModelFeatureName]) - extends CandidateInferInputTensorBuilder[Candidate, Option[Map[Int, Double]]]( - SparseMapInferInputTensorBuilder, - features) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala deleted file mode 100644 index a6fb674bc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Float32InferInputTensorBuilder.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import inference.GrpcService.ModelInferRequest.InferInputTensor - -case object Float32InferInputTensorBuilder extends InferInputTensorBuilder[AnyVal] { - - private def toFloat(x: AnyVal): Float = { - x match { - case y: Float => y - case y: Int => y.toFloat - case y: Long => y.toFloat - case y: Double => y.toFloat - case y => throw new UnexpectedDataTypeException(y, this) - } - } - - def apply( - featureName: String, - featureValues: Seq[AnyVal] - ): Seq[InferInputTensor] = { - val tensorShape = Seq(featureValues.size, 1) - InferInputTensorBuilder.buildFloat32InferInputTensor( - featureName, - featureValues.map(toFloat), - tensorShape) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala deleted file mode 100644 index d1f4f021f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/FloatTensorInferInputTensorBuilder.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import com.twitter.ml.api.thriftscala.FloatTensor -import inference.GrpcService.ModelInferRequest.InferInputTensor - -case object FloatTensorInferInputTensorBuilder extends InferInputTensorBuilder[FloatTensor] { - - private[tensorbuilder] def extractTensorShape(featureValues: Seq[FloatTensor]): Seq[Int] = { - val headFloatTensor = featureValues.head - if (headFloatTensor.shape.isEmpty) { - Seq( - featureValues.size, - featureValues.head.floats.size - ) - } else { - Seq(featureValues.size) ++ headFloatTensor.shape.get.map(_.toInt) - } - } - - def apply( - featureName: String, - featureValues: Seq[FloatTensor] - ): Seq[InferInputTensor] = { - if (featureValues.isEmpty) throw new EmptyFloatTensorException(featureName) - val tensorShape = extractTensorShape(featureValues) - val floatValues = featureValues.flatMap { featureValue => - featureValue.floats.map(_.toFloat) - } - InferInputTensorBuilder.buildFloat32InferInputTensor(featureName, floatValues, tensorShape) - } -} -class EmptyFloatTensorException(featureName: String) - extends RuntimeException(s"FloatTensor in feature $featureName is empty!") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala deleted file mode 100644 index e83fea4e2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/InferInputTensorBuilder.scala +++ /dev/null @@ -1,151 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import com.google.protobuf.ByteString -import com.twitter.product_mixer.core.feature.Feature -import inference.GrpcService.InferTensorContents -import inference.GrpcService.ModelInferRequest.InferInputTensor - -// This class contains most of common versions at Twitter, but in the future we can add more: -// https://github.com/kserve/kserve/blob/master/docs/predict-api/v2/required_api.md#tensor-data-1 - -trait InferInputTensorBuilder[Value] { - - def apply( - featureName: String, - featureValues: Seq[Value] - ): Seq[InferInputTensor] - -} - -object InferInputTensorBuilder { - - def checkTensorShapeMatchesValueLength( - featureName: String, - featureValues: Seq[Any], - tensorShape: Seq[Int] - ): Unit = { - val featureValuesSize = featureValues.size - val tensorShapeSize = tensorShape.product - if (featureValuesSize != tensorShapeSize) { - throw new FeatureValuesAndShapeMismatchException( - featureName, - featureValuesSize, - tensorShapeSize) - } - } - - def buildBoolInferInputTensor( - featureName: String, - featureValues: Seq[Boolean], - tensorShape: Seq[Int] - ): Seq[InferInputTensor] = { - - checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape) - - val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName) - tensorShape.foreach { shape => - inputTensorBuilder.addShape(shape) - } - val inputTensor = inputTensorBuilder - .setDatatype("BOOL") - .setContents { - val contents = InferTensorContents.newBuilder() - featureValues.foreach { featureValue => - contents.addBoolContents(featureValue) - } - contents - } - .build() - Seq(inputTensor) - } - - def buildBytesInferInputTensor( - featureName: String, - featureValues: Seq[String], - tensorShape: Seq[Int] - ): Seq[InferInputTensor] = { - - checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape) - - val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName) - tensorShape.foreach { shape => - inputTensorBuilder.addShape(shape) - } - val inputTensor = inputTensorBuilder - .setDatatype("BYTES") - .setContents { - val contents = InferTensorContents.newBuilder() - featureValues.foreach { featureValue => - val featureValueBytes = ByteString.copyFromUtf8(featureValue) - contents.addByteContents(featureValueBytes) - } - contents - } - .build() - Seq(inputTensor) - } - - def buildFloat32InferInputTensor( - featureName: String, - featureValues: Seq[Float], - tensorShape: Seq[Int] - ): Seq[InferInputTensor] = { - - checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape) - - val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName) - tensorShape.foreach { shape => - inputTensorBuilder.addShape(shape) - } - val inputTensor = inputTensorBuilder - .setDatatype("FP32") - .setContents { - val contents = InferTensorContents.newBuilder() - featureValues.foreach { featureValue => - contents.addFp32Contents(featureValue.floatValue) - } - contents - } - .build() - Seq(inputTensor) - } - - def buildInt64InferInputTensor( - featureName: String, - featureValues: Seq[Long], - tensorShape: Seq[Int] - ): Seq[InferInputTensor] = { - - checkTensorShapeMatchesValueLength(featureName, featureValues, tensorShape) - - val inputTensorBuilder = InferInputTensor.newBuilder().setName(featureName) - tensorShape.foreach { shape => - inputTensorBuilder.addShape(shape) - } - val inputTensor = inputTensorBuilder - .setDatatype("INT64") - .setContents { - val contents = InferTensorContents.newBuilder() - featureValues.foreach { featureValue => - contents.addInt64Contents(featureValue) - } - contents - } - .build() - Seq(inputTensor) - } -} - -class UnexpectedFeatureTypeException(feature: Feature[_, _]) - extends UnsupportedOperationException(s"Unsupported Feature type passed in $feature") - -class FeatureValuesAndShapeMismatchException( - featureName: String, - featureValuesSize: Int, - tensorShapeSize: Int) - extends UnsupportedOperationException( - s"Feature $featureName has mismatching FeatureValues (size: $featureValuesSize) and TensorShape (size: $tensorShapeSize)!") - -class UnexpectedDataTypeException[T](value: T, builder: InferInputTensorBuilder[_]) - extends UnsupportedOperationException( - s"Unsupported data type ${value} passed in at ${builder.getClass.toString}") diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala deleted file mode 100644 index 9743317d8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/Int64InferInputTensorBuilder.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import com.twitter.ml.featurestore.lib.Discrete -import inference.GrpcService.ModelInferRequest.InferInputTensor - -case object Int64InferInputTensorBuilder extends InferInputTensorBuilder[AnyVal] { - - private def toLong(x: AnyVal): Long = { - x match { - case y: Int => y.toLong - case y: Long => y - case y: Discrete => y.value - case y => throw new UnexpectedDataTypeException(y, this) - } - } - def apply( - featureName: String, - featureValues: Seq[AnyVal] - ): Seq[InferInputTensor] = { - val tensorShape = Seq(featureValues.size, 1) - InferInputTensorBuilder.buildInt64InferInputTensor( - featureName, - featureValues.map(toLong), - tensorShape) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala deleted file mode 100644 index e37c145fb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/ModelInferRequestBuilder.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import com.twitter.product_mixer.component_library.scorer.common.ModelSelector -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import inference.GrpcService.InferParameter -import inference.GrpcService.ModelInferRequest -import scala.collection.JavaConverters._ - -class ModelInferRequestBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]]( - queryInferInputTensorBuilders: Seq[QueryInferInputTensorBuilder[Query, Any]], - candidateInferInputTensorBuilders: Seq[ - CandidateInferInputTensorBuilder[Candidate, Any] - ], - modelSignatureName: String, - modelSelector: ModelSelector[Query]) { - - private val modelSignature: InferParameter = - InferParameter.newBuilder().setStringParam(modelSignatureName).build() - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]], - ): ModelInferRequest = { - val inferRequest = ModelInferRequest - .newBuilder() - .putParameters("signature_name", modelSignature) - modelSelector.apply(query).foreach { modelName => - inferRequest.setModelName(modelName) - } - queryInferInputTensorBuilders.foreach { builder => - inferRequest.addAllInputs(builder(query).asJava) - } - candidateInferInputTensorBuilders.foreach { builder => - inferRequest.addAllInputs(builder(candidates).asJava) - } - inferRequest.build() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala deleted file mode 100644 index 4415d61a1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/QueryInferInputTensorBuilder.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import com.twitter.ml.api.thriftscala.FloatTensor -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.ModelFeatureName -import com.twitter.product_mixer.core.feature.featuremap.featurestorev1.FeatureStoreV1FeatureMap._ -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import inference.GrpcService.ModelInferRequest.InferInputTensor - -class QueryInferInputTensorBuilder[-Query <: PipelineQuery, +Value]( - builder: InferInputTensorBuilder[Value], - features: Set[_ <: Feature[Query, _] with ModelFeatureName]) { - def apply(query: Query): Seq[InferInputTensor] = { - val featureMap = query.features.getOrElse(FeatureMap.empty) - features.flatMap { feature => - val queryFeatureValue: Value = feature match { - case feature: FeatureStoreV1QueryFeature[Query, _, Value] => - featureMap.getFeatureStoreV1QueryFeature(feature) - case feature: FeatureStoreV1CandidateFeature[Query, _, _, Value] => - throw new UnexpectedFeatureTypeException(feature) - case feature: FeatureWithDefaultOnFailure[Query, Value] => - featureMap.getTry(feature).toOption.getOrElse(feature.defaultValue) - case feature: Feature[Query, Value] => - featureMap.get(feature) - } - builder.apply(feature.featureName, Seq(queryFeatureValue)) - }.toSeq - } -} - -case class QueryBooleanInferInputTensorBuilder[-Query <: PipelineQuery]( - features: Set[_ <: Feature[Query, Boolean] with ModelFeatureName]) - extends QueryInferInputTensorBuilder[Query, Boolean](BooleanInferInputTensorBuilder, features) - -case class QueryBytesInferInputTensorBuilder[-Query <: PipelineQuery]( - features: Set[_ <: Feature[Query, String] with ModelFeatureName]) - extends QueryInferInputTensorBuilder[Query, String](BytesInferInputTensorBuilder, features) - -case class QueryFloat32InferInputTensorBuilder[-Query <: PipelineQuery]( - features: Set[_ <: Feature[Query, _ <: AnyVal] with ModelFeatureName]) - extends QueryInferInputTensorBuilder[Query, AnyVal](Float32InferInputTensorBuilder, features) - -case class QueryFloatTensorInferInputTensorBuilder[-Query <: PipelineQuery]( - features: Set[_ <: Feature[Query, FloatTensor] with ModelFeatureName]) - extends QueryInferInputTensorBuilder[Query, FloatTensor]( - FloatTensorInferInputTensorBuilder, - features) - -case class QueryInt64InferInputTensorBuilder[-Query <: PipelineQuery]( - features: Set[_ <: Feature[Query, _ <: AnyVal] with ModelFeatureName]) - extends QueryInferInputTensorBuilder[Query, AnyVal](Int64InferInputTensorBuilder, features) - -case class QuerySparseMapInferInputTensorBuilder[-Query <: PipelineQuery]( - features: Set[_ <: Feature[Query, Option[Map[Int, Double]]] with ModelFeatureName]) - extends QueryInferInputTensorBuilder[Query, Option[Map[Int, Double]]]( - SparseMapInferInputTensorBuilder, - features) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala deleted file mode 100644 index 038ff90db..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tensorbuilder/SparseMapInferInputTensorBuilder.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tensorbuilder - -import inference.GrpcService.InferTensorContents -import inference.GrpcService.ModelInferRequest.InferInputTensor - -case object SparseMapInferInputTensorBuilder - extends InferInputTensorBuilder[Option[Map[Int, Double]]] { - - private final val batchFeatureNameSuffix: String = "batch" - private final val keyFeatureNameSuffix: String = "key" - private final val valueFeatureNameSuffix: String = "value" - - def apply( - featureName: String, - featureValues: Seq[Option[Map[Int, Double]]] - ): Seq[InferInputTensor] = { - val batchIdsTensorContents = InferTensorContents.newBuilder() - val sparseKeysTensorContents = InferTensorContents.newBuilder() - val sparseValuesTensorContents = InferTensorContents.newBuilder() - featureValues.zipWithIndex.foreach { - case (featureValueOption, batchIndex) => - featureValueOption.foreach { featureValue => - featureValue.foreach { - case (sparseKey, sparseValue) => - batchIdsTensorContents.addInt64Contents(batchIndex.toLong) - sparseKeysTensorContents.addInt64Contents(sparseKey.toLong) - sparseValuesTensorContents.addFp32Contents(sparseValue.floatValue) - } - } - } - - val batchIdsInputTensor = InferInputTensor - .newBuilder() - .setName(Seq(featureName, batchFeatureNameSuffix).mkString("_")) - .addShape(batchIdsTensorContents.getInt64ContentsCount) - .addShape(1) - .setDatatype("INT64") - .setContents(batchIdsTensorContents) - .build() - - val sparseKeysInputTensor = InferInputTensor - .newBuilder() - .setName(Seq(featureName, keyFeatureNameSuffix).mkString("_")) - .addShape(sparseKeysTensorContents.getInt64ContentsCount) - .addShape(1) - .setDatatype("INT64") - .setContents(sparseKeysTensorContents) - .build() - - val sparseValuesInputTensor = InferInputTensor - .newBuilder() - .setName(Seq(featureName, valueFeatureNameSuffix).mkString("_")) - .addShape(sparseValuesTensorContents.getFp32ContentsCount) - .addShape(1) - .setDatatype("FP32") - .setContents(sparseValuesTensorContents) - .build() - - Seq(batchIdsInputTensor, sparseKeysInputTensor, sparseValuesInputTensor) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel deleted file mode 100644 index e306724d0..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/BUILD.bazel +++ /dev/null @@ -1,26 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "strato/config/columns/ml/featureStore:featureStore-strato-client", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/thrift/com/twitter/ml/featurestore/timelines:ml-features-timelines-scala", - "src/thrift/com/twitter/timelinescorer:thrift-scala", - "src/thrift/com/twitter/timelinescorer/server/internal:thrift-scala", - "strato/config/columns/ml/featureStore:featureStore-strato-client", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala deleted file mode 100644 index 69a803c90..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXStratoScorer.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tweet_tlx - -import com.twitter.ml.featurestore.timelines.thriftscala.TimelineScorerScoreView -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.strato.catalog.Fetch.Result -import com.twitter.strato.generated.client.ml.featureStore.TimelineScorerTweetScoresV1ClientColumn -import com.twitter.timelinescorer.thriftscala.v1 -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Score Tweets via Timeline Scorer (TLX) Strato API - * - * @note This results in an additional hop through Strato Server - * @note This is the [[Scorer]] version of - * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx.TweetTLXScoreCandidateFeatureHydrator]] - */ -@Singleton -class TweetTLXStratoScorer @Inject() (column: TimelineScorerTweetScoresV1ClientColumn) - extends Scorer[PipelineQuery, TweetCandidate] { - - override val identifier: ScorerIdentifier = ScorerIdentifier("TweetTLX") - - override val features: Set[Feature[_, _]] = Set(TLXScore) - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[TweetCandidate]] - ): Stitch[Seq[FeatureMap]] = query.getOptionalUserId match { - case Some(userId) => getScoredTweetsFromTLX(userId, candidates.map(_.candidate)) - case _ => - val defaultFeatureMap = FeatureMapBuilder().add(TLXScore, None).build() - Stitch.value(candidates.map(_ => defaultFeatureMap)) - } - - def getScoredTweetsFromTLX( - userId: Long, - tweetCandidates: Seq[TweetCandidate] - ): Stitch[Seq[FeatureMap]] = Stitch.collect(tweetCandidates.map { candidate => - column.fetcher - .fetch(candidate.id, TimelineScorerScoreView(Some(userId))) - .map { - case Result(Some(v1.ScoredTweet(_, score, _, _)), _) => - FeatureMapBuilder() - .add(TLXScore, score) - .build() - case fetchResult => throw new Exception(s"Invalid response from TLX: ${fetchResult.v}") - } - }) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala deleted file mode 100644 index e53f3dcfc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/scorer/tweet_tlx/TweetTLXThriftScorer.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.component_library.scorer.tweet_tlx - -import com.twitter.product_mixer.component_library.model.candidate.TweetCandidate -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelinescorer.thriftscala.v1 -import com.twitter.timelinescorer.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -/** - * @note This Feature is shared with - * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx.TweetTLXScoreCandidateFeatureHydrator]] - * and - * [[com.twitter.product_mixer.component_library.scorer.tweet_tlx.TweetTLXStratoScorer]] - * as the these components should not be used at the same time by the same Product - */ -object TLXScore extends FeatureWithDefaultOnFailure[TweetCandidate, Option[Double]] { - override val defaultValue = None -} - -/** - * Score Tweets via Timeline Scorer (TLX) Thrift API - * - * @note This is the [[Scorer]] version of - * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.tweet_tlx.TweetTLXScoreCandidateFeatureHydrator]] - */ -@Singleton -class TweetTLXThriftScorer @Inject() (timelineScorerClient: t.TimelineScorer.MethodPerEndpoint) - extends Scorer[PipelineQuery, TweetCandidate] { - - override val identifier: ScorerIdentifier = ScorerIdentifier("TLX") - - override val features: Set[Feature[_, _]] = Set(TLXScore) - - override def apply( - query: PipelineQuery, - candidates: Seq[CandidateWithFeatures[TweetCandidate]] - ): Stitch[Seq[FeatureMap]] = { - val userId = query.getOptionalUserId - val tweetScoringQuery = v1.TweetScoringQuery( - predictionPipeline = v1.PredictionPipeline.Recap, - tweetIds = candidates.map(_.candidate.id)) - - val tweetScoringRequest = t.TweetScoringRequest.V1( - v1.TweetScoringRequest( - tweetScoringRequestContext = Some(v1.TweetScoringRequestContext(userId = userId)), - tweetScoringQueries = Some(Seq(tweetScoringQuery)), - retrieveFeatures = Some(false) - )) - - Stitch.callFuture(timelineScorerClient.getTweetScores(tweetScoringRequest)).map { - case t.TweetScoringResponse.V1(response) => - val tweetIdScoreMap = response.tweetScoringResults - .flatMap { - _.headOption.map { - _.scoredTweets.flatMap(tweet => tweet.tweetId.map(_ -> tweet.score)) - } - }.getOrElse(Seq.empty).toMap - - candidates.map { candidateWithFeatures => - val score = tweetIdScoreMap.getOrElse(candidateWithFeatures.candidate.id, None) - FeatureMapBuilder() - .add(TLXScore, score) - .build() - - } - case t.TweetScoringResponse.UnknownUnionField(field) => - throw new UnsupportedOperationException(s"Unknown response type: ${field.field.name}") - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD deleted file mode 100644 index c07a21e65..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/BUILD +++ /dev/null @@ -1,47 +0,0 @@ -scala_library( - name = "insert_append_results", - sources = ["InsertAppendResults.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - ], -) - -scala_library( - sources = [ - "!InsertAppendResults.scala", - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ":insert_append_results", - "3rdparty/jvm/com/google/inject:guice", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - ], - exports = [ - ":insert_append_results", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala deleted file mode 100644 index d50394a2b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/Bucketer.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -/** - * Given a [[CandidateWithDetails]] return the corresponding [[Bucket]] - * it should be associated with when used in a `pattern` or `ratio` - * in [[InsertAppendPatternResults]] or [[InsertAppendRatioResults]] - */ -trait Bucketer[Bucket] { - def apply(candidateWithDetails: CandidateWithDetails): Bucket -} - -object Bucketer { - - /** A [[Bucketer]] that buckets by [[CandidateWithDetails.source]] */ - val ByCandidateSource: Bucketer[CandidatePipelineIdentifier] = - (candidateWithDetails: CandidateWithDetails) => candidateWithDetails.source -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala deleted file mode 100644 index 2ef321cd6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidateMergeStrategy.scala +++ /dev/null @@ -1,82 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.IsPinnedFeature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines -import com.twitter.product_mixer.core.model.common.presentation.CandidateSources -import com.twitter.product_mixer.core.model.common.presentation.CandidateSourcePosition - -/** - * Once a pair of duplicate candidates has been found we need to someone 'resolve' the duplication. - * This may be as simple as picking whichever candidate came first (see [[PickFirstCandidateMerger]] - * but this strategy could mean losing important candidate information. Candidates might, for - * example, have different features. [[CandidateMergeStrategy]] lets you define a custom behavior - * for resolving duplication to help support these more nuanced situations. - */ -trait CandidateMergeStrategy { - def apply( - existingCandidate: ItemCandidateWithDetails, - newCandidate: ItemCandidateWithDetails - ): ItemCandidateWithDetails -} - -/** - * Keep whichever candidate was encountered first. - */ -object PickFirstCandidateMerger extends CandidateMergeStrategy { - override def apply( - existingCandidate: ItemCandidateWithDetails, - newCandidate: ItemCandidateWithDetails - ): ItemCandidateWithDetails = existingCandidate -} - -/** - * Keep the candidate encountered first but combine all candidate feature maps. - */ -object CombineFeatureMapsCandidateMerger extends CandidateMergeStrategy { - override def apply( - existingCandidate: ItemCandidateWithDetails, - newCandidate: ItemCandidateWithDetails - ): ItemCandidateWithDetails = { - // Prepend new because list set keeps insertion order, and last operations in ListSet are O(1) - val mergedCandidateSourceIdentifiers = - newCandidate.features.get(CandidateSources) ++ existingCandidate.features - .get(CandidateSources) - val mergedCandidatePipelineIdentifiers = - newCandidate.features.get(CandidatePipelines) ++ existingCandidate.features - .get(CandidatePipelines) - - // the unitary features are pulled from the existing candidate as explained above, while - // Set Features are merged/accumulated. - val mergedCommonFeatureMap = FeatureMapBuilder() - .add(CandidatePipelines, mergedCandidatePipelineIdentifiers) - .add(CandidateSources, mergedCandidateSourceIdentifiers) - .add(CandidateSourcePosition, existingCandidate.sourcePosition) - .build() - - existingCandidate.copy(features = - existingCandidate.features ++ newCandidate.features ++ mergedCommonFeatureMap) - } -} - -/** - * Keep the pinnable candidate. For cases where we are dealing with duplicate entries across - * different candidate types, such as different sub-classes of - * [[com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate]], we will - * prioritize the candidate with [[IsPinnedFeature]] because it contains additional information - * needed for the positioning of a pinned entry on a timeline. - */ -object PickPinnedCandidateMerger extends CandidateMergeStrategy { - override def apply( - existingCandidate: ItemCandidateWithDetails, - newCandidate: ItemCandidateWithDetails - ): ItemCandidateWithDetails = - Seq(existingCandidate, newCandidate) - .collectFirst { - case candidate @ ItemCandidateWithDetails(_: BaseTweetCandidate, _, features) - if features.getTry(IsPinnedFeature).toOption.contains(true) => - candidate - }.getOrElse(existingCandidate) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala deleted file mode 100644 index f73b9bd37..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/CandidatePositionInResults.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.selector -import com.twitter.product_mixer.component_library.model.candidate.RelevancePromptCandidate -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Compute a position for inserting a specific candidate into the result sequence originally provided to the Selector. - * If a `None` is returned, the Selector using this would not insert that candidate into the result. - */ -trait CandidatePositionInResults[-Query <: PipelineQuery] { - def apply( - query: Query, - candidate: CandidateWithDetails, - result: Seq[CandidateWithDetails] - ): Option[Int] -} - -object PromptCandidatePositionInResults extends CandidatePositionInResults[PipelineQuery] { - override def apply( - query: PipelineQuery, - candidate: CandidateWithDetails, - result: Seq[CandidateWithDetails] - ): Option[Int] = candidate match { - case ItemCandidateWithDetails(candidate, _, _) => - candidate match { - case relevancePromptCandidate: RelevancePromptCandidate => relevancePromptCandidate.position - case _ => None - } - // not supporting ModuleCandidateWithDetails right now as RelevancePromptCandidate shouldn't be in a module - case _ => None - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala deleted file mode 100644 index 44c92826f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DeduplicationKey.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails - -/** - * [[DropSelector]] detects duplicates by looking for candidates with the same key. A key can be - * anything but is typically derived from a candidate's id and class. This approach is not always - * appropriate. For example, two candidate sources might both return different sub-classes of - * [[com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate]] resulting in - * them not being treated as duplicates. - */ -trait DeduplicationKey[Key] { - def apply(candidate: ItemCandidateWithDetails): Key -} - -/** - * Use candidate id and class to determine duplicates. - */ -object IdAndClassDuplicationKey extends DeduplicationKey[(String, Class[_ <: UniversalNoun[Any]])] { - def apply(item: ItemCandidateWithDetails): (String, Class[_ <: UniversalNoun[Any]]) = - (item.candidate.id.toString, item.candidate.getClass) -} - -/** - * Use candidate id to determine duplicates. - * This should be used instead of [[IdAndClassDuplicationKey]] in order to deduplicate across - * different candidate types, such as different implementations of - * [[com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate]]. - */ -object IdDuplicationKey extends DeduplicationKey[String] { - def apply(item: ItemCandidateWithDetails): String = item.candidate.id.toString -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala deleted file mode 100644 index a6c239151..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropAllCandidates.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Drops all Candidates on the `remainingCandidates` side which are in the [[pipelineScope]] - * - * This is typically used as a placeholder when templating out a new pipeline or - * as a simple filter to drop candidates based only on the [[CandidateScope]] - */ -case class DropAllCandidates(override val pipelineScope: CandidateScope = AllPipelines) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val PartitionedCandidates(inScope, outOfScope) = pipelineScope.partition(remainingCandidates) - - SelectorResult(remainingCandidates = outOfScope, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala deleted file mode 100644 index e52956ad3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateCandidates.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.DropSelector.dropDuplicates -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Keep only the first instance of a candidate in the `remainingCandidates` as determined by comparing - * the contained candidate ID and class type. Subsequent matching instances will be dropped. For - * more details, see DropSelector#dropDuplicates - * - * @param duplicationKey how to generate the key used to identify duplicate candidates (by default use id and class name) - * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one) - * - * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored. - * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored. - * - * @example if `remainingCandidates` - * `Seq(sourceA_Id1, sourceA_Id1, sourceA_Id2, sourceB_id1, sourceB_id2, sourceB_id3, sourceC_id4)` - * then the output candidates will be `Seq(sourceA_Id1, sourceA_Id2, sourceB_id3, sourceC_id4)` - */ -case class DropDuplicateCandidates( - override val pipelineScope: CandidateScope = AllPipelines, - duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey, - mergeStrategy: CandidateMergeStrategy = PickFirstCandidateMerger) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val dedupedCandidates = dropDuplicates( - pipelineScope = pipelineScope, - candidates = remainingCandidates, - duplicationKey = duplicationKey, - mergeStrategy = mergeStrategy) - - SelectorResult(remainingCandidates = dedupedCandidates, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala deleted file mode 100644 index 8c2c0002b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateModuleItemCandidates.scala +++ /dev/null @@ -1,88 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.DropSelector.dropDuplicates -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector._ -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object DropDuplicateModuleItemCandidates { - - /** - * Limit the number of module item candidates (for 1 or more modules) from a certain candidate - * source. See [[DropDuplicateModuleItemCandidates]] for more details. - * - * @param candidatePipeline pipelines on which to run the selector - * - * @note Scala doesn't allow overloaded methods with default arguments. Users wanting to customize - * the de-dupe logic should use the default constructor. We could provide multiple - * constructors but that seemed more confusing (five ways to instantiate the selector) or not - * necessarily less verbose (if we picked specific use-cases rather than trying to support - * everything). - */ - def apply(candidatePipeline: CandidatePipelineIdentifier) = new DropDuplicateModuleItemCandidates( - SpecificPipeline(candidatePipeline), - IdAndClassDuplicationKey, - PickFirstCandidateMerger) - - def apply(candidatePipelines: Set[CandidatePipelineIdentifier]) = - new DropDuplicateModuleItemCandidates( - SpecificPipelines(candidatePipelines), - IdAndClassDuplicationKey, - PickFirstCandidateMerger) -} - -/** - * Limit the number of module item candidates (for 1 or more modules) from certain candidate - * pipelines. - * - * This acts like a [[DropDuplicateCandidates]] but for modules in `remainingCandidates` - * from any of the provided [[candidatePipelines]]. Similar to [[DropDuplicateCandidates]], it - * keeps only the first instance of a candidate within a module as determined by comparing - * the contained candidate ID and class type. - * - * @param pipelineScope pipeline scope on which to run the selector - * @param duplicationKey how to generate the key used to identify duplicate candidates (by default use id and class name) - * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one) - * - * For example, if a candidatePipeline returned 5 modules each - * containing duplicate items in the candidate pool, then the module items in each of the - * 5 modules will be filtered to the unique items within each module. - * - * Another example is if you have 2 modules each with the same items as the other, - * it won't deduplicate across modules. - * - * @note this updates the module in the `remainingCandidates` - */ -case class DropDuplicateModuleItemCandidates( - override val pipelineScope: CandidateScope, - duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey, - mergeStrategy: CandidateMergeStrategy = PickFirstCandidateMerger) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val remainingCandidatesLimited = remainingCandidates.map { - case module: ModuleCandidateWithDetails if pipelineScope.contains(module) => - // this applies to all candidates in a module, even if they are from a different - // candidate source, which can happen if items are added to a module during selection - module.copy(candidates = dropDuplicates( - pipelineScope = AllPipelines, - candidates = module.candidates, - duplicationKey = duplicationKey, - mergeStrategy = mergeStrategy)) - case candidate => candidate - } - - SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala deleted file mode 100644 index bf15b3b5d..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropDuplicateResults.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.DropSelector.dropDuplicates -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Keep only the first instance of a candidate in the `result` as determined by comparing - * the contained candidate ID and class type. Subsequent matching instances will be dropped. For - * more details, see DropSelector#dropDuplicates - * - * @param duplicationKey how to generate the key used to identify duplicate candidates (by default use id and class name) - * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one) - * - * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored. - * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored. - * - * @example if `result` - * `Seq(sourceA_Id1, sourceA_Id1, sourceA_Id2, sourceB_id1, sourceB_id2, sourceB_id3, sourceC_id4)` - * then the output result will be `Seq(sourceA_Id1, sourceA_Id2, sourceB_id3, sourceC_id4)` - */ -case class DropDuplicateResults( - duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey, - mergeStrategy: CandidateMergeStrategy = PickFirstCandidateMerger) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = AllPipelines - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val dedupedResults = dropDuplicates( - pipelineScope = pipelineScope, - candidates = result, - duplicationKey = duplicationKey, - mergeStrategy = mergeStrategy) - - SelectorResult(remainingCandidates = remainingCandidates, result = dedupedResults) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala deleted file mode 100644 index fe893fbc3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredCandidates.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Predicate which will be applied to each candidate. True indicates that the candidate will be - * kept. - */ -trait ShouldKeepCandidate { - def apply(candidateWithDetails: CandidateWithDetails): Boolean -} - -object DropFilteredCandidates { - def apply(candidatePipeline: CandidatePipelineIdentifier, filter: ShouldKeepCandidate) = - new DropFilteredCandidates(SpecificPipeline(candidatePipeline), filter) - - def apply(candidatePipelines: Set[CandidatePipelineIdentifier], filter: ShouldKeepCandidate) = - new DropFilteredCandidates(SpecificPipelines(candidatePipelines), filter) -} - -/** - * Limit candidates from certain candidates sources to those which satisfy the provided predicate. - */ -case class DropFilteredCandidates( - override val pipelineScope: CandidateScope, - filter: ShouldKeepCandidate) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val candidatesUpdated = remainingCandidates.filter { candidate => - if (pipelineScope.contains(candidate)) filter.apply(candidate) - else true - } - - SelectorResult(remainingCandidates = candidatesUpdated, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala deleted file mode 100644 index 5a9b0f410..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropFilteredModuleItemCandidates.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object DropFilteredModuleItemCandidates { - def apply(candidatePipeline: CandidatePipelineIdentifier, filter: ShouldKeepCandidate) = - new DropFilteredModuleItemCandidates(SpecificPipeline(candidatePipeline), filter) - - def apply(candidatePipelines: Set[CandidatePipelineIdentifier], filter: ShouldKeepCandidate) = - new DropFilteredModuleItemCandidates(SpecificPipelines(candidatePipelines), filter) -} - -/** - * Limit candidates in modules from certain candidates sources to those which satisfy - * the provided predicate. - * - * This acts like a [[DropFilteredCandidates]] but for modules in `remainingCandidates` - * from any of the provided [[candidatePipelines]]. - * - * @note this updates the module in the `remainingCandidates` - */ -case class DropFilteredModuleItemCandidates( - override val pipelineScope: CandidateScope, - filter: ShouldKeepCandidate) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val candidatesUpdated = remainingCandidates.map { - case module: ModuleCandidateWithDetails if pipelineScope.contains(module) => - // this applies to all candidates in a module, even if they are from a different - // candidate source, which can happen if items are added to a module during selection - module.copy(candidates = module.candidates.filter(filter.apply)) - case candidate => candidate - } - - SelectorResult(remainingCandidates = candidatesUpdated, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala deleted file mode 100644 index 4982ac49a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxCandidates.scala +++ /dev/null @@ -1,84 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -trait MaxSelector[-Query <: PipelineQuery] { - def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): Int -} - -object DropMaxCandidates { - - /** - * A [[DropMaxCandidates]] Selector based on a [[Param]] applied to a single candidate pipeline - */ - def apply[Query <: PipelineQuery]( - candidatePipeline: CandidatePipelineIdentifier, - maxSelectionsParam: Param[Int] - ) = new DropMaxCandidates[Query]( - SpecificPipeline(candidatePipeline), - (query, _, _) => query.params(maxSelectionsParam)) - - /** - * A [[DropMaxCandidates]] Selector based on a [[Param]] with multiple candidate pipelines - */ - def apply[Query <: PipelineQuery]( - candidatePipelines: Set[CandidatePipelineIdentifier], - maxSelectionsParam: Param[Int] - ) = new DropMaxCandidates[Query]( - SpecificPipelines(candidatePipelines), - (query, _, _) => query.params(maxSelectionsParam)) - - /** - * A [[DropMaxCandidates]] Selector based on a [[Param]] that applies to a [[CandidateScope]] - */ - def apply[Query <: PipelineQuery]( - pipelineScope: CandidateScope, - maxSelectionsParam: Param[Int] - ) = new DropMaxCandidates[Query](pipelineScope, (query, _, _) => query.params(maxSelectionsParam)) -} - -/** - * Limit the number of item and module (not items inside modules) candidates from the - * specified pipelines based on the value provided by the [[MaxSelector]] - * - * For example, if value from the [[MaxSelector]] is 3, and a candidatePipeline returned 10 items - * in the candidate pool, then these items will be reduced to the first 3 items. Note that to - * update the ordering of the candidates, an UpdateCandidateOrderingSelector may be used prior to - * using this Selector. - * - * Another example, if the [[MaxSelector]] value is 3, and a candidatePipeline returned 10 modules - * in the candidate pool, then these will be reduced to the first 3 modules. The items inside the - * modeles will not be affected by this selector. To control the number of items inside modules see - * [[DropMaxModuleItemCandidates]]. - */ -case class DropMaxCandidates[-Query <: PipelineQuery]( - override val pipelineScope: CandidateScope, - maxSelector: MaxSelector[Query]) - extends Selector[Query] { - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val maxSelections = maxSelector(query, remainingCandidates, result) - assert(maxSelections > 0, "Max selections must be greater than zero") - - val remainingCandidatesLimited = - DropSelector.takeUntil(maxSelections, remainingCandidates, pipelineScope) - - SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala deleted file mode 100644 index f343d0e97..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxModuleItemCandidates.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Limit the number of module item candidates (for 1 or more modules) from a certain candidate - * source. - * - * For example, if maxModuleItemsParam is 3, and a candidatePipeline returned 1 module containing 10 - * items in the candidate pool, then these module items will be reduced to the first 3 module items. - * Note that to update the ordering of the candidates, an UpdateModuleItemsCandidateOrderingSelector - * may be used prior to using this selector. - * - * Another example, if maxModuleItemsParam is 3, and a candidatePipeline returned 5 modules each - * containing 10 items in the candidate pool, then the module items in each of the 5 modules will be - * reduced to the first 3 module items. - * - * @note this updates the module in the `remainingCandidates` - */ -case class DropMaxModuleItemCandidates( - candidatePipeline: CandidatePipelineIdentifier, - maxModuleItemsParam: Param[Int]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipeline) - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val maxModuleItemSelections = query.params(maxModuleItemsParam) - assert(maxModuleItemSelections > 0, "Max module item selections must be greater than zero") - - val remainingCandidatesLimited = remainingCandidates.map { - case module: ModuleCandidateWithDetails if pipelineScope.contains(module) => - // this applies to all candidates in a module, even if they are from a different - // candidate source which can happen if items are added to a module during selection - module.copy(candidates = DropSelector.takeUntil(maxModuleItemSelections, module.candidates)) - case candidate => candidate - } - - SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala deleted file mode 100644 index d5c655390..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropMaxResults.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Limit the number of results - * - * For example, if maxResultsParam is 3, and the results contain 10 items, then these items will be - * reduced to the first 3 selected items. Note that the ordering of results is determined by the - * selector configuration. - * - * Another example, if maxResultsParam is 3, and the results contain 10 modules, then these will be - * reduced to the first 3 modules. The items inside the modules will not be affected by this - * selector. - */ -case class DropMaxResults( - maxResultsParam: Param[Int]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = AllPipelines - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val maxResults = query.params(maxResultsParam) - assert(maxResults > 0, "Max results must be greater than zero") - - val resultUpdated = DropSelector.takeUntil(maxResults, result) - - SelectorResult(remainingCandidates = remainingCandidates, result = resultUpdated) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala deleted file mode 100644 index 18f8989d8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropModuleTooFewModuleItemResults.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Drop the module from the `result` if it doesn't contain enough item candidates. - * - * For example, for a given module, if minResultsParam is 3, and the results contain 2 items, - * then that module will be entirely dropped from the results. - */ -case class DropModuleTooFewModuleItemResults( - candidatePipeline: CandidatePipelineIdentifier, - minModuleItemsParam: Param[Int]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipeline) - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val minModuleItemSelections = query.params(minModuleItemsParam) - assert(minModuleItemSelections > 0, "Min results must be greater than zero") - - val updatedResults = result.filter { - case module: ModuleCandidateWithDetails - if pipelineScope.contains(module) && module.candidates.count { candidateWithDetails => - !candidateWithDetails.candidate.isInstanceOf[CursorCandidate] - } < minModuleItemSelections => - false - case _ => true - } - - SelectorResult(remainingCandidates = remainingCandidates, result = updatedResults) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala deleted file mode 100644 index 4bbfbe076..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropNonDuplicateCandidates.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Keep only the candidates in `remainingCandidates` that appear multiple times. - * This ignores modules and cursors from being removed. - * - * @param duplicationKey how to generate the key used to identify duplicate candidates - * - * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored. - * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored. - * - * @example if `remainingCandidates` - * `Seq(sourceA_Id1, sourceA_Id1, sourceA_Id2, sourceB_id1, sourceB_id2, sourceB_id3, sourceC_id4)` - * then the output result will be `Seq(sourceA_Id1, sourceA_Id2)` - */ -case class DropNonDuplicateCandidates( - override val pipelineScope: CandidateScope, - duplicationKey: DeduplicationKey[_] = IdAndClassDuplicationKey) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val duplicateCandidates = dropNonDuplicates( - pipelineScope = pipelineScope, - candidates = remainingCandidates, - duplicationKey = duplicationKey) - - SelectorResult(remainingCandidates = duplicateCandidates, result = result) - } - - /** - * Identify and keep candidates using the supplied key extraction and merger functions. By default - * this will keep only candidates that appear multiple times as determined by comparing - * the contained candidate ID and class type. Candidates appearing only once will be dropped. - * - * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored. - * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored. - * - * @param candidates which may have elements to drop - * @param duplicationKey how to generate a key for a candidate for identifying duplicates - */ - private[this] def dropNonDuplicates[Candidate <: CandidateWithDetails, Key]( - pipelineScope: CandidateScope, - candidates: Seq[Candidate], - duplicationKey: DeduplicationKey[Key], - ): Seq[Candidate] = { - // Here we are checking if each candidate has multiple appearances or not - val isCandidateADuplicate: Map[Key, Boolean] = candidates - .collect { - case item: ItemCandidateWithDetails - if pipelineScope.contains(item) && !item.candidate.isInstanceOf[CursorCandidate] => - item - }.groupBy(duplicationKey(_)) - .mapValues(_.length > 1) - - candidates.filter { - case item: ItemCandidateWithDetails => - isCandidateADuplicate.getOrElse(duplicationKey(item), true) - case _: ModuleCandidateWithDetails => true - case _ => false - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala deleted file mode 100644 index 036f91bf8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropOrthogonalCandidates.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Limit candidates to the first candidate source in the provided orthogonalCandidatePipelines - * seq that has candidates in the candidate pool. For the subsequent candidate sources in the seq, - * remove their candidates from the candidate pool. - * - * @example if [[orthogonalCandidatePipelines]] is `Seq(D, A, C)`, and the remaining candidates - * component identifiers are `Seq(A, A, A, B, B, C, C, D, D, D)`, then `Seq(B, B, D, D, D)` will remain - * in the candidate pool. - * - * @example if [[orthogonalCandidatePipelines]] is `Seq(D, A, C)`, and the remaining candidates - * component identifiers are `Seq(A, A, A, B, B, C, C)`, then `Seq(A, A, A, B, B)` will remain - * in the candidate pool. - */ -case class DropOrthogonalCandidates( - orthogonalCandidatePipelines: Seq[CandidatePipelineIdentifier]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = - SpecificPipelines(orthogonalCandidatePipelines.toSet) - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val firstMatchingOrthogonalSourceOpt = orthogonalCandidatePipelines - .find { orthogonalCandidatePipeline => - remainingCandidates.exists(_.source == orthogonalCandidatePipeline) - } - - val remainingCandidatesLimited = firstMatchingOrthogonalSourceOpt match { - case Some(firstMatchingOrthogonalSource) => - val subsequentOrthogonalSources = - orthogonalCandidatePipelines.toSet - firstMatchingOrthogonalSource - - remainingCandidates.filterNot { candidate => - subsequentOrthogonalSources.contains(candidate.source) - } - case None => remainingCandidates - } - - SelectorResult(remainingCandidates = remainingCandidatesLimited, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala deleted file mode 100644 index 47974aff9..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxModuleItemCandidates.scala +++ /dev/null @@ -1,68 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Limit the number of results (for 1 or more modules) from a certain candidate - * source to PipelineQuery.requestedMaxResults. - * - * PipelineQuery.requestedMaxResults is optionally set in the pipelineQuery. - * If it is not set, then the default value of DefaultRequestedMaxModuleItemsParam is used. - * - * For example, if PipelineQuery.requestedMaxResults is 3, and a candidatePipeline returned 1 module - * containing 10 items in the candidate pool, then these module items will be reduced to the first 3 - * module items. Note that to update the ordering of the candidates, an - * UpdateModuleItemsCandidateOrderingSelector may be used prior to using this selector. - * - * Another example, if PipelineQuery.requestedMaxResults is 3, and a candidatePipeline returned 5 - * modules each containing 10 items in the candidate pool, then the module items in each of the 5 - * modules will be reduced to the first 3 module items. - * - * @note this updates the module in the `remainingCandidates` - */ -case class DropRequestedMaxModuleItemCandidates( - override val pipelineScope: CandidateScope, - defaultRequestedMaxModuleItemResultsParam: Param[Int]) - extends Selector[PipelineQuery] { - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val requestedMaxModuleItemSelections = - query.maxResults(defaultRequestedMaxModuleItemResultsParam) - assert( - requestedMaxModuleItemSelections > 0, - "Requested Max module item selections must be greater than zero") - - val resultUpdated = result.map { - case module: ModuleCandidateWithDetails if pipelineScope.contains(module) => - // this applies to all candidates in a module, even if they are from a different - // candidate source which can happen if items are added to a module during selection - module.copy(candidates = - DropSelector.takeUntil(requestedMaxModuleItemSelections, module.candidates)) - case candidate => candidate - } - - SelectorResult(remainingCandidates = remainingCandidates, result = resultUpdated) - } -} - -object DropRequestedMaxModuleItemCandidates { - def apply( - candidatePipeline: CandidatePipelineIdentifier, - defaultRequestedMaxModuleItemResultsParam: Param[Int] - ) = - new DropRequestedMaxModuleItemCandidates( - SpecificPipeline(candidatePipeline), - defaultRequestedMaxModuleItemResultsParam) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala deleted file mode 100644 index d5da8f584..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropRequestedMaxResults.scala +++ /dev/null @@ -1,55 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.BoundedParam - -/** - * Limit the number of results to min(PipelineQuery.requestedMaxResults, ServerMaxResultsParam) - * - * PipelineQuery.requestedMaxResults is optionally set in the pipelineQuery. - * If it is not set, then the default value of DefaultRequestedMaxResultsParam is used. - * - * ServerMaxResultsParam specifies the maximum number of results supported, irrespective of what is - * specified by the client in PipelineQuery.requestedMaxResults - * (or the DefaultRequestedMaxResultsParam default if not specified) - * - * For example, if ServerMaxResultsParam is 5, PipelineQuery.requestedMaxResults is 3, - * and the results contain 10 items, then these items will be reduced to the first 3 selected items. - * - * If PipelineQuery.requestedMaxResults is not set, DefaultRequestedMaxResultsParam is 3, - * ServerMaxResultsParam is 5 and the results contain 10 items, - * then these items will be reduced to the first 3 selected items. - * - * Another example, if ServerMaxResultsParam is 5, PipelineQuery.requestedMaxResults is 8, - * and the results contain 10 items, then these will be reduced to the first 5 selected items. - * - * The items inside the modules will not be affected by this selector. - */ -case class DropRequestedMaxResults( - defaultRequestedMaxResultsParam: BoundedParam[Int], - serverMaxResultsParam: BoundedParam[Int]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = AllPipelines - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val requestedMaxResults = query.maxResults(defaultRequestedMaxResultsParam) - val serverMaxResults = query.params(serverMaxResultsParam) - assert(requestedMaxResults > 0, "Requested max results must be greater than zero") - assert(serverMaxResults > 0, "Server max results must be greater than zero") - - val appliedMaxResults = Math.min(requestedMaxResults, serverMaxResults) - val resultUpdated = DropSelector.takeUntil(appliedMaxResults, result) - - SelectorResult(remainingCandidates = remainingCandidates, result = resultUpdated) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala deleted file mode 100644 index b2a1a76e1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropSelector.scala +++ /dev/null @@ -1,111 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import scala.collection.mutable - -private[selector] object DropSelector { - - /** - * Identify and merge duplicates using the supplied key extraction and merger functions. By default - * this will keep only the first instance of a candidate in the `candidate` as determined by comparing - * the contained candidate ID and class type. Subsequent matching instances will be dropped. For - * more details, see DropSelector#dropDuplicates. - * - * @note [[com.twitter.product_mixer.component_library.model.candidate.CursorCandidate]] are ignored. - * @note [[com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails]] are ignored. - * - * @param candidates which may have elements to drop - * @param duplicationKey how to generate a key for a candidate for identifying duplicates - * @param mergeStrategy how to merge two candidates with the same key (by default pick the first one) - */ - def dropDuplicates[Candidate <: CandidateWithDetails, Key]( - pipelineScope: CandidateScope, - candidates: Seq[Candidate], - duplicationKey: DeduplicationKey[Key], - mergeStrategy: CandidateMergeStrategy - ): Seq[Candidate] = { - val seenCandidatePositions = mutable.HashMap[Key, Int]() - // We assume that, most of the time, most candidates aren't duplicates so the result Seq will be - // approximately the size of the candidates Seq. - val deduplicatedCandidates = new mutable.ArrayBuffer[Candidate](candidates.length) - - for (candidate <- candidates) { - candidate match { - - // candidate is from one of the Pipelines the selector applies to and is not a CursorCandidate - case item: ItemCandidateWithDetails - if pipelineScope.contains(item) && - !item.candidate.isInstanceOf[CursorCandidate] => - val key = duplicationKey(item) - - // Perform a merge if the candidate has been seen already - if (seenCandidatePositions.contains(key)) { - val candidateIndex = seenCandidatePositions(key) - - // Safe because only ItemCandidateWithDetails are added to seenCandidatePositions so - // seenCandidatePositions(key) *must* point to an ItemCandidateWithDetails - val originalCandidate = - deduplicatedCandidates(candidateIndex).asInstanceOf[ItemCandidateWithDetails] - - deduplicatedCandidates.update( - candidateIndex, - mergeStrategy(originalCandidate, item).asInstanceOf[Candidate]) - } else { - // Otherwise add a new entry to the list of kept candidates and update our map to track - // the new index - deduplicatedCandidates.append(item.asInstanceOf[Candidate]) - seenCandidatePositions.update(key, deduplicatedCandidates.length - 1) - } - case item => deduplicatedCandidates.append(item) - } - } - - deduplicatedCandidates - } - - /** - * Takes `candidates` from all [[CandidateWithDetails.source]]s but only `candidates` in the provided - * `pipelineScope` are counted towards the `max` non-cursor candidates are included. - * - * @param max the maximum number of non-cursor candidates from the provided `pipelineScope` to return - * @param candidates a sequence of candidates which may have elements dropped - * @param pipelineScope the scope of which `candidates` should count towards the `max` - */ - def takeUntil[Candidate <: CandidateWithDetails]( - max: Int, - candidates: Seq[Candidate], - pipelineScope: CandidateScope = AllPipelines - ): Seq[Candidate] = { - val resultsBuilder = Seq.newBuilder[Candidate] - resultsBuilder.sizeHint(candidates) - - candidates.foldLeft(0) { - case ( - count, - candidate @ ItemCandidateWithDetails(_: CursorCandidate, _, _) - ) => - // keep cursors, not included in the `count` - resultsBuilder += candidate.asInstanceOf[Candidate] - count - - case (count, candidate) if !pipelineScope.contains(candidate) => - // keep candidates that don't match the provided `pipelineScope`, not included in the `count` - resultsBuilder += candidate - count - - case (count, candidate) if count < max => - // keep candidates if theres space and increment the `count` - resultsBuilder += candidate - count + 1 - - case (dropCurrentCandidate, _) => - // drop non-cursor candidate because theres no space left - dropCurrentCandidate - } - resultsBuilder.result() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala deleted file mode 100644 index ce8be7d6a..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DropTooFewResults.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.timelines.configapi.Param - -/** - * Drop all results if the minimum item threshold is not met. Some products would rather return - * nothing than, for example, a single tweet. This lets us leverage existing client logic for - * handling no results such as logic to not render the product at all. - */ -case class DropTooFewResults(minResultsParam: Param[Int]) extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = AllPipelines - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val minResults = query.params(minResultsParam) - assert(minResults > 0, "Min results must be greater than zero") - - if (PipelineResult.resultSize(result) < minResults) { - SelectorResult(remainingCandidates = remainingCandidates, result = Seq.empty) - } else { - SelectorResult(remainingCandidates = remainingCandidates, result = result) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala deleted file mode 100644 index b0d3326fc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/DynamicPositionSelector.scala +++ /dev/null @@ -1,124 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -private[selector] object DynamicPositionSelector { - - sealed trait IndexType - case object RelativeIndices extends IndexType - case object AbsoluteIndices extends IndexType - - /** - * Given an existing `result` seq, inserts candidates from `candidatesToInsertByIndex` into the `result` 1-by-1 with - * the provided index being the index relative to the `result` if given [[RelativeIndices]] or - * absolute index if given [[AbsoluteIndices]] (excluding duplicate insertions at an index, see below). - * - * Indices below 0 are added to the front and indices > the length are added to the end - * - * @note if multiple candidates exist with the same index, they are inserted in the order which they appear and only count - * as a single element with regards to the absolute index values, see the example below - * - * @example when using [[RelativeIndices]] {{{ - * mergeByIndexIntoResult( - * Seq( - * 0 -> "a", - * 0 -> "b", - * 0 -> "c", - * 1 -> "e", - * 2 -> "g", - * 2 -> "h"), - * Seq( - * "D", - * "F" - * ), - * RelativeIndices) == Seq( - * "a", - * "b", - * "c", - * "D", - * "e", - * "F", - * "g", - * "h" - * ) - * }}} - * - * @example when using [[AbsoluteIndices]] {{{ - * mergeByIndexIntoResult( - * Seq( - * 0 -> "a", - * 0 -> "b", - * 1 -> "c", - * 3 -> "e", - * 5 -> "g", - * 6 -> "h"), - * Seq( - * "D", - * "F" - * ), - * AbsoluteIndices) == Seq( - * "a", // index 0, "a" and "b" together only count as 1 element with regards to indexes because they have duplicate insertion points - * "b", // index 0 - * "c", // index 1 - * "D", // index 2 - * "e", // index 3 - * "F", // index 4 - * "g", // index 5 - * "h" // index 6 - * ) - * }}} - */ - def mergeByIndexIntoResult[T]( // generic on `T` to simplify unit testing - candidatesToInsertByIndex: Seq[(Int, T)], - result: Seq[T], - indexType: IndexType - ): Seq[T] = { - val positionAndCandidateList = candidatesToInsertByIndex.sortWith { - case ((indexLeft: Int, _), (indexRight: Int, _)) => - indexLeft < indexRight // order by desired absolute index ascending - } - - // Merge result and positionAndCandidateList into resultUpdated while making sure that the entries - // from the positionAndCandidateList are inserted at the right index. - val resultUpdated = Seq.newBuilder[T] - resultUpdated.sizeHint(result.size + positionAndCandidateList.size) - - var currentResultIndex = 0 - val inputResultIterator = result.iterator - val positionAndCandidateIterator = positionAndCandidateList.iterator.buffered - var previousInsertPosition: Option[Int] = None - - while (inputResultIterator.nonEmpty && positionAndCandidateIterator.nonEmpty) { - positionAndCandidateIterator.head match { - case (nextInsertionPosition, nextCandidateToInsert) - if previousInsertPosition.contains(nextInsertionPosition) => - // inserting multiple candidates at the same index - resultUpdated += nextCandidateToInsert - // do not increment any indices, but insert the candidate and advance to the next candidate - positionAndCandidateIterator.next() - - case (nextInsertionPosition, nextCandidateToInsert) - if currentResultIndex >= nextInsertionPosition => - // inserting a candidate at a new index - // add candidate to the results - resultUpdated += nextCandidateToInsert - // save the position of the inserted element to handle duplicate index insertions - previousInsertPosition = Some(nextInsertionPosition) - // advance to next candidate - positionAndCandidateIterator.next() - if (indexType == AbsoluteIndices) { - // if the indices are absolute, instead of relative to the original `result` we need to - // count the insertions of candidates into the results towards the `currentResultIndex` - currentResultIndex += 1 - } - case _ => - // no candidate to insert by index so use the candidates from the result and increment the index - resultUpdated += inputResultIterator.next() - currentResultIndex += 1 - } - } - // one of the iterators is empty, so append the remaining candidates in order to the end - resultUpdated ++= positionAndCandidateIterator.map { case (_, candidate) => candidate } - resultUpdated ++= inputResultIterator - - resultUpdated.result() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala deleted file mode 100644 index 3096d9a50..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendIntoModuleCandidates.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleAndIndex -import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleWithItemsToAddAndOtherCandidates -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Append all candidates from [[candidatePipeline]] into a module from [[targetModuleCandidatePipeline]]. - * If the results contain multiple modules from the target candidate pipeline, - * then the candidates will be inserted into the first module. - * - * @note this will throw an [[UnsupportedOperationException]] if the [[candidatePipeline]] contains any modules. - * - * @note this updates the module in the `remainingCandidates` - */ -case class InsertAppendIntoModuleCandidates( - candidatePipeline: CandidatePipelineIdentifier, - targetModuleCandidatePipeline: CandidatePipelineIdentifier) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = - SpecificPipelines(candidatePipeline, targetModuleCandidatePipeline) - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val ModuleWithItemsToAddAndOtherCandidates( - moduleToUpdateAndIndex, - itemsToInsertIntoModule, - otherCandidates) = - InsertIntoModule.moduleToUpdate( - candidatePipeline, - targetModuleCandidatePipeline, - remainingCandidates) - - val updatedRemainingCandidates = moduleToUpdateAndIndex match { - case None => remainingCandidates - case _ if itemsToInsertIntoModule.isEmpty => remainingCandidates - case Some(ModuleAndIndex(moduleToUpdate, indexOfModuleInOtherCandidates)) => - val updatedModuleItems = moduleToUpdate.candidates ++ itemsToInsertIntoModule - val updatedModule = moduleToUpdate.copy(candidates = updatedModuleItems) - otherCandidates.updated(indexOfModuleInOtherCandidates, updatedModule) - } - - SelectorResult(remainingCandidates = updatedRemainingCandidates, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala deleted file mode 100644 index 79dda59f4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendPatternResults.scala +++ /dev/null @@ -1,105 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import scala.collection.mutable - -/** - * Select candidates and add them according to the `pattern`. - * The pattern is repeated until all candidates contained in the pattern are added to the `result`. - * If the candidates for a specific [[Bucket]] in the pattern are exhausted, that [[Bucket]] will be - * skipped on subsequent iterations. - * If a candidate has a [[Bucket]] that isn't in the pattern it is added to the end of the `result`. - * The end result is all candidates from all [[candidatePipelines]]s provided will end up in the result. - * - * @example If there are no more candidates from a given `CandidatePipeline` then it is skipped, so - * with the pattern `Seq(A, A, B, C)`, if there are no more candidates from `B` then it is - * effectively the same as `Seq(A, A, C)`. The `result` will contain all candidates from all - * `CandidatePipeline`s who's `Bucket` is in the `pattern`. - * - * @example If the pattern is `Seq(A, A, B, C)` and the remaining candidates - * from the provided `candidatePipelines` are: - * - 5 `A`s - * - 2 `B`s - * - 1 `C` - * - 1 `D`s - * - * then the resulting output for each iteration over the pattern is - * - `Seq(A, A, B, C)` - * - `Seq(A, A, B)` since there's no more `C`s - * - `Seq(A)` since there are no more `B`s or `C`s - * - `Seq(D)` since it wasn't in the pattern but is from one of the provided - * `candidatePipelines`, it's appended at the end - * - * so the `result` that's returned would be `Seq(A, A, B, C, A, A, B, A, D)` - */ -case class InsertAppendPatternResults[-Query <: PipelineQuery, Bucket]( - candidatePipelines: Set[CandidatePipelineIdentifier], - bucketer: Bucketer[Bucket], - pattern: Seq[Bucket]) - extends Selector[Query] { - - require(pattern.nonEmpty, "`pattern` must be non-empty") - - override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipelines) - - private sealed trait PatternResult - private case object NotASelectedCandidatePipeline extends PatternResult - private case object NotABucketInThePattern extends PatternResult - private case class Bucketed(bucket: Bucket) extends PatternResult - - private val allBucketsInPattern = pattern.toSet - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val groupedCandidates: Map[PatternResult, Seq[CandidateWithDetails]] = - remainingCandidates.groupBy { candidateWithDetails => - if (pipelineScope.contains(candidateWithDetails)) { - // if a candidate's Bucket doesnt appear in the pattern it's backfilled at the end - val bucket = bucketer(candidateWithDetails) - if (allBucketsInPattern.contains(bucket)) { - Bucketed(bucket) - } else { - NotABucketInThePattern - } - } else { - NotASelectedCandidatePipeline - } - } - - val otherCandidates = - groupedCandidates.getOrElse(NotASelectedCandidatePipeline, Seq.empty) - - val notABucketInThePattern = - groupedCandidates.getOrElse(NotABucketInThePattern, Seq.empty) - - // mutable so we can remove finished iterators to optimize when looping for large patterns - val groupedBucketsIterators = mutable.HashMap(groupedCandidates.collect { - case (Bucketed(bucket), candidatesWithDetails) => (bucket, candidatesWithDetails.iterator) - }.toSeq: _*) - - val patternIterator = Iterator.continually(pattern).flatten - - val newResult = new mutable.ArrayBuffer[CandidateWithDetails]() - while (groupedBucketsIterators.nonEmpty) { - val bucket = patternIterator.next() - groupedBucketsIterators.get(bucket) match { - case Some(iterator) if iterator.nonEmpty => newResult += iterator.next() - case Some(_) => groupedBucketsIterators.remove(bucket) - case None => - } - } - - SelectorResult( - remainingCandidates = otherCandidates, - result = result ++ newResult ++ notABucketInThePattern) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala deleted file mode 100644 index f60b0abbc..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendRatioResults.scala +++ /dev/null @@ -1,171 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param -import scala.annotation.tailrec -import scala.collection.mutable -import scala.util.Random - -/** - * Select candidates and add them according to the ratio assigned for each [[Bucket]] - * For instance, if given `Set((A, 0.8), (B, 0.2))` then candidates will randomly be added to the - * results with an 80% chance of any candidate being from `A` and 20% from`B`. If there are no more - * candidates from a given `CandidatePipeline` then it's simply skipped, so if we run out of `A` - * candidates the rest will be `B`. The end result is all candidates from all [[candidatePipelines]]s - * provided will end up in the result. - * - * For example, an output may look like `Seq(A, A, B, A, A)`, `Seq(A, A, A, A, B)`. If we eventually - * run out of `A` candidates then we would end up with the remaining candidates at the end, - * `Seq(A, A, B, A, A, A, B, A, A, A [run out of A], B, B, B, B, B, B)` - * - * @note the ratios provided are proportional to the sum of all ratios, so if you give 0.3 and 0.7, - * they will be function as to 30% and 70%, and the same for if you provided 3000 and 7000 for - * ratios. - * - * @note Its important to be sure to update all [[Param]]s when changing the ratio for 1 of them - * otherwise you may get unexpected results. For instance, of you have 0.3 and 0.7 which - * correspond to 30% and 70%, and you change `0.7 -> 0.9`, then the total sum of the ratios is - * now 1.2, so you have 25% and 75% when you intended to have 10% and 90%. To prevent this, - * be sure to update all [[Param]]s together, so `0.3 -> 0.1` and `0.7 -> 0.9` so the total - * remains the same. - */ -case class InsertAppendRatioResults[-Query <: PipelineQuery, Bucket]( - candidatePipelines: Set[CandidatePipelineIdentifier], - bucketer: Bucketer[Bucket], - ratios: Map[Bucket, Param[Double]], - random: Random = new Random(0)) - extends Selector[Query] { - - require(ratios.nonEmpty, "bucketRatios must be non-empty") - - override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipelines) - - private sealed trait PatternResult - private case object NotASelectedCandidatePipeline extends PatternResult - private case object NotABucketInThePattern extends PatternResult - private case class Bucketed(bucket: Bucket) extends PatternResult - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val groupedCandidates: Map[PatternResult, Seq[CandidateWithDetails]] = - remainingCandidates.groupBy { candidateWithDetails => - if (pipelineScope.contains(candidateWithDetails)) { - // if a candidate's Bucket doesnt appear in the pattern it's backfilled at the end - val bucket = bucketer(candidateWithDetails) - if (ratios.contains(bucket)) { - Bucketed(bucket) - } else { - NotABucketInThePattern - } - } else { - NotASelectedCandidatePipeline - } - } - - val otherCandidates = - groupedCandidates.getOrElse(NotASelectedCandidatePipeline, Seq.empty) - - val notABucketInThePattern = - groupedCandidates.getOrElse(NotABucketInThePattern, Seq.empty) - - val groupedCandidatesIterators = groupedCandidates.collect { - case (Bucketed(bucket), candidatesWithDetails) => (bucket, candidatesWithDetails.iterator) - } - - // using a LinkedHashMap and sorting by descending ratio - // the highest ratios will always be checked first when iterating - // mutable so we can remove finished ratios when they are finished to optimize looping for large numbers of ratios - val currentBucketRatios: mutable.Map[Bucket, Double] = { - val bucketsAndRatiosSortedByRatio = - ratios.iterator - .map { - case (bucket, param) => - val ratio = query.params(param) - require( - ratio >= 0, - "The ratio for an InsertAppendRatioResults selector can not be negative") - (bucket, ratio) - }.toSeq - .sortBy { case (_, ratio) => ratio }(Ordering.Double.reverse) - mutable.LinkedHashMap(bucketsAndRatiosSortedByRatio: _*) - } - - // keep track of the sum of all ratios so we can look only at random values between 0 and that - var ratioSum = currentBucketRatios.valuesIterator.sum - - // add candidates to `newResults` until all remaining candidates are for a single bucket - val newResult = new mutable.ArrayBuffer[CandidateWithDetails]() - while (currentBucketRatios.size > 1) { - // random number between 0 and the sum of the ratios of all params - val randomValue = random.nextDouble() * ratioSum - - val currentBucketRatiosIterator: Iterator[(Bucket, Double)] = - currentBucketRatios.iterator - val (currentBucket, ratio) = currentBucketRatiosIterator.next() - - val componentToTakeFrom = findBucketToTakeFrom( - randomValue = randomValue, - cumulativeSumOfRatios = ratio, - bucket = currentBucket, - bucketRatiosIterator = currentBucketRatiosIterator - ) - - groupedCandidatesIterators.get(componentToTakeFrom) match { - case Some(iteratorForBucket) if iteratorForBucket.nonEmpty => - newResult += iteratorForBucket.next() - case _ => - ratioSum -= currentBucketRatios(componentToTakeFrom) - currentBucketRatios.remove(componentToTakeFrom) - } - } - // with only have 1 source remaining, we can skip all the above work and insert them in bulk - val remainingBucketInRatio = - currentBucketRatios.keysIterator.flatMap(groupedCandidatesIterators.get).flatten - - SelectorResult( - remainingCandidates = otherCandidates, - result = result ++ newResult ++ remainingBucketInRatio ++ notABucketInThePattern) - } - - /** - * iterates through the `bucketRatiosIterator` until it finds a the - * [[Bucket]] that corresponds with the current `randomValue`. - * - * This method expects that `0 <= randomValue <= sum of all ratios` - * - * @example If the given ratios are `Seq(A -> 0.2, B -> 0.35, C -> 0.45)` - * check if the given `randomValue` is - * - `< 0.45`, if not then check - * - `< 0.8` (0.45 + 0.35), if not then check - * - `< 1.0` (0.45 + 0.35 + 0.2) - * - * and return the corresponding [[Bucket]] - */ - @tailrec private def findBucketToTakeFrom( - randomValue: Double, - cumulativeSumOfRatios: Double, - bucket: Bucket, - bucketRatiosIterator: Iterator[(Bucket, Double)] - ): Bucket = { - if (randomValue < cumulativeSumOfRatios || bucketRatiosIterator.isEmpty) { - bucket - } else { - val (nextBucket, ratio) = bucketRatiosIterator.next() - findBucketToTakeFrom( - randomValue, - cumulativeSumOfRatios + ratio, - nextBucket, - bucketRatiosIterator) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala deleted file mode 100644 index a3e8485c3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendResults.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object InsertAppendResults { - def apply(candidatePipeline: CandidatePipelineIdentifier): InsertAppendResults[PipelineQuery] = - new InsertAppendResults(SpecificPipeline(candidatePipeline)) - - def apply( - candidatePipelines: Set[CandidatePipelineIdentifier] - ): InsertAppendResults[PipelineQuery] = new InsertAppendResults( - SpecificPipelines(candidatePipelines)) -} - -/** - * Select all candidates from candidate pipeline(s) and append to the end of the result. - * - * @note that if multiple candidate pipelines are specified, their candidates will be added - * to the result in the order in which they appear in the candidate pool. This ordering often - * reflects the order in which the candidate pipelines were listed in the mixer/recommendations - * pipeline, unless for example an UpdateSortCandidates selector was run prior to running - * this selector which could change this ordering. - * - * @note if inserting results from multiple candidate pipelines (see note above related to ordering), - * it is more performant to include all (or a subset) of the candidate pipelines in a single - * InsertAppendResults, as opposed to calling InsertAppendResults individually for each - * candidate pipeline because each selector does an O(n) pass on the candidate pool. - */ -case class InsertAppendResults[-Query <: PipelineQuery]( - override val pipelineScope: CandidateScope) - extends Selector[Query] { - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val PartitionedCandidates(selectedCandidates, otherCandidates) = - pipelineScope.partition(remainingCandidates) - - val resultUpdated = result ++ selectedCandidates - - SelectorResult(remainingCandidates = otherCandidates, result = resultUpdated) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala deleted file mode 100644 index 73ba481b5..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWeaveResults.scala +++ /dev/null @@ -1,120 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import scala.collection.mutable - -object InsertAppendWeaveResults { - def apply[Query <: PipelineQuery, Bucket]( - candidatePipelines: Set[CandidatePipelineIdentifier], - bucketer: Bucketer[Bucket], - ): InsertAppendWeaveResults[Query, Bucket] = - new InsertAppendWeaveResults(SpecificPipelines(candidatePipelines), bucketer) - - def apply[Query <: PipelineQuery, Bucket]( - candidatePipeline: CandidatePipelineIdentifier, - bucketer: Bucketer[Bucket], - ): InsertAppendWeaveResults[Query, Bucket] = - new InsertAppendWeaveResults(SpecificPipeline(candidatePipeline), bucketer) -} - -/** - * Select candidates weave them together according to their [[Bucket]]. - * - * Candidates are grouped according to [[Bucket]] and one candidate is added from each group until - * no candidates belonging to any group are left. - * - * Functionally similar to [[InsertAppendPatternResults]]. [[InsertAppendPatternResults]] is useful - * if you have more complex ordering requirements but it requires you to know all the buckets in - * advance. - * - * @note The order in which candidates are weaved together depends on the order in which the buckets - * were first seen on candidates. - * - * @example If the candidates are Seq(Tweet(10), Tweet(8), Tweet(3), Tweet(13)) and they are bucketed - * using an IsEven bucketing function, then the resulting buckets would be: - * - * - Seq(Tweet(10), Tweet(8)) - * - Seq(Tweet(3), Tweet(13)) - * - * The selector would then loop through these buckets and produce: - * - * - Tweet(10) - * - Tweet(3) - * - Tweet(8) - * - Tweet(13) - * - * Note that first bucket encountered was the 'even' bucket so weaving proceeds first with - * the even bucket then the odd bucket. Tweet(3) had been first then the opposite would be - * true. - */ -case class InsertAppendWeaveResults[-Query <: PipelineQuery, Bucket]( - override val pipelineScope: CandidateScope, - bucketer: Bucketer[Bucket]) - extends Selector[Query] { - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val (bucketableCandidates, otherCandidates) = - remainingCandidates.partition(pipelineScope.contains) - - val groupedCandidates = groupByBucket(bucketableCandidates) - - val candidateBucketQueues: mutable.Queue[mutable.Queue[CandidateWithDetails]] = - mutable.Queue() ++= groupedCandidates - val newResult = mutable.ArrayBuffer[CandidateWithDetails]() - - // Take the next group of candidates from the queue and attempt to add the first candidate from - // that group into the result. The loop will terminate when every queue is empty. - while (candidateBucketQueues.nonEmpty) { - val nextCandidateQueue = candidateBucketQueues.dequeue() - - if (nextCandidateQueue.nonEmpty) { - newResult += nextCandidateQueue.dequeue() - - // Re-queue this bucket of candidates if it's still non-empty - if (nextCandidateQueue.nonEmpty) { - candidateBucketQueues.enqueue(nextCandidateQueue) - } - } - } - - SelectorResult(remainingCandidates = otherCandidates, result = result ++ newResult) - } - - /** - * Similar to `groupBy` but respect the order in which individual bucket values are first seen. - * This is useful when the candidates have already been sorted prior to the selector running. - */ - private def groupByBucket( - candidates: Seq[CandidateWithDetails] - ): mutable.ArrayBuffer[mutable.Queue[CandidateWithDetails]] = { - val bucketToCandidateGroupIndex = mutable.Map.empty[Bucket, Int] - val candidateGroups = mutable.ArrayBuffer[mutable.Queue[CandidateWithDetails]]() - - candidates.foreach { candidate => - val bucket = bucketer(candidate) - - // Index points to the specific sub-group in candidateGroups where we want to insert the next - // candidate. If a bucket has already been seen then this value is known, otherwise we need - // to add a new entry for it. - if (!bucketToCandidateGroupIndex.contains(bucket)) { - candidateGroups.append(mutable.Queue()) - bucketToCandidateGroupIndex.put(bucket, candidateGroups.length - 1) - } - - candidateGroups(bucketToCandidateGroupIndex(bucket)).enqueue(candidate) - } - - candidateGroups - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala deleted file mode 100644 index 26767ffb7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertAppendWithoutFeatureResults.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * A selector that appends all candidates missing a specific feature to the results pool and keeps - * the rest in the remaining candidates. This is useful for backfill scoring candidates without - * a score from a previous scorer. - * @param pipelineScope The pipeline scope to check - * @param missingFeature The missing feature to check for. - */ -case class InsertAppendWithoutFeatureResults( - override val pipelineScope: CandidateScope, - missingFeature: Feature[_, _]) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val (candidatesWithMissingFeature, candidatesWithFeature) = remainingCandidates.partition { - candidate => - pipelineScope.contains(candidate) && !candidate.features.getSuccessfulFeatures - .contains(missingFeature) - } - val updatedResults = result ++ candidatesWithMissingFeature - SelectorResult(remainingCandidates = candidatesWithFeature, result = updatedResults) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala deleted file mode 100644 index e0fb9bebb..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertDynamicPositionResults.scala +++ /dev/null @@ -1,69 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector._ -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object InsertDynamicPositionResults { - def apply[Query <: PipelineQuery]( - candidatePipeline: CandidatePipelineIdentifier, - dynamicInsertionPosition: DynamicInsertionPosition[Query], - ): InsertDynamicPositionResults[Query] = - new InsertDynamicPositionResults(SpecificPipeline(candidatePipeline), dynamicInsertionPosition) - - def apply[Query <: PipelineQuery]( - candidatePipelines: Set[CandidatePipelineIdentifier], - dynamicInsertionPosition: DynamicInsertionPosition[Query] - ): InsertDynamicPositionResults[Query] = - new InsertDynamicPositionResults( - SpecificPipelines(candidatePipelines), - dynamicInsertionPosition) -} - -/** - * Compute a position for inserting the candidates into result. If a `None` is returned, the - * Selector using this would not insert the candidates into the result. - */ -trait DynamicInsertionPosition[-Query <: PipelineQuery] { - def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): Option[Int] -} - -/** - * Insert all candidates in a pipeline scope at a 0-indexed dynamic position computed - * using the provided [[DynamicInsertionPosition]] instance. If the current results are a shorter - * length than the computed position, then the candidates will be appended to the results. - * If the [[DynamicInsertionPosition]] returns a `None`, the candidates are not - * added to the result. - */ -case class InsertDynamicPositionResults[-Query <: PipelineQuery]( - override val pipelineScope: CandidateScope, - dynamicInsertionPosition: DynamicInsertionPosition[Query]) - extends Selector[Query] { - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - dynamicInsertionPosition(query, remainingCandidates, result) match { - case Some(position) => - InsertSelector.insertIntoResultsAtPosition( - position = position, - pipelineScope = pipelineScope, - remainingCandidates = remainingCandidates, - result = result) - case None => - // When a valid position is not provided, do not insert the candidates. - // Both the remainingCandidates and result are unchanged. - SelectorResult(remainingCandidates = remainingCandidates, result = result) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala deleted file mode 100644 index 1fb4d61be..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionIntoModuleCandidates.scala +++ /dev/null @@ -1,69 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleAndIndex -import com.twitter.product_mixer.component_library.selector.InsertIntoModule.ModuleWithItemsToAddAndOtherCandidates -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Insert all candidates from [[candidatePipeline]] at a 0-indexed fixed position into a module from - * [[targetModuleCandidatePipeline]]. If the results contain multiple modules from the target candidate - * pipeline, then the candidates will be inserted into the first module. If the target module's - * items are a shorter length than the requested position, then the candidates will be appended - * to the results. - * - * @note this will throw an [[UnsupportedOperationException]] if the [[candidatePipeline]] contains any modules. - * - * @note this updates the module in the `remainingCandidates` - */ -case class InsertFixedPositionIntoModuleCandidates( - candidatePipeline: CandidatePipelineIdentifier, - targetModuleCandidatePipeline: CandidatePipelineIdentifier, - positionParam: Param[Int]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = - SpecificPipelines(candidatePipeline, targetModuleCandidatePipeline) - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val position = query.params(positionParam) - assert(position >= 0, "Position must be equal to or greater than zero") - - val ModuleWithItemsToAddAndOtherCandidates( - moduleToUpdateAndIndex, - itemsToInsertIntoModule, - otherCandidates) = - InsertIntoModule.moduleToUpdate( - candidatePipeline, - targetModuleCandidatePipeline, - remainingCandidates) - - val updatedRemainingCandidates = moduleToUpdateAndIndex match { - case None => remainingCandidates - case _ if itemsToInsertIntoModule.isEmpty => remainingCandidates - case Some(ModuleAndIndex(moduleToUpdate, indexOfModuleInOtherCandidates)) => - val updatedModuleItems = - if (position < moduleToUpdate.candidates.length) { - val (left, right) = moduleToUpdate.candidates.splitAt(position) - left ++ itemsToInsertIntoModule ++ right - } else { - moduleToUpdate.candidates ++ itemsToInsertIntoModule - } - val updatedModule = moduleToUpdate.copy(candidates = updatedModuleItems) - otherCandidates.updated(indexOfModuleInOtherCandidates, updatedModule) - } - - SelectorResult(remainingCandidates = updatedRemainingCandidates, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala deleted file mode 100644 index ef2f392a1..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertFixedPositionResults.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -object InsertFixedPositionResults { - def apply( - candidatePipeline: CandidatePipelineIdentifier, - positionParam: Param[Int], - ): InsertFixedPositionResults = - new InsertFixedPositionResults(SpecificPipeline(candidatePipeline), positionParam) - - def apply( - candidatePipelines: Set[CandidatePipelineIdentifier], - positionParam: Param[Int] - ): InsertFixedPositionResults = - new InsertFixedPositionResults(SpecificPipelines(candidatePipelines), positionParam) -} - -/** - * Insert all candidates in a pipeline scope at a 0-indexed fixed position. If the current - * results are a shorter length than the requested position, then the candidates will be appended - * to the results. - */ -case class InsertFixedPositionResults( - override val pipelineScope: CandidateScope, - positionParam: Param[Int]) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = InsertSelector.insertIntoResultsAtPosition( - position = query.params(positionParam), - pipelineScope = pipelineScope, - remainingCandidates = remainingCandidates, - result = result) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala deleted file mode 100644 index 53f3df75f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertIntoModule.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import scala.collection.immutable.Queue - -private[selector] object InsertIntoModule { - case class ModuleAndIndex( - moduleToInsertInto: ModuleCandidateWithDetails, - indexOfModuleInOtherCandidates: Int) - - case class ModuleWithItemsToAddAndOtherCandidates( - moduleToUpdateAndIndex: Option[ModuleAndIndex], - itemsToInsertIntoModule: Queue[ItemCandidateWithDetails], - otherCandidates: Queue[CandidateWithDetails]) - - /** - * Given a Seq of `candidates`, returns the first module with it's index that matches the - * `targetModuleCandidatePipeline` with all the [[ItemCandidateWithDetails]] that match the - * `candidatePipeline` added to the `itemsToInsert` and the remaining candidates, including the - * module, in the `otherCandidates` - */ - def moduleToUpdate( - candidatePipeline: CandidatePipelineIdentifier, - targetModuleCandidatePipeline: CandidatePipelineIdentifier, - candidates: Seq[CandidateWithDetails] - ): ModuleWithItemsToAddAndOtherCandidates = { - candidates.foldLeft[ModuleWithItemsToAddAndOtherCandidates]( - ModuleWithItemsToAddAndOtherCandidates(None, Queue.empty, Queue.empty)) { - case ( - state @ ModuleWithItemsToAddAndOtherCandidates(_, itemsToInsertIntoModule, _), - selectedItem: ItemCandidateWithDetails) if selectedItem.source == candidatePipeline => - state.copy(itemsToInsertIntoModule = itemsToInsertIntoModule :+ selectedItem) - - case ( - state @ ModuleWithItemsToAddAndOtherCandidates(None, _, otherCandidates), - module: ModuleCandidateWithDetails) if module.source == targetModuleCandidatePipeline => - val insertionIndex = otherCandidates.length - val moduleAndIndex = Some( - ModuleAndIndex( - moduleToInsertInto = module, - indexOfModuleInOtherCandidates = insertionIndex)) - val otherCandidatesWithModuleAppended = otherCandidates :+ module - state.copy( - moduleToUpdateAndIndex = moduleAndIndex, - otherCandidates = otherCandidatesWithModuleAppended) - - case (_, invalidModule: ModuleCandidateWithDetails) - if invalidModule.source == candidatePipeline => - /** - * while not exactly an illegal state, its most likely an incorrectly configured candidate pipeline - * that returned a module instead of returning the candidates the module contains. Since you can't - * nest a module inside of a module, we can either throw or ignore it and we choose to ignore it - * to catch a potential bug a customer may do accidentally. - */ - throw new UnsupportedOperationException( - s"Expected the candidatePipeline $candidatePipeline to contain items to put into the module from the targetModuleCandidatePipeline $targetModuleCandidatePipeline, but not contain modules itself. " + - s"This can occur if your $candidatePipeline was incorrectly configured and returns a module when you intended to return the candidates the module contained." - ) - - case ( - state @ ModuleWithItemsToAddAndOtherCandidates(_, _, otherCandidates), - unselectedCandidate) => - state.copy(otherCandidates = otherCandidates :+ unselectedCandidate) - } - } - -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala deleted file mode 100644 index 5c923ad9c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertPerCandidateDynamicPositionResults.scala +++ /dev/null @@ -1,78 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object InsertPerCandidateDynamicPositionResults { - def apply[Query <: PipelineQuery]( - candidatePipeline: CandidatePipelineIdentifier, - candidatePositionInResults: CandidatePositionInResults[Query] - ): InsertPerCandidateDynamicPositionResults[Query] = - InsertPerCandidateDynamicPositionResults[Query]( - SpecificPipeline(candidatePipeline), - candidatePositionInResults) - - def apply[Query <: PipelineQuery]( - candidatePipelines: Set[CandidatePipelineIdentifier], - candidatePositionInResults: CandidatePositionInResults[Query] - ): InsertPerCandidateDynamicPositionResults[Query] = - InsertPerCandidateDynamicPositionResults[Query]( - SpecificPipelines(candidatePipelines), - candidatePositionInResults) -} - -/** - * Insert each candidate in the [[CandidateScope]] at the index relative to the original candidate in the `result` - * at that index using the provided [[CandidatePositionInResults]] instance. If the current results are shorter - * length than the computed position, then the candidate will be appended to the results. - * - * When the [[CandidatePositionInResults]] returns a `None`, that candidate is not - * added to the result. Negative position values are treated as 0 (front of the results). - * - * @example if [[CandidatePositionInResults]] results in a candidate mapping from index to candidate of - * `{0 -> a, 0 -> b, 0 -> c, 1 -> e, 2 -> g, 2 -> h} ` with original `results` = `[D, F]`, - * then the resulting output would look like `[a, b, c, D, e, F, g, h]` - */ -case class InsertPerCandidateDynamicPositionResults[-Query <: PipelineQuery]( - pipelineScope: CandidateScope, - candidatePositionInResults: CandidatePositionInResults[Query]) - extends Selector[Query] { - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val (candidatesToInsert, otherRemainingCandidatesTuples) = remainingCandidates - .map { candidate: CandidateWithDetails => - val position = - if (pipelineScope.contains(candidate)) - candidatePositionInResults(query, candidate, result) - else - None - (position, candidate) - }.partition { case (index, _) => index.isDefined } - - val otherRemainingCandidates = otherRemainingCandidatesTuples.map { - case (_, candidate) => candidate - } - - val positionAndCandidateList = candidatesToInsert.collect { - case (Some(position), candidate) => (position, candidate) - } - - val mergedResult = DynamicPositionSelector.mergeByIndexIntoResult( - positionAndCandidateList, - result, - DynamicPositionSelector.RelativeIndices - ) - - SelectorResult(remainingCandidates = otherRemainingCandidates, result = mergedResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala deleted file mode 100644 index a6f4feae8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRandomPositionResults.scala +++ /dev/null @@ -1,139 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.InsertRandomPositionResults.randomIndices -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.configapi.StaticParam -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -import scala.collection.mutable -import scala.util.Random - -object InsertRandomPositionResults { - - /** - * Iterator containing random index between `startIndex` and `endIndex` + `n` - * where `n` is the number of times `next` has been called on the iterator - * without duplication - */ - private[selector] def randomIndices( - resultLength: Int, - startIndex: Int, - endIndex: Int, - random: Random - ): Iterator[Int] = { - - /** exclusive because [[Random.nextInt]]'s bound is exclusive */ - val indexUpperBound = Math.min(endIndex, resultLength) - - /** - * keep track of the available indices, `O(n)` space where `n` is `min(endIndex, resultLength) - max(startIndex, 0)` - * this ensures fairness which duplicate indices could otherwise skew - */ - val values = mutable.ArrayBuffer(Math.max(0, startIndex) to indexUpperBound: _*) - - /** - * Iterator that starts at 1 above the last valid index, [[indexUpperBound]] + 1, and increments monotonically - * representing the new highest index possible in the results for the next call - */ - Iterator - .from(indexUpperBound + 1) - .map { indexUpperBound => - /** - * pick a random index-to-insert-candidate-into-results from [[values]] replacing the value at - * the chosen index with the new highest index from [[indexUpperBound]], this results in - * constant time for picking the random index and adding the new highest valid index instead - * of removing the item from the middle and appending the new, which would be `O(n)` to shift - * all indices after the removal point - */ - val i = random.nextInt(values.length) - val randomIndexToUse = values(i) - // override the value at i with the new `upperBoundExclusive` to account for the new index value in the next iteration - values(i) = indexUpperBound - - randomIndexToUse - } - } -} - -sealed trait InsertedCandidateOrder - -/** - * Candidates from the `remainingCandidates` side will be inserted in a random order into the `result` - * - * @example if inserting `[ x, y, z ]` into the `result` then the relative positions of `x`, `y` and `z` - * to each other is random, e.g. `y` could come before `x` in the result. - */ -case object UnstableOrderingOfInsertedCandidates extends InsertedCandidateOrder - -/** - * Candidates from the `remainingCandidates` side will be inserted in their original order into the `result` - * - * @example if inserting `[ x, y, z ]` into the `result` then the relative positions of `x`, `y` and `z` - * to each other will remain the same, e.g. `x` is always before `y` is always before `z` in the final result - */ -case object StableOrderingOfInsertedCandidates extends InsertedCandidateOrder - -/** - * Insert `remainingCandidates` into a random position between the specified indices (inclusive) - * - * @example let `result` = `[ a, b, c, d ]` and we want to insert randomly `[ x, y, z ]` - * with `startIndex` = 1, `endIndex` = 2, and [[UnstableOrderingOfInsertedCandidates]]. - * We can expect a result that looks like `[ a, ... , d ]` where `...` is - * a random insertion of `x`, `y`, and `z` into `[ b, c ]`. So this could look like - * `[ a, y, b, x, c, z, d ]`, note that the inserted elements are randomly distributed - * among the elements that were originally between the specified indices. - * This functions like taking a slice of the original `result` between the indices, - * e.g. `[ b, c ]`, then randomly inserting into the slice, e.g. `[ y, b, x, c, z ]`, - * before reassembling the `result`, e.g. `[ a ] ++ [ y, b, x, c, z ] ++ [ d ]`. - * - * @example let `result` = `[ a, b, c, d ]` and we want to insert randomly `[ x, y, z ]` - * with `startIndex` = 1, `endIndex` = 2, and [[StableOrderingOfInsertedCandidates]]. - * We can expect a result that looks something like `[ a, x, b, y, c, z, d ]`, - * where `x` is before `y` which is before `z` - * - * @param startIndex an inclusive index which starts the range where the candidates will be inserted - * @param endIndex an inclusive index which ends the range where the candidates will be inserted - */ -case class InsertRandomPositionResults[-Query <: PipelineQuery]( - pipelineScope: CandidateScope, - remainingCandidateOrder: InsertedCandidateOrder, - startIndex: Param[Int] = StaticParam(0), - endIndex: Param[Int] = StaticParam(Int.MaxValue), - random: Random = new Random(0)) - extends Selector[Query] { - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val PartitionedCandidates(candidatesInScope, candidatesOutOfScope) = - pipelineScope.partition(remainingCandidates) - - val randomIndexIterator = { - val randomIndexIterator = - randomIndices(result.length, query.params(startIndex), query.params(endIndex), random) - - remainingCandidateOrder match { - case StableOrderingOfInsertedCandidates => - randomIndexIterator.take(candidatesInScope.length).toSeq.sorted.iterator - case UnstableOrderingOfInsertedCandidates => - randomIndexIterator - } - } - - val mergedResult = DynamicPositionSelector.mergeByIndexIntoResult( - candidatesToInsertByIndex = randomIndexIterator.zip(candidatesInScope.iterator).toSeq, - result = result, - DynamicPositionSelector.AbsoluteIndices - ) - - SelectorResult(remainingCandidates = candidatesOutOfScope, result = mergedResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala deleted file mode 100644 index e3212c58b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertRelativePositionResults.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -/** - * Insert all candidates from a candidate pipeline at a position below, relative to the last - * selection of the relative to candidate pipeline. If the relative to candidate pipeline does not - * contain candidates, then the candidates will be inserted with padding relative to position zero. - * If the current results are a shorter length than the requested padding, then the candidates will - * be appended to the results. - */ -case class InsertRelativePositionResults( - candidatePipeline: CandidatePipelineIdentifier, - relativeToCandidatePipeline: CandidatePipelineIdentifier, - paddingAboveParam: Param[Int]) - extends Selector[PipelineQuery] { - - override val pipelineScope: CandidateScope = SpecificPipelines(candidatePipeline) - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val paddingAbove = query.params(paddingAboveParam) - assert(paddingAbove >= 0, "Padding above must be equal to or greater than zero") - - val PartitionedCandidates(selectedCandidates, otherCandidates) = - pipelineScope.partition(remainingCandidates) - - val resultUpdated = if (selectedCandidates.nonEmpty) { - // If the relativeToCandidatePipeline has zero candidates, lastIndexWhere will return -1 which - // will start padding from the zero position - val relativePosition = result.lastIndexWhere(_.source == relativeToCandidatePipeline) + 1 - val position = relativePosition + paddingAbove - - if (position < result.length) { - val (left, right) = result.splitAt(position) - left ++ selectedCandidates ++ right - } else { - result ++ selectedCandidates - } - } else { - result - } - - SelectorResult(remainingCandidates = otherCandidates, result = resultUpdated) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala deleted file mode 100644 index dd814bf72..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/InsertSelector.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -private[selector] object InsertSelector { - - /** - * Insert all candidates from a candidate pipeline at a 0-indexed fixed position. If the current - * results are a shorter length than the requested position, then the candidates will be appended - * to the results. - */ - def insertIntoResultsAtPosition( - position: Int, - pipelineScope: CandidateScope, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - assert(position >= 0, "Position must be equal to or greater than zero") - - val PartitionedCandidates(selectedCandidates, otherCandidates) = - pipelineScope.partition(remainingCandidates) - - val resultUpdated = if (selectedCandidates.nonEmpty) { - if (position < result.length) { - val (left, right) = result.splitAt(position) - left ++ selectedCandidates ++ right - } else { - result ++ selectedCandidates - } - } else { - result - } - - SelectorResult(remainingCandidates = otherCandidates, result = resultUpdated) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala deleted file mode 100644 index f4e8bb515..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectConditionally.scala +++ /dev/null @@ -1,85 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.timelines.configapi.Param - -trait IncludeSelector[-Query <: PipelineQuery] { - def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): Boolean -} - -/** - * Run [[selector]] if [[includeSelector]] resolves to true, else no-op the selector - */ -case class SelectConditionally[-Query <: PipelineQuery]( - selector: Selector[Query], - includeSelector: IncludeSelector[Query]) - extends Selector[Query] { - - override val pipelineScope: CandidateScope = selector.pipelineScope - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - if (includeSelector(query, remainingCandidates, result)) { - selector(query, remainingCandidates, result) - } else SelectorResult(remainingCandidates = remainingCandidates, result = result) - } -} - -object SelectConditionally { - - /** - * Wrap each [[Selector]] in `selectors` in an [[IncludeSelector]] with `includeSelector` as the [[SelectConditionally.includeSelector]] - */ - def apply[Query <: PipelineQuery]( - selectors: Seq[Selector[Query]], - includeSelector: IncludeSelector[Query] - ): Seq[Selector[Query]] = - selectors.map(SelectConditionally(_, includeSelector)) - - /** - * A [[SelectConditionally]] based on a [[Param]] - */ - def paramGated[Query <: PipelineQuery]( - selector: Selector[Query], - enabledParam: Param[Boolean], - ): SelectConditionally[Query] = - SelectConditionally(selector, (query, _, _) => query.params(enabledParam)) - - /** - * Wrap each [[Selector]] in `selectors` in a [[SelectConditionally]] based on a [[Param]] - */ - def paramGated[Query <: PipelineQuery]( - selectors: Seq[Selector[Query]], - enabledParam: Param[Boolean], - ): Seq[Selector[Query]] = - selectors.map(SelectConditionally.paramGated(_, enabledParam)) - - /** - * A [[SelectConditionally]] based on an inverted [[Param]] - */ - def paramNotGated[Query <: PipelineQuery]( - selector: Selector[Query], - enabledParamToInvert: Param[Boolean], - ): SelectConditionally[Query] = - SelectConditionally(selector, (query, _, _) => !query.params(enabledParamToInvert)) - - /** - * Wrap each [[Selector]] in `selectors` in a [[SelectConditionally]] based on an inverted [[Param]] - */ - def paramNotGated[Query <: PipelineQuery]( - selectors: Seq[Selector[Query]], - enabledParamToInvert: Param[Boolean], - ): Seq[Selector[Query]] = - selectors.map(SelectConditionally.paramNotGated(_, enabledParamToInvert)) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala deleted file mode 100644 index 86ff297b7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/SelectFromSubpoolCandidates.scala +++ /dev/null @@ -1,147 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import scala.reflect.ClassTag - -sealed trait SubpoolIncludeTypes - -trait IncludeInSubpool[-Query <: PipelineQuery] extends SubpoolIncludeTypes { - - /** - * Given the `query`, current `remainingCandidate`, and the `result`, - * returns whether the specific `remainingCandidate` should be passed into the - * [[SelectFromSubpoolCandidates]]'s [[SelectFromSubpoolCandidates.selector]] - * - * @note the `result` contains the [[SelectorResult.result]] that was passed into this selector, - * so each `remainingCandidate` will get the same `result` Seq. - */ - def apply( - query: Query, - remainingCandidate: CandidateWithDetails, - result: Seq[CandidateWithDetails] - ): Boolean -} - -case class IncludeCandidateTypeInSubpool[CandidateType <: UniversalNoun[_]]( -)( - implicit tag: ClassTag[CandidateType]) - extends IncludeInSubpool[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidate: CandidateWithDetails, - result: Seq[CandidateWithDetails] - ): Boolean = remainingCandidate.isCandidateType[CandidateType]() -} - -trait IncludeSetInSubpool[-Query <: PipelineQuery] extends SubpoolIncludeTypes { - - /** - * Given the `query`, all `remainingCandidates`` and `results`, - * returns a Set of which candidates should be included in the subpool. - * - * @note the returned set is only used to determine subpool membership. Mutating the candidates - * is invalid and won't work. The order of the candidates will be preserved from the current - * order of the remaining candidates sequence. - */ - def apply( - query: Query, - remainingCandidate: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): Set[CandidateWithDetails] -} - -sealed trait SubpoolRemainingCandidatesHandler - -/** - * Candidates remaining in the subpool after running the selector will be - * prepended to the beginning of the [[SelectorResult.remainingCandidates]] - */ -case object PrependToBeginningOfRemainingCandidates extends SubpoolRemainingCandidatesHandler - -/** - * Candidates remaining in the subpool after running the selector will be - * appended to the end of the [[SelectorResult.remainingCandidates]] - */ -case object AppendToEndOfRemainingCandidates extends SubpoolRemainingCandidatesHandler - -/** - * Creates a subpool of all `remainingCandidates` for which [[subpoolInclude]] resolves to true - * (in the same order as the original `remainingCandidates`) and runs the [[selector]] with the - * subpool passed in as the `remainingCandidates`. - * - * Most customers want to use a IncludeInSubpool that chooses if each candidate should be included - * in the subpool. - * Where necessary, IncludeSetInSubpool allows you to define them in bulk w/ a Set. - * - * @note any candidates in the subpool which are not added to the [[SelectorResult.result]] - * will be treated according to the [[SubpoolRemainingCandidatesHandler]] - */ -class SelectFromSubpoolCandidates[-Query <: PipelineQuery] private[selector] ( - val selector: Selector[Query], - subpoolInclude: SubpoolIncludeTypes, - subpoolRemainingCandidatesHandler: SubpoolRemainingCandidatesHandler = - AppendToEndOfRemainingCandidates) - extends Selector[Query] { - - override val pipelineScope: CandidateScope = selector.pipelineScope - - override def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - - val (selectedCandidates, otherCandidates) = subpoolInclude match { - case includeInSubpool: IncludeInSubpool[Query] => - remainingCandidates.partition(candidate => - pipelineScope.contains(candidate) && includeInSubpool(query, candidate, result)) - case includeSetInSubpool: IncludeSetInSubpool[Query] => - val includeSet = - includeSetInSubpool(query, remainingCandidates.filter(pipelineScope.contains), result) - remainingCandidates.partition(candidate => includeSet.contains(candidate)) - } - - val underlyingSelectorResult = selector.apply(query, selectedCandidates, result) - val remainingCandidatesWithSubpoolRemainingCandidates = - subpoolRemainingCandidatesHandler match { - case AppendToEndOfRemainingCandidates => - otherCandidates ++ underlyingSelectorResult.remainingCandidates - case PrependToBeginningOfRemainingCandidates => - underlyingSelectorResult.remainingCandidates ++ otherCandidates - } - underlyingSelectorResult.copy(remainingCandidates = - remainingCandidatesWithSubpoolRemainingCandidates) - } - - override def toString: String = s"SelectFromSubpoolCandidates(${selector.toString}))" -} - -object SelectFromSubpoolCandidates { - def apply[Query <: PipelineQuery]( - selector: Selector[Query], - includeInSubpool: IncludeInSubpool[Query], - subpoolRemainingCandidatesHandler: SubpoolRemainingCandidatesHandler = - AppendToEndOfRemainingCandidates - ) = new SelectFromSubpoolCandidates[Query]( - selector, - includeInSubpool, - subpoolRemainingCandidatesHandler - ) - - def includeSet[Query <: PipelineQuery]( - selector: Selector[Query], - includeSetInSubpool: IncludeSetInSubpool[Query], - subpoolRemainingCandidatesHandler: SubpoolRemainingCandidatesHandler = - AppendToEndOfRemainingCandidates - ) = new SelectFromSubpoolCandidates[Query]( - selector, - includeSetInSubpool, - subpoolRemainingCandidatesHandler - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala deleted file mode 100644 index 235bcf778..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortCandidates.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering -import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector._ -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object UpdateSortCandidates { - def apply( - candidatePipeline: CandidatePipelineIdentifier, - sorterProvider: SorterProvider, - ) = new UpdateSortCandidates(SpecificPipeline(candidatePipeline), sorterProvider) - - def apply( - candidatePipeline: CandidatePipelineIdentifier, - ordering: Ordering[CandidateWithDetails] - ) = - new UpdateSortCandidates(SpecificPipeline(candidatePipeline), SorterFromOrdering(ordering)) - - def apply( - candidatePipelines: Set[CandidatePipelineIdentifier], - ordering: Ordering[CandidateWithDetails] - ) = - new UpdateSortCandidates(SpecificPipelines(candidatePipelines), SorterFromOrdering(ordering)) - - def apply( - candidatePipelines: Set[CandidatePipelineIdentifier], - sorterProvider: SorterProvider, - ) = new UpdateSortCandidates(SpecificPipelines(candidatePipelines), sorterProvider) - - def apply( - pipelineScope: CandidateScope, - ordering: Ordering[CandidateWithDetails] - ) = new UpdateSortCandidates(pipelineScope, SorterFromOrdering(ordering)) -} - -/** - * Sort item and module (not items inside modules) candidates in a pipeline scope. - * Note that if sorting across multiple candidate sources, the candidates will be grouped together - * in sorted order, starting from the position of the first candidate. - * - * For example, we could specify the following ordering to sort by score descending: - * Ordering - * .by[CandidateWithDetails, Double](_.features.get(ScoreFeature) match { - * case Scored(score) => score - * case _ => Double.MinValue - * }).reverse - */ -case class UpdateSortCandidates( - override val pipelineScope: CandidateScope, - sorterProvider: SorterProvider) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val PartitionedCandidates(selectedCandidates, otherCandidates) = - pipelineScope.partition(remainingCandidates) - - val updatedRemainingCandidates = if (selectedCandidates.nonEmpty) { - // Safe .head due to nonEmpty check - val position = remainingCandidates.indexOf(selectedCandidates.head) - val orderedSelectedCandidates = - sorterProvider.sorter(query, remainingCandidates, result).sort(selectedCandidates) - - if (position < otherCandidates.length) { - val (left, right) = otherCandidates.splitAt(position) - left ++ orderedSelectedCandidates ++ right - } else { - otherCandidates ++ orderedSelectedCandidates - } - } else { - remainingCandidates - } - - SelectorResult(remainingCandidates = updatedRemainingCandidates, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala deleted file mode 100644 index 33de20999..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortModuleItemCandidates.scala +++ /dev/null @@ -1,96 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering -import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.common.SpecificPipelines -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object UpdateSortModuleItemCandidates { - def apply( - candidatePipeline: CandidatePipelineIdentifier, - ordering: Ordering[CandidateWithDetails] - ): UpdateSortModuleItemCandidates = - UpdateSortModuleItemCandidates( - SpecificPipeline(candidatePipeline), - SorterFromOrdering(ordering)) - - def apply( - candidatePipeline: CandidatePipelineIdentifier, - sorterProvider: SorterProvider - ): UpdateSortModuleItemCandidates = - UpdateSortModuleItemCandidates(SpecificPipeline(candidatePipeline), sorterProvider) - - def apply( - candidatePipelines: Set[CandidatePipelineIdentifier], - ordering: Ordering[CandidateWithDetails] - ): UpdateSortModuleItemCandidates = - UpdateSortModuleItemCandidates( - SpecificPipelines(candidatePipelines), - SorterFromOrdering(ordering)) - - def apply( - candidatePipelines: Set[CandidatePipelineIdentifier], - sorterProvider: SorterProvider - ): UpdateSortModuleItemCandidates = - UpdateSortModuleItemCandidates(SpecificPipelines(candidatePipelines), sorterProvider) -} - -/** - * Sort items inside a module from a candidate source and update the remainingCandidates. - * - * For example, we could specify the following ordering to sort by score descending: - * - * {{{ - * Ordering - * .by[CandidateWithDetails, Double](_.features.get(ScoreFeature) match { - * case Scored(score) => score - * case _ => Double.MinValue - * }).reverse - * - * // Before sorting: - * ModuleCandidateWithDetails( - * Seq( - * ItemCandidateWithLowScore, - * ItemCandidateWithMidScore, - * ItemCandidateWithHighScore), - * ... other params - * ) - * - * // After sorting: - * ModuleCandidateWithDetails( - * Seq( - * ItemCandidateWithHighScore, - * ItemCandidateWithMidScore, - * ItemCandidateWithLowScore), - * ... other params - * ) - * }}} - * - * @note this updates the modules in the `remainingCandidates` - */ -case class UpdateSortModuleItemCandidates( - override val pipelineScope: CandidateScope, - sorterProvider: SorterProvider) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val updatedCandidates = remainingCandidates.map { - case module: ModuleCandidateWithDetails if pipelineScope.contains(module) => - module.copy(candidates = - sorterProvider.sorter(query, remainingCandidates, result).sort(module.candidates)) - case candidate => candidate - } - SelectorResult(remainingCandidates = updatedCandidates, result = result) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala deleted file mode 100644 index 76785780f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/UpdateSortResults.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.component_library.selector - -import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering -import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object UpdateSortResults { - def apply( - ordering: Ordering[CandidateWithDetails] - ) = - new UpdateSortResults((_, _, _) => SorterFromOrdering(ordering)) -} - -/** - * Sort item and module (not items inside modules) results. - * - * For example, we could specify the following ordering to sort by score descending: - * Ordering - * .by[CandidateWithDetails, Double](_.features.get(ScoreFeature) match { - * case Scored(score) => score - * case _ => Double.MinValue - * }).reverse - */ -case class UpdateSortResults( - sorterProvider: SorterProvider, - override val pipelineScope: CandidateScope = AllPipelines) - extends Selector[PipelineQuery] { - - override def apply( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - val updatedResult = sorterProvider.sorter(query, remainingCandidates, result).sort(result) - - SelectorResult(remainingCandidates = remainingCandidates, result = updatedResult) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala deleted file mode 100644 index 21d811ee7..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/AdsInjector.scala +++ /dev/null @@ -1,73 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.ads - -import com.google.inject.Inject -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.goldfinch.adaptors.ads.productmixer.ProductMixerPromotedEntriesAdaptor -import com.twitter.goldfinch.adaptors.productmixer.ProductMixerNonPromotedEntriesAdaptor -import com.twitter.goldfinch.adaptors.productmixer.ProductMixerQueryConverter -import com.twitter.goldfinch.api.AdsInjectionRequestContextConverter -import com.twitter.goldfinch.api.AdsInjectionSurfaceAreas.SurfaceAreaName -import com.twitter.goldfinch.api.{AdsInjector => GoldfinchAdsInjector} -import com.twitter.goldfinch.api.NonPromotedEntriesAdaptor -import com.twitter.goldfinch.api.PromotedEntriesAdaptor -import com.twitter.goldfinch.impl.injector.AdsInjectorBuilder -import com.twitter.goldfinch.impl.injector.product_mixer.AdsInjectionSurfaceAreaAdjustersMap -import com.twitter.goldfinch.impl.injector.product_mixer.VerticalSizeAdjustmentConfigMap -import com.twitter.inject.Logging -import com.twitter.product_mixer.component_library.model.query.ads._ -import com.twitter.product_mixer.core.model.common.presentation._ -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import javax.inject.Singleton -import com.twitter.goldfinch.impl.core.DefaultFeatureSwitchResultsFactory -import com.twitter.goldfinch.impl.core.LocalDevelopmentFeatureSwitchResultsFactory -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ConfigRepoLocalPath -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal - -@Singleton -class AdsInjector @Inject() ( - statsReceiver: StatsReceiver, - @Flag(ConfigRepoLocalPath) localConfigRepoPath: String, - @Flag(ServiceLocal) isServiceLocal: Boolean) - extends Logging { - private val adsQueryRequestConverter: AdsInjectionRequestContextConverter[ - PipelineQuery with AdsQuery - ] = ProductMixerQueryConverter - - def forSurfaceArea( - surfaceAreaName: SurfaceAreaName - ): GoldfinchAdsInjector[ - PipelineQuery with AdsQuery, - CandidateWithDetails, - CandidateWithDetails - ] = { - - val scopedStatsReceiver: StatsReceiver = - statsReceiver.scope("goldfinch", surfaceAreaName.toString) - - val nonAdsAdaptor: NonPromotedEntriesAdaptor[CandidateWithDetails] = - ProductMixerNonPromotedEntriesAdaptor( - VerticalSizeAdjustmentConfigMap.configsBySurfaceArea(surfaceAreaName), - scopedStatsReceiver) - - val adsAdaptor: PromotedEntriesAdaptor[CandidateWithDetails] = - new ProductMixerPromotedEntriesAdaptor(scopedStatsReceiver) - - val featureSwitchFactory = if (isServiceLocal) { - new LocalDevelopmentFeatureSwitchResultsFactory( - surfaceAreaName.toString, - configRepoAbsPath = localConfigRepoPath) - } else new DefaultFeatureSwitchResultsFactory(surfaceAreaName.toString) - - new AdsInjectorBuilder[PipelineQuery with AdsQuery, CandidateWithDetails, CandidateWithDetails]( - requestAdapter = adsQueryRequestConverter, - nonPromotedEntriesAdaptor = nonAdsAdaptor, - promotedEntriesAdaptor = adsAdaptor, - adjusters = - AdsInjectionSurfaceAreaAdjustersMap.getAdjusters(surfaceAreaName, scopedStatsReceiver), - featureSwitchFactory = featureSwitchFactory, - statsReceiver = scopedStatsReceiver, - logger = logger - ).build() - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel deleted file mode 100644 index 6536b7cf4..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/BUILD.bazel +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/inject:guice", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/adaptors/ads/productmixer", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/adaptors/ads/productmixer/util", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/adaptors/productmixer", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/api", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/core", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/injector", - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/injector/product_mixer", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - ], - exports = [ - "ads-injection/lib/src/main/scala/com/twitter/goldfinch/impl/injector", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala deleted file mode 100644 index 54eab9e69..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/ads/InsertAdResults.scala +++ /dev/null @@ -1,95 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.ads - -import com.twitter.goldfinch.api.AdsInjectionSurfaceAreas.SurfaceAreaName -import com.twitter.goldfinch.api.AdsInjectorAdditionalRequestParams -import com.twitter.goldfinch.api.AdsInjectorOutput -import com.twitter.goldfinch.api.{AdsInjector => GoldfinchAdsInjector} -import com.twitter.product_mixer.component_library.model.query.ads._ -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.functional_component.selector.Selector -import CandidateScope.PartitionedCandidates -import com.twitter.product_mixer.core.functional_component.common.SpecificPipeline -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Injects the sequence of AdCandidates in the `result` in the - * sequence of the Other Candidates(which are not ads). - * - * Every SurfaceArea or DisplayLocation runs their own desired set of adjusters(set in pipeline) - * to inject ads and reposition the ads in the sequence of other candidates of `result` : - * which are fetched by AdsInjectionSurfaceAreaAdjustersMap - * Note: The original sequence of non_promoted entries(non-ads) is retained and the ads - * are inserted in the sequence using `goldfinch` library based on the 'insertion-position' - * hydrated in AdsCandidate by Adserver/Admixer. - * - * ***** Goldfinch recommends to run this selector as close to the marshalling of candidates to have - * more realistic view of served-timeline in Goldfinch-BQ-Logs and avoid any further updates on the - * timeline(sequence of entries) created. **** - * - * Any surface area like `search_tweets(surface_area)` can call - * InsertAdResults(surfaceArea = "TweetSearch", candidatePipeline = adsCandidatePipeline.identifier, - * ProductMixerAdsInjector = productMixerAdsInjector) - * where the pipeline config can call - * productMixerAdsInjector.forSurfaceArea("TweetSearch") to get AdsInjector Object - * - * @example - * `Seq(source1NonAd_Id1, source1NonAd_Id2, source2NonAd_Id1, source2NonAd_Id2,source1NonAd_Id3, source3NonAd_Id3,source3Ad_Id1_InsertionPos1, source3Ad_Id2_InsertionPos4)` - * then the output result can be - * `Seq(source1NonAd_Id1, source3Ad_Id1_InsertionPos1, source1NonAd_Id2, source2NonAd_Id1, source3Ad_Id2_InsertionPos4,source2NonAd_Id2, source1NonAd_Id3, source3NonAd_Id3)` - * depending on the insertion position of Ads and other adjusters shifting the ads - */ -case class InsertAdResults( - surfaceAreaName: SurfaceAreaName, - adsInjector: GoldfinchAdsInjector[ - PipelineQuery with AdsQuery, - CandidateWithDetails, - CandidateWithDetails - ], - adsCandidatePipeline: CandidatePipelineIdentifier) - extends Selector[PipelineQuery with AdsQuery] { - - override val pipelineScope: CandidateScope = SpecificPipeline(adsCandidatePipeline) - - override def apply( - query: PipelineQuery with AdsQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult = { - // Read into ads and non-ads candidates. - val PartitionedCandidates(adCandidates, otherRemainingCandidates) = - pipelineScope.partition(remainingCandidates) - - // Create this param from Query/AdsCandidate based on surface_area, if required. - val adsInjectorAdditionalRequestParams = - AdsInjectorAdditionalRequestParams(budgetAwareExperimentId = None) - - val adsInjectorOutput: AdsInjectorOutput[CandidateWithDetails, CandidateWithDetails] = - adsInjector.applyForAllEntries( - query = query, - nonPromotedEntries = result, - promotedEntries = adCandidates, - adsInjectorAdditionalRequestParams = adsInjectorAdditionalRequestParams) - - val updatedRemainingCandidates = otherRemainingCandidates ++ - GoldfinchResults(adsInjectorOutput.unusedEntries).adapt - val mergedResults = GoldfinchResults(adsInjectorOutput.mergedEntries).adapt - SelectorResult(remainingCandidates = updatedRemainingCandidates, result = mergedResults) - } - - /** - * Goldfinch separates NonPromotedEntryType and PromotedEntryType models, while in ProMix both - * non-promoted and promoted entries are CandidateWithDetails. As such, we need to flatten the - * result back into a single Seq of CandidateWithDetails. See [[AdsInjectorOutput]] - */ - case class GoldfinchResults(results: Seq[Either[CandidateWithDetails, CandidateWithDetails]]) { - def adapt: Seq[CandidateWithDetails] = { - results.collect { - case Right(value) => value - case Left(value) => value - } - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD deleted file mode 100644 index a1c0b286f..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/BUILD +++ /dev/null @@ -1,20 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala deleted file mode 100644 index f1940f312..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/FeatureValueSorter.scala +++ /dev/null @@ -1,248 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import scala.reflect.runtime.universe._ - -object FeatureValueSorter { - - /** - * Sort by a feature value ascending. If the feature failed or is missing, use an inferred default - * based on the type of [[FeatureValue]]. For Numeric values this is the MinValue - * (e.g. Long.MinValue, Double.MinValue). - * - * @param feature feature with value to sort by - * @param dummyImplicit due to type erasure, implicit used to disambiguate `def ascending()` - * between def with param `feature: Feature[Candidate, FeatureValue]` - * from def with param `feature: Feature[Candidate, Option[FeatureValue]]` - * @param typeTag allows for inferring default value from the FeatureValue type. - * See [[featureValueSortDefaultValue]] - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, FeatureValue] - )( - implicit dummyImplicit: DummyImplicit, - typeTag: TypeTag[FeatureValue] - ): SorterProvider = { - val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Ascending) - - ascending(feature, defaultFeatureValue) - } - - /** - * Sort by a feature value ascending. If the feature failed or is missing, use the provided - * default. - * - * @param feature feature with value to sort by - * @param dummyImplicit due to type erasure, implicit used to disambiguate `def ascending()` - * between def with param `feature: Feature[Candidate, FeatureValue]` - * from def with param `feature: Feature[Candidate, Option[FeatureValue]]` - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, FeatureValue], - defaultFeatureValue: FeatureValue - )( - implicit dummyImplicit: DummyImplicit - ): SorterProvider = { - val ordering = Ordering.by[CandidateWithDetails, FeatureValue]( - _.features.getOrElse(feature, defaultFeatureValue)) - - SorterFromOrdering(ordering, Ascending) - } - - /** - * Sort by an optional feature value ascending. If the feature failed or is missing, use an - * inferred default based on the type of [[FeatureValue]]. For Numeric values this is the MinValue - * (e.g. Long.MinValue, Double.MinValue). - * - * @param feature feature with value to sort by - * @param typeTag allows for inferring default value from the FeatureValue type. - * See [[featureOptionalValueSortDefaultValue]] - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, Option[FeatureValue]] - )( - implicit typeTag: TypeTag[FeatureValue] - ): SorterProvider = { - val defaultFeatureValue: FeatureValue = featureOptionalValueSortDefaultValue(feature, Ascending) - - ascending(feature, defaultFeatureValue) - } - - /** - * Sort by an optional feature value ascending. If the feature failed or is missing, use the - * provided default. - * - * @param feature feature with value to sort by - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, Option[FeatureValue]], - defaultFeatureValue: FeatureValue - ): SorterProvider = { - val ordering = Ordering.by[CandidateWithDetails, FeatureValue]( - _.features.getOrElse(feature, None).getOrElse(defaultFeatureValue)) - - SorterFromOrdering(ordering, Ascending) - } - - /** - * Sort by a feature value descending. If the feature failed or is missing, use an inferred - * default based on the type of [[FeatureValue]]. For Numeric values this is the MaxValue - * (e.g. Long.MaxValue, Double.MaxValue). - * - * @param feature feature with value to sort by - * @param dummyImplicit due to type erasure, implicit used to disambiguate `def descending()` - * between def with param `feature: Feature[Candidate, FeatureValue]` - * from def with param `feature: Feature[Candidate, Option[FeatureValue]]` - * @param typeTag allows for inferring default value from the FeatureValue type. - * See [[featureValueSortDefaultValue]] - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, FeatureValue] - )( - implicit dummyImplicit: DummyImplicit, - typeTag: TypeTag[FeatureValue] - ): SorterProvider = { - val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Descending) - - descending(feature, defaultFeatureValue) - } - - /** - * Sort by a feature value descending. If the feature failed or is missing, use the provided - * default. - * - * @param feature feature with value to sort by - * @param dummyImplicit due to type erasure, implicit used to disambiguate `def descending()` - * between def with param `feature: Feature[Candidate, FeatureValue]` - * from def with param `feature: Feature[Candidate, Option[FeatureValue]]` - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, FeatureValue], - defaultFeatureValue: FeatureValue - )( - implicit dummyImplicit: DummyImplicit - ): SorterProvider = { - val ordering = Ordering.by[CandidateWithDetails, FeatureValue]( - _.features.getOrElse(feature, defaultFeatureValue)) - - SorterFromOrdering(ordering, Descending) - } - - /** - * Sort by an optional feature value descending. If the feature failed or is missing, use an - * inferred default based on the type of [[FeatureValue]]. For Numeric values this is the MaxValue - * (e.g. Long.MaxValue, Double.MaxValue). - * - * @param feature feature with value to sort by - * @param typeTag allows for inferring default value from the FeatureValue type. - * See [[featureOptionalValueSortDefaultValue]] - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, Option[FeatureValue]] - )( - implicit typeTag: TypeTag[FeatureValue] - ): SorterProvider = { - val defaultFeatureValue: FeatureValue = - featureOptionalValueSortDefaultValue(feature, Descending) - - descending(feature, defaultFeatureValue) - } - - /** - * Sort by an optional feature value descending. If the feature failed or is missing, use the - * provided default. - * - * @param feature feature with value to sort by - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: Feature[Candidate, Option[FeatureValue]], - defaultFeatureValue: FeatureValue - ): SorterProvider = { - val ordering = Ordering.by[CandidateWithDetails, FeatureValue]( - _.features.getOrElse(feature, None).getOrElse(defaultFeatureValue)) - - SorterFromOrdering(ordering, Descending) - } - - private[sorter] def featureValueSortDefaultValue[FeatureValue: Ordering]( - feature: Feature[_, FeatureValue], - sortOrder: SortOrder - )( - implicit typeTag: TypeTag[FeatureValue] - ): FeatureValue = { - val defaultValue = sortOrder match { - case Descending => - typeOf[FeatureValue] match { - case t if t <:< typeOf[Short] => Short.MinValue - case t if t <:< typeOf[Int] => Int.MinValue - case t if t <:< typeOf[Long] => Long.MinValue - case t if t <:< typeOf[Double] => Double.MinValue - case t if t <:< typeOf[Float] => Float.MinValue - case _ => - throw new UnsupportedOperationException(s"Default value not supported for $feature") - } - case Ascending => - typeOf[FeatureValue] match { - case t if t <:< typeOf[Short] => Short.MaxValue - case t if t <:< typeOf[Int] => Int.MaxValue - case t if t <:< typeOf[Long] => Long.MaxValue - case t if t <:< typeOf[Double] => Double.MaxValue - case t if t <:< typeOf[Float] => Float.MaxValue - case _ => - throw new UnsupportedOperationException(s"Default value not supported for $feature") - } - } - - defaultValue.asInstanceOf[FeatureValue] - } - - private[sorter] def featureOptionalValueSortDefaultValue[FeatureValue: Ordering]( - feature: Feature[_, Option[FeatureValue]], - sortOrder: SortOrder - )( - implicit typeTag: TypeTag[FeatureValue] - ): FeatureValue = { - val defaultValue = sortOrder match { - case Descending => - typeOf[Option[FeatureValue]] match { - case t if t <:< typeOf[Option[Short]] => Short.MinValue - case t if t <:< typeOf[Option[Int]] => Int.MinValue - case t if t <:< typeOf[Option[Long]] => Long.MinValue - case t if t <:< typeOf[Option[Double]] => Double.MinValue - case t if t <:< typeOf[Option[Float]] => Float.MinValue - case _ => - throw new UnsupportedOperationException(s"Default value not supported for $feature") - } - case Ascending => - typeOf[Option[FeatureValue]] match { - case t if t <:< typeOf[Option[Short]] => Short.MaxValue - case t if t <:< typeOf[Option[Int]] => Int.MaxValue - case t if t <:< typeOf[Option[Long]] => Long.MaxValue - case t if t <:< typeOf[Option[Double]] => Double.MaxValue - case t if t <:< typeOf[Option[Float]] => Float.MaxValue - case _ => - throw new UnsupportedOperationException(s"Default value not supported for $feature") - } - } - - defaultValue.asInstanceOf[FeatureValue] - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala deleted file mode 100644 index 1bd9ee317..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/RandomShuffleSorter.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import scala.util.Random - -/** - * Randomly shuffles candidates using the provided [[random]] - * - * @example `UpdateSortResults(RandomShuffleSorter())` - * @param random used to set the seed and for ease of testing, in most cases leaving it as the default is fine. - */ -case class RandomShuffleSorter(random: Random = new Random(0)) extends SorterProvider with Sorter { - - override def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] = - random.shuffle(candidates) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala deleted file mode 100644 index 418cf2982..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/ReverseSorter.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -/** - * Reverse candidates. - * - * @example `UpdateSortResults(ReverseSorter())` - */ -object ReverseSorter extends SorterProvider with Sorter { - - override def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] = - candidates.reverse -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala deleted file mode 100644 index 3ddd5fc84..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SortOrder.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter - -sealed trait SortOrder -case object Ascending extends SortOrder -case object Descending extends SortOrder diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala deleted file mode 100644 index c09792eb8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterFromOrdering.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -object SorterFromOrdering { - def apply(ordering: Ordering[CandidateWithDetails], sortOrder: SortOrder): SorterFromOrdering = - SorterFromOrdering(if (sortOrder == Descending) ordering.reverse else ordering) -} - -/** - * Sorts candidates based on the provided [[ordering]] - * - * @note the [[Ordering]] must be transitive, so if `A < B` and `B < C` then `A < C`. - * @note sorting randomly via `Ordering.by[CandidateWithDetails, Double](_ => Random.nextDouble())` - * is not safe and can fail at runtime since TimSort depends on stable sort values for - * pivoting. To sort randomly, use [[RandomShuffleSorter]] instead. - */ -case class SorterFromOrdering( - ordering: Ordering[CandidateWithDetails]) - extends SorterProvider - with Sorter { - - override def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] = - candidates.sorted(ordering) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala deleted file mode 100644 index d0c1a3eb2..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/SorterProvider.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Makes a [[Sorter]] to run for the given input based on the - * [[PipelineQuery]], the `remainingCandidates`, and the `result`. - * - * @note this should be used to choose between different [[Sorter]]s, - * if you want to conditionally sort wrap your [[Sorter]] with - * [[com.twitter.product_mixer.component_library.selector.SelectConditionally]] instead. - */ -trait SorterProvider { - - /** Makes a [[Sorter]] for the given inputs */ - def sorter( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): Sorter -} - -/** - * Sorts the candidates - * - * All [[Sorter]]s also implement [[SorterProvider]] to provide themselves for convenience. - */ -trait Sorter { self: SorterProvider => - - /** Sorts the `candidates` */ - def sort[Candidate <: CandidateWithDetails](candidates: Seq[Candidate]): Seq[Candidate] - - /** Any [[Sorter]] can be used in place of a [[SorterProvider]] to provide itself */ - override final def sorter( - query: PipelineQuery, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): Sorter = self -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD deleted file mode 100644 index a074c678b..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - scalac_plugins = ["no-roomba"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala deleted file mode 100644 index b4819e6a8..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector/sorter/featurestorev1/FeatureStoreV1FeatureValueSorter.scala +++ /dev/null @@ -1,98 +0,0 @@ -package com.twitter.product_mixer.component_library.selector.sorter.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.product_mixer.component_library.selector.sorter.Ascending -import com.twitter.product_mixer.component_library.selector.sorter.Descending -import com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter.featureValueSortDefaultValue -import com.twitter.product_mixer.component_library.selector.sorter.SorterFromOrdering -import com.twitter.product_mixer.component_library.selector.sorter.SorterProvider -import com.twitter.product_mixer.core.feature.featuremap.featurestorev1.FeatureStoreV1FeatureMap._ -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import scala.reflect.runtime.universe._ - -/** - * Feature Store v1 version of [[com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter]] - */ -object FeatureStoreV1FeatureValueSorter { - - /** - * Sort by a Feature Store v1 feature value ascending. If the feature failed or is missing, use an - * inferred default based on the type of [[FeatureValue]]. For Numeric values this is the MinValue - * (e.g. Long.MinValue, Double.MinValue). - * - * @param feature Feature Store v1 feature with value to sort by - * @param typeTag allows for inferring default value from the FeatureValue type. - * See [[com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter.featureValueSortDefaultValue]] - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue] - )( - implicit typeTag: TypeTag[FeatureValue] - ): SorterProvider = { - val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Ascending) - - ascending(feature, defaultFeatureValue) - } - - /** - * Sort by a Feature Store v1 feature value ascending. If the feature failed or is missing, use - * the provided default. - * - * @param feature Feature Store v1 feature with value to sort by - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def ascending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue], - defaultFeatureValue: FeatureValue - ): SorterProvider = { - val ordering = Ordering.by[CandidateWithDetails, FeatureValue]( - _.features.getOrElseFeatureStoreV1CandidateFeature(feature, defaultFeatureValue)) - - SorterFromOrdering(ordering, Ascending) - } - - /** - * Sort by a Feature Store v1 feature value descending. If the feature failed or is missing, use - * an inferred default based on the type of [[FeatureValue]]. For Numeric values this is the - * MaxValue (e.g. Long.MaxValue, Double.MaxValue). - * - * @param feature Feature Store v1 feature with value to sort by - * @param typeTag allows for inferring default value from the FeatureValue type. - * See [[com.twitter.product_mixer.component_library.selector.sorter.FeatureValueSorter.featureValueSortDefaultValue]] - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue] - )( - implicit typeTag: TypeTag[FeatureValue] - ): SorterProvider = { - val defaultFeatureValue: FeatureValue = featureValueSortDefaultValue(feature, Descending) - - descending(feature, defaultFeatureValue) - } - - /** - * Sort by a Feature Store v1 feature value descending. If the feature failed or is missing, use - * the provided default. - * - * @param feature Feature Store v1 feature with value to sort by - * @tparam Candidate candidate for the feature - * @tparam FeatureValue feature value with an [[Ordering]] context bound - */ - def descending[Candidate <: UniversalNoun[Any], FeatureValue: Ordering]( - feature: FeatureStoreV1CandidateFeature[PipelineQuery, Candidate, _ <: EntityId, FeatureValue], - defaultFeatureValue: FeatureValue - ): SorterProvider = { - val ordering = Ordering.by[CandidateWithDetails, FeatureValue]( - _.features.getOrElseFeatureStoreV1CandidateFeature(feature, defaultFeatureValue)) - - SorterFromOrdering(ordering, Descending) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD deleted file mode 100644 index 9d3a2bc80..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin", - "abdecider/src/main/scala:abdeciderutils", - "decider/src/main/scala", - "finatra-internal/messaging/kafka/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "scribelib/marshallers/src/main/scala/com/twitter/scribelib/marshallers", - "scribelib/validators/src/main/scala/com/twitter/scribelib/validators", - "scrooge/scrooge-serializer/src/main/scala", - "src/thrift/com/twitter/clientapp/gen:clientapp-scala", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/client", - "user_session_store/src/main/scala/com/twitter/user_session_store", - "util/util-core:util-core-util", - ], - exports = [ - "3rdparty/jvm/com/twitter/src/java/com/twitter/logpipeline/client:logpipeline-event-publisher-thin", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "scrooge/scrooge-serializer/src/main/scala", - "src/thrift/com/twitter/clientapp/gen:clientapp-scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala deleted file mode 100644 index 5bda25844..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/KafkaPublishingSideEffect.scala +++ /dev/null @@ -1,233 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.conversions.DurationOps._ -import com.twitter.conversions.StorageUnitOps._ -import com.twitter.finatra.kafka.producers.FinagleKafkaProducerBuilder -import com.twitter.finatra.kafka.producers.KafkaProducerBase -import com.twitter.finatra.kafka.producers.TwitterKafkaProducerConfig -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.util.Duration -import com.twitter.util.StorageUnit -import org.apache.kafka.clients.producer.ProducerRecord -import org.apache.kafka.common.serialization.Serializer -import org.apache.kafka.common.record.CompressionType - -/** - * The Kafka publishing side effect. - * This class creates a Kafka producer with provided and default parameters. - * Note that callers may not provide arbitrary params as this class will do validity check on some - * params, e.g. maxBlock, to make sure it is safe for online services. - * - * PLEASE NOTE: caller needs to add the following to the Aurora file to successfully enable the TLS - * '-com.twitter.finatra.kafka.producers.principal={{role}}', - * - * @tparam K type of the key - * @tparam V type of the value - * @tparam Query pipeline query - */ -trait KafkaPublishingSideEffect[K, V, Query <: PipelineQuery, ResponseType <: HasMarshalling] - extends PipelineResultSideEffect[Query, ResponseType] { - - /** - * Kafka servers list. It is usually a WilyNs name at Twitter - */ - val bootstrapServer: String - - /** - * The serde of the key - */ - val keySerde: Serializer[K] - - /** - * The serde of the value - */ - val valueSerde: Serializer[V] - - /** - * An id string to pass to the server when making requests. - * The purpose of this is to be able to track the source of requests beyond just ip/port by - * allowing a logical application name to be included in server-side request logging. - */ - val clientId: String - - /** - * The configuration controls how long KafkaProducer.send() and - * KafkaProducer.partitionsFor() will block. - * These methods can be blocked either because the buffer is full or metadata unavailable. - * Blocking in the user-supplied serializers or partitioner will not be counted against this timeout. - * - * Set 200ms by default to not blocking the thread too long which is critical to most ProMixer - * powered services. Please note that there is a hard limit check of not greater than 1 second. - * - */ - val maxBlock: Duration = 200.milliseconds - - /** - * Retries due to broker failures, etc., may write duplicates of the retried message in the - * stream. Note that enabling idempotence requires - * MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION to be less than or equal to 5, - * RETRIES_CONFIG to be greater than 0 and ACKS_CONFIG - * must be 'all'. If these values are not explicitly set by the user, suitable values will be - * chosen. If incompatible values are set, a ConfigException will be thrown. - * - * false by default, setting to true may introduce issues to brokers since brokers will keep - * tracking all requests which is resource expensive. - */ - val idempotence: Boolean = false - - /** - * The producer will attempt to batch records together into fewer requests whenever multiple - * records are being sent to the same partition. This helps performance on both the client and - * the server. This configuration controls the default batch size in bytes. - * No attempt will be made to batch records larger than this size. - * Requests sent to brokers will contain multiple batches, one for each partition with data - * available to be sent. A small batch size will make batching less common and may reduce - * throughput (a batch size of zero will disable batching entirely). - * A very large batch size may use memory a bit more wastefully as we will always allocate a - * buffer of the specified batch size in anticipation of additional records. - * - * Default 16KB which comes from Kafka's default - */ - val batchSize: StorageUnit = 16.kilobytes - - /** - * The producer groups together any records that arrive in between request transmissions into - * a single batched request. "Normally this occurs only under load when records arrive faster - * than they can be sent out. However in some circumstances the client may want to reduce the - * number of requests even under moderate load. This setting accomplishes this by adding a - * small amount of artificial delay—that is, rather than immediately sending out a record - * the producer will wait for up to the given delay to allow other records to be sent so that - * the sends can be batched together. This can be thought of as analogous to Nagle's algorithm - * in TCP. This setting gives the upper bound on the delay for batching: once we get - * BATCH_SIZE_CONFIG worth of records for a partition it will be sent immediately regardless - * of this setting, however if we have fewer than this many bytes accumulated for this - * partition we will 'linger' for the specified time waiting for more records to show up. - * This setting defaults to 0 (i.e. no delay). Setting LINGER_MS_CONFIG=5, for example, - * would have the effect of reducing the number of requests sent but would add up to 5ms of - * latency to records sent in the absence of load. - * - * Default 0ms, which is Kafka's default. If the record size is much larger than the batchSize, - * you may consider to enlarge both batchSize and linger to have better compression (only when - * compression is enabled.) - */ - val linger: Duration = 0.milliseconds - - /** - * The total bytes of memory the producer can use to buffer records waiting to be sent to the - * server. If records are sent faster than they can be delivered to the server the producer - * will block for MAX_BLOCK_MS_CONFIG after which it will throw an exception. - * This setting should correspond roughly to the total memory the producer will use, but is not - * a hard bound since not all memory the producer uses is used for buffering. - * Some additional memory will be used for compression (if compression is enabled) as well as - * for maintaining in-flight requests. - * - * Default 32MB which is Kafka's default. Please consider to enlarge this value if the EPS and - * the per-record size is large (millions EPS with >1KB per-record size) in case the broker has - * issues (which fills the buffer pretty quickly.) - */ - val bufferMemorySize: StorageUnit = 32.megabytes - - /** - * Producer compression type - * - * Default LZ4 which is a good tradeoff between compression and efficiency. - * Please be careful of choosing ZSTD, which the compression rate is better it might introduce - * huge burden to brokers once the topic is consumed, which needs decompression at the broker side. - */ - val compressionType: CompressionType = CompressionType.LZ4 - - /** - * Setting a value greater than zero will cause the client to resend any request that fails - * with a potentially transient error - * - * Default set to 3, to intentionally reduce the retries. - */ - val retries: Int = 3 - - /** - * The amount of time to wait before attempting to retry a failed request to a given topic - * partition. This avoids repeatedly sending requests in a tight loop under some failure - * scenarios - */ - val retryBackoff: Duration = 1.second - - /** - * The configuration controls the maximum amount of time the client will wait - * for the response of a request. If the response is not received before the timeout - * elapses the client will resend the request if necessary or fail the request if - * retries are exhausted. - * - * Default 5 seconds which is intentionally low but not too low. - * Since Kafka's publishing is async this is in general safe (as long as the bufferMem is not full.) - */ - val requestTimeout: Duration = 5.seconds - - require( - maxBlock.inMilliseconds <= 1000, - "We intentionally set the maxBlock to be smaller than 1 second to not block the thread for too long!") - - lazy val kafkaProducer: KafkaProducerBase[K, V] = { - val jaasConfig = TwitterKafkaProducerConfig().configMap - val builder = FinagleKafkaProducerBuilder[K, V]() - .keySerializer(keySerde) - .valueSerializer(valueSerde) - .dest(bootstrapServer, 1.second) // NOTE: this method blocks! - .clientId(clientId) - .maxBlock(maxBlock) - .batchSize(batchSize) - .linger(linger) - .bufferMemorySize(bufferMemorySize) - .maxRequestSize(4.megabytes) - .compressionType(compressionType) - .enableIdempotence(idempotence) - .maxInFlightRequestsPerConnection(5) - .retries(retries) - .retryBackoff(retryBackoff) - .requestTimeout(requestTimeout) - .withConfig("acks", "all") - .withConfig("delivery.timeout.ms", requestTimeout + linger) - - builder.withConfig(jaasConfig).build() - } - - /** - * Build the record to be published to Kafka from query, selections and response - * @param query PipelineQuery - * @param selectedCandidates Result after Selectors are executed - * @param remainingCandidates Candidates which were not selected - * @param droppedCandidates Candidates dropped during selection - * @param response Result after Unmarshalling - * @return A sequence of to-be-published ProducerRecords - */ - def buildRecords( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: ResponseType - ): Seq[ProducerRecord[K, V]] - - final override def apply( - inputs: PipelineResultSideEffect.Inputs[Query, ResponseType] - ): Stitch[Unit] = { - val records = buildRecords( - query = inputs.query, - selectedCandidates = inputs.selectedCandidates, - remainingCandidates = inputs.remainingCandidates, - droppedCandidates = inputs.droppedCandidates, - response = inputs.response - ) - - Stitch - .collect( - records - .map { record => - Stitch.callFuture(kafkaProducer.send(record)) - } - ).unit - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala deleted file mode 100644 index a84fa1ee3..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ParamGatedPipelineResultSideEffect.scala +++ /dev/null @@ -1,76 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.product_mixer.component_library.side_effect.ParamGatedPipelineResultSideEffect.IdentifierPrefix -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.side_effect.ExecuteSynchronously -import com.twitter.product_mixer.core.functional_component.side_effect.FailOpen -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -/** - * A [[PipelineResultSideEffect]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this filter on and off - * @param sideEffect the underlying side effect to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - */ -sealed case class ParamGatedPipelineResultSideEffect[ - -Query <: PipelineQuery, - ResultType <: HasMarshalling -] private ( - enabledParam: Param[Boolean], - sideEffect: PipelineResultSideEffect[Query, ResultType]) - extends PipelineResultSideEffect[Query, ResultType] - with PipelineResultSideEffect.Conditionally[Query, ResultType] { - override val identifier: SideEffectIdentifier = SideEffectIdentifier( - IdentifierPrefix + sideEffect.identifier.name) - override val alerts: Seq[Alert] = sideEffect.alerts - override def onlyIf( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: ResultType - ): Boolean = - Conditionally.and( - PipelineResultSideEffect - .Inputs(query, selectedCandidates, remainingCandidates, droppedCandidates, response), - sideEffect, - query.params(enabledParam)) - override def apply(inputs: PipelineResultSideEffect.Inputs[Query, ResultType]): Stitch[Unit] = - sideEffect.apply(inputs) -} - -object ParamGatedPipelineResultSideEffect { - - val IdentifierPrefix = "ParamGated" - - /** - * A [[PipelineResultSideEffect]] with [[Conditionally]] based on a [[Param]] - * - * @param enabledParam the param to turn this filter on and off - * @param sideEffect the underlying side effect to run when `enabledParam` is true - * @tparam Query The domain model for the query or request - */ - def apply[Query <: PipelineQuery, ResultType <: HasMarshalling]( - enabledParam: Param[Boolean], - sideEffect: PipelineResultSideEffect[Query, ResultType] - ): ParamGatedPipelineResultSideEffect[Query, ResultType] = { - sideEffect match { - case _: FailOpen => - new ParamGatedPipelineResultSideEffect(enabledParam, sideEffect) - with ExecuteSynchronously - with FailOpen - case _: ExecuteSynchronously => - new ParamGatedPipelineResultSideEffect(enabledParam, sideEffect) with ExecuteSynchronously - case _ => - new ParamGatedPipelineResultSideEffect(enabledParam, sideEffect) - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala deleted file mode 100644 index bee6ec92e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeClientEventSideEffect.scala +++ /dev/null @@ -1,118 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.abdecider.ScribingABDeciderUtil -import com.twitter.clientapp.thriftscala.LogEvent -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.scribelib.marshallers -import com.twitter.scribelib.marshallers.ClientDataProvider -import com.twitter.scribelib.marshallers.LogEventMarshaller - -/** - * Side effect to log client events server-side. Create an implementation of this trait by - * defining the `buildClientEvents` method, and the `page` val. - * The ClientEvent will be automatically converted into a [[LogEvent]] and scribed. - */ -trait ScribeClientEventSideEffect[ - Query <: PipelineQuery, - UnmarshalledResponseType <: HasMarshalling] - extends ScribeLogEventSideEffect[LogEvent, Query, UnmarshalledResponseType] { - - /** - * The page which will be defined in the namespace. This is typically the service name that's scribing - */ - val page: String - - /** - * Build the client events from query, selections and response - * - * @param query PipelineQuery - * @param selectedCandidates Result after Selectors are executed - * @param remainingCandidates Candidates which were not selected - * @param droppedCandidates Candidates dropped during selection - * @param response Result after Unmarshalling - */ - def buildClientEvents( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: UnmarshalledResponseType - ): Seq[ScribeClientEventSideEffect.ClientEvent] - - final override def buildLogEvents( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: UnmarshalledResponseType - ): Seq[LogEvent] = { - buildClientEvents( - query = query, - selectedCandidates = selectedCandidates, - remainingCandidates = remainingCandidates, - droppedCandidates = droppedCandidates, - response = response).flatMap { event => - val clientData = clientContextToClientDataProvider(query) - - val clientName = ScribingABDeciderUtil.clientForAppId(clientData.clientApplicationId) - - val namespaceMap: Map[String, String] = Map( - "client" -> Some(clientName), - "page" -> Some(page), - "section" -> event.namespace.section, - "component" -> event.namespace.component, - "element" -> event.namespace.element, - "action" -> event.namespace.action - ).collect { case (k, Some(v)) => k -> v } - - val data: Map[Any, Any] = Seq( - event.eventValue.map("event_value" -> _), - event.latencyMs.map("latency_ms" -> _) - ).flatten.toMap - - val clientEventData = data + - ("event_namespace" -> namespaceMap) + - (marshallers.CategoryKey -> "client_event") - - LogEventMarshaller.marshal( - data = clientEventData, - clientData = clientData - ) - } - } - - /** - * Makes a [[ClientDataProvider]] from the [[PipelineQuery.clientContext]] from the [[query]] - */ - private def clientContextToClientDataProvider(query: Query): ClientDataProvider = { - new ClientDataProvider { - override val userId = query.clientContext.userId - override val guestId = query.clientContext.guestId - override val personalizationId = None - override val deviceId = query.clientContext.deviceId - override val clientApplicationId = query.clientContext.appId - override val parentApplicationId = None - override val countryCode = query.clientContext.countryCode - override val languageCode = query.clientContext.languageCode - override val userAgent = query.clientContext.userAgent - override val isSsl = None - override val referer = None - override val externalReferer = None - } - } -} - -object ScribeClientEventSideEffect { - case class EventNamespace( - section: Option[String] = None, - component: Option[String] = None, - element: Option[String] = None, - action: Option[String] = None) - - case class ClientEvent( - namespace: EventNamespace, - eventValue: Option[Long] = None, - latencyMs: Option[Long] = None) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala deleted file mode 100644 index f27e9190e..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventAsyncSideEffect.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.logpipeline.client.common.EventPublisher -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.scrooge.ThriftStruct -import com.twitter.stitch.Stitch - -/** - * A [[PipelineResultSideEffect]] that logs [[Thrift]] data may not already be available to Scribe - */ -trait ScribeLogEventAsyncSideEffect[ - Thrift <: ThriftStruct, - Query <: PipelineQuery, - ResponseType <: HasMarshalling] - extends PipelineResultSideEffect[Query, ResponseType] { - - /** - * Build the log events from query, selections and response - * @param query PipelineQuery - * @param selectedCandidates Result after Selectors are executed - * @param remainingCandidates Candidates which were not selected - * @param droppedCandidates Candidates dropped during selection - * @param response Result after Unmarshalling - * @return LogEvent in thrift - */ - def buildLogEvents( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: ResponseType - ): Stitch[Seq[Thrift]] - - val logPipelinePublisher: EventPublisher[Thrift] - - final override def apply( - inputs: PipelineResultSideEffect.Inputs[Query, ResponseType] - ): Stitch[Unit] = { - val logEvents = buildLogEvents( - query = inputs.query, - selectedCandidates = inputs.selectedCandidates, - remainingCandidates = inputs.remainingCandidates, - droppedCandidates = inputs.droppedCandidates, - response = inputs.response - ) - - logEvents.flatMap { logEvents: Seq[Thrift] => - Stitch.collect { - logEvents.map { logEvent => - Stitch.callFuture(logPipelinePublisher.publish(logEvent)) - } - }.unit - } - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala deleted file mode 100644 index df9551e15..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/ScribeLogEventSideEffect.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.logpipeline.client.common.EventPublisher -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.scrooge.ThriftStruct -import com.twitter.stitch.Stitch - -/** - * A [[PipelineResultSideEffect]] that logs [[Thrift]] data that's already available to Scribe - */ -trait ScribeLogEventSideEffect[ - Thrift <: ThriftStruct, - Query <: PipelineQuery, - ResponseType <: HasMarshalling] - extends PipelineResultSideEffect[Query, ResponseType] { - - /** - * Build the log events from query, selections and response - * @param query PipelineQuery - * @param selectedCandidates Result after Selectors are executed - * @param remainingCandidates Candidates which were not selected - * @param droppedCandidates Candidates dropped during selection - * @param response Result after Unmarshalling - * @return LogEvent in thrift - */ - def buildLogEvents( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: ResponseType - ): Seq[Thrift] - - val logPipelinePublisher: EventPublisher[Thrift] - - final override def apply( - inputs: PipelineResultSideEffect.Inputs[Query, ResponseType] - ): Stitch[Unit] = { - val logEvents = buildLogEvents( - query = inputs.query, - selectedCandidates = inputs.selectedCandidates, - remainingCandidates = inputs.remainingCandidates, - droppedCandidates = inputs.droppedCandidates, - response = inputs.response - ) - - Stitch - .collect( - logEvents - .map { logEvent => - Stitch.callFuture(logPipelinePublisher.publish(logEvent)) - } - ).unit - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala deleted file mode 100644 index 77d9b815c..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/StratoInsertSideEffect.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Inserter - -/** - * Side effect that writes to Strato column's Insert Op. Create an implementation of this trait by - * defining the `buildEvents` method and providing a Strato Column inserter of type - * (StratoKeyarg, StratoValue) -> Any. - * See https://docbird.twitter.biz/strato/ColumnCatalog.html#insert for information about - * the Insert operation in Strato. - * - * @tparam StratoKeyarg Argument used as a key for Strato column. Could be Unit for common use-cases. - * @tparam StratoValue Value that is inserted at the Strato column. - * @tparam Query PipelineQuery - * @tparam DomainResponseType Timeline response that is marshalled to domain model (e.g. URT, Slice etc). - */ -trait StratoInsertSideEffect[ - StratoKeyarg, - StratoValue, - Query <: PipelineQuery, - DomainResponseType <: HasMarshalling] - extends PipelineResultSideEffect[Query, DomainResponseType] { - - /** - * Inserter for the InsertOp on a StratoColumn. In Strato, the InsertOp is represented as - * (Keyarg, Value) => Key, where Key represents the result returned by the Insert operation. - * For the side-effect behavior, we do not need the return value and use Any instead. - */ - val stratoInserter: Inserter[StratoKeyarg, StratoValue, Any] - - /** - * Builds the events that are inserted to the Strato column. This method supports generating - * multiple events for a single side-effect invocation. - * - * @param query PipelineQuery - * @param selectedCandidates Result after Selectors are executed - * @param remainingCandidates Candidates which were not selected - * @param droppedCandidates Candidates dropped during selection - * @param response Timeline response that is marshalled to domain model (e.g. URT, Slice etc). - * @return Tuples of (StratoKeyArg, StratoValue) that are used to call the stratoInserter. - */ - def buildEvents( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: DomainResponseType - ): Seq[(StratoKeyarg, StratoValue)] - - final override def apply( - inputs: PipelineResultSideEffect.Inputs[Query, DomainResponseType] - ): Stitch[Unit] = { - val events = buildEvents( - query = inputs.query, - selectedCandidates = inputs.selectedCandidates, - remainingCandidates = inputs.remainingCandidates, - droppedCandidates = inputs.droppedCandidates, - response = inputs.response - ) - - Stitch - .traverse(events) { case (keyarg, value) => stratoInserter.insert(keyarg, value) } - .unit - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala deleted file mode 100644 index 6199794d6..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/UserSessionStoreUpdateSideEffect.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect - -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.user_session_store.ReadWriteUserSessionStore -import com.twitter.user_session_store.WriteRequest - -/** - * A [[PipelineResultSideEffect]] that writes to a [[ReadWriteUserSessionStore]] - */ -trait UserSessionStoreUpdateSideEffect[ - Request <: WriteRequest, - Query <: PipelineQuery, - ResponseType <: HasMarshalling] - extends PipelineResultSideEffect[Query, ResponseType] { - - /** - * Build the write request from the query - * @param query PipelineQuery - * @return WriteRequest - */ - def buildWriteRequest(query: Query): Option[Request] - - val userSessionStore: ReadWriteUserSessionStore - - final override def apply( - inputs: PipelineResultSideEffect.Inputs[Query, ResponseType] - ): Stitch[Unit] = { - buildWriteRequest(inputs.query) - .map(userSessionStore.write) - .getOrElse(Stitch.Unit) - } -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel deleted file mode 100644 index 7f8229524..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "util/util-core:util-core-util", - "util/util-slf4j-api/src/main/scala/com/twitter/util/logging", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect", - ], -) diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala deleted file mode 100644 index 1dfcd8865..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/CandidateMetricFunction.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect.metrics - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate -import com.twitter.product_mixer.component_library.side_effect.metrics.CandidateMetricFunction.getCountForType -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails - -/** - * Function to extract numerical metric value from [[CandidateWithDetails]]. - * This CandidateMetricFunction will be applied on all [[CandidateWithDetails]] instances in the - * candidateSelection from the RecommendationPipeline. - */ -trait CandidateMetricFunction { - def apply(candidateWithDetails: CandidateWithDetails): Long -} - -object CandidateMetricFunction { - - private val defaultCountOnePf: PartialFunction[CandidateWithDetails, Long] = { - case _ => 0L - } - - /** - * Count the occurrences of a certain candidate type from [[CandidateWithDetails]]. - */ - def getCountForType( - candidateWithDetails: CandidateWithDetails, - countOnePf: PartialFunction[CandidateWithDetails, Long] - ): Long = { - (countOnePf orElse defaultCountOnePf)(candidateWithDetails) - } -} - -object DefaultServedTweetsSumFunction extends CandidateMetricFunction { - override def apply(candidateWithDetails: CandidateWithDetails): Long = - getCountForType( - candidateWithDetails, - { - case item: ItemCandidateWithDetails => - item.candidate match { - case _: BaseTweetCandidate => 1L - case _ => 0L - } - }) -} - -object DefaultServedUsersSumFunction extends CandidateMetricFunction { - override def apply(candidateWithDetails: CandidateWithDetails): Long = - getCountForType( - candidateWithDetails, - { - case item: ItemCandidateWithDetails => - item.candidate match { - case _: BaseUserCandidate => 1L - case _ => 0L - } - }) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala deleted file mode 100644 index 1c3d2e817..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffect.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect.metrics - -import com.twitter.clientapp.thriftscala.LogEvent -import com.twitter.logpipeline.client.common.EventPublisher -import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect -import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect.EventNamespace -import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect.ClientEvent -import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Config of a client event to be scribed under certain namespace. - * @param eventNamespaceOverride overrides the default eventNamespace in the side effect. - * Note that its fields (section/component/element/action) will - * override the default namespace fields only if the fields are not - * None. i.e. if you want to override the "section" field in the - * default namespace with an empty section, you must specify - * section = Some("") - * in the override instead of - * section = None - * - * @param metricFunction the function that extracts the metric value from a candidate. - */ -case class EventConfig( - eventNamespaceOverride: EventNamespace, - metricFunction: CandidateMetricFunction) - -/** - * Side effect to log client events server-side and to build metrics in the metric center. - * By default will return "requests" event config. - */ -class ScribeClientEventMetricsSideEffect[ - Query <: PipelineQuery, - UnmarshalledResponseType <: HasMarshalling -]( - override val identifier: SideEffectIdentifier, - override val logPipelinePublisher: EventPublisher[LogEvent], - override val page: String, - defaultEventNamespace: EventNamespace, - eventConfigs: Seq[EventConfig]) - extends ScribeClientEventSideEffect[Query, UnmarshalledResponseType] { - - override def buildClientEvents( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: UnmarshalledResponseType - ): Seq[ScribeClientEventSideEffect.ClientEvent] = { - // count the number of client events of type "requests" - val requestClientEvent = ClientEvent( - namespace = buildEventNamespace(EventNamespace(action = Some("requests"))) - ) - - eventConfigs - .map { config => - ClientEvent( - namespace = buildEventNamespace(config.eventNamespaceOverride), - eventValue = Some(selectedCandidates.map(config.metricFunction(_)).sum)) - } - // scribe client event only when the metric sum is non-zero - .filter(clientEvent => clientEvent.eventValue.exists(_ > 0L)) :+ requestClientEvent - } - - private def buildEventNamespace(eventNamespaceOverride: EventNamespace): EventNamespace = - EventNamespace( - section = eventNamespaceOverride.section.orElse(defaultEventNamespace.section), - component = eventNamespaceOverride.component.orElse(defaultEventNamespace.component), - element = eventNamespaceOverride.element.orElse(defaultEventNamespace.element), - action = eventNamespaceOverride.action.orElse(defaultEventNamespace.action) - ) -} diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala deleted file mode 100644 index ae3c69353..000000000 --- a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/side_effect/metrics/ScribeClientEventMetricsSideEffectBuilder.scala +++ /dev/null @@ -1,84 +0,0 @@ -package com.twitter.product_mixer.component_library.side_effect.metrics - -import com.twitter.clientapp.thriftscala.LogEvent -import com.twitter.logpipeline.client.common.EventPublisher -import com.twitter.product_mixer.component_library.side_effect.ScribeClientEventSideEffect.EventNamespace -import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Build [[ScribeClientEventMetricsSideEffect]] with extra [[EventConfig]] - */ -case class ScribeClientEventMetricsSideEffectBuilder( - eventConfigs: Seq[EventConfig] = Seq.empty) { - - /** - * Append extra [[EventConfig]] to [[ScribeClientEventMetricsSideEffectBuilder]] - */ - def withEventConfig( - eventConfig: EventConfig - ): ScribeClientEventMetricsSideEffectBuilder = - this.copy(eventConfigs = this.eventConfigs :+ eventConfig) - - /** - * Build [[EventConfig]] with customized [[EventNamespace]] and customized [[CandidateMetricFunction]] - * @param eventNamespaceOverride Override the default event namespace in [[ScribeClientEventMetricsSideEffect]] - * @param metricFunction [[CandidateMetricFunction]] - */ - def withEventConfig( - eventNamespaceOverride: EventNamespace, - metricFunction: CandidateMetricFunction - ): ScribeClientEventMetricsSideEffectBuilder = - withEventConfig(EventConfig(eventNamespaceOverride, metricFunction)) - - /** - * Log served tweets events server side and build metrics in the metric center. - * Default event name space action is "served_tweets", default metric function is [[DefaultServedTweetsSumFunction]] - * @param eventNamespaceOverride Override the default event namespace in [[ScribeClientEventMetricsSideEffect]] - * @param metricFunction [[CandidateMetricFunction]] - */ - def withServedTweets( - eventNamespaceOverride: EventNamespace = EventNamespace(action = Some("served_tweets")), - metricFunction: CandidateMetricFunction = DefaultServedTweetsSumFunction - ): ScribeClientEventMetricsSideEffectBuilder = withEventConfig( - eventNamespaceOverride = eventNamespaceOverride, - metricFunction = metricFunction) - - /** - * Log served users events server side and build metrics in the metric center. - * Default event name space action is "served_users", default metric function is [[DefaultServedUsersSumFunction]] - * @param eventNamespaceOverride Override the default event namespace in [[ScribeClientEventMetricsSideEffect]] - * @param metricFunction [[CandidateMetricFunction]] - */ - def withServedUsers( - eventNamespaceOverride: EventNamespace = EventNamespace(action = Some("served_users")), - metricFunction: CandidateMetricFunction = DefaultServedUsersSumFunction - ): ScribeClientEventMetricsSideEffectBuilder = withEventConfig( - eventNamespaceOverride = eventNamespaceOverride, - metricFunction = metricFunction) - - /** - * Build [[ScribeClientEventMetricsSideEffect]] - * @param identifier unique identifier of the side effect - * @param defaultEventNamespace default event namespace to log - * @param logPipelinePublisher [[EventPublisher]] to publish events - * @param page The page which will be defined in the namespace. This is typically the service name that's scribing - * @tparam Query [[PipelineQuery]] - * @tparam UnmarshalledResponseType [[HasMarshalling]] - * @return [[ScribeClientEventMetricsSideEffect]] - */ - def build[Query <: PipelineQuery, UnmarshalledResponseType <: HasMarshalling]( - identifier: SideEffectIdentifier, - defaultEventNamespace: EventNamespace, - logPipelinePublisher: EventPublisher[LogEvent], - page: String - ): ScribeClientEventMetricsSideEffect[Query, UnmarshalledResponseType] = { - new ScribeClientEventMetricsSideEffect[Query, UnmarshalledResponseType]( - identifier = identifier, - logPipelinePublisher = logPipelinePublisher, - defaultEventNamespace = defaultEventNamespace, - page = page, - eventConfigs = eventConfigs) - } -} diff --git a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD b/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD deleted file mode 100644 index d6cf0b82c..000000000 --- a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/BUILD +++ /dev/null @@ -1,8 +0,0 @@ -java_library( - sources = ["*.java"], - platform = "java8", - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/inject:guice", - ], -) diff --git a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java b/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java deleted file mode 100644 index dffc5cd7f..000000000 --- a/product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope/ProductScoped.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.product.guice.scope; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import java.lang.annotation.Retention; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Target; - -import com.google.inject.ScopeAnnotation; - -@Target({ TYPE, METHOD }) -@Retention(RUNTIME) -@ScopeAnnotation -public @interface ProductScoped {} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala deleted file mode 100644 index 05240a66a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/AlertConfig.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.common.alert.NotificationGroup -import com.twitter.product_mixer.core.functional_component.common.alert.Source - -/** - * Simple representation for an [[Alert]] used for Product Mixer's JSON API, which in turn is - * consumed by our monitoring script generation job and Turntable. - * - * @note not all mixers will upgrade at the same time so new fields should be added with backwards - * compatibility in mind. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -private[core] case class AlertConfig( - source: Source, - metricType: String, - notificationGroup: NotificationGroup, - warnPredicate: PredicateConfig, - criticalPredicate: PredicateConfig, - runbookLink: Option[String], - metricSuffix: Option[String]) - -private[core] object AlertConfig { - - /** Represent this [[Alert]] as an [[AlertConfig]] case class */ - private[core] def apply(alert: Alert): AlertConfig = - AlertConfig( - alert.source, - alert.alertType.metricType, - alert.notificationGroup, - PredicateConfig(alert.warnPredicate), - PredicateConfig(alert.criticalPredicate), - alert.runbookLink, - alert.metricSuffix - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD deleted file mode 100644 index 879a1f49d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/BUILD +++ /dev/null @@ -1,39 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/twitter/bijection:core", - "3rdparty/jvm/javax/inject:javax.inject", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/http-server/src/main/scala/com/twitter/finatra/http", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry", - "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema", - "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/json", - "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/scrooge/scala", - "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/serialization/thrift", - "scrooge-internal/scrooge-schema/src/main/scala/com/twitter/scrooge/schema/tree", - "scrooge/scrooge-core/src/main/scala", - "scrooge/scrooge-generator/src/main/scala", - "scrooge/scrooge-serializer", - "src/thrift/com/twitter/context:twitter-context-scala", - "src/thrift/com/twitter/scrooge_internal/schema:thrift-scala", - "twitter-context/src/main/scala", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "src/thrift/com/twitter/context:twitter-context-scala", - "twitter-context/src/main/scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala deleted file mode 100644 index 29d1a904c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/DebugTwitterContext.scala +++ /dev/null @@ -1,55 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -import com.twitter.context.TwitterContext -import com.twitter.context.thriftscala.Viewer -import com.twitter.product_mixer.TwitterContextPermit -import com.twitter.product_mixer.core.model.marshalling.request.ClientContext - -/** - * Mixes in support to forge the UserIds in TwitterContext for debug purposes. - * - * A thrift controller can extend DebugTwitterContext and wrap it's execution logic: - * - * {{{ - * withDebugTwitterContext(request.clientContext) { - * Stitch.run(...) - * } - * }}} - */ -trait DebugTwitterContext { - - private val ctx = TwitterContext(TwitterContextPermit) - - /** - * Wrap some function in a debug TwitterContext with hardcoded userIds - * to the ClientContext.userId. - * - * @param clientContext - A product mixer request client context - * @param f The function to wrap - */ - def withDebugTwitterContext[T](clientContext: ClientContext)(f: => T): T = { - ctx.let( - forgeTwitterContext( - clientContext.userId - .getOrElse(throw new IllegalArgumentException("missing required field: user id"))) - )(f) - } - - // Generate a fake Twitter Context for debug usage. - // Generally the TwitterContext is created by the API service, and Strato uses it for permission control. - // When we use our debug endpoint, we instead create our own context so that Strato finds something useful. - // We enforce ACLs directly via Thrift Web Forms' permission system. - private def forgeTwitterContext(userId: Long): Viewer = { - Viewer( - auditIp = None, - ipTags = Set.empty, - userId = Some(userId), - guestId = None, - clientApplicationId = None, - userAgent = None, - locationToken = None, - authenticatedUserId = Some(userId), - guestToken = None - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala deleted file mode 100644 index 543888093..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetComponentRegistryHandler.scala +++ /dev/null @@ -1,114 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -import com.twitter.finagle.http.Request -import com.twitter.inject.Injector -import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy -import com.twitter.product_mixer.core.functional_component.common.access_policy.WithDebugAccessPolicies -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineConfig -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineConfig -import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineConfig -import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig -import com.twitter.product_mixer.core.service.component_registry -import com.twitter.product_mixer.core.service.component_registry.ComponentRegistry -import com.twitter.product_mixer.core.service.component_registry.ComponentRegistrySnapshot -import com.twitter.util.Future - -case class GetComponentRegistryHandler(injector: Injector) { - lazy val componentRegistry: ComponentRegistry = injector.instance[ComponentRegistry] - - def apply(request: Request): Future[ComponentRegistryResponse] = { - componentRegistry.get.map { currentComponentRegistry: ComponentRegistrySnapshot => - val registeredComponents = currentComponentRegistry.getAllRegisteredComponents.map { - registeredComponent => - val componentIdentifier = registeredComponent.identifier - val childComponents = currentComponentRegistry - .getChildComponents(componentIdentifier) - .map { childComponent => - ChildComponent( - componentType = childComponent.componentType, - name = childComponent.name, - relativeScopes = componentIdentifier.toScopes ++ childComponent.toScopes, - qualityFactorMonitoringConfig = - buildQualityFactoringMonitoringConfig(registeredComponent, childComponent) - ) - } - - RegisteredComponent( - componentType = componentIdentifier.componentType, - name = componentIdentifier.name, - scopes = componentIdentifier.toScopes, - children = childComponents, - alertConfig = Some(registeredComponent.component.alerts.map(AlertConfig.apply)), - sourceFile = Some(registeredComponent.sourceFile), - debugAccessPolicies = Some(registeredComponent.component match { - case withDebugAccessPolicies: WithDebugAccessPolicies => - withDebugAccessPolicies.debugAccessPolicies - case _ => Set.empty - }) - ) - } - - ComponentRegistryResponse(registeredComponents) - } - } - - private def buildQualityFactoringMonitoringConfig( - parent: component_registry.RegisteredComponent, - child: ComponentIdentifier - ): Option[QualityFactorMonitoringConfig] = { - val qualityFactorConfigs: Option[Map[ComponentIdentifier, QualityFactorConfig]] = - parent.component match { - case pipeline: Pipeline[_, _] => - pipeline.config match { - case config: RecommendationPipelineConfig[_, _, _, _] => - Some(config.qualityFactorConfigs) - case config: MixerPipelineConfig[_, _, _] => - Some( - config.qualityFactorConfigs - .asInstanceOf[Map[ComponentIdentifier, QualityFactorConfig]]) - case config: ProductPipelineConfig[_, _, _] => - Some(config.qualityFactorConfigs) - case _ => None - } - case _ => None - } - - val qfConfigForChild: Option[QualityFactorConfig] = qualityFactorConfigs.flatMap(_.get(child)) - - qfConfigForChild.map { qfConfig => - QualityFactorMonitoringConfig( - boundMin = qfConfig.qualityFactorBounds.bounds.minInclusive, - boundMax = qfConfig.qualityFactorBounds.bounds.maxInclusive - ) - } - } -} - -case class RegisteredComponent( - componentType: String, - name: String, - scopes: Seq[String], - children: Seq[ChildComponent], - alertConfig: Option[Seq[AlertConfig]], - sourceFile: Option[String], - debugAccessPolicies: Option[Set[AccessPolicy]]) - -case class ChildComponent( - componentType: String, - name: String, - relativeScopes: Seq[String], - qualityFactorMonitoringConfig: Option[QualityFactorMonitoringConfig]) - -/** - * The shape of the data returned to callers after hitting the `component-registry` endpoint - * - * @note changes to [[ComponentRegistryResponse]] or contained types should be reflected - * in dashboard generation code in the `monitoring-configs/product_mixer` directory. - */ -case class ComponentRegistryResponse( - registeredComponents: Seq[RegisteredComponent]) - -case class ProductPipeline(identifier: String) -case class ProductPipelinesResponse(productPipelines: Seq[ProductPipeline]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala deleted file mode 100644 index 7814100dd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/GetDebugConfigurationHandler.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -import com.twitter.finagle.http.Request -import com.twitter.scrooge.BinaryThriftStructSerializer -import com.twitter.scrooge.ThriftMethod -import com.twitter.scrooge.schema.ThriftDefinitions -import com.twitter.scrooge.schema.scrooge.scala.CompiledScroogeDefBuilder -import com.twitter.scrooge.schema.serialization.thrift.ReferenceResolver -import com.twitter.scrooge.schema.serialization.thrift.ThriftDefinitionsSerializer -import com.twitter.scrooge.schema.{thriftscala => THRIFT} - -/** - * Endpoint to expose a Mixer's expected query configuration, including the request schema. - * - * @param debugEndpoint the debug Thrift endpoint. Passing [[None]] disables the query debugging - * feature. - * @tparam ServiceIface a thrift service containing the [[debugEndpoint]] - */ -case class GetDebugConfigurationHandler[ServiceIface]( - thriftMethod: ThriftMethod -)( - implicit val serviceIFace: Manifest[ServiceIface]) { - - // We need to binary encode the service def because the underlying Thrift isn't sufficiently - // annotated to be serialized/deserialized by Jackson - private val serviceDef = { - val fullServiceDefinition: ThriftDefinitions.ServiceDef = CompiledScroogeDefBuilder - .build(serviceIFace).asInstanceOf[ThriftDefinitions.ServiceDef] - - val endpointDefinition: ThriftDefinitions.ServiceEndpointDef = - fullServiceDefinition.endpointsByName(thriftMethod.name) - - // Create a service definition which just contains the debug endpoint. At a bare minimum, we need - // to give callers a way to identify the debug endpoint. Sending back all the endpoints is - // redundant. - val serviceDefinition: ThriftDefinitions.ServiceDef = - fullServiceDefinition.copy(endpoints = Seq(endpointDefinition)) - - val thriftDefinitionsSerializer = { - // We don't make use of references but a reference resolver is required by the Scrooge API - val noopReferenceResolver: ReferenceResolver = - (_: THRIFT.ReferenceDef) => throw new Exception("no references") - - new ThriftDefinitionsSerializer(noopReferenceResolver, enableReferences = false) - } - - val thriftBinarySerializer = BinaryThriftStructSerializer.apply(THRIFT.Definition) - - val serializedServiceDef = thriftDefinitionsSerializer(serviceDefinition) - - thriftBinarySerializer.toBytes(serializedServiceDef) - } - - def apply(request: Request): DebugConfigurationResponse = - DebugConfigurationResponse(thriftMethod.name, serviceDef) -} - -case class DebugConfigurationResponse( - debugEndpointName: String, - serviceDefinition: Array[Byte]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala deleted file mode 100644 index c2f217400..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/PredicateConfig.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.Predicate - -/** Simple representation for a [[Predicate]] used for dashboard generation */ -private[core] case class PredicateConfig( - operator: String, - threshold: Double, - datapointsPastThreshold: Int, - duration: Int, - metricGranularity: String) - -private[core] object PredicateConfig { - - /** Convert this [[Predicate]] into a [[PredicateConfig]] */ - def apply(predicate: Predicate): PredicateConfig = PredicateConfig( - predicate.operator.toString, - predicate.threshold, - predicate.datapointsPastThreshold, - predicate.duration, - predicate.metricGranularity.unit) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala deleted file mode 100644 index e7f761825..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/ProductMixerController.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -import com.twitter.finagle.http.Request -import com.twitter.finagle.http.Response -import com.twitter.finagle.http.Status -import com.twitter.finagle.http.RouteIndex -import com.twitter.finatra.http.Controller -import com.twitter.scrooge.ThriftMethod -import com.twitter.inject.Injector -import com.twitter.inject.annotations.Flags -import com.twitter.product_mixer.core.model.common.identifier.ProductIdentifier -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.core.service.component_registry.ComponentRegistry -import com.twitter.product_mixer.core.service.component_registry.{ - RegisteredComponent => ComponentRegistryRegisteredComponent -} -import com.twitter.util.Future -import java.net.URLEncoder - -/** - * Register endpoints necessary for enabling Product Mixer tooling such as alerts, dashboard - * generation and Turntable. - * - * @param debugEndpoint a debug endpoint to run queries against. This feature is experimental and we - * do not recommend that teams use it yet. Providing [[None]] will disable - * debug queries. - * @tparam ServiceIface a thrift service containing the [[debugEndpoint]] - */ -case class ProductMixerController[ServiceIface]( - injector: Injector, - debugEndpoint: ThriftMethod, -)( - implicit val serviceIFace: Manifest[ServiceIface]) - extends Controller { - - val isLocal: Boolean = injector.instance[Boolean](Flags.named(ServiceLocal)) - - if (!isLocal) { - prefix("/admin/product-mixer") { - val productNamesFut: Future[Seq[String]] = - injector.instance[ComponentRegistry].get.map { componentRegistry => - componentRegistry.getAllRegisteredComponents.collect { - case ComponentRegistryRegisteredComponent(identifier: ProductIdentifier, _, _) => - identifier.name - } - } - - productNamesFut.map { productNames => - productNames.foreach { productName => - get( - route = "/debug-query/" + productName, - admin = true, - index = Some(RouteIndex(alias = "Query " + productName, group = "Feeds/Debug Query")) - ) { _: Request => - val auroraPath = - URLEncoder.encode(System.getProperty("aurora.instanceKey", ""), "UTF-8") - - // Extract service name from clientId since there isn't a specific flag for that - val serviceName = injector - .instance[String](Flags.named("thrift.clientId")) - .split("\\.")(0) - - val redirectUrl = - s"https://feeds.twitter.biz/dtab/$serviceName/$productName?servicePath=$auroraPath" - - val response = Response().status(Status.Found) - response.location = redirectUrl - response - } - } - } - } - } - - prefix("/product-mixer") { - get(route = "/component-registry")(GetComponentRegistryHandler(injector).apply) - get(route = "/debug-configuration")(GetDebugConfigurationHandler(debugEndpoint).apply) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala deleted file mode 100644 index 12bbe4850..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/controllers/QualityFactorMonitoringConfig.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.controllers - -// Bounds here are inclusive -case class QualityFactorMonitoringConfig( - boundMin: Double, - boundMax: Double) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD deleted file mode 100644 index cd054940f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/BUILD +++ /dev/null @@ -1,10 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "util/util-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala deleted file mode 100644 index 820abe25c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/Feature.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.core.feature - -/** - * A [[Feature]] is a single measurable or computable property of an entity. - * - * @note If a [[Feature]] is optional then the [[Value]] should be `Option[Value]` - * - * @note If a [[Feature]] is populated with a [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]] - * and the hydration fails, a failure will be stored for the [[Feature]]. - * If that [[Feature]] is accessed with [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.get]] - * then the stored exception will be thrown, essentially failing-closed. - * You can use [[FeatureWithDefaultOnFailure]] or [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.getOrElse]] - * instead to avoid these issues and instead fail-open. - * If correctly hydrating a Feature's value is essential to the request being correct, - * then you should fail-closed on failure to hydrate it by extending [[Feature]] directly. - * - * This does not apply to [[Feature]]s from [[com.twitter.product_mixer.core.functional_component.transformer.FeatureTransformer]] - * which throw in the calling Pipeline instead of storing their failures. - * - * @tparam Entity The type of entity that this feature works with. This could be a User, Tweet, - * Query, etc. - * @tparam Value The type of the value of this feature. - */ -trait Feature[-Entity, Value] { self => - override def toString: String = { - Feature.getSimpleName(self.getClass) - } -} - -/** - * With a [[Feature]], if the [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]] fails, - * the failure will be caught by the platform and stored in the [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]]. - * Accessing a failed feature via [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.get()]] - * will throw the exception that was caught while attempting to hydrate the feature. If there's a - * reasonable default for a [[Feature]] to fail-open with, then throwing the exception at read time - * can be prevented by defining a `defaultValue` via [[FeatureWithDefaultOnFailure]]. When accessing - * a failed feature via [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.get()]] - * for a [[FeatureWithDefaultOnFailure]], the `defaultValue` will be returned. - * - * - * @note [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.getOrElse()]] can also be used - * to access a failed feature without throwing the exception, by defining the default via the - * [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap.getOrElse()]] method call - * instead of as part of the feature declaration. - * @note This does not apply to [[FeatureWithDefaultOnFailure]]s from [[com.twitter.product_mixer.core.functional_component.transformer.FeatureTransformer]] - * which throw in the calling Pipeline instead of storing their failures. - * - * @tparam Entity The type of entity that this feature works with. This could be a User, Tweet, - * Query, etc. - * @tparam Value The type of the value of this feature. - */ -trait FeatureWithDefaultOnFailure[Entity, Value] extends Feature[Entity, Value] { - - /** The default value a feature should return should it fail to be hydrated */ - def defaultValue: Value -} - -trait ModelFeatureName { self: Feature[_, _] => - def featureName: String -} - -object Feature { - - /** - * Avoid `malformed class name` exceptions due to the presence of the `$` character - * Also strip off trailing $ signs for readability - */ - def getSimpleName[T](c: Class[T]): String = { - c.getName.stripSuffix("$").lastIndexOf("$") match { - case -1 => c.getSimpleName.stripSuffix("$") - case index => c.getName.substring(index + 1).stripSuffix("$") - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD deleted file mode 100644 index c94c4bec6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "src/java/com/twitter/ml/api:api-base", - "src/scala/com/twitter/ml/api/util:datarecord", - "src/thrift/com/twitter/dal/personal_data:personal_data-java", - "src/thrift/com/twitter/ml/api:data-java", - "src/thrift/com/twitter/ml/api:data-scala", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "src/thrift/com/twitter/dal/personal_data:personal_data-java", - "src/thrift/com/twitter/ml/api:data-java", - "src/thrift/com/twitter/ml/api:data-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala deleted file mode 100644 index 1a69e9a7f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordCompatible.scala +++ /dev/null @@ -1,316 +0,0 @@ -package com.twitter.product_mixer.core.feature.datarecord - -import com.twitter.dal.personal_data.thriftjava.PersonalDataType -import com.twitter.ml.api.Feature -import com.twitter.ml.api.DataType -import com.twitter.ml.api.thriftscala.GeneralTensor -import com.twitter.ml.api.thriftscala.StringTensor -import com.twitter.ml.api.util.ScalaToJavaDataRecordConversions -import com.twitter.ml.api.{GeneralTensor => JGeneralTensor} -import com.twitter.ml.api.{RawTypedTensor => JRawTypedTensor} -import com.twitter.ml.api.{Feature => MlFeature} -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.util.{Map => JMap} -import java.util.{Set => JSet} -import java.lang.{Long => JLong} -import java.lang.{Boolean => JBoolean} -import java.lang.{Double => JDouble} -import scala.collection.JavaConverters._ - -/** - * Defines a conversion function for customers to mix-in when constructing a DataRecord supported - * feature. We do this because the ML Feature representation is written in Java and uses Java types. - * Furthermore, allowing customers to construct their own ML Feature directly can leave room - * for mistyping errors, such as using a Double ML Feature on a String Product Mixer feature. - * This mix in enforces that the customer only uses the right types, while making it easier - * to setup a DataRecord Feature with nothing but a feature name and personal data types. - * @tparam FeatureValueType The type of the underlying Product Mixer feature value. - */ -sealed trait DataRecordCompatible[FeatureValueType] { - // The feature value type in ProMix. - final type FeatureType = FeatureValueType - // The underlying DataRecord value type, sometimes this differs from the Feature Store and ProMix type. - type DataRecordType - - def featureName: String - def personalDataTypes: Set[PersonalDataType] - - private[product_mixer] def mlFeature: MlFeature[DataRecordType] - - /** - * To & from Data Record value converters. In most cases, this is one to one when the types match - * but in some cases, certain features are modeled as different types in Data Record. For example, - * some features that are Long (e.g, such as TweepCred) are sometimes stored as Doubles. - */ - private[product_mixer] def toDataRecordFeatureValue(featureValue: FeatureType): DataRecordType - private[product_mixer] def fromDataRecordFeatureValue(featureValue: DataRecordType): FeatureType - -} - -/** - * Converter for going from String feature value to String ML Feature. - */ -trait StringDataRecordCompatible extends DataRecordCompatible[String] { - override type DataRecordType = String - - final override lazy val mlFeature: MlFeature[String] = - new MlFeature.Text(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: String - ): String = featureValue - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: String - ): String = featureValue -} - -/** - * Converter for going from Long feature value to Discrete/Long ML Feature. - */ -trait LongDiscreteDataRecordCompatible extends DataRecordCompatible[Long] { - override type DataRecordType = JLong - - final override lazy val mlFeature: MlFeature[JLong] = - new Feature.Discrete(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JLong - ): Long = featureValue - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: Long - ): JLong = featureValue -} - -/** - * Converter for going from Long feature value to Continuous/Double ML Feature. - */ -trait LongContinuousDataRecordCompatible extends DataRecordCompatible[Long] { - override type DataRecordType = JDouble - - final override lazy val mlFeature: MlFeature[JDouble] = - new Feature.Continuous(featureName, personalDataTypes.asJava) - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: FeatureType - ): JDouble = featureValue.toDouble - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JDouble - ): Long = featureValue.longValue() -} - -/** - * Converter for going from an Integer feature value to Long/Discrete ML Feature. - */ -trait IntDiscreteDataRecordCompatible extends DataRecordCompatible[Int] { - override type DataRecordType = JLong - - final override lazy val mlFeature: MlFeature[JLong] = - new MlFeature.Discrete(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JLong - ): Int = featureValue.toInt - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: Int - ): JLong = featureValue.toLong -} - -/** - * Converter for going from Integer feature value to Continuous/Double ML Feature. - */ -trait IntContinuousDataRecordCompatible extends DataRecordCompatible[Int] { - override type DataRecordType = JDouble - - final override lazy val mlFeature: MlFeature[JDouble] = - new Feature.Continuous(featureName, personalDataTypes.asJava) - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: Int - ): JDouble = featureValue.toDouble - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JDouble - ): Int = featureValue.toInt -} - -/** - * Converter for going from Double feature value to Continuous/Double ML Feature. - */ -trait DoubleDataRecordCompatible extends DataRecordCompatible[Double] { - override type DataRecordType = JDouble - - final override lazy val mlFeature: MlFeature[JDouble] = - new MlFeature.Continuous(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JDouble - ): Double = featureValue - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: Double - ): JDouble = featureValue -} - -/** - * Converter for going from Boolean feature value to Boolean ML Feature. - */ -trait BoolDataRecordCompatible extends DataRecordCompatible[Boolean] { - override type DataRecordType = JBoolean - - final override lazy val mlFeature: MlFeature[JBoolean] = - new MlFeature.Binary(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JBoolean - ): Boolean = featureValue - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: Boolean - ): JBoolean = featureValue -} - -/** - * Converter for going from a ByteBuffer feature value to ByteBuffer ML Feature. - */ -trait BlobDataRecordCompatible extends DataRecordCompatible[ByteBuffer] { - override type DataRecordType = ByteBuffer - - final override lazy val mlFeature: MlFeature[ByteBuffer] = - new Feature.Blob(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: ByteBuffer - ): ByteBuffer = featureValue - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: ByteBuffer - ): ByteBuffer = featureValue -} - -/** - * Converter for going from a Map[String, Double] feature value to Sparse Double/Continious ML Feature. - */ -trait SparseContinuousDataRecordCompatible extends DataRecordCompatible[Map[String, Double]] { - override type DataRecordType = JMap[String, JDouble] - - final override lazy val mlFeature: MlFeature[JMap[String, JDouble]] = - new Feature.SparseContinuous(featureName, personalDataTypes.asJava) - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: Map[String, Double] - ): JMap[String, JDouble] = - featureValue.mapValues(_.asInstanceOf[JDouble]).asJava - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JMap[String, JDouble] - ) = featureValue.asScala.toMap.mapValues(_.doubleValue()) -} - -/** - * Converter for going from a Set[String] feature value to SparseBinary/String Set ML Feature. - */ -trait SparseBinaryDataRecordCompatible extends DataRecordCompatible[Set[String]] { - override type DataRecordType = JSet[String] - - final override lazy val mlFeature: MlFeature[JSet[String]] = - new Feature.SparseBinary(featureName, personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JSet[String] - ) = featureValue.asScala.toSet - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: FeatureType - ): JSet[String] = featureValue.asJava -} - -/** - * Marker trait for any feature value to Tensor ML Feature. Not directly usable. - */ -sealed trait TensorDataRecordCompatible[FeatureV] extends DataRecordCompatible[FeatureV] { - override type DataRecordType = JGeneralTensor - override def mlFeature: MlFeature[JGeneralTensor] -} - -/** - * Converter for a double to a Tensor feature encoded as float encoded RawTypedTensor - */ -trait RawTensorFloatDoubleDataRecordCompatible extends TensorDataRecordCompatible[Double] { - final override lazy val mlFeature: MlFeature[JGeneralTensor] = - new Feature.Tensor( - featureName, - DataType.FLOAT, - List.empty[JLong].asJava, - personalDataTypes.asJava) - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: FeatureType - ) = { - val byteBuffer: ByteBuffer = - ByteBuffer - .allocate(4).order(ByteOrder.LITTLE_ENDIAN).putFloat(featureValue.toFloat) - byteBuffer.flip() - val tensor = new JGeneralTensor() - tensor.setRawTypedTensor(new JRawTypedTensor(DataType.FLOAT, byteBuffer)) - tensor - } - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JGeneralTensor - ) = { - val tensor = Option(featureValue.getRawTypedTensor) - .getOrElse(throw new UnexpectedTensorException(featureValue)) - tensor.content.order(ByteOrder.LITTLE_ENDIAN).getFloat().toDouble - } -} - -/** - * Converter for a scala general tensor to java general tensor ML feature. - */ -trait GeneralTensorDataRecordCompatible extends TensorDataRecordCompatible[GeneralTensor] { - - def dataType: DataType - final override lazy val mlFeature: MlFeature[JGeneralTensor] = - new Feature.Tensor(featureName, dataType, List.empty[JLong].asJava, personalDataTypes.asJava) - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: FeatureType - ) = ScalaToJavaDataRecordConversions.scalaTensor2Java(featureValue) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JGeneralTensor - ) = ScalaToJavaDataRecordConversions.javaTensor2Scala(featureValue) -} - -/** - * Converter for a scala string tensor to java general tensor ML feature. - */ -trait StringTensorDataRecordCompatible extends TensorDataRecordCompatible[StringTensor] { - final override lazy val mlFeature: MlFeature[JGeneralTensor] = - new Feature.Tensor( - featureName, - DataType.STRING, - List.empty[JLong].asJava, - personalDataTypes.asJava) - - override private[product_mixer] def fromDataRecordFeatureValue( - featureValue: JGeneralTensor - ) = { - ScalaToJavaDataRecordConversions.javaTensor2Scala(featureValue) match { - case GeneralTensor.StringTensor(stringTensor) => stringTensor - case _ => throw new UnexpectedTensorException(featureValue) - } - } - - override private[product_mixer] def toDataRecordFeatureValue( - featureValue: FeatureType - ) = ScalaToJavaDataRecordConversions.scalaTensor2Java(GeneralTensor.StringTensor(featureValue)) -} - -class UnexpectedTensorException(tensor: JGeneralTensor) - extends Exception(s"Unexpected Tensor: $tensor") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala deleted file mode 100644 index a718f9644..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord/DataRecordFeature.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.core.feature.datarecord - -import com.twitter.ml.api.DataRecord -import com.twitter.product_mixer.core.feature.Feature - -/** - * A DataRecord supported feature mixin for enabling conversions from Product Mixer Features - * to DataRecords. When using Feature Store features, this is pre-configured for the customer - * under the hood. For non-Feature Store features, customers must mix in either [[DataRecordFeature]] - * for required features, or [[DataRecordOptionalFeature]] for optional features, as well as mixing - * in a corresponding [[DataRecordCompatible]] for their feature type. - * @tparam Entity The type of entity that this feature works with. This could be a User, Tweet, - * Query, etc. - * @tparam Value The type of the value of this feature. - */ -sealed trait BaseDataRecordFeature[-Entity, Value] extends Feature[Entity, Value] - -private[product_mixer] abstract class FeatureStoreDataRecordFeature[-Entity, Value] - extends BaseDataRecordFeature[Entity, Value] - -/** - * Feature in a DataRecord for a required feature value; the corresponding feature will always be - * available in the built DataRecord. - */ -trait DataRecordFeature[-Entity, Value] extends BaseDataRecordFeature[Entity, Value] { - self: DataRecordCompatible[Value] => -} - -/** - * Feature in a DataRecord for an optional feature value; the corresponding feature will only - * ever be set in a DataRecord if the value in the feature map is defined (Some(V)). - */ -trait DataRecordOptionalFeature[-Entity, Value] - extends BaseDataRecordFeature[Entity, Option[Value]] { - self: DataRecordCompatible[Value] => -} - -/** - * An entire DataRecord as a feature. This is useful when there is an existing DataRecord that - * should be used as a whole instead of as individual [[DataRecordFeature]]s for example. - */ -trait DataRecordInAFeature[-Entity] extends BaseDataRecordFeature[Entity, DataRecord] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD deleted file mode 100644 index ea22972ca..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue", - "util/util-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "util/util-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala deleted file mode 100644 index 870f8ad9f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMap.scala +++ /dev/null @@ -1,195 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap - -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.{ - FeatureStoreV1ResponseFeature => FSv1Feature -} -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try - -/** - * A set of features and their values. Associated with a specific instance of an Entity, though - * that association is maintained by the framework. - * - * [[FeatureMapBuilder]] is used to build new FeatureMap instances - */ -@JsonSerialize(using = classOf[FeatureMapSerializer]) -case class FeatureMap private[feature] ( - private[core] val underlyingMap: Map[Feature[_, _], Try[_]]) { - - /** - * Returns the [[Value]] associated with the Feature - * - * If the Feature is missing from the feature map, it throws a [[MissingFeatureException]]. - * If the Feature failed and isn't a [[FeatureWithDefaultOnFailure]] this will throw the underlying exception - * that the feature failed with during hydration. - */ - def get[Value](feature: Feature[_, Value]): Value = - getOrElse(feature, throw MissingFeatureException(feature), None) - - /** - * Returns the [[Value]] associated with the Feature with the same semantics as - * [[FeatureMap.get()]], but the underlying [[Try]] is returned to allow for checking the success - * or error state of a feature hydration. This is helpful for implementing fall-back behavior in - * case the feature is missing or hydration failed without a [[FeatureWithDefaultOnFailure]] set. - * - * @note The [[FeatureMap.getOrElse()]] logic is duplicated here to avoid unpacking and repacking - * the [[Try]] that is already available in the [[underlyingMap]] - */ - def getTry[Value](feature: Feature[_, Value]): Try[Value] = - underlyingMap.get(feature) match { - case None => Throw(MissingFeatureException(feature)) - case Some(value @ Return(_)) => value.asInstanceOf[Return[Value]] - case Some(value @ Throw(_)) => - feature match { - case f: FeatureWithDefaultOnFailure[_, Value] @unchecked => Return(f.defaultValue) - case _ => value.asInstanceOf[Throw[Value]] - } - } - - /** - * Returns the [[Value]] associated with the feature or a default if the key is not contained in the map - * `default` can also be used to throw an exception. - * - * e.g. `.getOrElse(feature, throw new MyCustomException())` - * - * @note for [[FeatureWithDefaultOnFailure]], the [[FeatureWithDefaultOnFailure.defaultValue]] - * will be returned if the [[Feature]] failed, but if it is missing/never hydrated, - * then the `default` provided here will be used. - */ - def getOrElse[Value](feature: Feature[_, Value], default: => Value): Value = { - getOrElse(feature, default, Some(default)) - } - - /** - * Private helper for getting features from the feature map, allowing us to define a default - * when the feature is missing from the feature map, vs when its in the feature map but failed. - * In the case of failed features, if the feature is a [FeatureWithDefaultOnFailure], it will - * prioritize that default. - * @param feature The feature to retrieve - * @param missingDefault The default value to use when the feature is missing from the map. - * @param failureDefault The default value to use when the feature is present but failed. - * @tparam Value The value type of the feature. - * @return The value stored in the map. - */ - private def getOrElse[Value]( - feature: Feature[_, Value], - missingDefault: => Value, - failureDefault: => Option[Value] - ): Value = - underlyingMap.get(feature) match { - case None => missingDefault - case Some(Return(value)) => value.asInstanceOf[Value] - case Some(Throw(err)) => - feature match { - case f: FeatureWithDefaultOnFailure[_, Value] @unchecked => f.defaultValue - case _ => failureDefault.getOrElse(throw err) - } - } - - /** - * returns a new FeatureMap with - * - the new Feature and Value pair if the Feature was not present - * - overriding the previous Value if that Feature was previously present - */ - def +[V](key: Feature[_, V], value: V): FeatureMap = - new FeatureMap(underlyingMap + (key -> Return(value))) - - /** - * returns a new FeatureMap with all the elements of current FeatureMap and `other`. - * - * @note if a [[Feature]] exists in both maps, the Value from `other` takes precedence - */ - def ++(other: FeatureMap): FeatureMap = { - if (other.isEmpty) { - this - } else if (isEmpty) { - other - } else if (this.getFeatures.contains(FSv1Feature) && other.getFeatures.contains(FSv1Feature)) { - val mergedResponse = - FeatureStoreV1Response.merge(this.get(FSv1Feature), other.get(FSv1Feature)) - val mergedResponseFeatureMap = FeatureMapBuilder().add(FSv1Feature, mergedResponse).build() - new FeatureMap(underlyingMap ++ other.underlyingMap ++ mergedResponseFeatureMap.underlyingMap) - } else { - new FeatureMap(underlyingMap ++ other.underlyingMap) - } - } - - /** returns the keySet of Features in the map */ - def getFeatures: Set[Feature[_, _]] = underlyingMap.keySet - - /** - * The Set of Features in the FeatureMap that have a successfully returned value. Failed features - * will obviously not be here. - */ - def getSuccessfulFeatures: Set[Feature[_, _]] = underlyingMap.collect { - case (feature, Return(_)) => feature - }.toSet - - def isEmpty: Boolean = underlyingMap.isEmpty - - override def toString: String = s"FeatureMap(${underlyingMap.toString})" -} - -object FeatureMap { - // Restrict access to the apply method. - // This shouldn't be required after scala 2.13.2 (https://github.com/scala/scala/pull/7702) - private[feature] def apply(underlyingMap: Map[Feature[_, _], Try[_]]): FeatureMap = - FeatureMap(underlyingMap) - - /** Merges an arbitrary number of [[FeatureMap]]s from left-to-right */ - def merge(featureMaps: TraversableOnce[FeatureMap]): FeatureMap = { - val builder = FeatureMapBuilder() - - /** - * merge the current [[FSv1Feature]] with the existing accumulated one - * and add the rest of the [[FeatureMap]]'s [[Feature]]s to the `builder` - */ - def mergeInternal( - featureMap: FeatureMap, - accumulatedFsV1Response: Option[FeatureStoreV1Response] - ): Option[FeatureStoreV1Response] = { - if (featureMap.isEmpty) { - accumulatedFsV1Response - } else { - - val currentFsV1Response = - if (featureMap.getFeatures.contains(FSv1Feature)) - Some(featureMap.get(FSv1Feature)) - else - None - - val mergedFsV1Response = (accumulatedFsV1Response, currentFsV1Response) match { - case (Some(merged), Some(current)) => - // both present so merge them - Some(FeatureStoreV1Response.merge(merged, current)) - case (merged, current) => - // one or both are missing so use whichever is available - merged.orElse(current) - } - - featureMap.underlyingMap.foreach { - case (FSv1Feature, _) => // FSv1Feature is only added once at the very end - case (feature, value) => builder.addWithoutValidation(feature, value) - } - mergedFsV1Response - } - } - - featureMaps - .foldLeft[Option[FeatureStoreV1Response]](None) { - case (fsV1Response, featureMap) => mergeInternal(featureMap, fsV1Response) - }.foreach( - // add merged `FSv1Feature` to the `builder` at the end - builder.add(FSv1Feature, _) - ) - - builder.build() - } - - val empty = new FeatureMap(Map.empty) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala deleted file mode 100644 index 91fe54d44..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapBuilder.scala +++ /dev/null @@ -1,110 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try -import scala.collection.mutable - -/** - * [[FeatureMapBuilder]] is a typesafe way (it checks types vs the [[Feature]]s on `.add`) to build a [[FeatureMap]]. - * - * Throws a [[DuplicateFeatureException]] if you try to add the same [[Feature]] more than once. - * - * These builders are __not__ reusable. - */ - -class FeatureMapBuilder { - private val underlying = Map.newBuilder[Feature[_, _], Try[Any]] - private val keys = mutable.HashSet.empty[Feature[_, _]] - private var built = false - - /** - * Add a [[Try]] of a [[Feature]] `value` to the map, - * handling both the [[Return]] and [[Throw]] cases. - * - * Throws a [[DuplicateFeatureException]] if it's already present. - * - * @note If you have a [[Feature]] with a non-optional value type `Feature[_, V]` - * but have an `Option[V]` you can use [[Try.orThrow]] to convert the [[Option]] - * to a [[Try]], which will store the successful or failed [[Feature]] in the map. - */ - def add[V](feature: Feature[_, V], value: Try[V]): FeatureMapBuilder = addTry(feature, value) - - /** - * Add a successful [[Feature]] `value` to the map - * - * Throws a [[DuplicateFeatureException]] if it's already present. - * - * @note If you have a [[Feature]] with a non-optional value type `Feature[_, V]` - * but have an `Option[V]` you can use [[Option.get]] or [[Option.getOrElse]] - * to convert the [[Option]] to extract the underlying value, - * which will throw immediately if it's [[None]] or add the successful [[Feature]] in the map. - */ - def add[V](feature: Feature[_, V], value: V): FeatureMapBuilder = - addTry(feature, Return(value)) - - /** - * Add a failed [[Feature]] `value` to the map - * - * Throws a [[DuplicateFeatureException]] if it's already present. - */ - def addFailure(feature: Feature[_, _], throwable: Throwable): FeatureMapBuilder = - addTry(feature, Throw(throwable)) - - /** - * [[add]] but for when the [[Feature]] types aren't known - * - * Add a [[Try]] of a [[Feature]] `value` to the map, - * handling both the [[Return]] and [[Throw]] cases. - * - * Throws a [[DuplicateFeatureException]] if it's already present. - * - * @note If you have a [[Feature]] with a non-optional value type `Feature[_, V]` - * but have an `Option[V]` you can use [[Try.orThrow]] to convert the [[Option]] - * to a [[Try]], which will store the successful or failed [[Feature]] in the map. - */ - def addTry(feature: Feature[_, _], value: Try[_]): FeatureMapBuilder = { - if (keys.contains(feature)) { - throw new DuplicateFeatureException(feature) - } - addWithoutValidation(feature, value) - } - - /** - * [[addTry]] but without a [[DuplicateFeatureException]] check - * - * @note Only for use internally within [[FeatureMap.merge]] - */ - private[featuremap] def addWithoutValidation( - feature: Feature[_, _], - value: Try[_] - ): FeatureMapBuilder = { - keys += feature - underlying += ((feature, value)) - this - } - - /** Builds the FeatureMap */ - def build(): FeatureMap = { - if (built) { - throw ReusedFeatureMapBuilderException - } - - built = true - new FeatureMap(underlying.result()) - } -} - -object FeatureMapBuilder { - - /** Returns a new [[FeatureMapBuilder]] for making [[FeatureMap]]s */ - def apply(): FeatureMapBuilder = new FeatureMapBuilder -} - -class DuplicateFeatureException(feature: Feature[_, _]) - extends UnsupportedOperationException(s"Feature $feature already exists in FeatureMap") - -object ReusedFeatureMapBuilderException - extends UnsupportedOperationException( - "build() cannot be called more than once since FeatureMapBuilders are not reusable") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala deleted file mode 100644 index bbd57cfb6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapException.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap - -import com.twitter.product_mixer.core.feature.Feature - -case class MissingFeatureException(feature: Feature[_, _]) - extends Exception("Missing value for " + feature) { - override def toString: String = getMessage -} - -class InvalidPredictionRecordMergeException - extends Exception( - "Use FeatureMap.plusPlusOptimized instead of FeatureMap.++ when the FeatureMaps on both sides of the merge contain PredictionRecords") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala deleted file mode 100644 index 746f178fb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/FeatureMapSerializer.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.JsonSerializer -import com.fasterxml.jackson.databind.SerializerProvider -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature -import com.twitter.util.Return - -/** - * Rendering feature maps is dangerous because we don't control all the data that's stored in them. - * This can result failed requests, as we might try to render a recursive structure, very large - * structure, etc. Create a simple map using toString, this mostly works and is better than failing - * the request. - * - * @note changes to serialization logic can have serious performance implications given how hot the - * serialization path is. Consider benchmarking changes with [[com.twitter.product_mixer.core.benchmark.CandidatePipelineResultSerializationBenchmark]] - */ -private[featuremap] class FeatureMapSerializer() extends JsonSerializer[FeatureMap] { - override def serialize( - featureMap: FeatureMap, - gen: JsonGenerator, - serializers: SerializerProvider - ): Unit = { - gen.writeStartObject() - - featureMap.underlyingMap.foreach { - case (FeatureStoreV1ResponseFeature, Return(value)) => - // We know that value has to be [[FeatureStoreV1Response]] but its type has been erased, - // preventing us from pattern-matching. - val featureStoreResponse = value.asInstanceOf[FeatureStoreV1Response] - - val featuresIterator = featureStoreResponse.richDataRecord.allFeaturesIterator() - while (featuresIterator.moveNext()) { - gen.writeStringField( - featuresIterator.getFeature.getFeatureName, - s"${featuresIterator.getFeatureType.name}(${truncateString( - featuresIterator.getFeatureValue.toString)})") - } - - featureStoreResponse.failedFeatures.foreach { - case (failedFeature, failureReasons) => - gen.writeStringField( - failedFeature.toString, - s"Failed(${truncateString(failureReasons.toString)})") - } - case (name, Return(value)) => - gen.writeStringField(name.toString, truncateString(value.toString)) - case (name, error) => - // Note: we don't match on Throw(error) because we want to keep it for the toString - gen.writeStringField(name.toString, truncateString(error.toString)) - - } - - gen.writeEndObject() - } - - // Some features can be very large when stringified, for example when a dependant candidate - // pipeline is used, the entire previous candidate pipeline result is serialized into a feature. - // This causes significant performance issues when the result is later sent over the wire. - private def truncateString(input: String): String = - if (input.length > 1000) input.take(1000) + "..." else input -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala deleted file mode 100644 index 49d2d44eb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMap.scala +++ /dev/null @@ -1,134 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap - -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.stitch.Stitch - -import scala.collection.immutable.Queue - -/** - * An internal representation of an async [[FeatureMap]] containing [[Stitch]]s of [[FeatureMap]]s - * which are already running in the background. - * - * Async features are added by providing the [[PipelineStepIdentifier]] of the [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step Step]] - * before which the async [[Feature]]s are needed, and a [[Stitch]] of the async [[FeatureMap]]. - * It's expected that the [[Stitch]] has already been started and is running in the background. - * - * While not essential to it's core behavior, [[AsyncFeatureMap]] also keeps track of the [[FeatureHydratorIdentifier]] - * and the Set of [[Feature]]s which will be hydrated for each [[Stitch]] of a [[FeatureMap]] it's given. - * - * @param asyncFeatureMaps the [[FeatureMap]]s for [[PipelineStepIdentifier]]s which have not been reached yet - * - * @note [[PipelineStepIdentifier]]s must only refer to [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step Step]]s - * in the current [[com.twitter.product_mixer.core.pipeline.Pipeline Pipeline]]. - * Only plain [[FeatureMap]]s are passed into underlying [[com.twitter.product_mixer.core.model.common.Component Component]]s and - * [[com.twitter.product_mixer.core.pipeline.Pipeline Pipeline]]s so [[AsyncFeatureMap]]s are scoped - * for a specific [[com.twitter.product_mixer.core.pipeline.Pipeline Pipeline]] only. - */ -@JsonSerialize(using = classOf[AsyncFeatureMapSerializer]) -private[core] case class AsyncFeatureMap( - asyncFeatureMaps: Map[PipelineStepIdentifier, Queue[ - (FeatureHydratorIdentifier, Set[Feature[_, _]], Stitch[FeatureMap]) - ]]) { - - def ++(right: AsyncFeatureMap): AsyncFeatureMap = { - val map = Map.newBuilder[ - PipelineStepIdentifier, - Queue[(FeatureHydratorIdentifier, Set[Feature[_, _]], Stitch[FeatureMap])]] - (asyncFeatureMaps.keysIterator ++ right.asyncFeatureMaps.keysIterator).foreach { key => - val currentThenRightAsyncFeatureMaps = - asyncFeatureMaps.getOrElse(key, Queue.empty) ++ - right.asyncFeatureMaps.getOrElse(key, Queue.empty) - map += (key -> currentThenRightAsyncFeatureMaps) - } - AsyncFeatureMap(map.result()) - } - - /** - * Returns a new [[AsyncFeatureMap]] which now keeps track of the provided `features` - * and will make them available when calling [[hydrate]] with `hydrateBefore`. - * - * @param featureHydratorIdentifier the [[FeatureHydratorIdentifier]] of the [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator FeatureHydrator]] - * which these [[Feature]]s are from - * @param hydrateBefore the [[PipelineStepIdentifier]] before which the [[Feature]]s need to be hydrated - * @param featuresToHydrate a Set of the [[Feature]]s which will be hydrated - * @param features a [[Stitch]] of the [[FeatureMap]] - */ - def addAsyncFeatures( - featureHydratorIdentifier: FeatureHydratorIdentifier, - hydrateBefore: PipelineStepIdentifier, - featuresToHydrate: Set[Feature[_, _]], - features: Stitch[FeatureMap] - ): AsyncFeatureMap = { - val featureMapList = - asyncFeatureMaps.getOrElse(hydrateBefore, Queue.empty) :+ - ((featureHydratorIdentifier, featuresToHydrate, features)) - AsyncFeatureMap(asyncFeatureMaps + (hydrateBefore -> featureMapList)) - } - - /** - * The current state of the [[AsyncFeatureMap]] excluding the [[Stitch]]s. - */ - def features: Map[PipelineStepIdentifier, Seq[(FeatureHydratorIdentifier, Set[Feature[_, _]])]] = - asyncFeatureMaps.mapValues(_.map { - case (featureHydratorIdentifier, features, _) => (featureHydratorIdentifier, features) - }) - - /** - * Returns a [[Some]] containing a [[Stitch]] with a [[FeatureMap]] holding the [[Feature]]s that are - * supposed to be hydrated at `identifier` if there are [[Feature]]s to hydrate at `identifier` - * - * Returns [[None]] if there are no [[Feature]]s to hydrate at the provided `identifier`, - * this allows for determining if there is work to do without running a [[Stitch]]. - * - * @note this only hydrates the [[Feature]]s for the specific `identifier`, it does not hydrate - * [[Feature]]s for earlier Steps. - * @param identifier the [[PipelineStepIdentifier]] to hydrate [[Feature]]s for - */ - def hydrate( - identifier: PipelineStepIdentifier - ): Option[Stitch[FeatureMap]] = - asyncFeatureMaps.get(identifier) match { - case Some(Queue((_, _, featureMap))) => - // if there is only 1 `FeatureMap` we dont need to do a collect so just return that Stitch - Some(featureMap) - case Some(featureMapList) => - // if there are multiple `FeatureMap`s we need to collect and merge them together - Some( - Stitch - .collect(featureMapList.map { case (_, _, featureMap) => featureMap }) - .map { featureMapList => FeatureMap.merge(featureMapList) }) - case None => - // No results for the provided `identifier` so return `None` - None - } -} - -private[core] object AsyncFeatureMap { - val empty: AsyncFeatureMap = AsyncFeatureMap(Map.empty) - - /** - * Builds the an [[AsyncFeatureMap]] from a Seq of [[Stitch]] of [[FeatureMap]] - * tupled with the relevant metadata we use to build the necessary state. - * - * This is primarily for convenience, since in most cases an [[AsyncFeatureMap]] - * will be built from the result of individual [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator FeatureHydrator]]s - * and combining them into the correct internal state. - */ - def fromFeatureMaps( - asyncFeatureMaps: Seq[ - (FeatureHydratorIdentifier, PipelineStepIdentifier, Set[Feature[_, _]], Stitch[FeatureMap]) - ] - ): AsyncFeatureMap = - AsyncFeatureMap( - asyncFeatureMaps - .groupBy { case (_, hydrateBefore, _, _) => hydrateBefore } - .mapValues(featureMaps => - Queue(featureMaps.map { - case (hydratorIdentifier, _, featuresToHydrate, stitch) => - (hydratorIdentifier, featuresToHydrate, stitch) - }: _*))) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala deleted file mode 100644 index 2ed4c6735..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/AsyncFeatureMapSerializer.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.JsonSerializer -import com.fasterxml.jackson.databind.SerializerProvider - -/** - * Since an [[AsyncFeatureMap]] is typically incomplete, and by the time it's serialized, all the [[com.twitter.product_mixer.core.feature.Feature]]s - * it will typically be completed and part of the Query or Candidate's individual [[com.twitter.product_mixer.core.feature.Feature]]s - * we instead opt to provide a summary of the Features which would be hydrated using [[AsyncFeatureMap.features]] - * - * This indicates which [[com.twitter.product_mixer.core.feature.Feature]]s will be ready at which Steps - * and which [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]] - * are responsible for those [[com.twitter.product_mixer.core.feature.Feature]] - * - * @note changes to serialization logic can have serious performance implications given how hot the - * serialization path is. Consider benchmarking changes with [[com.twitter.product_mixer.core.benchmark.AsyncQueryFeatureMapSerializationBenchmark]] - */ -private[asyncfeaturemap] class AsyncFeatureMapSerializer() extends JsonSerializer[AsyncFeatureMap] { - override def serialize( - asyncFeatureMap: AsyncFeatureMap, - gen: JsonGenerator, - serializers: SerializerProvider - ): Unit = { - gen.writeStartObject() - - asyncFeatureMap.features.foreach { - case (stepIdentifier, featureHydrators) => - gen.writeObjectFieldStart(stepIdentifier.toString) - - featureHydrators.foreach { - case (hydratorIdentifier, featuresFromHydrator) => - gen.writeArrayFieldStart(hydratorIdentifier.toString) - - featuresFromHydrator.foreach(feature => gen.writeString(feature.toString)) - - gen.writeEndArray() - } - - gen.writeEndObject() - } - - gen.writeEndObject() - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD deleted file mode 100644 index 2d193a3b8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "stitch/stitch-core", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD deleted file mode 100644 index 8511d47bc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/java/com/twitter/ml/api:api-base", - "src/scala/com/twitter/ml/api/util:datarecord", - "util/util-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "util/util-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala deleted file mode 100644 index 56533bd88..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordConverter.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap.datarecord - -import com.twitter.ml.api.DataRecord -import com.twitter.ml.api.DataRecordMerger -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.datarecord._ -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap - -object DataRecordConverter { - val merger = new DataRecordMerger -} - -/** - * Constructs a FeatureMap from a DataRecord, given a predefined set of features from a FeaturesScope. - * - * @param featuresScope scope of predefined set of BaseDataRecordFeatures that should be included in the output FeatureMap. - */ -class DataRecordConverter[DRFeature <: BaseDataRecordFeature[_, _]]( - featuresScope: FeaturesScope[DRFeature]) { - import DataRecordConverter._ - - def toDataRecord(featureMap: FeatureMap): DataRecord = { - // Initialize a DataRecord with the Feature Store features in it and then add all the - // non-Feature Store features that support DataRecords to DataRecord. We don't - // need to add Feature Store features because they're already in the initial DataRecord. - // If there are any pre-built DataRecords, we merge those in. - val richDataRecord = featuresScope.getFeatureStoreFeaturesDataRecord(featureMap) - val features = featuresScope.getNonFeatureStoreDataRecordFeatures(featureMap) - features.foreach { - case _: FeatureStoreDataRecordFeature[_, _] => - case requiredFeature: DataRecordFeature[_, _] with DataRecordCompatible[_] => - richDataRecord.setFeatureValue( - requiredFeature.mlFeature, - requiredFeature.toDataRecordFeatureValue( - featureMap.get(requiredFeature).asInstanceOf[requiredFeature.FeatureType])) - case optionalFeature: DataRecordOptionalFeature[_, _] with DataRecordCompatible[_] => - featureMap - .get( - optionalFeature.asInstanceOf[Feature[_, Option[optionalFeature.FeatureType]]]).foreach { - value => - richDataRecord - .setFeatureValue( - optionalFeature.mlFeature, - optionalFeature.toDataRecordFeatureValue(value)) - } - case dataRecordInAFeature: DataRecordInAFeature[_] => - merger.merge(richDataRecord.getRecord, featureMap.get(dataRecordInAFeature)) - } - richDataRecord.getRecord - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala deleted file mode 100644 index a91b01d22..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/DataRecordExtractor.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap.datarecord - -import com.twitter.ml.api.DataRecord -import com.twitter.ml.api.FeatureContext -import com.twitter.ml.api.util.SRichDataRecord -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.datarecord._ -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import scala.collection.JavaConverters._ - -/** - * Constructs a DataRecord from a FeatureMap, given a predefined set of features. - * - * @param features predefined set of BaseDataRecordFeatures that should be included in the output DataRecord. - */ -class DataRecordExtractor[DRFeature <: BaseDataRecordFeature[_, _]]( - features: Set[DRFeature]) { - - private val featureContext = new FeatureContext(features.collect { - case dataRecordCompatible: DataRecordCompatible[_] => dataRecordCompatible.mlFeature - }.asJava) - - def fromDataRecord(dataRecord: DataRecord): FeatureMap = { - val featureMapBuilder = FeatureMapBuilder() - val richDataRecord = SRichDataRecord(dataRecord, featureContext) - features.foreach { - // FeatureStoreDataRecordFeature is currently not supported - case _: FeatureStoreDataRecordFeature[_, _] => - throw new UnsupportedOperationException( - "FeatureStoreDataRecordFeature cannot be extracted from a DataRecord") - case feature: DataRecordFeature[_, _] with DataRecordCompatible[_] => - // Java API will return null, so use Option to convert it to Scala Option which is None when null. - richDataRecord.getFeatureValueOpt(feature.mlFeature)( - feature.fromDataRecordFeatureValue) match { - case Some(value) => - featureMapBuilder.add(feature.asInstanceOf[Feature[_, feature.FeatureType]], value) - case None => - featureMapBuilder.addFailure( - feature, - PipelineFailure( - IllegalStateFailure, - s"Required DataRecord feature is missing: ${feature.mlFeature.getFeatureName}") - ) - } - case feature: DataRecordOptionalFeature[_, _] with DataRecordCompatible[_] => - val featureValue = - richDataRecord.getFeatureValueOpt(feature.mlFeature)(feature.fromDataRecordFeatureValue) - featureMapBuilder - .add(feature.asInstanceOf[Feature[_, Option[feature.FeatureType]]], featureValue) - // DataRecordInAFeature is currently not supported - case _: DataRecordInAFeature[_] => - throw new UnsupportedOperationException( - "DataRecordInAFeature cannot be extracted from a DataRecord") - } - featureMapBuilder.build() - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala deleted file mode 100644 index 8ef1898a9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/datarecord/FeaturesScope.scala +++ /dev/null @@ -1,157 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap.datarecord - -import com.twitter.ml.api.DataRecord -import com.twitter.ml.api.FeatureContext -import com.twitter.ml.api.util.SRichDataRecord -import scala.collection.JavaConverters._ -import com.twitter.product_mixer.core.feature.datarecord.BaseDataRecordFeature -import com.twitter.product_mixer.core.feature.datarecord.DataRecordCompatible -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1Feature -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature - -/** - * FeaturesScope for defining what features should be included in a DataRecord from a FeatureMap. - * Where possible, prefer [[SpecificFeatures]]. It fails loudly on missing features which can help - * identify programmer error, but can be complex to manage for multi-phase hydrators. - */ -sealed trait FeaturesScope[+DRFeature <: BaseDataRecordFeature[_, _]] { - def getNonFeatureStoreDataRecordFeatures(featureMap: FeatureMap): Seq[DRFeature] - - /** - * Because Feature Store features aren't direct features in the FeatureMap and instead live - * aggregated in a DataRecord in our Feature Map, we need to interface with the underlying Data - * Record instead. e.g. for the `AllFeatures` case, we won't know what all FStore ProMix Features - * we have in a FeatureMap just by looping through features & need to just return the DataRecord. - */ - def getFeatureStoreFeaturesDataRecord(featureMap: FeatureMap): SRichDataRecord -} - -/** - * Use all DataRecord features on a FeatureMap to output a DataRecord. - */ -case class AllFeatures[-Entity]() extends FeaturesScope[BaseDataRecordFeature[Entity, _]] { - override def getNonFeatureStoreDataRecordFeatures( - featureMap: FeatureMap - ): Seq[BaseDataRecordFeature[Entity, _]] = { - - /** - * See [[com.twitter.product_mixer.core.benchmark.FeatureMapBenchmark]] - * - * `toSeq`` is a no-op, `view`` makes later compositions lazy. Currently we only perform a `forEach` - * on the result but `view` here has no performance impact but protects us if we accidentally add - * more compositions in the middle. - * - * Feature Store features aren't in the FeatureMap so this will only ever return the non-FStore Features. - */ - featureMap.getFeatures.toSeq.view.collect { - case feature: BaseDataRecordFeature[Entity, _] => feature - } - } - - // Get the entire underlying DataRecord if available. - override def getFeatureStoreFeaturesDataRecord( - featureMap: FeatureMap - ): SRichDataRecord = if (featureMap.getFeatures.contains(FeatureStoreV1ResponseFeature)) { - // Note, we do not copy over the feature context because JRichDataRecord will enforce that - // all features are in the FeatureContext which we do not know at init time, and it's pricey - // to compute at run time. - SRichDataRecord(featureMap.get(FeatureStoreV1ResponseFeature).richDataRecord.getRecord) - } else { - SRichDataRecord(new DataRecord()) - } -} - -/** - * Build a DataRecord with only the given features from the FeatureMap used. Missing features - * will fail loudly. - * @param features the specific features to include in the DataRecord. - */ -case class SpecificFeatures[DRFeature <: BaseDataRecordFeature[_, _]]( - features: Set[DRFeature]) - extends FeaturesScope[DRFeature] { - - private val featuresForContext = features.collect { - case featureStoreFeatures: FeatureStoreV1Feature[_, _, _, _] => - featureStoreFeatures.boundFeature.mlApiFeature - case dataRecordCompatible: DataRecordCompatible[_] => dataRecordCompatible.mlFeature - }.asJava - - private val featureContext = new FeatureContext(featuresForContext) - - private val fsFeatures = features - .collect { - case featureStoreV1Feature: FeatureStoreV1Feature[_, _, _, _] => - featureStoreV1Feature - } - - // Since it's possible a customer will pass feature store features in the DR Feature list, let's - // partition them out to only return non-FS ones in getFeatures. See [[FeaturesScope]] comment. - private val nonFsFeatures: Seq[DRFeature] = features.flatMap { - case _: FeatureStoreV1Feature[_, _, _, _] => - None - case otherFeature => Some(otherFeature) - }.toSeq - - override def getNonFeatureStoreDataRecordFeatures( - featureMap: FeatureMap - ): Seq[DRFeature] = nonFsFeatures - - override def getFeatureStoreFeaturesDataRecord( - featureMap: FeatureMap - ): SRichDataRecord = - if (fsFeatures.nonEmpty && featureMap.getFeatures.contains(FeatureStoreV1ResponseFeature)) { - // Return a DataRecord only with the explicitly requested features set. - val richDataRecord = SRichDataRecord(new DataRecord(), featureContext) - val existingDataRecord = featureMap.get(FeatureStoreV1ResponseFeature).richDataRecord - fsFeatures.foreach { feature => - richDataRecord.setFeatureValue( - feature.boundFeature.mlApiFeature, - existingDataRecord.getFeatureValue(feature.boundFeature.mlApiFeature)) - } - richDataRecord - } else { - SRichDataRecord(new DataRecord()) - } -} - -/** - * Build a DataRecord with every feature available in a FeatureMap except for the ones provided. - * @param featuresToExclude the features to be excluded in the DataRecord. - */ -case class AllExceptFeatures( - featuresToExclude: Set[BaseDataRecordFeature[_, _]]) - extends FeaturesScope[BaseDataRecordFeature[_, _]] { - - private val fsFeatures = featuresToExclude - .collect { - case featureStoreV1Feature: FeatureStoreV1Feature[_, _, _, _] => - featureStoreV1Feature - } - - override def getNonFeatureStoreDataRecordFeatures( - featureMap: FeatureMap - ): Seq[BaseDataRecordFeature[_, _]] = - featureMap.getFeatures - .collect { - case feature: BaseDataRecordFeature[_, _] => feature - }.filterNot(featuresToExclude.contains).toSeq - - override def getFeatureStoreFeaturesDataRecord( - featureMap: FeatureMap - ): SRichDataRecord = if (featureMap.getFeatures.contains(FeatureStoreV1ResponseFeature)) { - // Return a data record only with the explicitly requested features set. Do this by copying - // the existing one and removing the features in the denylist. - // Note, we do not copy over the feature context because JRichDataRecord will enforce that - // all features are in the FeatureContext which we do not know at init time, and it's pricey - // to compute at run time. - val richDataRecord = SRichDataRecord( - featureMap.get(FeatureStoreV1ResponseFeature).richDataRecord.getRecord.deepCopy()) - fsFeatures.foreach { feature => - richDataRecord.clearFeature(feature.boundFeature.mlApiFeature) - } - richDataRecord - } else { - SRichDataRecord(new DataRecord()) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD deleted file mode 100644 index b34c59913..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala deleted file mode 100644 index 54abfc05e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/featurestorev1/FeatureStoreV1FeatureMap.scala +++ /dev/null @@ -1,191 +0,0 @@ -package com.twitter.product_mixer.core.feature.featuremap.featurestorev1 - -import com.twitter.ml.api.DataRecord -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.MissingFeatureException -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateFeatureGroup -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryFeatureGroup -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.util.Try - -object FeatureStoreV1FeatureMap { - - /** - * Implicitly add convenience accessors for FeatureStoreV1 features in [[FeatureMap]]. Note that - * we cannot add these methods directly to [[FeatureMap]] because it would introduce a circular - * dependency ([[PipelineQuery]] depends on [[FeatureMap]], and the methods below depend on - * [[PipelineQuery]]) - * - * @param featureMap the featureMap we are wrapping - * @note The FeatureStoreV1Feature::defaultValue set on the BoundFeature is only used and set - * during PredictionRecord to DataRecord conversion. Therefore, the default will not be set - * on the PredictionRecord value if reading from it directly, and as such for convenience - * the defaultValue is manually returned during retrieval from PredictionRecord. - * @note the Value generic type on the methods below cannot be passed to - * FeatureStoreV1QueryFeature's Value generic type. While this is actually the same type, - * (note the explicit type cast back to Value), we must instead use an existential on - * FeatureStoreV1QueryFeature since it is constructed with an existential for the Value - * generic (see [[FeatureStoreV1QueryFeature]] and [[FeatureStoreV1CandidateFeature]]) - */ - implicit class FeatureStoreV1FeatureMapAccessors(private val featureMap: FeatureMap) { - - def getFeatureStoreV1QueryFeature[Query <: PipelineQuery, Value]( - feature: FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value] - ): Value = - getOrElseFeatureStoreV1QueryFeature( - feature, - feature.defaultValue.getOrElse { - throw MissingFeatureException(feature) - }) - - def getFeatureStoreV1QueryFeatureTry[Query <: PipelineQuery, Value]( - feature: FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value] - ): Try[Value] = - Try(getFeatureStoreV1QueryFeature(feature)) - - def getOrElseFeatureStoreV1QueryFeature[Query <: PipelineQuery, Value]( - feature: FeatureStoreV1QueryFeature[Query, _ <: EntityId, Value], - default: => Value - ): Value = { - - /** - * FeatureStoreV1ResponseFeature should never be missing from the FeatureMap as FSv1 is - * guaranteed to return a prediction record per feature store request. However, this may be - * called on candidates that never hydrated FSv1 features. For example by - * [[com.twitter.product_mixer.component_library.selector.sorter.featurestorev1.FeatureStoreV1FeatureValueSorter]] - */ - val featureStoreV1FeatureValueOpt = featureMap.getTry(FeatureStoreV1ResponseFeature).toOption - - val dataRecordValue: Option[Value] = featureStoreV1FeatureValueOpt.flatMap { - featureStoreV1FeatureValue => - featureStoreV1FeatureValue.richDataRecord.getFeatureValueOpt( - feature.boundFeature.mlApiFeature)(feature.fromDataRecordValue) - } - - dataRecordValue.getOrElse(default) - } - - def getFeatureStoreV1CandidateFeature[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - Value - ]( - feature: FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] - ): Value = - getOrElseFeatureStoreV1CandidateFeature( - feature, - feature.defaultValue.getOrElse { - throw MissingFeatureException(feature) - }) - - def getFeatureStoreV1CandidateFeatureTry[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - Value - ]( - feature: FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value] - ): Try[Value] = - Try(getFeatureStoreV1CandidateFeature(feature)) - - def getOrElseFeatureStoreV1CandidateFeature[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - Value - ]( - feature: FeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, Value], - default: => Value - ): Value = { - - /** - * FeatureStoreV1ResponseFeature should never be missing from the FeatureMap as FSv1 is - * guaranteed to return a prediction record per feature store request. However, this may be - * called on candidates that never hydrated FSv1 features. For example by - * [[com.twitter.product_mixer.component_library.selector.sorter.featurestorev1.FeatureStoreV1FeatureValueSorter]] - */ - val featureStoreV1FeatureValueOpt = featureMap.getTry(FeatureStoreV1ResponseFeature).toOption - - val dataRecordValue: Option[Value] = featureStoreV1FeatureValueOpt.flatMap { - featureStoreV1FeatureValue => - featureStoreV1FeatureValue.richDataRecord.getFeatureValueOpt( - feature.boundFeature.mlApiFeature)(feature.fromDataRecordValue) - } - - dataRecordValue.getOrElse(default) - } - - /** - * Get queryFeatureGroup, which is store in the featureMap as a DataRecordInAFeature - * It doesn't have the mlApiFeature as other regular FeatureStoreV1 features - * Please refer to [[com.twitter.product_mixer.core.feature.datarecord.DataRecordInAFeature]] scaladoc for more details - */ - def getFeatureStoreV1QueryFeatureGroup[Query <: PipelineQuery]( - featureGroup: FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId] - ): DataRecord = - getOrElseFeatureStoreV1QueryFeatureGroup( - featureGroup, - throw MissingFeatureException(featureGroup) - ) - - def getFeatureStoreV1CandidateFeatureGroupTry[Query <: PipelineQuery]( - featureGroup: FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId] - ): Try[DataRecord] = - Try(getFeatureStoreV1QueryFeatureGroup(featureGroup)) - - def getOrElseFeatureStoreV1QueryFeatureGroup[Query <: PipelineQuery]( - featureGroup: FeatureStoreV1QueryFeatureGroup[Query, _ <: EntityId], - default: => DataRecord - ): DataRecord = { - featureMap.getTry(featureGroup).toOption.getOrElse(default) - } - - /** - * Get candidateFeatureGroup, which is store in the featureMap as a DataRecordInAFeature - * It doesn't have the mlApiFeature as other regular FeatureStoreV1 features - * Please refer to [[com.twitter.product_mixer.core.feature.datarecord.DataRecordInAFeature]] scaladoc for more details - */ - def getFeatureStoreV1CandidateFeatureGroup[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] - ]( - featureGroup: FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId] - ): DataRecord = - getOrElseFeatureStoreV1CandidateFeatureGroup( - featureGroup, - throw MissingFeatureException(featureGroup) - ) - - def getFeatureStoreV1CandidateFeatureGroupTry[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] - ]( - featureGroup: FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId] - ): Try[DataRecord] = - Try(getFeatureStoreV1CandidateFeatureGroup(featureGroup)) - - def getOrElseFeatureStoreV1CandidateFeatureGroup[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] - ]( - featureGroup: FeatureStoreV1CandidateFeatureGroup[Query, Candidate, _ <: EntityId], - default: => DataRecord - ): DataRecord = { - featureMap.getTry(featureGroup).toOption.getOrElse(default) - } - - def getOrElseFeatureStoreV1FeatureDataRecord( - default: => DataRecord - ) = { - val featureStoreV1FeatureValueOpt = featureMap.getTry(FeatureStoreV1ResponseFeature).toOption - - featureStoreV1FeatureValueOpt - .map { featureStoreV1FeatureValue => - featureStoreV1FeatureValue.richDataRecord.getRecord - }.getOrElse(default) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD deleted file mode 100644 index 408a2b569..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/BUILD +++ /dev/null @@ -1,29 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/scala/com/twitter/ml/featurestore/catalog/entities/core", - "src/scala/com/twitter/ml/featurestore/lib/data", - "src/scala/com/twitter/ml/featurestore/lib/dynamic", - "src/scala/com/twitter/ml/featurestore/lib/feature", - "src/scala/com/twitter/ml/featurestore/lib/feature:aggregates-feature-group", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "src/scala/com/twitter/ml/featurestore/catalog/entities/core", - "src/scala/com/twitter/ml/featurestore/lib/data", - "src/scala/com/twitter/ml/featurestore/lib/dynamic", - "src/scala/com/twitter/ml/featurestore/lib/feature", - "src/scala/com/twitter/ml/featurestore/lib/feature:aggregates-feature-group", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala deleted file mode 100644 index bd47a18c4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Entity.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.feature.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.entity.Entity -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -sealed trait FeatureStoreV1Entity[ - -Query <: PipelineQuery, - -Input, - FeatureStoreEntityId <: EntityId] { - - val entity: Entity[FeatureStoreEntityId] -} - -trait FeatureStoreV1QueryEntity[-Query <: PipelineQuery, FeatureStoreEntityId <: EntityId] - extends FeatureStoreV1Entity[Query, Query, FeatureStoreEntityId] { - - def entityWithId(query: Query): EntityWithId[FeatureStoreEntityId] -} - -trait FeatureStoreV1CandidateEntity[ - -Query <: PipelineQuery, - -Input <: UniversalNoun[Any], - FeatureStoreEntityId <: EntityId] - extends FeatureStoreV1Entity[Query, Input, FeatureStoreEntityId] { - - def entityWithId( - query: Query, - input: Input, - existingFeatures: FeatureMap - ): EntityWithId[FeatureStoreEntityId] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala deleted file mode 100644 index 0dc64e19e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/FeatureStoreV1Feature.scala +++ /dev/null @@ -1,312 +0,0 @@ -package com.twitter.product_mixer.core.feature.featurestorev1 - -import com.twitter.ml.api.DataRecord -import com.twitter.ml.api.transform.FeatureRenameTransform -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.dynamic.BaseGatedFeatures -import com.twitter.ml.featurestore.lib.feature.BoundFeature -import com.twitter.ml.featurestore.lib.feature.BoundFeatureSet -import com.twitter.ml.featurestore.lib.feature.TimelinesAggregationFrameworkFeatureGroup -import com.twitter.ml.featurestore.lib.feature.{Feature => FSv1Feature} -import com.twitter.product_mixer.core.feature.ModelFeatureName -import com.twitter.product_mixer.core.feature.datarecord.FeatureStoreDataRecordFeature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.servo.util.{Gate => ServoGate} -import com.twitter.timelines.configapi.FSParam -import scala.reflect.ClassTag - -/** - * The base trait for all feature store features on ProMix. This should not be constructed directly - * and should instead be used through the other implementations below - * @tparam Query Product Mixer Query Type - * @tparam Input The input type the feature should be keyed on, this is same as Query for query - * features and - * @tparam FeatureStoreEntityId Feature Store Entity Type - * @tparam Value The type of the value of this feature. - */ -sealed trait BaseFeatureStoreV1Feature[ - -Query <: PipelineQuery, - -Input, - FeatureStoreEntityId <: EntityId, - Value] - extends FeatureStoreDataRecordFeature[Input, Value] - with BaseGatedFeatures[Query] { - val fsv1Feature: FSv1Feature[FeatureStoreEntityId, Value] - - val entity: FeatureStoreV1Entity[Query, Input, FeatureStoreEntityId] - - val enabledParam: Option[FSParam[Boolean]] - - override final lazy val gate: ServoGate[Query] = enabledParam - .map { param => - new ServoGate[PipelineQuery] { - override def apply[U](query: U)(implicit asT: <:<[U, PipelineQuery]): Boolean = { - query.params(param) - } - } - }.getOrElse(ServoGate.True) - - override final lazy val boundFeatureSet: BoundFeatureSet = new BoundFeatureSet(Set(boundFeature)) - - val boundFeature: BoundFeature[FeatureStoreEntityId, Value] - - /** - * Since this trait is normally constructed inline, avoid the anonymous toString and use the bounded feature name. - */ - override lazy val toString: String = boundFeature.name -} - -/** - * A unitary (non-aggregate group) feature store feature in ProMix. This should be constructed using - * [[FeatureStoreV1CandidateFeature]] or [[FeatureStoreV1QueryFeature]]. - * @tparam Query Product Mixer Query Type - * @tparam Input The input type the feature should be keyed on, this is same as Query for query - * features and - * @tparam FeatureStoreEntityId Feature Store Entity Type - * @tparam Value The type of the value of this feature. - */ -sealed trait FeatureStoreV1Feature[ - -Query <: PipelineQuery, - -Input, - FeatureStoreEntityId <: EntityId, - Value] - extends BaseFeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, Value] - with ModelFeatureName { - - val legacyName: Option[String] - val defaultValue: Option[Value] - - override lazy val featureName: String = boundFeature.name - - override final lazy val boundFeature = (legacyName, defaultValue) match { - case (Some(legacyName), Some(defaultValue)) => - fsv1Feature.bind(entity.entity).withLegacyName(legacyName).withDefault(defaultValue) - case (Some(legacyName), _) => - fsv1Feature.bind(entity.entity).withLegacyName(legacyName) - case (_, Some(defaultValue)) => - fsv1Feature.bind(entity.entity).withDefault(defaultValue) - case _ => - fsv1Feature.bind(entity.entity) - } - - def fromDataRecordValue(recordValue: boundFeature.feature.mfc.V): Value = - boundFeature.feature.mfc.fromDataRecordValue(recordValue) -} - -/** - * A feature store aggregated group feature in ProMix. This should be constructed using - * [[FeatureStoreV1CandidateFeatureGroup]] or [[FeatureStoreV1QueryFeatureGroup]]. - * - * @tparam Query Product Mixer Query Type - * @tparam Input The input type the feature should be keyed on, this is same as Query for query - * features and - * @tparam FeatureStoreEntityId Feature Store Entity Type - */ -abstract class FeatureStoreV1FeatureGroup[ - -Query <: PipelineQuery, - -Input, - FeatureStoreEntityId <: EntityId: ClassTag] - extends BaseFeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, DataRecord] { - val keepLegacyNames: Boolean - val featureNameTransform: Option[FeatureRenameTransform] - - val featureGroup: TimelinesAggregationFrameworkFeatureGroup[FeatureStoreEntityId] - - override lazy val fsv1Feature: FSv1Feature[FeatureStoreEntityId, DataRecord] = - featureGroup.FeaturesAsDataRecord - - override final lazy val boundFeature = (keepLegacyNames, featureNameTransform) match { - case (_, Some(transform)) => - fsv1Feature.bind(entity.entity).withLegacyIndividualFeatureNames(transform) - case (true, _) => - fsv1Feature.bind(entity.entity).keepLegacyNames - case _ => - fsv1Feature.bind(entity.entity) - } -} - -sealed trait BaseFeatureStoreV1QueryFeature[ - -Query <: PipelineQuery, - FeatureStoreEntityId <: EntityId, - Value] - extends BaseFeatureStoreV1Feature[Query, Query, FeatureStoreEntityId, Value] { - - override val entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId] -} - -trait FeatureStoreV1QueryFeature[-Query <: PipelineQuery, FeatureStoreEntityId <: EntityId, Value] - extends FeatureStoreV1Feature[Query, Query, FeatureStoreEntityId, Value] - with BaseFeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, Value] - -trait FeatureStoreV1QueryFeatureGroup[-Query <: PipelineQuery, FeatureStoreEntityId <: EntityId] - extends FeatureStoreV1FeatureGroup[Query, Query, FeatureStoreEntityId] - with BaseFeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, DataRecord] - -object FeatureStoreV1QueryFeature { - - /** - * Query-based Feature Store backed feature - * @param feature The underling feature store feature this represents. - * @param _entity The entity for binding the Feature Store features - * @param _legacyName Feature Store legacy name if required - * @param _defaultValue The default value to return for this feature if not hydrated. - * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none. - * @tparam Query The Product Mixer query type this feature is keyed on. - * @tparam FeatureStoreEntityId Feature Store Entity ID - * @tparam Value The type of the value this feature contains. - * @return Product Mixer Feature - */ - def apply[Query <: PipelineQuery, FeatureStoreEntityId <: EntityId, Value]( - feature: FSv1Feature[FeatureStoreEntityId, Value], - _entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId], - _legacyName: Option[String] = None, - _defaultValue: Option[Value] = None, - _enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, Value] = - new FeatureStoreV1QueryFeature[Query, FeatureStoreEntityId, Value] { - override val fsv1Feature: FSv1Feature[FeatureStoreEntityId, Value] = feature - override val entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId] = _entity - override val legacyName: Option[String] = _legacyName - override val defaultValue: Option[Value] = _defaultValue - override val enabledParam: Option[FSParam[Boolean]] = _enabledParam - } -} - -object FeatureStoreV1QueryFeatureGroup { - - /** - * Query-based Feature Store Aggregated group backed feature - * - * @param featureGroup The underling aggregation group feature this represents. - * @param _entity The entity for binding the Feature Store features - * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none. - * @param _keepLegacyNames Whether to keep the legacy names as is for the entire group - * @param _featureNameTransform Rename the entire group's legacy names using the [[FeatureRenameTransform]] - * @tparam Query The Product Mixer query type this feature is keyed on. - * @tparam FeatureStoreEntityId Feature Store Entity ID - * - * @return Product Mixer Feature - */ - def apply[Query <: PipelineQuery, FeatureStoreEntityId <: EntityId: ClassTag]( - _featureGroup: TimelinesAggregationFrameworkFeatureGroup[FeatureStoreEntityId], - _entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId], - _enabledParam: Option[FSParam[Boolean]] = None, - _keepLegacyNames: Boolean = false, - _featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1QueryFeatureGroup[Query, FeatureStoreEntityId] = - new FeatureStoreV1QueryFeatureGroup[Query, FeatureStoreEntityId] { - override val entity: FeatureStoreV1QueryEntity[Query, FeatureStoreEntityId] = _entity - override val featureGroup: TimelinesAggregationFrameworkFeatureGroup[ - FeatureStoreEntityId - ] = _featureGroup - - override val enabledParam: Option[FSParam[Boolean]] = _enabledParam - - override val keepLegacyNames: Boolean = _keepLegacyNames - override val featureNameTransform: Option[FeatureRenameTransform] = _featureNameTransform - } -} - -sealed trait BaseFeatureStoreV1CandidateFeature[ - -Query <: PipelineQuery, - -Input <: UniversalNoun[Any], - FeatureStoreEntityId <: EntityId, - Value] - extends BaseFeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, Value] { - - override val entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId] -} - -trait FeatureStoreV1CandidateFeature[ - -Query <: PipelineQuery, - -Input <: UniversalNoun[Any], - FeatureStoreEntityId <: EntityId, - Value] - extends FeatureStoreV1Feature[Query, Input, FeatureStoreEntityId, Value] - with BaseFeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, Value] - -trait FeatureStoreV1CandidateFeatureGroup[ - -Query <: PipelineQuery, - -Input <: UniversalNoun[Any], - FeatureStoreEntityId <: EntityId] - extends FeatureStoreV1FeatureGroup[Query, Input, FeatureStoreEntityId] - with BaseFeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, DataRecord] - -object FeatureStoreV1CandidateFeature { - - /** - * Candidate-based Feature Store backed feature - * @param feature The underling feature store feature this represents. - * @param _entity The entity for binding the Feature Store features - * @param _legacyName Feature Store legacy name if required - * @param _defaultValue The default value to return for this feature if not hydrated. - * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none. - * @tparam Query The Product Mixer query type this feature is keyed on. - * @tparam FeatureStoreEntityId The feature store entity type - * @tparam Input The type of the candidate this feature is keyed on - * @tparam Value The type of value this feature contains. - * @return Product Mixer Feature - */ - def apply[ - Query <: PipelineQuery, - Input <: UniversalNoun[Any], - FeatureStoreEntityId <: EntityId, - Value - ]( - feature: FSv1Feature[FeatureStoreEntityId, Value], - _entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId], - _legacyName: Option[String] = None, - _defaultValue: Option[Value] = None, - _enabledParam: Option[FSParam[Boolean]] = None - ): FeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, Value] = - new FeatureStoreV1CandidateFeature[Query, Input, FeatureStoreEntityId, Value] { - override val fsv1Feature: FSv1Feature[FeatureStoreEntityId, Value] = feature - override val entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId] = - _entity - override val legacyName: Option[String] = _legacyName - override val defaultValue: Option[Value] = _defaultValue - override val enabledParam: Option[FSParam[Boolean]] = _enabledParam - } -} - -object FeatureStoreV1CandidateFeatureGroup { - - /** - * Candidate-based Feature Store Aggregated group backed feature - * - * @param featureGroup The underling aggregation group feature this represents. - * @param _entity The entity for binding the Feature Store features - * @param _enabledParam The Feature Switch Param to gate this feature, always enabled if none. - * @param _keepLegacyNames Whether to keep the legacy names as is for the entire group - * @param _featureNameTransform Rename the entire group's legacy names using the [[FeatureRenameTransform]] - * @tparam Query The Product Mixer query type this feature is keyed on. - * @tparam Input The type of the candidate this feature is keyed on - * @tparam FeatureStoreEntityId Feature Store Entity ID - * - * @return Product Mixer Feature - */ - def apply[ - Query <: PipelineQuery, - Input <: UniversalNoun[Any], - FeatureStoreEntityId <: EntityId: ClassTag, - ]( - _featureGroup: TimelinesAggregationFrameworkFeatureGroup[FeatureStoreEntityId], - _entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId], - _enabledParam: Option[FSParam[Boolean]] = None, - _keepLegacyNames: Boolean = false, - _featureNameTransform: Option[FeatureRenameTransform] = None - ): FeatureStoreV1CandidateFeatureGroup[Query, Input, FeatureStoreEntityId] = - new FeatureStoreV1CandidateFeatureGroup[Query, Input, FeatureStoreEntityId] { - override val entity: FeatureStoreV1CandidateEntity[Query, Input, FeatureStoreEntityId] = - _entity - override val featureGroup: TimelinesAggregationFrameworkFeatureGroup[ - FeatureStoreEntityId - ] = _featureGroup - - override val enabledParam: Option[FSParam[Boolean]] = _enabledParam - - override val keepLegacyNames: Boolean = _keepLegacyNames - override val featureNameTransform: Option[FeatureRenameTransform] = _featureNameTransform - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD deleted file mode 100644 index 931ea442a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "src/scala/com/twitter/ml/api/util:datarecord", - "src/scala/com/twitter/ml/featurestore/lib/data", - "src/scala/com/twitter/ml/featurestore/lib/dynamic", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "src/scala/com/twitter/ml/api/util:datarecord", - "src/scala/com/twitter/ml/featurestore/lib/data", - "src/scala/com/twitter/ml/featurestore/lib/dynamic", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala deleted file mode 100644 index e1f495346..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue/FeatureStoreV1Response.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.core.feature.featurestorev1.featurevalue - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty -import com.twitter.ml.api.DataRecordMerger -import com.twitter.ml.api.util.SRichDataRecord -import com.twitter.ml.featurestore.lib.data.HydrationError -import com.twitter.product_mixer.core.feature.Feature - -private[product_mixer] object FeatureStoreV1ResponseFeature - extends Feature[Any, FeatureStoreV1Response] - -@JsonIgnoreProperties(Array("richDataRecord", "failedFeatures")) -private[product_mixer] case class FeatureStoreV1Response( - @JsonProperty("richDataRecord") richDataRecord: SRichDataRecord, - @JsonProperty("failedFeatures") failedFeatures: Map[_ <: Feature[_, _], Set[HydrationError]]) { - // Since RichDataRecord is Java, we need to override this. - override def equals(obj: Any): Boolean = obj match { - case that: FeatureStoreV1Response => - failedFeatures == that.failedFeatures && richDataRecord.getRecord.equals( - that.richDataRecord.getRecord) - case _ => false - } -} - -private[product_mixer] object FeatureStoreV1Response { - val dataRecordMerger = new DataRecordMerger - def merge( - left: FeatureStoreV1Response, - right: FeatureStoreV1Response - ): FeatureStoreV1Response = { - val newDataRecord = left.richDataRecord.getRecord.deepCopy() - dataRecordMerger.merge(newDataRecord, right.richDataRecord.getRecord) - FeatureStoreV1Response( - richDataRecord = SRichDataRecord(newDataRecord), - left.failedFeatures ++ right.failedFeatures - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD deleted file mode 100644 index cb0e59b7c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/access_policy/BUILD +++ /dev/null @@ -1,9 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD deleted file mode 100644 index fe3e5b6bb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala deleted file mode 100644 index 2d93ab91a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidateSource.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch - -sealed trait BaseCandidateSource[-Request, +Candidate] extends Component { - - /** @see [[CandidateSourceIdentifier]] */ - val identifier: CandidateSourceIdentifier -} - -/** - * A [[CandidateSource]] returns a Seq of ''potential'' content - * - * @note [[CandidateSource]]s that return a single value need to transform - * it into a Seq, either by doing `Seq(value)` or extracting - * candidates from the value. - * - * @tparam Request arguments to get the potential content - * @tparam Candidate the potential content - */ -trait CandidateSource[-Request, +Candidate] extends BaseCandidateSource[Request, Candidate] { - - /** returns a Seq of ''potential'' content */ - def apply(request: Request): Stitch[Seq[Candidate]] -} - -/** - * A [[CandidateSourceWithExtractedFeatures]] returns a result containing both a Seq of - * ''potential'' candidates as well as an extracted feature map that will later be appended - * to the pipeline's [[com.twitter.product_mixer.core.pipeline.PipelineQuery]] feature map. This is - * useful for candidate sources that return features that might be useful later on without needing - * to re-hydrate them. - * - * @note [[CandidateSource]]s that return a single value need to transform - * it into a Seq, either by doing `Seq(value)` or extracting - * candidates from the value. - * - * @tparam Request arguments to get the potential content - * @tparam Candidate the potential content - */ -trait CandidateSourceWithExtractedFeatures[-Request, +Candidate] - extends BaseCandidateSource[Request, Candidate] { - - /** returns a result containing a seq of ''potential'' content and extracted features - * from the candidate source. - * */ - def apply(request: Request): Stitch[CandidatesWithSourceFeatures[Candidate]] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala deleted file mode 100644 index 124f9a044..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/CandidatesWithSourceFeatures.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap - -/** - * Results from a candidate source, optionally carrying extracted query level features to add - * to the query's feature map (e.g, extracting reusable features from the thrift response of thrift - * call). - * @param candidates The candidates returned from the underlying CandidateSoure - * @param features [[FeatureMap]] containing the features from the candidate source - * to merge back into the PipelineQuery FeatureMap. - * @tparam Candidate The type of result - */ -case class CandidatesWithSourceFeatures[+Candidate]( - candidates: Seq[Candidate], - features: FeatureMap) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala deleted file mode 100644 index ff51cace1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/PassthroughCandidateSource.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Retrieve Candidates from the Query - */ -trait CandidateExtractor[-Request, +Candidate] { - - def apply(query: Request): Seq[Candidate] -} - -/** - * Identity extractor for returning the Request as a Seq of candidates - */ -case class IdentityCandidateExtractor[Request]() extends CandidateExtractor[Request, Request] { - - def apply(candidate: Request): Seq[Request] = Seq(candidate) -} - -/** - * Retrieve Candidates from a [[Feature]] on the [[PipelineQuery]]'s FeatureMap. This extractor - * supports a transform if the Feature value and the Seq of [[Candidate]] types do not match - */ -trait QueryFeatureCandidateExtractor[-Query <: PipelineQuery, FeatureValue, +Candidate] - extends CandidateExtractor[Query, Candidate] { - - def feature: Feature[Query, FeatureValue] - - override def apply(query: Query): Seq[Candidate] = - query.features.map(featureMap => transform(featureMap.get(feature))).getOrElse(Seq.empty) - - def transform(featureValue: FeatureValue): Seq[Candidate] -} - -/** - * Retrieve Candidates from a [[Feature]] on the [[PipelineQuery]]'s FeatureMap. This extractor can - * be used with a single [[Feature]] if the Feature value and the Seq of [[Candidate]] types match. - */ -case class CandidateQueryFeatureCandidateExtractor[-Query <: PipelineQuery, Candidate]( - override val feature: Feature[Query, Seq[Candidate]]) - extends QueryFeatureCandidateExtractor[Query, Seq[Candidate], Candidate] { - - override def transform(featureValue: Seq[Candidate]): Seq[Candidate] = featureValue -} - -/** - * A [[CandidateSource]] that retrieves candidates from the Request via a [[CandidateExtractor]] - */ -case class PassthroughCandidateSource[-Request, +Candidate]( - override val identifier: CandidateSourceIdentifier, - candidateExtractor: CandidateExtractor[Request, Candidate]) - extends CandidateSource[Request, Candidate] { - - def apply(query: Request): Stitch[Seq[Candidate]] = Stitch.value(candidateExtractor(query)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala deleted file mode 100644 index 7a1f3d4dd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/StaticCandidateSource.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source - -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.stitch.Stitch - -/** - * A [[CandidateSource]] that always returns [[result]] regardless of the input - */ -case class StaticCandidateSource[Candidate]( - override val identifier: CandidateSourceIdentifier, - result: Seq[Candidate]) - extends CandidateSource[Any, Candidate] { - - def apply(request: Any): Stitch[Seq[Candidate]] = Stitch.value(result) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD deleted file mode 100644 index f0cc41a88..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala deleted file mode 100644 index 646b09928..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/product_pipeline/ProductPipelineCandidateSource.scala +++ /dev/null @@ -1,71 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.product_pipeline - -import com.google.inject.Provider -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.configapi.ParamsBuilder -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest -import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry -import com.twitter.stitch.Stitch -import scala.reflect.runtime.universe._ - -/** - * A [[CandidateSource]] for getting candidates from a different - * [[com.twitter.product_mixer.core.model.marshalling.request.Product]] within the same Product - * Mixer-based service. This is useful when calling a RecommendationPipeline-based Product from a - * MixerPipeline-based Product. In this scenario, the two Products can remain - * independent and encapsulated within the Product Mixer service, which provides future optionality - * for migrating one of the two products into a new Product Mixer-based service based on the - * scaling needs. - * - * @tparam Query [[PipelineQuery]] from the originating Product - * @tparam MixerRequest the [[Request]] domain model for the Product Mixer service. Adds a Context - * bound (syntactic sugar) to add TypeTag to implicit scope for - * [[ProductPipelineRegistry.getProductPipeline()]]. Note that `trait` does not - * support context bounds, so this abstraction is expressed as an - * `abstract class`. - * @tparam ProductPipelineResult the return type of the candidate source Product. Adds a Context - * bound (syntactic sugar) to add TypeTag to implicit scope for - * [[ProductPipelineRegistry.getProductPipeline()]] - * @tparam Candidate the type of candidate returned by this candidate source, which is typically - * extracted from within the ProductPipelineResult type - */ -abstract class ProductPipelineCandidateSource[ - -Query <: PipelineQuery, - MixerRequest <: Request: TypeTag, - ProductPipelineResult: TypeTag, - +Candidate] - extends CandidateSource[Query, Candidate] { - - /** - * @note Define as a Guice [[Provider]] in order to break the circular injection dependency - */ - val productPipelineRegistry: Provider[ProductPipelineRegistry] - - /** - * @note Define as a Guice [[Provider]] in order to break the circular injection dependency - */ - val paramsBuilder: Provider[ParamsBuilder] - - def pipelineRequestTransformer(currentPipelineQuery: Query): MixerRequest - - def productPipelineResultTransformer(productPipelineResult: ProductPipelineResult): Seq[Candidate] - - override def apply(query: Query): Stitch[Seq[Candidate]] = { - val request = pipelineRequestTransformer(query) - - val params = paramsBuilder - .get().build( - clientContext = request.clientContext, - product = request.product, - featureOverrides = request.debugParams.flatMap(_.featureOverrides).getOrElse(Map.empty) - ) - - productPipelineRegistry - .get() - .getProductPipeline[MixerRequest, ProductPipelineResult](request.product) - .process(ProductPipelineRequest(request, params)) - .map(productPipelineResultTransformer) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD deleted file mode 100644 index 24dea9785..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - "strato/src/main/scala/com/twitter/strato/response", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "stitch/stitch-core", - "strato/src/main/scala/com/twitter/strato/catalog", - "strato/src/main/scala/com/twitter/strato/client", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala deleted file mode 100644 index 4e72f1c44..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoErrCategorizer.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.Unauthorized -import com.twitter.stitch.Stitch -import com.twitter.strato.response.Err - -/** - * Categorize Strato's Err messages to our PipelineFailures. - * - * This should be used by all strato-based candidate source, and we can - * add more cases here as they're useful. - */ -object StratoErrCategorizer { - val CategorizeStratoException: PartialFunction[Throwable, Stitch[Nothing]] = { - case err @ Err(Err.Authorization, reason, context) => - Stitch.exception( - PipelineFailure(Unauthorized, s"$reason [${context.toString}]", underlying = Some(err)) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala deleted file mode 100644 index 19c8a6dba..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSeqSource.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Fetcher - -/** - * A [[CandidateSource]] for getting Candidates from Strato where the - * Strato column's View is [[Unit]] and the Value is a Seq of [[StratoResult]] - * - * @tparam StratoKey the column's Key type - * @tparam StratoResult the column's Value's Seq type - */ -trait StratoKeyFetcherSeqSource[StratoKey, StratoResult] - extends CandidateSource[StratoKey, StratoResult] { - - val fetcher: Fetcher[StratoKey, Unit, Seq[StratoResult]] - - override def apply(key: StratoKey): Stitch[Seq[StratoResult]] = { - fetcher - .fetch(key) - .map { result => - result.v - .getOrElse(Seq.empty) - }.rescue(StratoErrCategorizer.CategorizeStratoException) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala deleted file mode 100644 index 9d3f0e113..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherSource.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Fetcher - -/** - * A [[CandidateSource]] for getting Candidates from Strato where the - * Strato column's View is [[Unit]] and the Value is a [[StratoValue]] - * - * A `stratoResultTransformer` must be defined to convert the [[StratoValue]] into a Seq of [[Candidate]] - * - * If you need to extract features from the [[StratoValue]] (like a cursor), - * use [[StratoKeyFetcherWithSourceFeaturesSource]] instead. - * - * @tparam StratoKey the column's Key type - * @tparam StratoValue the column's Value type - */ -trait StratoKeyFetcherSource[StratoKey, StratoValue, Candidate] - extends CandidateSource[StratoKey, Candidate] { - - val fetcher: Fetcher[StratoKey, Unit, StratoValue] - - /** - * Transforms the value type returned by Strato into a Seq[Candidate]. - * - * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate. - * - * Often, it just extracts a Seq from within a larger wrapper object. - * - * If there is global metadata that you need to include, you can zip it with the candidates, - * returning something like Seq((candiate, metadata), (candidate, metadata)) etc. - */ - protected def stratoResultTransformer(stratoResult: StratoValue): Seq[Candidate] - - override def apply(key: StratoKey): Stitch[Seq[Candidate]] = { - fetcher - .fetch(key) - .map { result => - result.v - .map(stratoResultTransformer) - .getOrElse(Seq.empty) - }.rescue(StratoErrCategorizer.CategorizeStratoException) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala deleted file mode 100644 index d868d2862..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyFetcherWithSourceFeaturesSource.scala +++ /dev/null @@ -1,65 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Fetcher - -/** - * A [[CandidateSource]] for getting Candidates from Strato where the - * Strato column's View is [[Unit]] and the Value is a [[StratoValue]] - * - * A [[stratoResultTransformer]] must be defined to convert the - * [[StratoValue]] into a Seq of [[Candidate]] - * - * A [[extractFeaturesFromStratoResult]] must be defined to extract a - * [[FeatureMap]] from the [[StratoValue]]. If you don't need to do that, - * use a [[StratoKeyFetcherSource]] instead. - * - * @tparam StratoKey the column's Key type - * @tparam StratoValue the column's Value type - */ -trait StratoKeyFetcherWithSourceFeaturesSource[StratoKey, StratoValue, Candidate] - extends CandidateSourceWithExtractedFeatures[StratoKey, Candidate] { - - val fetcher: Fetcher[StratoKey, Unit, StratoValue] - - /** - * Transforms the value type returned by Strato into a Seq[Candidate]. - * - * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate. - * - * Often, it just extracts a Seq from within a larger wrapper object. - * - * If there is global metadata that you need to include, see [[extractFeaturesFromStratoResult]] - * below to put that into a Feature. - */ - protected def stratoResultTransformer(stratoResult: StratoValue): Seq[Candidate] - - /*** - * Transforms the value type returned by Strato into a FeatureMap. - * - * Override this to extract global metadata like cursors and place the results - * into a Feature. - * - * For example, a cursor. - */ - protected def extractFeaturesFromStratoResult(stratoResult: StratoValue): FeatureMap - - override def apply(key: StratoKey): Stitch[CandidatesWithSourceFeatures[Candidate]] = { - fetcher - .fetch(key) - .map { result => - val candidates = result.v - .map(stratoResultTransformer) - .getOrElse(Seq.empty) - - val features = result.v - .map(extractFeaturesFromStratoResult) - .getOrElse(FeatureMap.empty) - - CandidatesWithSourceFeatures(candidates, features) - }.rescue(StratoErrCategorizer.CategorizeStratoException) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala deleted file mode 100644 index 564ea253c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyView.scala +++ /dev/null @@ -1,4 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -/** Represents a Strato column's Key and View arguments */ -case class StratoKeyView[StratoKey, StratoView](key: StratoKey, view: StratoView) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala deleted file mode 100644 index f1bcddbd3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSeqSource.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Fetcher - -/** - * A [[CandidateSource]] for getting Candidates from Strato where the - * Strato column's View is [[StratoView]] and the Value is a Seq of [[StratoResult]] - * - * @tparam StratoKey the column's Key type - * @tparam StratoView the column's View type - * @tparam StratoResult the column's Value's Seq type - */ -trait StratoKeyViewFetcherSeqSource[StratoKey, StratoView, StratoResult] - extends CandidateSource[StratoKeyView[StratoKey, StratoView], StratoResult] { - - val fetcher: Fetcher[StratoKey, StratoView, Seq[StratoResult]] - - override def apply( - request: StratoKeyView[StratoKey, StratoView] - ): Stitch[Seq[StratoResult]] = { - fetcher - .fetch(request.key, request.view) - .map { result => - result.v - .getOrElse(Seq.empty) - }.rescue(StratoErrCategorizer.CategorizeStratoException) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala deleted file mode 100644 index 718dc632a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherSource.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Fetcher - -/** - * A [[CandidateSource]] for getting Candidates from Strato where the - * Strato column's View is [[StratoView]] and the Value is a [[StratoValue]] - * - * A `stratoResultTransformer` must be defined to convert the [[StratoValue]] into a Seq of [[Candidate]] - * - * If you need to extract features from the [[StratoValue]] (like a cursor), - * use [[StratoKeyViewFetcherWithSourceFeaturesSource]] instead. - * - * @tparam StratoKey the column's Key type - * @tparam StratoView the column's View type - * @tparam StratoValue the column's Value type - */ -trait StratoKeyViewFetcherSource[StratoKey, StratoView, StratoValue, Candidate] - extends CandidateSource[StratoKeyView[StratoKey, StratoView], Candidate] { - - val fetcher: Fetcher[StratoKey, StratoView, StratoValue] - - /** - * Transforms the value type returned by Strato into a Seq[Candidate]. - * - * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate. - * - * Often, it just extracts a Seq from within a larger wrapper object. - * - * If there is global metadata that you need to include, you can zip it with the candidates, - * returning something like Seq((candiate, metadata), (candidate, metadata)) etc. - */ - protected def stratoResultTransformer( - stratoKey: StratoKey, - stratoResult: StratoValue - ): Seq[Candidate] - - override def apply( - request: StratoKeyView[StratoKey, StratoView] - ): Stitch[Seq[Candidate]] = { - fetcher - .fetch(request.key, request.view) - .map { result => - result.v - .map((stratoResult: StratoValue) => stratoResultTransformer(request.key, stratoResult)) - .getOrElse(Seq.empty) - }.rescue(StratoErrCategorizer.CategorizeStratoException) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala deleted file mode 100644 index 65678a14c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source/strato/StratoKeyViewFetcherWithSourceFeaturesSource.scala +++ /dev/null @@ -1,75 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.candidate_source.strato - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.stitch.Stitch -import com.twitter.strato.client.Fetcher - -/** - * A [[CandidateSource]] for getting Candidates from Strato where the - * Strato column's View is [[StratoView]] and the Value is a [[StratoValue]] - * - * A [[stratoResultTransformer]] must be defined to convert the - * [[StratoValue]] into a Seq of [[Candidate]] - * - * [[extractFeaturesFromStratoResult]] must be defined to extract a - * [[FeatureMap]] from the [[StratoValue]]. If you don't need to do that, - * use a [[StratoKeyViewFetcherSource]] instead. - * - * @tparam StratoKey the column's Key type - * @tparam StratoView the column's View type - * @tparam StratoValue the column's Value type - */ -trait StratoKeyViewFetcherWithSourceFeaturesSource[StratoKey, StratoView, StratoValue, Candidate] - extends CandidateSourceWithExtractedFeatures[StratoKeyView[StratoKey, StratoView], Candidate] { - - val fetcher: Fetcher[StratoKey, StratoView, StratoValue] - - /** - * Transforms the value type returned by Strato into a Seq[Candidate]. - * - * This might be as simple as `Seq(stratoResult)` if you're always returning a single candidate. - * - * Often, it just extracts a Seq from within a larger wrapper object. - * - * If there is global metadata that you need to include, see [[extractFeaturesFromStratoResult]] - * below to put that into a Feature. - */ - protected def stratoResultTransformer( - stratoKey: StratoKey, - stratoResult: StratoValue - ): Seq[Candidate] - - /** - * Transforms the value type returned by Strato into a FeatureMap. - * - * Override this to extract global metadata like cursors and place the results - * into a Feature. - * - * For example, a cursor. - */ - protected def extractFeaturesFromStratoResult( - stratoKey: StratoKey, - stratoResult: StratoValue - ): FeatureMap - - override def apply( - request: StratoKeyView[StratoKey, StratoView] - ): Stitch[CandidatesWithSourceFeatures[Candidate]] = { - fetcher - .fetch(request.key, request.view) - .map { result => - val candidates = result.v - .map((stratoResult: StratoValue) => stratoResultTransformer(request.key, stratoResult)) - .getOrElse(Seq.empty) - - val features = result.v - .map((stratoResult: StratoValue) => - extractFeaturesFromStratoResult(request.key, stratoResult)) - .getOrElse(FeatureMap.empty) - - CandidatesWithSourceFeatures(candidates, features) - }.rescue(StratoErrCategorizer.CategorizeStratoException) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD deleted file mode 100644 index c0bae6c88..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala deleted file mode 100644 index b01d0207b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/CandidateScope.scala +++ /dev/null @@ -1,98 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common - -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines - -/** - * Specifies whether a function component (e.g, [[Gate]] or [[Selector]]) - * should apply to a given [[CandidateWithDetails]] - */ -sealed trait CandidateScope { - - /** - * returns True if the provided `candidate` is in scope - */ - def contains(candidate: CandidateWithDetails): Boolean - - /** partitions `candidates` into those that this scope [[contains]] and those it does not */ - final def partition( - candidates: Seq[CandidateWithDetails] - ): CandidateScope.PartitionedCandidates = { - val (candidatesInScope, candidatesOutOfScope) = candidates.partition(contains) - CandidateScope.PartitionedCandidates(candidatesInScope, candidatesOutOfScope) - } -} - -object CandidateScope { - case class PartitionedCandidates( - candidatesInScope: Seq[CandidateWithDetails], - candidatesOutOfScope: Seq[CandidateWithDetails]) -} - -/** - * A [[CandidateScope]] that applies the given functional component - * to all candidates regardless of which pipeline is their [[com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails.source]]. - */ -case object AllPipelines extends CandidateScope { - override def contains(candidate: CandidateWithDetails): Boolean = true -} - -/** - * A [[CandidateScope]] that applies the given [[com.twitter.product_mixer.core.functional_component.selector.Selector]] - * only to candidates whose [[com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines]] - * has an Identifier in the [[pipelines]] Set. - * In most cases where candidates are not pre-merged, the Set contains the candidate pipeline identifier the candidate - * came from. In the case where a candidate's feature maps were merged using [[CombineFeatureMapsCandidateMerger]], the - * set contains all candidate pipelines the merged candidate came from and this scope will include the candidate if any - * of the pipelines match. - */ -case class SpecificPipelines(pipelines: Set[CandidatePipelineIdentifier]) extends CandidateScope { - - require( - pipelines.nonEmpty, - "Expected `SpecificPipelines` have a non-empty Set of CandidatePipelineIdentifiers.") - - override def contains(candidate: CandidateWithDetails): Boolean = { - candidate.features.get(CandidatePipelines).exists(pipelines.contains) - } -} - -/** - * A [[CandidateScope]] that applies the given [[com.twitter.product_mixer.core.functional_component.selector.Selector]] - * only to candidates whose [[com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails.source]] - * is [[pipeline]]. - */ -case class SpecificPipeline(pipeline: CandidatePipelineIdentifier) extends CandidateScope { - - override def contains(candidate: CandidateWithDetails): Boolean = candidate.features - .get(CandidatePipelines).contains(pipeline) -} - -object SpecificPipelines { - def apply( - pipeline: CandidatePipelineIdentifier, - pipelines: CandidatePipelineIdentifier* - ): CandidateScope = { - if (pipelines.isEmpty) - SpecificPipeline(pipeline) - else - SpecificPipelines((pipeline +: pipelines).toSet) - } -} - -/** - * A [[CandidateScope]] that applies the given [[com.twitter.product_mixer.core.functional_component.selector.Selector]] - * to all candidates except for the candidates whose [[com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines]] - * has an Identifier in the [[pipelinesToExclude]] Set. - * In most cases where candidates are not pre-merged, the Set contains the candidate pipeline identifier the candidate - * came from. In the case where a candidate's feature maps were merged using [[CombineFeatureMapsCandidateMerger]], the - * set contains all candidate pipelines the merged candidate came from and this scope will include the candidate if any - * of the pipelines match. - */ -case class AllExceptPipelines( - pipelinesToExclude: Set[CandidatePipelineIdentifier]) - extends CandidateScope { - override def contains(candidate: CandidateWithDetails): Boolean = !candidate.features - .get(CandidatePipelines).exists(pipelinesToExclude.contains) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala deleted file mode 100644 index 4a1d9d11c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicy.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.access_policy - -import com.fasterxml.jackson.annotation.JsonSubTypes -import com.fasterxml.jackson.annotation.JsonTypeInfo - -/** - * The Access Policy to set for gating querying in the turntable tool. - * - * @note implementations must be simple case classes with unique structures for serialization - */ -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) -@JsonSubTypes( - Array( - new JsonSubTypes.Type(value = classOf[AllowedLdapGroups], name = "AllowedLdapGroups"), - new JsonSubTypes.Type(value = classOf[BlockEverything], name = "BlockEverything") - ) -) -sealed trait AccessPolicy - -/** - * Users must be in *at least* one of the provided LDAP groups in order to make a query. - * - * @param groups LDAP groups allowed to access this product - */ -case class AllowedLdapGroups(groups: Set[String]) extends AccessPolicy - -object AllowedLdapGroups { - def apply(group: String): AllowedLdapGroups = AllowedLdapGroups(Set(group)) -} - -/** - * Block all requests to a product. - * - * @note this needs to be a case class rather than an object because classOf doesn't work on objects - * and JsonSubTypes requires the annotation argument to be a constant (ruling out .getClass). - * This issue may be resolved in Scala 2.13: https://github.com/scala/scala/pull/9279 - */ -case class BlockEverything() extends AccessPolicy diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala deleted file mode 100644 index eaaa24fac..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/AccessPolicyEvaluator.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.access_policy - -/** - * Controls how access policies are applied to allow/reject a request - */ -object AccessPolicyEvaluator { - def evaluate(productAccessPolicies: Set[AccessPolicy], userLdapGroups: Set[String]): Boolean = - productAccessPolicies.exists { - case AllowedLdapGroups(allowedGroups) => allowedGroups.exists(userLdapGroups.contains) - case _: BlockEverything => false - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD deleted file mode 100644 index 0c605fff9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - ], - exports = [ - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala deleted file mode 100644 index 52322802c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy/WithDebugAccessPolicies.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.access_policy - -import com.twitter.product_mixer.core.model.common.Component - -private[core] trait WithDebugAccessPolicies { self: Component => - - /** The [[AccessPolicy]]s that will be used for this component in turntable & other debug tooling - * to execute arbitrary queries against the component */ - val debugAccessPolicies: Set[AccessPolicy] = Set.empty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala deleted file mode 100644 index b22a566a6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Alert.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.Predicate - -/** - * [[Alert]]s will trigger notifications to their [[NotificationGroup]] - * when the [[Predicate]]s are triggered. - */ -trait Alert { - - /** A group of alert levels and where the alerts for those levels should be sent */ - val notificationGroup: NotificationGroup - - /** Predicate indicating that the component is in a degraded state */ - val warnPredicate: Predicate - - /** Predicate indicating that the component is not functioning correctly */ - val criticalPredicate: Predicate - - /** An optional link to the runbook detailing how to respond to this alert */ - val runbookLink: Option[String] - - /** Indicates which metrics this [[Alert]] is for */ - val alertType: AlertType - - /** Where the metrics are from, @see [[Source]] */ - val source: Source = Server() - - /** A suffix to add to the end of the metric, this is often a [[Percentile]] */ - val metricSuffix: Option[String] = None -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala deleted file mode 100644 index 58ae57b8a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/AlertType.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -/** - * [[AlertType]] is used to indicate which metric an alert is for - * - * @note adding new [[AlertType]]s requires updating the dashboard generation code - */ -sealed trait AlertType { val metricType: String } - -/** Monitors the latency */ -case object Latency extends AlertType { override val metricType: String = "Latency" } - -/** Monitors the success rate __excluding__ client failures */ -case object SuccessRate extends AlertType { override val metricType: String = "SuccessRate" } - -/** Monitors the throughput */ -case object Throughput extends AlertType { override val metricType: String = "Throughput" } - -/** Monitors the empty response rate */ -case object EmptyResponseRate extends AlertType { - override val metricType: String = "EmptyResponseRate" -} - -/** Monitors the empty response size */ -case object ResponseSize extends AlertType { override val metricType: String = "ResponseSize" } diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD deleted file mode 100644 index bfdea7743..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "3rdparty/jvm/javax/inject:javax.inject", - "3rdparty/jvm/javax/mail", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate", - "strato/src/main/scala/com/twitter/strato/catalog", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate", - "strato/src/main/scala/com/twitter/strato/catalog", - "util/util-core:scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala deleted file mode 100644 index d937abd80..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/EmptyResponseRateAlert.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfAbove - -/** - * [[EmptyResponseRateAlert]] triggers when the percentage of requests with empty responses (defined - * as the number of items returned excluding cursors) rises above the [[TriggerIfAbove]] threshold - * for a configured amount of time. - * - * @note EmptyResponseRate thresholds must be between 0 and 100% - */ -case class EmptyResponseRateAlert( - override val notificationGroup: NotificationGroup, - override val warnPredicate: TriggerIfAbove, - override val criticalPredicate: TriggerIfAbove, - override val runbookLink: Option[String] = None) - extends Alert { - override val alertType: AlertType = EmptyResponseRate - require( - warnPredicate.threshold > 0 && warnPredicate.threshold <= 100, - s"EmptyResponseRateAlert predicates must be between 0 and 100 but got warnPredicate = ${warnPredicate.threshold}" - ) - require( - criticalPredicate.threshold > 0 && criticalPredicate.threshold <= 100, - s"EmptyResponseRateAlert predicates must be between 0 and 100 but got criticalPredicate = ${criticalPredicate.threshold}" - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala deleted file mode 100644 index a8a7c91ba..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientLatencyAlert.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfLatencyAbove - -/** - * Similar to [[LatencyAlert]] but intended for use with an external client calling Product Mixer. - * - * [[GenericClientLatencyAlert]] triggers when the Latency for the specified client - * rises above the [[TriggerIfLatencyAbove]] threshold for the configured amount of time. - */ -case class GenericClientLatencyAlert( - override val source: GenericClient, - override val notificationGroup: NotificationGroup, - override val warnPredicate: TriggerIfLatencyAbove, - override val criticalPredicate: TriggerIfLatencyAbove, - override val runbookLink: Option[String] = None) - extends Alert { - override val alertType: AlertType = Latency -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala deleted file mode 100644 index 27c03a2f9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientSuccessRateAlert.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfBelow - -/** - * Similar to [[SuccessRateAlert]] but intended for use with an external client calling Product Mixer - * - * [[GenericClientSuccessRateAlert]] triggers when the Success Rate for the external client - * drops below the [[TriggerIfBelow]] threshold for the configured amount of time - * - * @note SuccessRate thresholds must be between 0 and 100% - */ -case class GenericClientSuccessRateAlert( - override val source: GenericClient, - override val notificationGroup: NotificationGroup, - override val warnPredicate: TriggerIfBelow, - override val criticalPredicate: TriggerIfBelow, - override val runbookLink: Option[String] = None) - extends Alert { - override val alertType: AlertType = SuccessRate - require( - warnPredicate.threshold > 0 && warnPredicate.threshold <= 100, - s"SuccessRateAlert predicates must be between 0 and 100 but got warnPredicate = ${warnPredicate.threshold}" - ) - require( - criticalPredicate.threshold > 0 && criticalPredicate.threshold <= 100, - s"SuccessRateAlert predicates must be between 0 and 100 but got criticalPredicate = ${criticalPredicate.threshold}" - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala deleted file mode 100644 index e69b226d1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/GenericClientThroughputAlert.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.ThroughputPredicate - -/** - * Similar to [[ThroughputAlert]] but intended for an external client calling Product Mixer. - * - * [[GenericClientThroughputAlert]] triggers when the requests/sec for the external client - * is outside of the predicate set by a [[ThroughputPredicate]] for the configured amount of time - */ -case class GenericClientThroughputAlert( - override val source: GenericClient, - override val notificationGroup: NotificationGroup, - override val warnPredicate: ThroughputPredicate, - override val criticalPredicate: ThroughputPredicate, - override val runbookLink: Option[String] = None) - extends Alert { - override val alertType: AlertType = Throughput - require( - warnPredicate.threshold >= 0, - s"ThroughputAlert predicates must be >= 0 but got warnPredicate = ${warnPredicate.threshold}") - require( - criticalPredicate.threshold >= 0, - s"ThroughputAlert predicates must be >= 0 but got criticalPredicate = ${criticalPredicate.threshold}") -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala deleted file mode 100644 index 08fe3f459..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/IsObservableFromStrato.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -/** - * Indicates that an [[Alert]] can be passed to [[StratoColumnAlert]]. Not all [[Alert]]s can be - * Strato alerts since our ability to observe from Strato's perspective is limited by the available - * metrics. - * - * @note can only be used in conjunction with [[Alert]] - */ -trait IsObservableFromStrato { _: Alert => } diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala deleted file mode 100644 index 47819f2d0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/LatencyAlert.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfLatencyAbove - -/** - * [[GenericClientLatencyAlert]] triggers when the Latency for the component this is used with - * rises above the [[TriggerIfLatencyAbove]] threshold for the configured amount of time - */ -case class LatencyAlert( - override val notificationGroup: NotificationGroup, - percentile: Percentile, - override val warnPredicate: TriggerIfLatencyAbove, - override val criticalPredicate: TriggerIfLatencyAbove, - override val runbookLink: Option[String] = None) - extends Alert - with IsObservableFromStrato { - override val alertType: AlertType = Latency - - override val metricSuffix: Option[String] = Some(percentile.metricSuffix) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala deleted file mode 100644 index 400c122c8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/NotificationGroup.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.util.Try -import javax.mail.internet.InternetAddress - -/** - * Destination represents the place to which alerts will be sent. Often you will only need one field - * populated (either a Pager Duty key or a list of emails). - * - * See the Monitoring 2.0 docs for more information on [[https://docbird.twitter.biz/mon/how-to-guides.html?highlight=notificationgroup#set-up-email-pagerduty-and-slack-notifications setting up a Pager Duty rotation]] - */ -case class Destination( - pagerDutyKey: Option[String] = None, - emails: Seq[String] = Seq.empty) { - - require( - pagerDutyKey.forall(_.length == 32), - s"Expected `pagerDutyKey` to be 32 characters long but got `$pagerDutyKey`") - emails.foreach { email => - require( - Try(new InternetAddress(email).validate()).isReturn, - s"Expected only valid email addresses but got an invalid email address: `$email`") - } - require( - pagerDutyKey.nonEmpty || emails.nonEmpty, - s"Expected a `pagerDutyKey` or at least 1 email address but got neither") -} - -/** - * NotificationGroup maps alert levels to destinations. Having different destinations based on the - * urgency of the alert can sometimes be useful. For example, you could have a daytime on-call for - * warn alerts and a 24 on-call for critical alerts. - */ -case class NotificationGroup( - critical: Destination, - warn: Destination) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala deleted file mode 100644 index f2961b8bc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Percentile.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -/** - * [[Percentile]] is the specific metric that should be monitored. - * Some metrics such as Latency are recorded using [[https://twitter.github.io/util/docs/com/twitter/finagle/stats/Stat.html Stats]] - * the stats are recorded as various percentiles such as `my/stat.p95` or `my/stat.min`. - */ -sealed trait Percentile { val metricSuffix: String } -case object Min extends Percentile { override val metricSuffix: String = ".min" } -case object Avg extends Percentile { override val metricSuffix: String = ".avg" } -case object P50 extends Percentile { override val metricSuffix: String = ".p50" } -case object P90 extends Percentile { override val metricSuffix: String = ".p90" } -case object P95 extends Percentile { override val metricSuffix: String = ".p95" } -case object P99 extends Percentile { override val metricSuffix: String = ".p99" } -case object P999 extends Percentile { override val metricSuffix: String = ".p9990" } -case object P9999 extends Percentile { override val metricSuffix: String = ".p9999" } -case object Max extends Percentile { override val metricSuffix: String = ".max" } diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala deleted file mode 100644 index 263354c24..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ResponseSizeAlert.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.ThroughputPredicate - -/** - * [[ResponseSizeAlert]] triggers when the specified percentile of requests with empty responses (defined - * as the number of items returned excluding cursors) is beyond the [[ThroughputPredicate]] threshold - * for a configured amount of time. - */ -case class ResponseSizeAlert( - override val notificationGroup: NotificationGroup, - percentile: Percentile, - override val warnPredicate: ThroughputPredicate, - override val criticalPredicate: ThroughputPredicate, - override val runbookLink: Option[String] = None) - extends Alert { - override val metricSuffix: Option[String] = Some(percentile.metricSuffix) - override val alertType: AlertType = ResponseSize - require( - warnPredicate.threshold >= 0, - s"ResponseSizeAlert predicates must be >= 0 but got warnPredicate = ${warnPredicate.threshold}" - ) - require( - criticalPredicate.threshold >= 0, - s"ResponseSizeAlert predicates must be >= 0 but got criticalPredicate = ${criticalPredicate.threshold}" - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala deleted file mode 100644 index 3e961c561..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/Source.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.fasterxml.jackson.annotation.JsonSubTypes -import com.fasterxml.jackson.annotation.JsonTypeInfo - -/** - * where the metric originates from, such as from the server or from a client - * - * @note implementations must be simple case classes with unique structures for serialization - */ -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) -@JsonSubTypes( - Array( - new JsonSubTypes.Type(value = classOf[Server], name = "Server"), - new JsonSubTypes.Type(value = classOf[Strato], name = "Strato"), - new JsonSubTypes.Type(value = classOf[GenericClient], name = "GenericClient") - ) -) -sealed trait Source - -/** metrics for the Product Mixer server */ -case class Server() extends Source - -/** metrics from the perspective of a Strato column */ -case class Strato(stratoColumnPath: String, stratoColumnOp: String) extends Source - -/** - * metrics from the perspective of a generic client - * - * @param displayName human readable name for the client - * @param service service referenced in the query, of the form .. - * @param metricSource the source of the metric query, usually of the form sd... - * @param failureMetric the name of the metric indicating a client failure - * @param requestMetric the name of the metric indicating a request has been made - * @param latencyMetric the name of the metric measuring a request's latency - * - * @note We strongly recommend the use of [[Strato]] where possible. [[GenericClient]] is provided as a - * catch-all source for teams that have unusual legacy call paths (such as Macaw). - */ -case class GenericClient( - displayName: String, - service: String, - metricSource: String, - failureMetric: String, - requestMetric: String, - latencyMetric: String) - extends Source diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala deleted file mode 100644 index 7f000e039..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/StratoColumnAlert.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.Predicate -import com.twitter.strato.catalog.OpTag - -/** - * triggers when the a Strato column's is outside of the predicate set by the provided [[Alert]] - * - * @note the [[Alert]] passed into a [[StratoColumnAlert]] - * can not be a [[StratoColumnAlert]] - */ -case class StratoColumnAlert(column: String, op: OpTag, alert: Alert with IsObservableFromStrato) - extends Alert { - - override val source: Source = Strato(column, op.tag) - override val notificationGroup: NotificationGroup = alert.notificationGroup - override val warnPredicate: Predicate = alert.warnPredicate - override val criticalPredicate: Predicate = alert.criticalPredicate - override val runbookLink: Option[String] = alert.runbookLink - override val alertType: AlertType = alert.alertType - override val metricSuffix: Option[String] = alert.metricSuffix -} - -object StratoColumnAlerts { - - /** Make a seq of Alerts for the provided Strato column */ - def apply( - column: String, - op: OpTag, - alerts: Seq[Alert with IsObservableFromStrato] - ): Seq[Alert] = { - alerts.map(StratoColumnAlert(column, op, _)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala deleted file mode 100644 index f8ccbf8a2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/SuccessRateAlert.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.TriggerIfBelow - -/** - * [[SuccessRateAlert]] triggers when the Success Rate for the component this is used - * with drops below the [[TriggerIfBelow]] threshold for the configured amount of time - * - * @note SuccessRate thresholds must be between 0 and 100% - */ -case class SuccessRateAlert( - override val notificationGroup: NotificationGroup, - override val warnPredicate: TriggerIfBelow, - override val criticalPredicate: TriggerIfBelow, - override val runbookLink: Option[String] = None) - extends Alert - with IsObservableFromStrato { - override val alertType: AlertType = SuccessRate - require( - warnPredicate.threshold > 0 && warnPredicate.threshold <= 100, - s"SuccessRateAlert predicates must be between 0 and 100 but got warnPredicate = ${warnPredicate.threshold}" - ) - require( - criticalPredicate.threshold > 0 && criticalPredicate.threshold <= 100, - s"SuccessRateAlert predicates must be between 0 and 100 but got criticalPredicate = ${criticalPredicate.threshold}" - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala deleted file mode 100644 index d8a947ce1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/ThroughputAlert.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert - -import com.twitter.product_mixer.core.functional_component.common.alert.predicate.ThroughputPredicate - -/** - * [[ThroughputAlert]] triggers when the requests/sec for the component this is used - * with is outside of the predicate set by a [[ThroughputPredicate]] for - * the configured amount of time - */ -case class ThroughputAlert( - override val notificationGroup: NotificationGroup, - override val warnPredicate: ThroughputPredicate, - override val criticalPredicate: ThroughputPredicate, - override val runbookLink: Option[String] = None) - extends Alert - with IsObservableFromStrato { - override val alertType: AlertType = Throughput - require( - warnPredicate.threshold >= 0, - s"ThroughputAlert predicates must be >= 0 but got warnPredicate = ${warnPredicate.threshold}") - require( - criticalPredicate.threshold >= 0, - s"ThroughputAlert predicates must be >= 0 but got criticalPredicate = ${criticalPredicate.threshold}") -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD deleted file mode 100644 index 1aee67e8e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "util/util-core:scala", - ], - exports = [ - "util/util-core:scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala deleted file mode 100644 index c0a6d2a56..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/MetricGranularity.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert.predicate - -/** - * Specifies the metric granularity - * - * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DURATION]] - */ -sealed trait MetricGranularity { val unit: String } - -/** - * Use minutely metrics and have alert durations in terms of minutes - * - * i.e. for a [[Predicate]] if [[Predicate.datapointsPastThreshold]] = 5 and [[Predicate.duration]] = 10 - * then the alert will trigger if there are at least 5 '''minutely''' metric points that are past the threshold - * in any 10 '''minute''' period - */ -case object Minutes extends MetricGranularity { override val unit: String = "m" } - -/** - * Use hourly metrics and have alert durations in terms of hours - * - * i.e. for a [[Predicate]] if [[Predicate.datapointsPastThreshold]] = 5 and [[Predicate.duration]] = 10 - * then the alert will trigger if there are at least 5 '''hourly''' metric points that are past the threshold - * in any 10 '''hour''' period - */ -case object Hours extends MetricGranularity { override val unit: String = "h" } - -/** - * Use daily metrics and have alert durations in terms of days - * - * i.e. for a [[Predicate]] if [[Predicate.datapointsPastThreshold]] = 5 and [[Predicate.duration]] = 10 - * then the alert will trigger if there are at least 5 '''daily''' metric points that are past the threshold - * in any 10 '''day''' period - */ -case object Days extends MetricGranularity { override val unit: String = "d" } diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala deleted file mode 100644 index d3f7dd033..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Operator.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert.predicate - -/** - * Used for building [[Predicate]]s - * - * @see [[https://docbird.twitter.biz/mon/reference.html#predicate OPERATOR]] - */ -private[alert] sealed trait Operator -private[alert] case object `>` extends Operator -private[alert] case object `>=` extends Operator -private[alert] case object `<` extends Operator -private[alert] case object `<=` extends Operator -private[alert] case object `!=` extends Operator -private[alert] case object `=` extends Operator diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala deleted file mode 100644 index 5d6ad23fe..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/Predicate.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert.predicate - -/** - * [[Predicate]]s will trigger if the metric's value is past the - * `threshold` for `datapointsPastThreshold` or more datapoints - * in a given `duration` - * - * @see [[https://docbird.twitter.biz/mon/reference.html#predicate Predicate]] - */ -trait Predicate { - - /** @see [[https://docbird.twitter.biz/mon/reference.html#predicate OPERATOR]] */ - val operator: Operator - - /** @see [[https://docbird.twitter.biz/mon/reference.html#predicate THRESHOLD]] */ - val threshold: Double - - /** - * The number of datapoints in a given duration beyond the threshold that will trigger an alert - * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DATAPOINTS]] - */ - val datapointsPastThreshold: Int - - /** - * @note if using a [[metricGranularity]] of [[Minutes]] then this must be >= 3 - * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DURATION]] - */ - val duration: Int - - /** - * Specifies the metric granularity - * @see [[https://docbird.twitter.biz/mon/reference.html#predicate DURATION]] - */ - val metricGranularity: MetricGranularity - - require( - datapointsPastThreshold > 0, - s"`datapointsPastThreshold` must be > 0 but got `datapointsPastThreshold` = $datapointsPastThreshold" - ) - - require( - datapointsPastThreshold <= duration, - s"`datapointsPastThreshold` must be <= than `duration.inMinutes` but got `datapointsPastThreshold` = $datapointsPastThreshold `duration` = $duration" - ) - require( - metricGranularity != Minutes || duration >= 3, - s"Predicate durations must be at least 3 minutes but got $duration" - ) -} - -/** [[ThroughputPredicate]]s are predicates that can trigger when the throughput is too low or high */ -trait ThroughputPredicate extends Predicate diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala deleted file mode 100644 index 8356a2e18..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfAbove.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert.predicate - -/** - * A [[Predicate]] that triggers if the metric this is used with rises above - * the [[threshold]] for [[datapointsPastThreshold]] per [[duration]] - */ -case class TriggerIfAbove( - override val threshold: Double, - override val datapointsPastThreshold: Int = 10, - override val duration: Int = 15, - override val metricGranularity: MetricGranularity = Minutes) - extends Predicate - with ThroughputPredicate { - override val operator: Operator = `>` -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala deleted file mode 100644 index b528c15d6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfBelow.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert.predicate - -/** - * A [[Predicate]] that triggers if the metric this is used with lowers below - * the [[threshold]] for [[datapointsPastThreshold]] per [[duration]] - */ -case class TriggerIfBelow( - override val threshold: Double, - override val datapointsPastThreshold: Int = 10, - override val duration: Int = 15, - override val metricGranularity: MetricGranularity = Minutes) - extends Predicate - with ThroughputPredicate { - override val operator: Operator = `<` -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala deleted file mode 100644 index 726e83ed5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert/predicate/TriggerIfLatencyAbove.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.common.alert.predicate - -import com.twitter.util.Duration - -/** - * A [[Predicate]] that triggers if the metric this is used with rises above the - * [[latencyThreshold]] for [[datapointsPastThreshold]] per [[duration]] - * - * @note [[latencyThreshold]] must be > 0 - */ -case class TriggerIfLatencyAbove( - latencyThreshold: Duration, - override val datapointsPastThreshold: Int = 10, - override val duration: Int = 15, - override val metricGranularity: MetricGranularity = Minutes) - extends Predicate { - override val threshold: Double = latencyThreshold.inMillis - override val operator: Operator = `>` - require( - latencyThreshold > Duration.Zero, - s"TriggerIfLatencyAbove thresholds must be greater than 0 but got $latencyThreshold") -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD deleted file mode 100644 index 5baced00c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "configapi/configapi-featureswitches:v2", - "featureswitches/featureswitches-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "configapi/configapi-featureswitches:v2", - "featureswitches/featureswitches-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala deleted file mode 100644 index a805af6b9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ConfigBuilder.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi - -import com.twitter.product_mixer.core.functional_component.configapi.registry.GlobalParamRegistry -import com.twitter.product_mixer.core.product.registry.ProductParamRegistry -import com.twitter.timelines.configapi.CompositeConfig -import com.twitter.timelines.configapi.Config -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConfigBuilder @Inject() ( - productParamRegistry: ProductParamRegistry, - globalParamRegistry: GlobalParamRegistry) { - - def build(): Config = - new CompositeConfig(productParamRegistry.build() ++ Seq(globalParamRegistry.build())) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala deleted file mode 100644 index d1e570b59..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/ParamsBuilder.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.marshalling.request.ClientContext -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.twitter.servo.util.MemoizingStatsReceiver -import com.twitter.timelines.configapi.Config -import com.twitter.timelines.configapi.FeatureValue -import com.twitter.timelines.configapi.Params -import javax.inject.Inject -import javax.inject.Singleton - -/** Singleton object for building [[Params]] to override */ -@Singleton -class ParamsBuilder @Inject() ( - config: Config, - requestContextBuilder: RequestContextBuilder, - statsReceiver: StatsReceiver) { - - private[this] val scopedStatsReceiver = - new MemoizingStatsReceiver(statsReceiver.scope("configapi")) - - def build( - clientContext: ClientContext, - product: Product, - featureOverrides: Map[String, FeatureValue], - fsCustomMapInput: Map[String, Any] = Map.empty - ): Params = { - val requestContext = - requestContextBuilder.build(clientContext, product, featureOverrides, fsCustomMapInput) - - config(requestContext, scopedStatsReceiver) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala deleted file mode 100644 index 82bcbb92f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContext.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi - -import com.twitter.timelines.configapi.BaseRequestContext -import com.twitter.timelines.configapi.FeatureContext -import com.twitter.timelines.configapi.GuestId -import com.twitter.timelines.configapi.UserId -import com.twitter.timelines.configapi.WithFeatureContext -import com.twitter.timelines.configapi.WithGuestId -import com.twitter.timelines.configapi.WithUserId - -/** Represents [[com.twitter.timelines.configapi]]'s context information */ -case class RequestContext( - userId: Option[UserId], - guestId: Option[GuestId], - featureContext: FeatureContext) - extends BaseRequestContext - with WithUserId - with WithGuestId - with WithFeatureContext diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala deleted file mode 100644 index fe06fbeb6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/RequestContextBuilder.scala +++ /dev/null @@ -1,72 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi - -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.featureswitches.UserAgent -import com.twitter.featureswitches.{Recipient => FeatureSwitchRecipient} -import com.twitter.product_mixer.core.model.marshalling.request.ClientContext -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.twitter.timelines.configapi.featureswitches.v2.FeatureSwitchResultsFeatureContext -import com.twitter.timelines.configapi.FeatureContext -import com.twitter.timelines.configapi.FeatureValue -import com.twitter.timelines.configapi.ForcedFeatureContext -import com.twitter.timelines.configapi.OrElseFeatureContext -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Request Context Factory is used to build RequestContext objects which are used - * by the config api to determine the param overrides to apply to the request. - * The param overrides are determined per request by configs which specify which - * FS/Deciders/AB translate to what param overrides. - */ -@Singleton -class RequestContextBuilder @Inject() (featureSwitches: FeatureSwitches) { - - /** - * @param `fsCustomMapInput` allows you to set custom fields on your feature switches. - * This feature isn't directly supported by product mixer yet, so using this argument - * will likely result in future cleanup work. - * - */ - def build( - clientContext: ClientContext, - product: Product, - featureOverrides: Map[String, FeatureValue], - fsCustomMapInput: Map[String, Any] - ): RequestContext = { - val featureContext = - getFeatureContext(clientContext, product, featureOverrides, fsCustomMapInput) - - RequestContext(clientContext.userId, clientContext.guestId, featureContext) - } - - private[configapi] def getFeatureContext( - clientContext: ClientContext, - product: Product, - featureOverrides: Map[String, FeatureValue], - fsCustomMapInput: Map[String, Any] - ): FeatureContext = { - val recipient = getFeatureSwitchRecipient(clientContext) - .withCustomFields("product" -> product.identifier.toString, fsCustomMapInput.toSeq: _*) - - val results = featureSwitches.matchRecipient(recipient) - OrElseFeatureContext( - ForcedFeatureContext(featureOverrides), - new FeatureSwitchResultsFeatureContext(results)) - } - - private[configapi] def getFeatureSwitchRecipient( - clientContext: ClientContext - ): FeatureSwitchRecipient = FeatureSwitchRecipient( - userId = clientContext.userId, - userRoles = clientContext.userRoles, - deviceId = clientContext.deviceId, - guestId = clientContext.guestId, - languageCode = clientContext.languageCode, - countryCode = clientContext.countryCode, - userAgent = clientContext.userAgent.flatMap(UserAgent.apply), - isVerified = None, - clientApplicationId = clientContext.appId, - isTwoffice = clientContext.isTwoffice - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala deleted file mode 100644 index 8e29a926f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/StaticParam.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi - -import com.twitter.timelines.configapi.Param - -/** A [[Param]] used for constant values where we do not require backing by feature switches or deciders */ -case class StaticParam[ValueType](value: ValueType) extends Param[ValueType](value) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD deleted file mode 100644 index 3d66cd35c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "configapi/configapi-decider", - "servo/decider", - "util/util-core:util-core-util", - "util/util-logging", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "configapi/configapi-decider", - "servo/decider", - "util/util-core:util-core-util", - "util/util-logging", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala deleted file mode 100644 index 8175508cb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamConfig.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi.registry - -/** - * Register Params that do not relate to a specific product. - * See [[ParamConfig]] for hooks to register Params based on type. - */ -trait GlobalParamConfig extends ParamConfig with ParamConfigBuilder diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala deleted file mode 100644 index 6df7cf35f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/GlobalParamRegistry.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi.registry - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.BaseConfigBuilder -import com.twitter.timelines.configapi.Config -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GlobalParamRegistry @Inject() ( - globalParamConfig: GlobalParamConfig, - deciderGateBuilder: DeciderGateBuilder, - statsReceiver: StatsReceiver) { - - def build(): Config = { - val globalConfigs = globalParamConfig.build(deciderGateBuilder, statsReceiver) - - BaseConfigBuilder(globalConfigs).build("GlobalParamRegistry") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala deleted file mode 100644 index 20434dcc6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfig.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi.registry - -import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.DefinedFeatureName -import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.EnumParamWithFeatureName -import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.EnumSeqParamWithFeatureName -import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil.ValueFeatureName -import com.twitter.timelines.configapi.decider.HasDecider -import com.twitter.timelines.configapi.Bounded -import com.twitter.timelines.configapi.FSName -import com.twitter.timelines.configapi.HasDurationConversion -import com.twitter.timelines.configapi.OptionalOverride -import com.twitter.timelines.configapi.Param -import com.twitter.util.Duration - -/** ParamConfig is used to configure overrides for [[Param]]s of various types */ -trait ParamConfig { - - def booleanDeciderOverrides: Seq[Param[Boolean] with HasDecider] = Seq.empty - - def booleanFSOverrides: Seq[Param[Boolean] with FSName] = Seq.empty - - def optionalBooleanOverrides: Seq[ - (Param[Option[Boolean]], DefinedFeatureName, ValueFeatureName) - ] = Seq.empty - - def enumFSOverrides: Seq[EnumParamWithFeatureName[_ <: Enumeration]] = Seq.empty - - def enumSeqFSOverrides: Seq[EnumSeqParamWithFeatureName[_ <: Enumeration]] = Seq.empty - - /** - * Support for non-Duration supplied FS overrides (e.g. `timeFromStringFSOverrides`, - * `timeFromNumberFSOverrides`, `getBoundedOptionalDurationFromMillisOverrides`) is not provided - * as Duration is preferred - */ - def boundedDurationFSOverrides: Seq[ - Param[Duration] with Bounded[Duration] with FSName with HasDurationConversion - ] = Seq.empty - - /** Support for unbounded numeric FS overrides is not provided as bounded is preferred */ - def boundedIntFSOverrides: Seq[Param[Int] with Bounded[Int] with FSName] = Seq.empty - - def boundedOptionalIntOverrides: Seq[ - (Param[Option[Int]] with Bounded[Option[Int]], DefinedFeatureName, ValueFeatureName) - ] = Seq.empty - - def intSeqFSOverrides: Seq[Param[Seq[Int]] with FSName] = Seq.empty - - def boundedLongFSOverrides: Seq[Param[Long] with Bounded[Long] with FSName] = Seq.empty - - def boundedOptionalLongOverrides: Seq[ - (Param[Option[Long]] with Bounded[Option[Long]], DefinedFeatureName, ValueFeatureName) - ] = Seq.empty - - def longSeqFSOverrides: Seq[Param[Seq[Long]] with FSName] = Seq.empty - - def longSetFSOverrides: Seq[Param[Set[Long]] with FSName] = Seq.empty - - def boundedDoubleFSOverrides: Seq[Param[Double] with Bounded[Double] with FSName] = Seq.empty - - def boundedOptionalDoubleOverrides: Seq[ - (Param[Option[Double]] with Bounded[Option[Double]], DefinedFeatureName, ValueFeatureName) - ] = Seq.empty - - def doubleSeqFSOverrides: Seq[Param[Seq[Double]] with FSName] = Seq.empty - - def stringFSOverrides: Seq[Param[String] with FSName] = Seq.empty - - def stringSeqFSOverrides: Seq[Param[Seq[String]] with FSName] = Seq.empty - - def optionalStringOverrides: Seq[(Param[Option[String]], DefinedFeatureName, ValueFeatureName)] = - Seq.empty - - def gatedOverrides: Map[String, Seq[OptionalOverride[_]]] = Map.empty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala deleted file mode 100644 index 5bb5f1ea7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry/ParamConfigBuilder.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.configapi.registry - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.logging.Logger -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil -import com.twitter.timelines.configapi.OptionalOverride -import com.twitter.timelines.configapi.decider.DeciderUtils - -trait ParamConfigBuilder { paramConfig: ParamConfig => - - /** Builds a Seq of [[OptionalOverride]]s based on the [[paramConfig]] */ - def build( - deciderGateBuilder: DeciderGateBuilder, - statsReceiver: StatsReceiver - ): Seq[OptionalOverride[_]] = { - val logger = Logger(classOf[ParamConfig]) - - DeciderUtils.getBooleanDeciderOverrides(deciderGateBuilder, booleanDeciderOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBooleanFSOverrides(booleanFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getOptionalBooleanOverrides(optionalBooleanOverrides: _*) ++ - FeatureSwitchOverrideUtil.getEnumFSOverrides( - statsReceiver.scope("enumConversion"), - logger, - enumFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getEnumSeqFSOverrides( - statsReceiver.scope("enumSeqConversion"), - logger, - enumSeqFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedDurationFSOverrides(boundedDurationFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedIntFSOverrides(boundedIntFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedOptionalIntOverrides(boundedOptionalIntOverrides: _*) ++ - FeatureSwitchOverrideUtil.getIntSeqFSOverrides(intSeqFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedLongFSOverrides(boundedLongFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedOptionalLongOverrides(boundedOptionalLongOverrides: _*) ++ - FeatureSwitchOverrideUtil.getLongSeqFSOverrides(longSeqFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getLongSetFSOverrides(longSetFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedDoubleFSOverrides(boundedDoubleFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getBoundedOptionalDoubleOverrides( - boundedOptionalDoubleOverrides: _*) ++ - FeatureSwitchOverrideUtil.getDoubleSeqFSOverrides(doubleSeqFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getStringFSOverrides(stringFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getStringSeqFSOverrides(stringSeqFSOverrides: _*) ++ - FeatureSwitchOverrideUtil.getOptionalStringOverrides(optionalStringOverrides: _*) ++ - gatedOverrides.flatMap { - case (fsName, overrides) => FeatureSwitchOverrideUtil.gatedOverrides(fsName, overrides: _*) - }.toSeq - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD deleted file mode 100644 index 4db994de8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -scala_library( - name = "decoration", - sources = ["Decoration.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - ], -) - -scala_library( - sources = [ - "!Decoration.scala", - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ":decoration", - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - ":decoration", - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala deleted file mode 100644 index 4a6a213b7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/CandidateDecorator.scala +++ /dev/null @@ -1,61 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.DecoratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * [[CandidateDecorator]] generates a [[com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation]] - * for Candidates, which encapsulate information about how to present the candidate - * - * @see [[https://docbird.twitter.biz/product-mixer/functional-components.html#candidate-decorator]] - * @see [[com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation]] - */ -trait CandidateDecorator[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] - extends Component { - - override val identifier: DecoratorIdentifier = CandidateDecorator.DefaultCandidateDecoratorId - - /** - * Given a Seq of `Candidate`, returns a [[Decoration]] for candidates which should be decorated - * - * `Candidate`s which aren't decorated can be omitted from the results - */ - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[Decoration]] -} - -object CandidateDecorator { - private[core] val DefaultCandidateDecoratorId: DecoratorIdentifier = - DecoratorIdentifier(ComponentIdentifier.BasedOnParentComponent) - - /** - * For use when building a [[CandidateDecorator]] in a [[com.twitter.product_mixer.core.pipeline.PipelineBuilder]] - * to ensure that the identifier is updated with the parent [[com.twitter.product_mixer.core.pipeline.Pipeline.identifier]] - */ - private[core] def copyWithUpdatedIdentifier[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] - ]( - decorator: CandidateDecorator[Query, Candidate], - parentIdentifier: ComponentIdentifier - ): CandidateDecorator[Query, Candidate] = { - if (decorator.identifier == DefaultCandidateDecoratorId) { - new CandidateDecorator[Query, Candidate] { - override val identifier: DecoratorIdentifier = DecoratorIdentifier(parentIdentifier.name) - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[Decoration]] = decorator.apply(query, candidates) - } - } else { - decorator - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala deleted file mode 100644 index 74c9121b1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/Decoration.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation - -/** - * Decoration associates specific [[UniversalPresentation]] with a candidate - */ -case class Decoration( - candidate: UniversalNoun[Any], - presentation: UniversalPresentation) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD deleted file mode 100644 index 23bf323c6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala deleted file mode 100644 index 5ee3d5e25..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/slice/builder/CandidateSliceItemBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.slice.builder - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait CandidateSliceItemBuilder[ - -Query <: PipelineQuery, - -BuilderInput <: UniversalNoun[Any], - BuilderOutput <: SliceItem] { - - def apply(query: Query, candidate: BuilderInput, featureMap: FeatureMap): BuilderOutput -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD deleted file mode 100644 index 436d75e75..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -scala_library( - sources = ["**/*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala deleted file mode 100644 index f14abc28c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/CandidateUrtEntryBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait CandidateUrtEntryBuilder[ - -Query <: PipelineQuery, - -BuilderInput <: UniversalNoun[Any], - BuilderOutput <: TimelineEntry] { - - def apply(query: Query, candidate: BuilderInput, candidateFeatures: FeatureMap): BuilderOutput -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala deleted file mode 100644 index 7dbe7f567..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/icon/BaseHorizonIconBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.icon - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseHorizonIconBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[HorizonIcon] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala deleted file mode 100644 index 00b4d0454..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseDurationBuilder.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.util.Duration - -trait BaseDurationBuilder[-Query <: PipelineQuery] { - - def apply(query: Query, candidate: ShowAlertCandidate, features: FeatureMap): Option[Duration] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala deleted file mode 100644 index cb95bf2aa..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertColorConfigurationBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseShowAlertColorConfigurationBuilder[-Query <: PipelineQuery] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): ShowAlertColorConfiguration -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala deleted file mode 100644 index 4f64e37bf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertDisplayLocationBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseShowAlertDisplayLocationBuilder[-Query <: PipelineQuery] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): ShowAlertDisplayLocation -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala deleted file mode 100644 index 1d14099b1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertIconDisplayInfoBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseShowAlertIconDisplayInfoBuilder[-Query <: PipelineQuery] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): Option[ShowAlertIconDisplayInfo] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala deleted file mode 100644 index af9eb6a7f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertNavigationMetadataBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertNavigationMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseShowAlertNavigationMetadataBuilder[-Query <: PipelineQuery] { - - def apply( - query: Query, - candidate: ShowAlertCandidate, - features: FeatureMap - ): Option[ShowAlertNavigationMetadata] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala deleted file mode 100644 index 17de7cd81..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/alert/BaseShowAlertUserIdsBuilder.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.alert - -import com.twitter.product_mixer.component_library.model.candidate.ShowAlertCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseShowAlertUserIdsBuilder[-Query <: PipelineQuery] { - - def apply(query: Query, candidate: ShowAlertCandidate, features: FeatureMap): Option[Seq[Long]] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala deleted file mode 100644 index 879aa99b0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicDisplayTypeBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType - -trait BaseTopicDisplayTypeBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: PipelineQuery, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[TopicDisplayType] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala deleted file mode 100644 index 664a4a14c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/topic/BaseTopicFunctionalityTypeBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.topic - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType - -trait BaseTopicFunctionalityTypeBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: PipelineQuery, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[TopicFunctionalityType] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala deleted file mode 100644 index 9c8a0e6bc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseEntryIdToReplaceBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseEntryIdToReplaceBuilder[-Query <: PipelineQuery, -Candidate <: BaseTweetCandidate] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[String] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala deleted file mode 100644 index cae142bdd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTimelinesScoreInfoBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TimelinesScoreInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseTimelinesScoreInfoBuilder[-Query <: PipelineQuery, -Candidate <: BaseTweetCandidate] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[TimelinesScoreInfo] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala deleted file mode 100644 index c3dc6cfe6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/tweet/BaseTweetHighlightsBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.tweet - -import com.twitter.product_mixer.component_library.model.candidate.BaseTweetCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetHighlights -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseTweetHighlightsBuilder[-Query <: PipelineQuery, -Candidate <: BaseTweetCandidate] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[TweetHighlights] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala deleted file mode 100644 index 17aada2f8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/item/user/BaseUserReactiveTriggersBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.item.user - -import com.twitter.product_mixer.component_library.model.candidate.BaseUserCandidate -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserReactiveTriggers -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseUserReactiveTriggersBuilder[-Query <: PipelineQuery, -Candidate <: BaseUserCandidate] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[UserReactiveTriggers] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala deleted file mode 100644 index e0c662bcc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventDetailsBuilder.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseClientEventDetailsBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - /** - * @return a [[ClientEventDetails]] for the provided [[Candidate]] - * @see [[ClientEventDetails]] - */ - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[ClientEventDetails] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala deleted file mode 100644 index 27729a162..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseClientEventInfoBuilder.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseClientEventInfoBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - /** - * @return a [[ClientEventInfo]] for the provided [[Candidate]] - * @see [[ClientEventInfo]] - */ - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap, - element: Option[String] - ): Option[ClientEventInfo] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala deleted file mode 100644 index d1482fcf1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseFeedbackActionInfoBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseFeedbackActionInfoBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[FeedbackActionInfo] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala deleted file mode 100644 index 4470ab3dd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseModuleStr.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleStr[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): String -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala deleted file mode 100644 index ad1516aa1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseStr.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseStr[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): String -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala deleted file mode 100644 index 221a9107b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/metadata/BaseUrlBuilder.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.metadata - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap - -trait BaseUrlBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): Url -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala deleted file mode 100644 index 673ad7542..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/promoted/BasePromotedMetadataBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.promoted - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BasePromotedMetadataBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[PromotedMetadata] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala deleted file mode 100644 index db4238d11..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/richtext/BaseRichTextBuilder.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.richtext - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseRichTextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): RichText -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala deleted file mode 100644 index 659d6c401..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseModuleSocialContextBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleSocialContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[SocialContext] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala deleted file mode 100644 index f51933456..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/social_context/BaseSocialContextBuilder.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.social_context - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseSocialContextBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidate: Candidate, - candidateFeatures: FeatureMap - ): Option[SocialContext] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala deleted file mode 100644 index 0dc6fe5f9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseModuleStringCenterPlaceholderBuilder.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleStringCenterPlaceholderBuilder[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any]] { - - def apply(query: Query, candidates: Seq[CandidateWithFeatures[Candidate]]): Map[String, Any] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala deleted file mode 100644 index d006f1bbb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/stringcenter/BaseStringCenterPlaceholderBuilder.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.stringcenter - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseStringCenterPlaceholderBuilder[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any]] { - - def apply(query: Query, candidate: Candidate, candidateFeatures: FeatureMap): Map[String, Any] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala deleted file mode 100644 index df44ce8e9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleDisplayTypeBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleDisplayTypeBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): ModuleDisplayType -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala deleted file mode 100644 index f30761822..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleFooterBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleFooterBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[ModuleFooter] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala deleted file mode 100644 index 0e0145f10..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleHeaderBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Option[ModuleHeader] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala deleted file mode 100644 index e1218613f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleHeaderDisplayTypeBuilder.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeaderDisplayType -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleHeaderDisplayTypeBuilder[ - -Query <: PipelineQuery, - -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): ModuleHeaderDisplayType -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala deleted file mode 100644 index 6d2e417c3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleMetadataBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleMetadataBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): ModuleMetadata -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala deleted file mode 100644 index 2cdf0c8ff..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseModuleShowMoreBehaviorBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseModuleShowMoreBehaviorBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): ModuleShowMoreBehavior -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala deleted file mode 100644 index bf7bcaba1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator/urt/builder/timeline_module/BaseTimelineModuleBuilder.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.decorator.urt.builder.timeline_module - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait BaseTimelineModuleBuilder[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] { - - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): TimelineModule -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD deleted file mode 100644 index 5f388dfc5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala deleted file mode 100644 index 069884466..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/CandidateFeatureHydrator.scala +++ /dev/null @@ -1,96 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.SupportsConditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Hydrate features for a specific candidate - * e.g. if the candidate is a Tweet then a feature could be whether it's is marked as sensitive - * - * @note if you want to conditionally run a [[BaseCandidateFeatureHydrator]] you can use the mixin [[com.twitter.product_mixer.core.model.common.Conditionally]] - * or to gate on a [[com.twitter.timelines.configapi.Param]] you can use - * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedCandidateFeatureHydrator]] or - * [[com.twitter.product_mixer.component_library.feature_hydrator.candidate.param_gated.ParamGatedBulkCandidateFeatureHydrator]] - */ -sealed trait BaseCandidateFeatureHydrator[ - -Query <: PipelineQuery, - -Result <: UniversalNoun[Any], - FeatureType <: Feature[_, _]] - extends FeatureHydrator[FeatureType] - with SupportsConditionally[Query] - -/** - * A candidate feature hydrator that provides an implementation for hydrating a single candidate - * at the time. Product Mixer core takes care of hydrating all your candidates for you by - * calling this for each candidate. This is useful for Stitch-powered downstream APIs (such - * as Strato, Gizmoduck, etc) where the API takes a single candidate/key and Stitch handles - * batching for you. - * - * @note Any exceptions that are thrown or returned as [[Stitch.exception]] will be added to the - * [[FeatureMap]] for *all* [[Feature]]s intended to be hydrated. - * Accessing a failed Feature will throw if using [[FeatureMap.get]] for Features that aren't - * [[com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure]] - * - * @tparam Query The query type - * @tparam Result The Candidate type - */ -trait CandidateFeatureHydrator[-Query <: PipelineQuery, -Result <: UniversalNoun[Any]] - extends BaseCandidateFeatureHydrator[Query, Result, Feature[_, _]] { - - override val identifier: FeatureHydratorIdentifier - - /** Hydrates a [[FeatureMap]] for a single candidate */ - def apply(query: Query, candidate: Result, existingFeatures: FeatureMap): Stitch[FeatureMap] -} - -/** - * Hydrate features for a list of candidates - * e.g. for a list of Tweet candidates, a feature could be the visibility reason whether to show or not show each Tweet - */ -trait BaseBulkCandidateFeatureHydrator[ - -Query <: PipelineQuery, - -Result <: UniversalNoun[Any], - FeatureType <: Feature[_, _]] - extends BaseCandidateFeatureHydrator[Query, Result, FeatureType] { - - /** - * Hydrates a set of [[FeatureMap]]s for the bulk list of candidates. Every input candidate must - * have corresponding entry in the returned seq with a feature map. - */ - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Result]] - ): Stitch[Seq[FeatureMap]] -} - -/** - * A candidate feature hydrator that allows a user to bulk hydrate features for all candidates - * at once. This is useful for downstream APIs that take a list of candidates in one go such - * as feature store or scorers. - * - * @note Any exceptions that are thrown or returned as [[Stitch.exception]] will be added to the - * [[FeatureMap]] for *all* [[Feature]]s of *all* candidates intended to be hydrated. - * An alternative to throwing an exception is per-candidate failure handling (e.g. adding - * a failed [[Feature]] with `addFailure`, a Try with `add`, or an optional value with `add` - * using [[FeatureMapBuilder]]). - * Accessing a failed Feature will throw if using [[FeatureMap.get]] for Features that aren't - * [[com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure]]. - * - * @tparam Query The query type - * @tparam Result The Candidate type - */ -trait BulkCandidateFeatureHydrator[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends BaseBulkCandidateFeatureHydrator[Query, Candidate, Feature[_, _]] { - override val identifier: FeatureHydratorIdentifier - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala deleted file mode 100644 index 62c07353f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/FeatureHydrator.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.Component - -/** Hydrates a [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]] for a given input */ -trait FeatureHydrator[FeatureType <: Feature[_, _]] extends Component { - def features: Set[FeatureType] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala deleted file mode 100644 index f78e1135a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/HydratorCandidateResult.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun - -case class HydratorCandidateResult[+Candidate <: UniversalNoun[Any]]( - override val candidate: Candidate, - override val features: FeatureMap) - extends CandidateWithFeatures[Candidate] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala deleted file mode 100644 index e40f1ccb8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/QueryFeatureHydrator.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.SupportsConditionally -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Hydrate features about the query itself (not about the candidates) - * e.g. features about the user who is making the request, what country the request originated from, etc. - * - * @note [[BaseQueryFeatureHydrator]]s populate [[Feature]]s with last-write-wins semantics for - * duplicate [[Feature]]s, where the last hydrator to run that populates a [[Feature]] will - * override any previously run [[BaseQueryFeatureHydrator]]s values for that [[Feature]]. - * In a [[com.twitter.product_mixer.core.pipeline.PipelineConfig PipelineConfig]] this means - * that the right-most [[BaseQueryFeatureHydrator]] to populate a given [[Feature]] will be - * the value that is available to use. - * - * @note if you want to conditionally run a [[BaseQueryFeatureHydrator]] you can use the mixin [[com.twitter.product_mixer.core.model.common.Conditionally]] - * or to gate on a [[com.twitter.timelines.configapi.Param]] you can use [[com.twitter.product_mixer.component_library.feature_hydrator.query.param_gated.ParamGatedQueryFeatureHydrator]] - * - * @note Any exceptions that are thrown or returned as [[Stitch.exception]] will be added to the - * [[FeatureMap]] for the [[Feature]]s that were supposed to be hydrated. - * Accessing a failed Feature will throw if using [[FeatureMap.get]] for Features that aren't - * [[com.twitter.product_mixer.core.feature.FeatureWithDefaultOnFailure]] - */ -trait BaseQueryFeatureHydrator[-Query <: PipelineQuery, FeatureType <: Feature[_, _]] - extends FeatureHydrator[FeatureType] - with SupportsConditionally[Query] { - - override val identifier: FeatureHydratorIdentifier - - /** Hydrates a [[FeatureMap]] for a given [[Query]] */ - def hydrate(query: Query): Stitch[FeatureMap] -} - -trait QueryFeatureHydrator[-Query <: PipelineQuery] - extends BaseQueryFeatureHydrator[Query, Feature[_, _]] - -/** - * When an [[AsyncHydrator]] is run it will hydrate features in the background - * and will make them available starting at the specified point in execution. - * - * When `hydrateBefore` is reached, any duplicate [[Feature]]s that were already hydrated will be - * overridden with the new value from the [[AsyncHydrator]] - * - * @note [[AsyncHydrator]]s have the same last-write-wins semantics for duplicate [[Feature]]s - * as [[BaseQueryFeatureHydrator]] but with some nuance. If [[AsyncHydrator]]s for the - * same [[Feature]] have the same `hydrateBefore` then the right-most [[AsyncHydrator]]s - * value takes precedence. Similarly, [[AsyncHydrator]]s always hydrate after any other - * [[BaseQueryFeatureHydrator]]. See the examples for more detail. - * @example if [[QueryFeatureHydrator]]s that populate the same [[Feature]] are defined in a `PipelineConfig` - * such as `[ asyncHydratorForFeatureA, normalHydratorForFeatureA ]`, where `asyncHydratorForFeatureA` - * is an [[AsyncHydrator]], when `asyncHydratorForFeatureA` reaches it's `hydrateBefore` - * Step in the Pipeline, the value for `FeatureA` from the `asyncHydratorForFeatureA` will override - * the existing value from `normalHydratorForFeatureA`, even though in the initial `PipelineConfig` - * they are ordered differently. - * @example if [[AsyncHydrator]]s that populate the same [[Feature]] are defined in a `PipelineConfig` - * such as `[ asyncHydratorForFeatureA1, asyncHydratorForFeatureA2 ]`, where both [[AsyncHydrator]]s - * have the same `hydrateBefore`, when `hydrateBefore` is reached, the value for `FeatureA` from - * `asyncHydratorForFeatureA2` will override the value from `asyncHydratorForFeatureA1`. - */ -trait AsyncHydrator { - _: BaseQueryFeatureHydrator[_, _] => - - /** - * A [[PipelineStepIdentifier]] from the [[com.twitter.product_mixer.core.pipeline.PipelineConfig]] this is used in - * by which the [[FeatureMap]] returned by this [[AsyncHydrator]] will be completed. - * - * Access to the [[Feature]]s from this [[AsyncHydrator]] prior to reaching the provided - * [[PipelineStepIdentifier]]s will result in a [[com.twitter.product_mixer.core.feature.featuremap.MissingFeatureException]]. - * - * @note If [[PipelineStepIdentifier]] is a Step which is run in parallel, the [[Feature]]s will be available for all the parallel Steps. - */ - def hydrateBefore: PipelineStepIdentifier -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD deleted file mode 100644 index bd8d63134..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/datarecord", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/scala/com/twitter/ml/featurestore/lib/online", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1/featurevalue", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "src/scala/com/twitter/ml/featurestore/lib/online", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala deleted file mode 100644 index 7b723bdd5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreDatasetErrorHandler.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.data.DatasetErrorsById -import com.twitter.ml.featurestore.lib.data.HydrationError -import com.twitter.ml.featurestore.lib.dataset.DatasetId -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1Feature -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object FeatureStoreDatasetErrorHandler { - - /** - * This function takes a set of feature store features and constructs a mapping from the underlying - * feature store dataset back to the features. This is useful for looking up what ProMix features - * failed based off of a failed feature store dataset at request time. A ProMix feature can be - * powered by multiple feature store datasets, and conversely, a dataset can be used by many features. - */ - def datasetToFeaturesMapping[ - Query <: PipelineQuery, - Input, - FeatureType <: BaseFeatureStoreV1Feature[Query, Input, _ <: EntityId, _] - ]( - features: Set[FeatureType] - ): Map[DatasetId, Set[FeatureType]] = { - val datasetsAndFeatures: Set[(DatasetId, FeatureType)] = features - .flatMap { feature: FeatureType => - feature.boundFeatureSet.sourceDatasets.map(_.id).map { datasetId: DatasetId => - datasetId -> feature - } - } - - datasetsAndFeatures - .groupBy { case (datasetId, _) => datasetId }.mapValues(_.map { - case (_, feature) => feature - }) - } - - /** - * This takes a mapping of Feature Store Dataset => ProMix Features, as well as the dataset errors - * from PredictionRecord and computing a final, deduped mapping from ProMix Feature to Exceptions. - */ - def featureToHydrationErrors[ - Query <: PipelineQuery, - Input, - FeatureType <: BaseFeatureStoreV1Feature[Query, Input, _ <: EntityId, _] - ]( - datasetToFeatures: Map[DatasetId, Set[ - FeatureType - ]], - errorsByDatasetId: DatasetErrorsById - ): Map[FeatureType, Set[HydrationError]] = { - val hasError = errorsByDatasetId.datasets.nonEmpty - if (hasError) { - val featuresAndErrors: Set[(FeatureType, Set[HydrationError])] = errorsByDatasetId.datasets - .flatMap { id: DatasetId => - val errors: Set[HydrationError] = errorsByDatasetId.get(id).values.toSet - if (errors.nonEmpty) { - val datasetFeatures: Set[FeatureType] = datasetToFeatures.getOrElse(id, Set.empty) - datasetFeatures.map { feature => - feature -> errors - }.toSeq - } else { - Seq.empty - } - } - featuresAndErrors - .groupBy { case (feature, _) => feature }.mapValues(_.flatMap { - case (_, errors: Set[HydrationError]) => errors - }) - } else { - Map.empty - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala deleted file mode 100644 index e80d55302..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1CandidateFeatureHydrator.scala +++ /dev/null @@ -1,97 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1 - -import com.twitter.ml.api.util.SRichDataRecord -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.data.PredictionRecordAdapter -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.online.FeatureStoreRequest -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1CandidateEntity -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseBulkCandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.FeatureHydrationFailed -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch -import com.twitter.util.logging.Logging - -trait FeatureStoreV1CandidateFeatureHydrator[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any]] - extends BaseBulkCandidateFeatureHydrator[ - Query, - Candidate, - BaseFeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, _] - ] - with Logging { - - override def features: Set[BaseFeatureStoreV1CandidateFeature[Query, Candidate, _ <: EntityId, _]] - - def clientBuilder: FeatureStoreV1DynamicClientBuilder - - private lazy val hydrationConfig = FeatureStoreV1CandidateFeatureHydrationConfig(features) - - private lazy val client = clientBuilder.build(hydrationConfig) - - private lazy val datasetToFeatures = - FeatureStoreDatasetErrorHandler.datasetToFeaturesMapping(features) - - private lazy val dataRecordAdapter = - PredictionRecordAdapter.oneToOne(hydrationConfig.allBoundFeatures) - - private lazy val featureContext = hydrationConfig.allBoundFeatures.toFeatureContext - - override def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] = { - // Duplicate entities are expected across features, so de-dupe via the Set before converting to Seq - val entities: Seq[FeatureStoreV1CandidateEntity[Query, Candidate, _ <: EntityId]] = - features.map(_.entity).toSeq - - val featureStoreRequests = candidates.map { candidate => - val candidateEntityIds: Seq[EntityWithId[_ <: EntityId]] = - entities.map(_.entityWithId(query, candidate.candidate, candidate.features)) - - FeatureStoreRequest(entityIds = candidateEntityIds) - } - - val featureMaps = client(featureStoreRequests, query).map { predictionRecords => - if (predictionRecords.size == candidates.size) - predictionRecords - .zip(candidates).map { - case (predictionRecord, candidate) => - val datasetErrors = predictionRecord.getDatasetHydrationErrors - val errorMap = - FeatureStoreDatasetErrorHandler.featureToHydrationErrors( - datasetToFeatures, - datasetErrors) - - if (errorMap.nonEmpty) { - logger.debug(() => - s"$identifier hydration errors for candidate ${candidate.candidate.id}: $errorMap") - } - val dataRecord = - new SRichDataRecord( - dataRecordAdapter.adaptToDataRecord(predictionRecord), - featureContext) - val featureStoreResponse = - FeatureStoreV1Response(dataRecord, errorMap) - FeatureMapBuilder() - .add(FeatureStoreV1ResponseFeature, featureStoreResponse).build() - } - else - // Should not happen as FSv1 is guaranteed to return a prediction record per feature store request - throw PipelineFailure( - FeatureHydrationFailed, - "Unexpected response length from Feature Store V1 while hydrating candidate features") - } - - Stitch.callFuture(featureMaps) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala deleted file mode 100644 index 70bcc15cf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1DynamicClientBuilder.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1 - -import com.twitter.ml.featurestore.lib.dynamic.BaseDynamicHydrationConfig -import com.twitter.ml.featurestore.lib.dynamic.BaseGatedFeatures -import com.twitter.ml.featurestore.lib.dynamic.DynamicFeatureStoreClient -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait FeatureStoreV1DynamicClientBuilder { - def build[Query <: PipelineQuery]( - dynamicHydrationConfig: BaseDynamicHydrationConfig[Query, _ <: BaseGatedFeatures[Query]] - ): DynamicFeatureStoreClient[Query] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala deleted file mode 100644 index e740628fd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1HydrationConfig.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1 - -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.dynamic.BaseDynamicHydrationConfig -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1CandidateFeature -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -case class FeatureStoreV1QueryFeatureHydrationConfig[Query <: PipelineQuery]( - features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]]) - extends BaseDynamicHydrationConfig[ - Query, - BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _] - ](features) - -case class FeatureStoreV1CandidateFeatureHydrationConfig[ - Query <: PipelineQuery, - Input <: UniversalNoun[Any] -]( - features: Set[BaseFeatureStoreV1CandidateFeature[Query, Input, _ <: EntityId, _]]) - extends BaseDynamicHydrationConfig[ - Query, - BaseFeatureStoreV1CandidateFeature[Query, Input, _ <: EntityId, _] - ](features) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala deleted file mode 100644 index 143801e6f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1/FeatureStoreV1QueryFeatureHydrator.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1 - -import com.twitter.ml.api.util.SRichDataRecord -import com.twitter.ml.featurestore.lib.EntityId -import com.twitter.ml.featurestore.lib.data.PredictionRecordAdapter -import com.twitter.ml.featurestore.lib.entity.EntityWithId -import com.twitter.ml.featurestore.lib.online.FeatureStoreRequest -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.feature.featurestorev1.BaseFeatureStoreV1QueryFeature -import com.twitter.product_mixer.core.feature.featurestorev1.FeatureStoreV1QueryEntity -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1Response -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.FeatureHydrationFailed -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch -import com.twitter.util.logging.Logging - -trait FeatureStoreV1QueryFeatureHydrator[Query <: PipelineQuery] - extends BaseQueryFeatureHydrator[ - Query, - BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _] - ] - with Logging { - - def features: Set[BaseFeatureStoreV1QueryFeature[Query, _ <: EntityId, _]] - - def clientBuilder: FeatureStoreV1DynamicClientBuilder - - private lazy val hydrationConfig = FeatureStoreV1QueryFeatureHydrationConfig(features) - - private lazy val client = clientBuilder.build(hydrationConfig) - - private lazy val datasetToFeatures = - FeatureStoreDatasetErrorHandler.datasetToFeaturesMapping(features) - - private lazy val dataRecordAdapter = - PredictionRecordAdapter.oneToOne(hydrationConfig.allBoundFeatures) - - private lazy val featureContext = hydrationConfig.allBoundFeatures.toFeatureContext - - override def hydrate( - query: Query - ): Stitch[FeatureMap] = { - // Duplicate entities are expected across features, so de-dupe via the Set before converting to Seq - val entities: Seq[FeatureStoreV1QueryEntity[Query, _ <: EntityId]] = - features.map(_.entity).toSeq - val entityIds: Seq[EntityWithId[_ <: EntityId]] = entities.map(_.entityWithId(query)) - - val featureStoreRequest = Seq(FeatureStoreRequest(entityIds = entityIds)) - - val featureMap = client(featureStoreRequest, query).map { predictionRecords => - // Should not happen as FSv1 is guaranteed to return a prediction record per feature store request - val predictionRecord = predictionRecords.headOption.getOrElse { - throw PipelineFailure( - FeatureHydrationFailed, - "Unexpected empty response from Feature Store V1 while hydrating query features") - } - - val datasetErrors = predictionRecord.getDatasetHydrationErrors - val errorMap = - FeatureStoreDatasetErrorHandler.featureToHydrationErrors(datasetToFeatures, datasetErrors) - - if (errorMap.nonEmpty) { - logger.debug(() => s"$identifier hydration errors for query: $errorMap") - } - - val richDataRecord = - SRichDataRecord(dataRecordAdapter.adaptToDataRecord(predictionRecord), featureContext) - val featureStoreResponse = - FeatureStoreV1Response(richDataRecord, errorMap) - FeatureMapBuilder().add(FeatureStoreV1ResponseFeature, featureStoreResponse).build() - } - - Stitch.callFuture(featureMap) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD deleted file mode 100644 index e3e7cf018..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala deleted file mode 100644 index 7cf225838..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/Filter.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.filter - -import com.twitter.product_mixer.core.functional_component.filter.Filter.SupportsConditionally -import com.twitter.product_mixer.core.model.common -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** - * Takes a sequence of candidates and can filter some out - * - * @note if you want to conditionally run a [[Filter]] you can use the mixin [[Filter.Conditionally]] - * or to gate on a [[com.twitter.timelines.configapi.Param]] you can use [[com.twitter.product_mixer.component_library.filter.ParamGatedFilter]] - * - * @tparam Query The domain model for the query or request - * @tparam Candidate The type of the candidates - */ -trait Filter[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends Component - with SupportsConditionally[Query, Candidate] { - - /** @see [[FilterIdentifier]] */ - override val identifier: FilterIdentifier - - /** - * Filter the list of candidates - * - * @return a FilterResult including both the list of kept candidate and the list of removed candidates - */ - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[FilterResult[Candidate]] -} - -object Filter { - - /** - * Mixin for when you want to conditionally run a [[Filter]] - * - * This is a thin wrapper around [[common.Conditionally]] exposing a nicer API for the [[Filter]] specific use-case. - */ - trait Conditionally[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends common.Conditionally[Input[Query, Candidate]] { _: Filter[Query, Candidate] => - - /** @see [[common.Conditionally.onlyIf]] */ - def onlyIf( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Boolean - - override final def onlyIf(input: Input[Query, Candidate]): Boolean = - onlyIf(input.query, input.candidates) - } - - /** Type alias to obscure [[Filter.Input]] from customers */ - type SupportsConditionally[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] = - common.SupportsConditionally[Input[Query, Candidate]] - - /** A case class representing the input arguments to a [[Filter]], mostly for internal use */ - case class Input[+Query <: PipelineQuery, +Candidate <: UniversalNoun[Any]]( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala deleted file mode 100644 index 436127381..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter/FilterResult.scala +++ /dev/null @@ -1,4 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.filter - -/** `Candidate`s were `kept` and `removed` by a [[Filter]] */ -case class FilterResult[+Candidate](kept: Seq[Candidate], removed: Seq[Candidate]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD deleted file mode 100644 index 73d60be75..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala deleted file mode 100644 index 691f30c19..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/Gate.scala +++ /dev/null @@ -1,127 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate.SkippedResult -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.CandidatePipelineResults -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch - -/** - * A gate controls if a pipeline or other component is executed - * - * A gate is mostly controlled by it's `shouldContinue` function - when this function - * returns true, execution Continues. - * - * Gates also have a optional `shouldSkip`- When it returns - * true, then we Continue without executing `main`. - * - * @tparam Query The query type that the gate will receive as input - * - * @return A GateResult includes both the boolean `continue` and a specific reason. See [[GateResult]] for more - * information. - */ - -sealed trait BaseGate[-Query <: PipelineQuery] extends Component { - override val identifier: GateIdentifier - - /** - * If a shouldSkip returns true, the gate returns a Skip(continue=true) without executing - * the main predicate. We expect this to be useful for debugging, dogfooding, etc. - */ - def shouldSkip(query: Query): Stitch[Boolean] = Stitch.False - - /** - * The main predicate that controls this gate. If this predicate returns true, the gate returns Continue. - */ - def shouldContinue(query: Query): Stitch[Boolean] - - /** returns a [[GateResult]] to determine whether a pipeline should be executed based on `t` */ - final def apply(t: Query): Stitch[GateResult] = { - shouldSkip(t).flatMap { skipResult => - if (skipResult) { - SkippedResult - } else { - shouldContinue(t).map { mainResult => - if (mainResult) GateResult.Continue else GateResult.Stop - } - } - } - } - - /** Arrow representation of `this` [[Gate]] */ - final def arrow: Arrow[Query, GateResult] = Arrow(apply) -} - -/** - * A regular Gate which only has access to the Query typed PipelineQuery. This can be used anywhere - * Gates are available. - * - * A gate is mostly controlled by it's `shouldContinue` function - when this function - * returns true, execution Continues. - * - * Gates also have a optional `shouldSkip`- When it returns - * true, then we Continue without executing `main`. - * @tparam Query The query type that the gate will receive as input - * - * @return A GateResult includes both the boolean `continue` and a specific reason. See [[GateResult]] for more - * information. - */ -trait Gate[-Query <: PipelineQuery] extends BaseGate[Query] - -/** - * A Query And Candidate Gate which only has access both to the Query typed PipelineQuery and the - * list of previously fetched candidates. This can be used on dependent candidate pipelines to - * make a decision on whether to enable/disable them based on previous candidates. - * - * A gate is mostly controlled by it's `shouldContinue` function - when this function - * returns true, execution Continues. - * - * Gates also have a optional `shouldSkip`- When it returns - * true, then we Continue without executing `main`. - * - * @tparam Query The query type that the gate will receive as input - * - * @return A GateResult includes both the boolean `continue` and a specific reason. See [[GateResult]] for more - * information. - */ -trait QueryAndCandidateGate[-Query <: PipelineQuery] extends BaseGate[Query] { - - /** - * If a shouldSkip returns true, the gate returns a Skip(continue=true) without executing - * the main predicate. We expect this to be useful for debugging, dogfooding, etc. - */ - def shouldSkip(query: Query, candidates: Seq[CandidateWithDetails]): Stitch[Boolean] = - Stitch.False - - /** - * The main predicate that controls this gate. If this predicate returns true, the gate returns Continue. - */ - def shouldContinue(query: Query, candidates: Seq[CandidateWithDetails]): Stitch[Boolean] - - final override def shouldSkip(query: Query): Stitch[Boolean] = { - val candidates = query.features - .map(_.get(CandidatePipelineResults)).getOrElse( - throw PipelineFailure( - IllegalStateFailure, - "Candidate Pipeline Results Feature missing from query features")) - shouldSkip(query, candidates) - } - - final override def shouldContinue(query: Query): Stitch[Boolean] = { - val candidates = query.features - .map(_.get(CandidatePipelineResults)).getOrElse( - throw PipelineFailure( - IllegalStateFailure, - "Candidate Pipeline Results Feature missing from query features")) - shouldContinue(query, candidates) - } -} - -object Gate { - val SkippedResult: Stitch[GateResult] = Stitch.value(GateResult.Skipped) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala deleted file mode 100644 index 8d7b9165c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/GateResult.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.gate - -/** - * A [[Gate]] controls if a pipeline or other component is executed. - * - * Application logic should usually use `GateResult.continue: Boolean` to interpret a GateResult. `continue` will be - * true if we should continue with execution, and false if we should stop. - * - * You can case match against the `GateResult` to understand how exactly execution happened. See `object GateResult` - * below, but this is useful if you want to know if we are continuing due to the skip or main predicates. - */ -sealed trait GateResult { - - /** Should we continue? */ - val continue: Boolean -} - -object GateResult { - - /** - * Continue Execution - * - * the Skip predicate evaluated to true, - * so we Skipped execution of the Main predicate and should continue - */ - case object Skipped extends GateResult { - override val continue = true - } - - /** - * Continue Execution - * - * the main predicate evaluated to true - */ - case object Continue extends GateResult { - override val continue = true - } - - /** - * Stop execution - * - * the main predicate evaluated to false - */ - case object Stop extends GateResult { - override val continue = false - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala deleted file mode 100644 index c5a09d88c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate/ShouldContinue.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.gate - -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait ShouldContinue[Query <: PipelineQuery] { - def apply(query: Query): Boolean -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD deleted file mode 100644 index 8590c0c97..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala deleted file mode 100644 index 0617d5733..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/TransportMarshaller.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling - -object TransportMarshaller { - - /** Avoid `malformed class name` exceptions due to the presence of the `$` character */ - def getSimpleName[T](c: Class[T]): String = { - c.getName.lastIndexOf("$") match { - case -1 => c.getSimpleName - case index => c.getName.substring(index + 1) - } - } -} - -/** - * Marshals a [[MarshallerInput]] into a type that can be sent over the wire - * - * This transformation should be mechanical and not contain business logic - * - * @note this is different from `com.twitter.product_mixer.core.functional_component.premarshaller` - * which can contain business logic. - */ -trait TransportMarshaller[-MarshallerInput <: HasMarshalling, +MarshallerOutput] extends Component { - - override val identifier: TransportMarshallerIdentifier - - def apply(input: MarshallerInput): MarshallerOutput -} - -/** - * No op marshalling that passes through a [[HasMarshalling]] into any type. This is useful if - * the response does not need to be sent over the wire, such as with a - * [[com.twitter.product_mixer.core.functional_component.candidate_source.product_pipeline.ProductPipelineCandidateSource]] - */ -object NoOpTransportMarshaller extends TransportMarshaller[HasMarshalling, Any] { - override val identifier: TransportMarshallerIdentifier = TransportMarshallerIdentifier("NoOp") - - override def apply(input: HasMarshalling): Any = input -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD deleted file mode 100644 index 7ebb59e7f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala deleted file mode 100644 index 6e3b91046..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextMarshaller.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.request - -import com.twitter.product_mixer.core.model.marshalling.request.ClientContext -import com.twitter.product_mixer.core.{thriftscala => t} - -object ClientContextMarshaller { - - def apply(clientContext: ClientContext): t.ClientContext = { - t.ClientContext( - userId = clientContext.userId, - guestId = clientContext.guestId, - appId = clientContext.appId, - ipAddress = clientContext.ipAddress, - userAgent = clientContext.userAgent, - countryCode = clientContext.countryCode, - languageCode = clientContext.languageCode, - isTwoffice = clientContext.isTwoffice, - userRoles = clientContext.userRoles, - deviceId = clientContext.deviceId, - mobileDeviceId = clientContext.mobileDeviceId, - mobileDeviceAdId = clientContext.mobileDeviceAdId, - limitAdTracking = clientContext.limitAdTracking, - guestIdAds = clientContext.guestIdAds, - guestIdMarketing = clientContext.guestIdMarketing - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala deleted file mode 100644 index 4bc48485a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/ClientContextUnmarshaller.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.request - -import com.twitter.product_mixer.core.model.marshalling.request.ClientContext -import com.twitter.product_mixer.core.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ClientContextUnmarshaller @Inject() () { - - def apply(clientContext: t.ClientContext): ClientContext = { - ClientContext( - userId = clientContext.userId, - guestId = clientContext.guestId, - guestIdAds = clientContext.guestIdAds, - guestIdMarketing = clientContext.guestIdMarketing, - appId = clientContext.appId, - ipAddress = clientContext.ipAddress, - userAgent = clientContext.userAgent, - countryCode = clientContext.countryCode, - languageCode = clientContext.languageCode, - isTwoffice = clientContext.isTwoffice, - userRoles = clientContext.userRoles.map(_.toSet), - deviceId = clientContext.deviceId, - mobileDeviceId = clientContext.mobileDeviceId, - mobileDeviceAdId = clientContext.mobileDeviceAdId, - limitAdTracking = clientContext.limitAdTracking - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala deleted file mode 100644 index b693e2060..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/request/FeatureValueUnmarshaller.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.request - -import com.twitter.product_mixer.core.{thriftscala => t} -import com.twitter.timelines.configapi.BooleanFeatureValue -import com.twitter.timelines.configapi.FeatureValue -import com.twitter.timelines.configapi.NumberFeatureValue -import com.twitter.timelines.configapi.StringFeatureValue -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FeatureValueUnmarshaller @Inject() () { - - def apply(featureValue: t.FeatureValue): FeatureValue = featureValue match { - case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.BoolValue(bool)) => - BooleanFeatureValue(bool) - case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.StrValue(string)) => - StringFeatureValue(string) - case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.IntValue(int)) => - NumberFeatureValue(int) - case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.LongValue(long)) => - NumberFeatureValue(long) - case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.DoubleValue(double)) => - NumberFeatureValue(double) - case t.FeatureValue.PrimitiveValue(t.PrimitiveFeatureValue.UnknownUnionField(field)) => - throw new UnsupportedOperationException( - s"Unknown feature value primitive: ${field.field.name}") - case t.FeatureValue.UnknownUnionField(field) => - throw new UnsupportedOperationException(s"Unknown feature value: ${field.field.name}") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD deleted file mode 100644 index f340ee389..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala deleted file mode 100644 index e65247485..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/ContextualTweetRefMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref - -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.ContextualTweetRef -import com.twitter.strato.graphql.contextual_refs.{thriftscala => thrift} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ContextualTweetRefMarshaller @Inject() ( - tweetHydrationContextMarshaller: TweetHydrationContextMarshaller) { - - def apply(contextualTweetRef: ContextualTweetRef): thrift.ContextualTweetRef = - thrift.ContextualTweetRef( - id = contextualTweetRef.id, - hydrationContext = - contextualTweetRef.hydrationContext.map(tweetHydrationContextMarshaller(_))) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala deleted file mode 100644 index 35ba7bfa3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/OuterTweetContextMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref - -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.OuterTweetContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.QuoteTweetId -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.RetweetId -import com.twitter.strato.graphql.contextual_refs.{thriftscala => thrift} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class OuterTweetContextMarshaller @Inject() () { - - def apply(outerTweetContext: OuterTweetContext): thrift.OuterTweetContext = - outerTweetContext match { - case QuoteTweetId(id) => thrift.OuterTweetContext.QuoteTweetId(id) - case RetweetId(id) => thrift.OuterTweetContext.RetweetId(id) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala deleted file mode 100644 index a2bd6d82c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref/TweetHydrationContextMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref - -import com.twitter.product_mixer.core.functional_component.marshaller.response.rtf.safety_level.SafetyLevelMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.TweetHydrationContext -import com.twitter.strato.graphql.contextual_refs.{thriftscala => thrift} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetHydrationContextMarshaller @Inject() ( - safetyLevelMarshaller: SafetyLevelMarshaller, - outerTweetContextMarshaller: OuterTweetContextMarshaller) { - - def apply(tweetHydrationContext: TweetHydrationContext): thrift.TweetHydrationContext = - thrift.TweetHydrationContext( - safetyLevelOverride = tweetHydrationContext.safetyLevelOverride.map(safetyLevelMarshaller(_)), - outerTweetContext = - tweetHydrationContext.outerTweetContext.map(outerTweetContextMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD deleted file mode 100644 index afdc7e043..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala deleted file mode 100644 index c2283082a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/rtf/safety_level/SafetyLevelMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.rtf.safety_level - -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.ConversationFocalTweetSafetyLevel -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.ConversationInjectedTweetSafetyLevel -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.ConversationReplySafetyLevel -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.SafetyLevel -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.TimelineFocalTweetSafetyLevel -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.TimelineHomePromotedHydrationSafetyLevel -import com.twitter.spam.rtf.{thriftscala => thrift} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SafetyLevelMarshaller @Inject() () { - - def apply(safetyLevel: SafetyLevel): thrift.SafetyLevel = safetyLevel match { - case ConversationFocalTweetSafetyLevel => thrift.SafetyLevel.ConversationFocalTweet - case ConversationReplySafetyLevel => thrift.SafetyLevel.ConversationReply - case ConversationInjectedTweetSafetyLevel => thrift.SafetyLevel.ConversationInjectedTweet - case TimelineFocalTweetSafetyLevel => thrift.SafetyLevel.TimelineFocalTweet - case TimelineHomePromotedHydrationSafetyLevel => - thrift.SafetyLevel.TimelineHomePromotedHydration - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD deleted file mode 100644 index 98699bf17..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/thrift/com/twitter/product_mixer/component_library:thrift-scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - "strato/config/src/thrift/com/twitter/strato/graphql:api-media-graphql-scala", - "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala", - "strato/config/src/thrift/com/twitter/strato/graphql:topics-graphql-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala deleted file mode 100644 index 50351870f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/CursorTypeMarshaller.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.slice - -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.product_mixer.component_library.{thriftscala => t} -import com.twitter.product_mixer.core.model.marshalling.response.slice.NextCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.PreviousCursor -import com.twitter.product_mixer.core.model.marshalling.response.slice.CursorType -import com.twitter.product_mixer.core.model.marshalling.response.slice.GapCursor - -@Singleton -class CursorTypeMarshaller @Inject() () { - - def apply(cursorType: CursorType): t.CursorType = cursorType match { - case NextCursor => t.CursorType.Next - case PreviousCursor => t.CursorType.Previous - case GapCursor => t.CursorType.Gap - } - - def unmarshall(cursorType: t.CursorType): CursorType = cursorType match { - case t.CursorType.Next => NextCursor - case t.CursorType.Previous => PreviousCursor - case t.CursorType.Gap => GapCursor - case t.CursorType.EnumUnknownCursorType(id) => - throw new UnsupportedOperationException( - s"Attempted to unmarshall unrecognized cursor type: $id") - } - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala deleted file mode 100644 index e3b1561c1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceItemMarshaller.scala +++ /dev/null @@ -1,147 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.slice - -import com.twitter.product_mixer.core.model.marshalling.response.slice.AdType -import com.twitter.product_mixer.core.model.marshalling.response.slice -import com.twitter.strato.graphql.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SliceItemMarshaller @Inject() () { - def apply(item: slice.SliceItem): t.SliceItem = { - item match { - case item: slice.TweetItem => - t.SliceItem.TweetItem(t.TweetItem(id = item.id)) - case item: slice.UserItem => - t.SliceItem.UserItem(t.UserItem(id = item.id)) - case item: slice.TwitterListItem => - t.SliceItem.TwitterListItem(t.TwitterListItem(id = item.id)) - case item: slice.DMConvoSearchItem => - t.SliceItem.DmConvoSearchItem(t.DMConvoSearchItem(id = item.id)) - case item: slice.DMConvoItem => - t.SliceItem.DmConvoItem(t.DMConvoItem(id = item.id)) - case item: slice.DMEventItem => - t.SliceItem.DmEventItem(t.DMEventItem(id = item.id)) - case item: slice.DMMessageSearchItem => - t.SliceItem.DmMessageSearchItem(t.DMMessageSearchItem(id = item.id)) - case item: slice.TopicItem => - t.SliceItem.TopicItem(t.TopicItem(id = item.id.toString)) - case item: slice.TypeaheadEventItem => - t.SliceItem.TypeaheadEventItem( - t.TypeaheadEventItem( - eventId = item.eventId, - metadata = item.metadata.map(marshalTypeaheadMetadata) - ) - ) - case item: slice.TypeaheadQuerySuggestionItem => - t.SliceItem.TypeaheadQuerySuggestionItem( - t.TypeaheadQuerySuggestionItem( - query = item.query, - metadata = item.metadata.map(marshalTypeaheadMetadata) - ) - ) - case item: slice.TypeaheadUserItem => - t.SliceItem.TypeaheadUserItem( - t.TypeaheadUserItem( - userId = item.userId, - metadata = item.metadata.map(marshalTypeaheadMetadata), - badges = Some(item.badges.map { badge => - t.UserBadge( - badgeUrl = badge.badgeUrl, - description = Some(badge.description), - badgeType = Some(badge.badgeType)) - }) - ) - ) - case item: slice.AdItem => - t.SliceItem.AdItem( - t.AdItem( - adKey = t.AdKey( - adAccountId = item.adAccountId, - adUnitId = item.adUnitId, - ) - ) - ) - case item: slice.AdCreativeItem => - t.SliceItem.AdCreativeItem( - t.AdCreativeItem( - adCreativeKey = t.AdCreativeKey( - adAccountId = item.adAccountId, - adType = marshalAdType(item.adType), - creativeId = item.creativeId - ) - ) - ) - case item: slice.AdGroupItem => - t.SliceItem.AdGroupItem( - t.AdGroupItem( - adGroupKey = t.AdGroupKey( - adAccountId = item.adAccountId, - adGroupId = item.adGroupId - ) - ) - ) - case item: slice.CampaignItem => - t.SliceItem.CampaignItem( - t.CampaignItem( - campaignKey = t.CampaignKey( - adAccountId = item.adAccountId, - campaignId = item.campaignId - ) - ) - ) - case item: slice.FundingSourceItem => - t.SliceItem.FundingSourceItem( - t.FundingSourceItem( - fundingSourceKey = t.FundingSourceKey( - adAccountId = item.adAccountId, - fundingSourceId = item.fundingSourceId - ) - ) - ) - } - } - - private def marshalTypeaheadMetadata(metadata: slice.TypeaheadMetadata) = { - t.TypeaheadMetadata( - score = metadata.score, - source = metadata.source, - resultContext = metadata.context.map(context => - t.TypeaheadResultContext( - displayString = context.displayString, - contextType = marshalRequestContextType(context.contextType), - iconUrl = context.iconUrl - )) - ) - } - - private def marshalRequestContextType( - context: slice.TypeaheadResultContextType - ): t.TypeaheadResultContextType = { - context match { - case slice.You => t.TypeaheadResultContextType.You - case slice.Location => t.TypeaheadResultContextType.Location - case slice.NumFollowers => t.TypeaheadResultContextType.NumFollowers - case slice.FollowRelationship => t.TypeaheadResultContextType.FollowRelationship - case slice.Bio => t.TypeaheadResultContextType.Bio - case slice.NumTweets => t.TypeaheadResultContextType.NumTweets - case slice.Trending => t.TypeaheadResultContextType.Trending - case slice.HighlightedLabel => t.TypeaheadResultContextType.HighlightedLabel - case _ => t.TypeaheadResultContextType.Undefined - } - } - - private def marshalAdType( - adType: AdType - ): t.AdType = { - adType match { - case AdType.Tweet => t.AdType.Tweet - case AdType.Account => t.AdType.Account - case AdType.InStreamVideo => t.AdType.InStreamVideo - case AdType.DisplayCreative => t.AdType.DisplayCreative - case AdType.Trend => t.AdType.Trend - case AdType.Spotlight => t.AdType.Spotlight - case AdType.Takeover => t.AdType.Takeover - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala deleted file mode 100644 index a59102940..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/slice/SliceTransportMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.slice - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.slice.Slice -import com.twitter.strato.graphql.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SliceTransportMarshaller @Inject() (sliceItemMarshaller: SliceItemMarshaller) - extends TransportMarshaller[Slice, t.SliceResult] { - - override val identifier: TransportMarshallerIdentifier = TransportMarshallerIdentifier("Slice") - - override def apply(slice: Slice): t.SliceResult = { - t.SliceResult.Slice( - t.Slice( - items = slice.items.map(sliceItemMarshaller(_)), - sliceInfo = t.SliceInfo( - previousCursor = slice.sliceInfo.previousCursor, - nextCursor = slice.sliceInfo.nextCursor - ) - )) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD deleted file mode 100644 index 214dfdda1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - "src/thrift/com/twitter/pages/render:thrift-scala", - "strato/config/src/thrift/com/twitter/strato/graphql/timelines:graphql-timelines-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - "src/thrift/com/twitter/pages/render:thrift-scala", - "strato/config/src/thrift/com/twitter/strato/graphql/timelines:graphql-timelines-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala deleted file mode 100644 index ecd8386b0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageBodyMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageBody -import com.twitter.product_mixer.core.model.marshalling.response.urp.SegmentedTimelinesPageBody -import com.twitter.product_mixer.core.model.marshalling.response.urp.TimelineKeyPageBody -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PageBodyMarshaller @Inject() ( - timelineKeyMarshaller: TimelineKeyMarshaller, - segmentedTimelinesMarshaller: SegmentedTimelinesMarshaller) { - - def apply(pageBody: PageBody): urp.PageBody = pageBody match { - case pageBody: TimelineKeyPageBody => - urp.PageBody.Timeline(timelineKeyMarshaller(pageBody.timeline)) - case pageBody: SegmentedTimelinesPageBody => - urp.PageBody.SegmentedTimelines(segmentedTimelinesMarshaller(pageBody)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala deleted file mode 100644 index 656c1f165..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageHeaderMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageHeader -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeader -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PageHeaderMarshaller @Inject() ( - topicPageHeaderMarshaller: TopicPageHeaderMarshaller) { - - def apply(pageHeader: PageHeader): urp.PageHeader = pageHeader match { - case pageHeader: TopicPageHeader => - urp.PageHeader.TopicPageHeader(topicPageHeaderMarshaller(pageHeader)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala deleted file mode 100644 index da03466bf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/PageNavBarMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.model.marshalling.response.urp.PageNavBar -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageNavBar -import com.twitter.product_mixer.core.model.marshalling.response.urp.TitleNavBar -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PageNavBarMarshaller @Inject() ( - topicPageNavBarMarshaller: TopicPageNavBarMarshaller, - titleNavBarMarshaller: TitleNavBarMarshaller) { - - def apply(pageNavBar: PageNavBar): urp.PageNavBar = pageNavBar match { - case pageNavBar: TopicPageNavBar => - urp.PageNavBar.TopicPageNavBar(topicPageNavBarMarshaller(pageNavBar)) - case pageNavBar: TitleNavBar => - urp.PageNavBar.TitleNavBar(titleNavBarMarshaller(pageNavBar)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala deleted file mode 100644 index 1d2bdc504..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelineMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.TimelineScribeConfigMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urp.SegmentedTimeline -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SegmentedTimelineMarshaller @Inject() ( - timelineKeyMarshaller: TimelineKeyMarshaller, - timelineScribeConfigMarshaller: TimelineScribeConfigMarshaller) { - - def apply(segmentedTimeline: SegmentedTimeline): urp.SegmentedTimeline = urp.SegmentedTimeline( - id = segmentedTimeline.id, - labelText = segmentedTimeline.labelText, - timeline = timelineKeyMarshaller(segmentedTimeline.timeline), - scribeConfig = segmentedTimeline.scribeConfig.map(timelineScribeConfigMarshaller(_)), - refreshIntervalSec = segmentedTimeline.refreshIntervalSec - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala deleted file mode 100644 index a05e0037f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/SegmentedTimelinesMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.model.marshalling.response.urp.SegmentedTimelinesPageBody -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SegmentedTimelinesMarshaller @Inject() ( - segmentedTimelineMarshaller: SegmentedTimelineMarshaller) { - - def apply(segmentedTimelinesPageBody: SegmentedTimelinesPageBody): urp.SegmentedTimelines = - urp.SegmentedTimelines( - initialTimeline = segmentedTimelineMarshaller(segmentedTimelinesPageBody.initialTimeline), - timelines = segmentedTimelinesPageBody.timelines.map(segmentedTimelineMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala deleted file mode 100644 index 91936e4d0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TimelineKeyMarshaller.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.product_mixer.core.model.marshalling.response.urp.FollowedTopicsMeTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.FollowedTopicsOtherTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.ForYouExploreMixerTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NoteworthyAccountsTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NotInterestedTopicsMeTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxForYouCategoryUserRecommendationsTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxGeoCategoryUserRecommendationsTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxPymkCategoryUserRecommendationsTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxSingleInterestCategoryUserRecommendationsTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.NuxUserRecommendationsTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.ShoppingHomeTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.TimelineKey -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicsLandingTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicsPickerTimeline -import com.twitter.product_mixer.core.model.marshalling.response.urp.TrendingExploreMixerTimeline -import com.twitter.strato.graphql.timelines.{thriftscala => graphql} -import javax.inject.Singleton - -@Singleton -class TimelineKeyMarshaller { - - def apply(timelineKey: TimelineKey): graphql.TimelineKey = timelineKey match { - case TopicsLandingTimeline(topicId) => - graphql.TimelineKey.TopicTimeline(graphql.TopicId(topicId)) - case NoteworthyAccountsTimeline(topicId) => - graphql.TimelineKey.NoteworthyAccountsTimeline(graphql.TopicId(topicId)) - case TopicsPickerTimeline(topicId) => - graphql.TimelineKey.TopicsPickerTimeline(graphql.TopicId(topicId)) - case FollowedTopicsMeTimeline() => - graphql.TimelineKey.FollowedTopicsMeTimeline(graphql.Void()) - case NotInterestedTopicsMeTimeline() => - graphql.TimelineKey.NotInterestedTopicsMeTimeline(graphql.Void()) - case FollowedTopicsOtherTimeline(userId) => - graphql.TimelineKey.FollowedTopicsOtherTimeline(userId) - case NuxUserRecommendationsTimeline() => - graphql.TimelineKey.NuxUserRecommendationsTimeline(graphql.Void()) - case NuxForYouCategoryUserRecommendationsTimeline() => - graphql.TimelineKey.NuxForYouCategoryUserRecommendationsTimeline(graphql.Void()) - case NuxPymkCategoryUserRecommendationsTimeline() => - graphql.TimelineKey.NuxPymkCategoryUserRecommendationsTimeline(graphql.Void()) - case NuxGeoCategoryUserRecommendationsTimeline() => - graphql.TimelineKey.NuxGeoCategoryUserRecommendationsTimeline(graphql.Void()) - case NuxSingleInterestCategoryUserRecommendationsTimeline(topicId) => - graphql.TimelineKey.NuxSingleInterestCategoryUserRecommendationsTimeline( - graphql.TopicId(topicId)) - case ShoppingHomeTimeline() => graphql.TimelineKey.ShoppingHome(graphql.Void()) - case ForYouExploreMixerTimeline() => - graphql.TimelineKey.ForYouExploreMixerTimeline(graphql.Void()) - case TrendingExploreMixerTimeline() => - graphql.TimelineKey.TrendingExploreMixerTimeline(graphql.Void()) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala deleted file mode 100644 index 446771772..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TitleNavBarMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urp.TitleNavBar -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TitleNavBarMarshaller @Inject() ( - clientEventInfoMarshaller: ClientEventInfoMarshaller) { - - def apply(titleNavBar: TitleNavBar): urp.TitleNavBar = - urp.TitleNavBar( - title = titleNavBar.title, - subtitle = titleNavBar.subtitle, - clientEventInfo = titleNavBar.clientEventInfo.map(clientEventInfoMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala deleted file mode 100644 index 9644ee6d4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderDisplayTypeMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.product_mixer.core.model.marshalling.response.urp.BasicTopicPageHeaderDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urp.PersonalizedTopicPageHeaderDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeaderDisplayType -import com.twitter.pages.render.{thriftscala => urp} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicPageHeaderDisplayTypeMarshaller @Inject() () { - - def apply( - topicPageHeaderDisplayType: TopicPageHeaderDisplayType - ): urp.TopicPageHeaderDisplayType = topicPageHeaderDisplayType match { - case BasicTopicPageHeaderDisplayType => urp.TopicPageHeaderDisplayType.Basic - case PersonalizedTopicPageHeaderDisplayType => urp.TopicPageHeaderDisplayType.Personalized - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala deleted file mode 100644 index d15585bdd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderFacepileMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeaderFacepile -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicPageHeaderFacepileMarshaller @Inject() ( - urlMarshaller: UrlMarshaller) { - - def apply(topicPageHeaderFacepile: TopicPageHeaderFacepile): urp.TopicPageHeaderFacepile = - urp.TopicPageHeaderFacepile( - userIds = topicPageHeaderFacepile.userIds, - facepileUrl = topicPageHeaderFacepile.facepileUrl.map(urlMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala deleted file mode 100644 index 44c4fa48a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageHeaderMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageHeader -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicPageHeaderMarshaller @Inject() ( - topicPageHeaderFacepileMarshaller: TopicPageHeaderFacepileMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - topicPageHeaderDisplayTypeMarshaller: TopicPageHeaderDisplayTypeMarshaller) { - - def apply(topicPageHeader: TopicPageHeader): urp.TopicPageHeader = - urp.TopicPageHeader( - topicId = topicPageHeader.topicId, - facepile = topicPageHeader.facepile.map(topicPageHeaderFacepileMarshaller(_)), - clientEventInfo = topicPageHeader.clientEventInfo.map(clientEventInfoMarshaller(_)), - landingContext = topicPageHeader.landingContext, - displayType = topicPageHeader.displayType - .map(topicPageHeaderDisplayTypeMarshaller(_)).getOrElse( - urp.TopicPageHeaderDisplayType.Basic) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala deleted file mode 100644 index 9bf0838e2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/TopicPageNavBarMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urp.TopicPageNavBar -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicPageNavBarMarshaller @Inject() ( - clientEventInfoMarshaller: ClientEventInfoMarshaller) { - - def apply(topicPageNavBar: TopicPageNavBar): urp.TopicPageNavBar = - urp.TopicPageNavBar( - topicId = topicPageNavBar.topicId, - clientEventInfo = topicPageNavBar.clientEventInfo.map(clientEventInfoMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala deleted file mode 100644 index 45f5dd721..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshaller.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.TimelineScribeConfigMarshaller -import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.urp.Page -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UrpTransportMarshaller @Inject() ( - pageBodyMarshaller: PageBodyMarshaller, - timelineScribeConfigMarshaller: TimelineScribeConfigMarshaller, - pageHeaderMarshaller: PageHeaderMarshaller, - pageNavBarMarshaller: PageNavBarMarshaller) - extends TransportMarshaller[Page, urp.Page] { - - override val identifier: TransportMarshallerIdentifier = - TransportMarshallerIdentifier("UnifiedRichPage") - - override def apply(page: Page): urp.Page = urp.Page( - id = page.id, - pageBody = pageBodyMarshaller(page.pageBody), - scribeConfig = page.scribeConfig.map(timelineScribeConfigMarshaller(_)), - pageHeader = page.pageHeader.map(pageHeaderMarshaller(_)), - pageNavBar = page.pageNavBar.map(pageNavBarMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala deleted file mode 100644 index c9f5f597d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp/UrpTransportMarshallerBuilder.scala +++ /dev/null @@ -1,65 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urp - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.TimelineScribeConfigMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ArticleDetailsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventDetailsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CommerceDetailsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ConversationDetailsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ConversationSectionMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.LiveEventDetailsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.TimelinesDetailsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrtEndpointOptionsMarshaller - -object UrpTransportMarshallerBuilder { - // Convenience constructor for services not using dependency injection and unit tests. If using - // dependency injection, instead @Inject an instance of UrpTransportMarshaller to construct. - - val timelineKeyMarshaller = new TimelineKeyMarshaller - val timelineScribeConfigMarshaller = new TimelineScribeConfigMarshaller - val urlMarshaller = new UrlMarshaller(new UrlTypeMarshaller, new UrtEndpointOptionsMarshaller) - val clientEventInfoMarshaller = new ClientEventInfoMarshaller( - new ClientEventDetailsMarshaller( - new ConversationDetailsMarshaller(new ConversationSectionMarshaller), - new TimelinesDetailsMarshaller, - new ArticleDetailsMarshaller, - new LiveEventDetailsMarshaller, - new CommerceDetailsMarshaller) - ) - - val segmentedTimelineMarshaller = - new SegmentedTimelineMarshaller(timelineKeyMarshaller, timelineScribeConfigMarshaller) - val segmentedTimelinesMarshaller = new SegmentedTimelinesMarshaller(segmentedTimelineMarshaller) - - val pageBodyMarshaller: PageBodyMarshaller = new PageBodyMarshaller( - timelineKeyMarshaller, - segmentedTimelinesMarshaller - ) - - val topicPageHeaderFacepileMarshaller = new TopicPageHeaderFacepileMarshaller(urlMarshaller) - val topicPageHeaderDisplayTypeMarshaller = new TopicPageHeaderDisplayTypeMarshaller - val topicPageHeaderMarshaller = new TopicPageHeaderMarshaller( - topicPageHeaderFacepileMarshaller, - clientEventInfoMarshaller, - topicPageHeaderDisplayTypeMarshaller - ) - val pageHeaderMarshaller: PageHeaderMarshaller = new PageHeaderMarshaller( - topicPageHeaderMarshaller) - - val topicPageNavBarMarshaller = new TopicPageNavBarMarshaller(clientEventInfoMarshaller) - val titleNavBarMarshaller = new TitleNavBarMarshaller(clientEventInfoMarshaller) - val pageNavBarMarshaller: PageNavBarMarshaller = new PageNavBarMarshaller( - topicPageNavBarMarshaller, - titleNavBarMarshaller - ) - - val marshaller: UrpTransportMarshaller = - new UrpTransportMarshaller( - pageBodyMarshaller = pageBodyMarshaller, - timelineScribeConfigMarshaller = timelineScribeConfigMarshaller, - pageHeaderMarshaller = pageHeaderMarshaller, - pageNavBarMarshaller = pageNavBarMarshaller - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala deleted file mode 100644 index 6effca5ae..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddEntriesInstructionMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AddEntriesInstructionMarshaller @Inject() ( - timelineEntryMarshaller: TimelineEntryMarshaller) { - - def apply(instruction: AddEntriesTimelineInstruction): urt.AddEntries = urt.AddEntries( - entries = instruction.entries.map(timelineEntryMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala deleted file mode 100644 index ce0c37139..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/AddToModuleInstructionMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddToModuleTimelineInstruction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AddToModuleInstructionMarshaller @Inject() (moduleItemMarshaller: ModuleItemMarshaller) { - - def apply(instruction: AddToModuleTimelineInstruction): urt.AddToModule = urt.AddToModule( - moduleItems = instruction.moduleItems.map(moduleItemMarshaller(_, instruction.moduleEntryId)), - moduleEntryId = instruction.moduleEntryId, - moduleItemEntryId = instruction.moduleItemEntryId, - prepend = instruction.prepend - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD deleted file mode 100644 index c2f8069b6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/BUILD +++ /dev/null @@ -1,40 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/timelines/render:thrift-scala", - "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "src/thrift/com/twitter/spam/rtf:safety-level-scala", - "src/thrift/com/twitter/timelines/render:thrift-scala", - "strato/config/src/thrift/com/twitter/strato/graphql/contextual_refs:graphql-refs-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala deleted file mode 100644 index d7bc4e8d4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/CoverMarshaller.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCover -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCover -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CoverMarshaller @Inject() ( - coverContentMarshaller: CoverContentMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller) { - - def apply(cover: Cover): urt.ShowCover = cover match { - case halfCover: HalfCover => - urt.ShowCover( - cover = coverContentMarshaller(halfCover.content), - clientEventInfo = cover.clientEventInfo.map(clientEventInfoMarshaller(_))) - case fullCover: FullCover => - urt.ShowCover( - cover = coverContentMarshaller(fullCover.content), - clientEventInfo = cover.clientEventInfo.map(clientEventInfoMarshaller(_))) - } -} - -class UnsupportedTimelineCoverException(cover: Cover) - extends UnsupportedOperationException( - "Unsupported timeline cover " + TransportMarshaller.getSimpleName(cover.getClass)) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala deleted file mode 100644 index 4f0e94c44..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/MarkEntriesUnreadInstructionMarshaller.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.MarkEntriesUnreadInstruction -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class MarkEntriesUnreadInstructionMarshaller @Inject() () { - - def apply(instruction: MarkEntriesUnreadInstruction): urt.MarkEntriesUnread = - urt.MarkEntriesUnread(entryIds = instruction.entryIds) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala deleted file mode 100644 index 439ce87da..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleItemMarshaller @Inject() ( - timelineItemMarshaller: TimelineItemMarshaller, - moduleItemTreeDisplayMarshaller: ModuleItemTreeDisplayMarshaller) { - - def apply(moduleItem: ModuleItem, moduleEntryId: String): urt.ModuleItem = urt.ModuleItem( - /* Module items have an identifier comprising both the module entry id and the module item id. - Some URT clients will deduplicate globally across different modules. - Using the entry id as a prefix ensures that deduplication only happens within a single module, - which we believe better aligns with engineers' intentions. */ - entryId = moduleEntryId + "-" + moduleItem.item.entryIdentifier, - item = timelineItemMarshaller(moduleItem.item), - dispensable = moduleItem.dispensable, - treeDisplay = moduleItem.treeDisplay.map(moduleItemTreeDisplayMarshaller.apply) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala deleted file mode 100644 index 26f93db2a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ModuleItemTreeDisplayMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleDisplayTypeMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItemTreeDisplay -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleItemTreeDisplayMarshaller @Inject() ( - moduleDisplayTypeMarshaller: ModuleDisplayTypeMarshaller) { - - def apply(moduleItemTreeDisplay: ModuleItemTreeDisplay): urt.ModuleItemTreeDisplay = - urt.ModuleItemTreeDisplay( - parentModuleItemEntryId = moduleItemTreeDisplay.parentModuleEntryItemId, - indentFromParent = moduleItemTreeDisplay.indentFromParent, - displayType = moduleItemTreeDisplay.displayType.map(moduleDisplayTypeMarshaller(_)), - isAnchorChild = moduleItemTreeDisplay.isAnchorChild - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala deleted file mode 100644 index 62eb202d9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/PinEntryInstructionMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.PinEntryTimelineInstruction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PinEntryInstructionMarshaller @Inject() ( - timelineEntryMarshaller: TimelineEntryMarshaller) { - - def apply(instruction: PinEntryTimelineInstruction): urt.PinEntry = { - urt.PinEntry(entry = timelineEntryMarshaller(instruction.entry)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala deleted file mode 100644 index d0c71e3aa..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReaderModeConfigMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.ReaderModeConfig -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReaderModeConfigMarshaller @Inject() (urlMarshaller: UrlMarshaller) { - - def apply(readerModeConfig: ReaderModeConfig): urt.ReaderModeConfig = urt.ReaderModeConfig( - isReaderModeAvailable = readerModeConfig.isReaderModeAvailable, - landingUrl = urlMarshaller(readerModeConfig.landingUrl) - ) - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala deleted file mode 100644 index 5011721b8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ReplaceEntryInstructionMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.ReplaceEntryTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReplaceEntryInstructionMarshaller @Inject() ( - timelineEntryMarshaller: TimelineEntryMarshaller) { - - def apply(instruction: ReplaceEntryTimelineInstruction): urt.ReplaceEntry = { - val instructionEntry = instruction.entry - urt.ReplaceEntry( - entryIdToReplace = instructionEntry.entryIdToReplace - .getOrElse(throw new MissingEntryToReplaceException(instructionEntry)), - entry = timelineEntryMarshaller(instructionEntry) - ) - } -} - -class MissingEntryToReplaceException(entry: TimelineEntry) - extends IllegalArgumentException( - s"Missing entry ID to replace ${TransportMarshaller.getSimpleName(entry.getClass)}") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala deleted file mode 100644 index 5a5eec0e7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/ShowAlertInstructionMarshaller.scala +++ /dev/null @@ -1,41 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertColorConfigurationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertDisplayLocationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertIconDisplayInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertNavigationMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlertInstruction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ShowAlertInstructionMarshaller @Inject() ( - showAlertTypeMarshaller: ShowAlertTypeMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - richTextMarshaller: RichTextMarshaller, - showAlertIconDisplayInfoMarshaller: ShowAlertIconDisplayInfoMarshaller, - showAlertColorConfigurationMarshaller: ShowAlertColorConfigurationMarshaller, - showAlertDisplayLocationMarshaller: ShowAlertDisplayLocationMarshaller, - showAlertNavigationMetadataMarshaller: ShowAlertNavigationMetadataMarshaller, -) { - - def apply(instruction: ShowAlertInstruction): urt.ShowAlert = urt.ShowAlert( - alertType = showAlertTypeMarshaller(instruction.showAlert.alertType), - triggerDelayMs = instruction.showAlert.triggerDelay.map(_.inMillis.toInt), - displayDurationMs = instruction.showAlert.displayDuration.map(_.inMillis.toInt), - clientEventInfo = instruction.showAlert.clientEventInfo.map(clientEventInfoMarshaller(_)), - collapseDelayMs = instruction.showAlert.collapseDelay.map(_.inMillis.toInt), - userIds = instruction.showAlert.userIds, - richText = instruction.showAlert.richText.map(richTextMarshaller(_)), - iconDisplayInfo = - instruction.showAlert.iconDisplayInfo.map(showAlertIconDisplayInfoMarshaller(_)), - colorConfig = showAlertColorConfigurationMarshaller(instruction.showAlert.colorConfig), - displayLocation = showAlertDisplayLocationMarshaller(instruction.showAlert.displayLocation), - navigationMetadata = - instruction.showAlert.navigationMetadata.map(showAlertNavigationMetadataMarshaller(_)), - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala deleted file mode 100644 index 5fa2a9bab..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TerminateTimelineInstructionMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.BottomTermination -import com.twitter.product_mixer.core.model.marshalling.response.urt.TerminateTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TopTermination -import com.twitter.product_mixer.core.model.marshalling.response.urt.TopAndBottomTermination -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TerminateTimelineInstructionMarshaller @Inject() () { - - def apply(instruction: TerminateTimelineInstruction): urt.TerminateTimeline = - urt.TerminateTimeline( - direction = instruction.terminateTimelineDirection match { - case TopTermination => urt.TimelineTerminationDirection.Top - case BottomTermination => urt.TimelineTerminationDirection.Bottom - case TopAndBottomTermination => urt.TimelineTerminationDirection.TopAndBottom - } - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala deleted file mode 100644 index 2589df862..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryContentMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineEntryContentMarshaller @Inject() ( - timelineItemMarshaller: TimelineItemMarshaller, - timelineModuleMarshaller: TimelineModuleMarshaller, - timelineOperationMarshaller: TimelineOperationMarshaller) { - - def apply(entry: TimelineEntry): urt.TimelineEntryContent = entry match { - case item: TimelineItem => - urt.TimelineEntryContent.Item(timelineItemMarshaller(item)) - case module: TimelineModule => - urt.TimelineEntryContent.TimelineModule(timelineModuleMarshaller(module)) - case operation: TimelineOperation => - urt.TimelineEntryContent.Operation(timelineOperationMarshaller(operation)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala deleted file mode 100644 index 8d937289c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineEntryMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineEntryMarshaller @Inject() ( - timelineEntryContentMarshaller: TimelineEntryContentMarshaller) { - - def apply(entry: TimelineEntry): urt.TimelineEntry = - urt.TimelineEntry( - entryId = entry.entryIdentifier, - sortIndex = entry.sortIndex.getOrElse(throw new TimelineEntryMissingSortIndexException), - content = timelineEntryContentMarshaller(entry), - expiryTime = entry.expirationTimeInMillis - ) -} - -class TimelineEntryMissingSortIndexException - extends UnsupportedOperationException("Timeline entry missing sort index") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala deleted file mode 100644 index e3727dab2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineInstructionMarshaller.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddEntriesTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.AddToModuleTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.ClearCacheTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.MarkEntriesUnreadInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.PinEntryTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.ReplaceEntryTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlertInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowCoverInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TerminateTimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineInstructionMarshaller @Inject() ( - addEntriesInstructionMarshaller: AddEntriesInstructionMarshaller, - addToModuleInstructionMarshaller: AddToModuleInstructionMarshaller, - markEntriesUnreadInstructionMarshaller: MarkEntriesUnreadInstructionMarshaller, - pinEntryInstructionMarshaller: PinEntryInstructionMarshaller, - replaceEntryInstructionMarshaller: ReplaceEntryInstructionMarshaller, - showAlertInstructionMarshaller: ShowAlertInstructionMarshaller, - terminateTimelineInstructionMarshaller: TerminateTimelineInstructionMarshaller, - coverMarshaller: CoverMarshaller) { - - def apply(instruction: TimelineInstruction): urt.TimelineInstruction = instruction match { - case instruction: AddEntriesTimelineInstruction => - urt.TimelineInstruction.AddEntries(addEntriesInstructionMarshaller(instruction)) - case instruction: AddToModuleTimelineInstruction => - urt.TimelineInstruction.AddToModule(addToModuleInstructionMarshaller(instruction)) - case _: ClearCacheTimelineInstruction => - urt.TimelineInstruction.ClearCache(urt.ClearCache()) - case instruction: MarkEntriesUnreadInstruction => - urt.TimelineInstruction.MarkEntriesUnread( - markEntriesUnreadInstructionMarshaller(instruction) - ) - case instruction: PinEntryTimelineInstruction => - urt.TimelineInstruction.PinEntry(pinEntryInstructionMarshaller(instruction)) - case instruction: ReplaceEntryTimelineInstruction => - urt.TimelineInstruction.ReplaceEntry(replaceEntryInstructionMarshaller(instruction)) - case instruction: ShowCoverInstruction => - urt.TimelineInstruction.ShowCover(coverMarshaller(instruction.cover)) - case instruction: ShowAlertInstruction => - urt.TimelineInstruction.ShowAlert(showAlertInstructionMarshaller(instruction)) - case instruction: TerminateTimelineInstruction => - urt.TimelineInstruction.TerminateTimeline(terminateTimelineInstructionMarshaller(instruction)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala deleted file mode 100644 index dee74d6b1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemContentMarshaller.scala +++ /dev/null @@ -1,130 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductGroupItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.audio_space.AudioSpaceItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card.CardItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event.EventSummaryItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.icon_label.IconLabelItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label.LabelItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message.MessagePromptItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.moment.MomentAnnotationItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt.PromptItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.SpellingItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread.ThreadHeaderItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.TileItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFollowPromptItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.trend.TrendItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer.TweetComposerItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list.TwitterListItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorItemMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label.IconLabelItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.label.LabelItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment.MomentAnnotationItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread.ThreadHeaderItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFollowPromptItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.TrendItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineItemContentMarshaller @Inject() ( - articleItemMarshaller: ArticleItemMarshaller, - audioSpaceItemMarshaller: AudioSpaceItemMarshaller, - cardItemMarshaller: CardItemMarshaller, - cursorItemMarshaller: CursorItemMarshaller, - eventSummaryItemMarshaller: EventSummaryItemMarshaller, - iconLabelItemMarshaller: IconLabelItemMarshaller, - labelItemMarshaller: LabelItemMarshaller, - messagePromptItemMarshaller: MessagePromptItemMarshaller, - tileItemMarshaller: TileItemMarshaller, - tombstoneItemMarshaller: TombstoneItemMarshaller, - topicFollowPromptItemMarshaller: TopicFollowPromptItemMarshaller, - topicItemMarshaller: TopicItemMarshaller, - tweetComposerItemMarshaller: TweetComposerItemMarshaller, - tweetItemMarshaller: TweetItemMarshaller, - twitterListItemMarshaller: TwitterListItemMarshaller, - userItemMarshaller: UserItemMarshaller, - verticalGridItemMarshaller: VerticalGridItemMarshaller, - threadHeaderItemMarshaller: ThreadHeaderItemMarshaller, - promptItemMarshaller: PromptItemMarshaller, - spellingItemMarshaller: SpellingItemMarshaller, - momentAnnotationItemMarshaller: MomentAnnotationItemMarshaller, - genericSummaryItemMarshaller: GenericSummaryItemMarshaller, - commerceProductItemMarshaller: CommerceProductItemMarshaller, - commerceProductGroupItemMarshaller: CommerceProductGroupItemMarshaller, - trendItemMarshaller: TrendItemMarshaller) { - - def apply(item: TimelineItem): urt.TimelineItemContent = item match { - case articleItem: ArticleItem => articleItemMarshaller(articleItem) - case audioSpaceItem: AudioSpaceItem => audioSpaceItemMarshaller(audioSpaceItem) - case cardItem: CardItem => cardItemMarshaller(cardItem) - case cursorItem: CursorItem => cursorItemMarshaller(cursorItem) - case eventSummaryItem: EventSummaryItem => eventSummaryItemMarshaller(eventSummaryItem) - case genericSummaryItem: GenericSummaryItem => genericSummaryItemMarshaller(genericSummaryItem) - case iconLabelItem: IconLabelItem => iconLabelItemMarshaller(iconLabelItem) - case labelItem: LabelItem => labelItemMarshaller(labelItem) - case messagePromptItem: MessagePromptItem => messagePromptItemMarshaller(messagePromptItem) - case tileItem: TileItem => tileItemMarshaller(tileItem) - case tombstoneItem: TombstoneItem => tombstoneItemMarshaller(tombstoneItem) - case topicFollowPromptItem: TopicFollowPromptItem => - topicFollowPromptItemMarshaller(topicFollowPromptItem) - case topicItem: TopicItem => topicItemMarshaller(topicItem) - case tweetComposerItem: TweetComposerItem => tweetComposerItemMarshaller(tweetComposerItem) - case tweetItem: TweetItem => tweetItemMarshaller(tweetItem) - case twitterListItem: TwitterListItem => twitterListItemMarshaller(twitterListItem) - case userItem: UserItem => userItemMarshaller(userItem) - case verticalGridItem: VerticalGridItem => verticalGridItemMarshaller(verticalGridItem) - case threadHeaderItem: ThreadHeaderItem => threadHeaderItemMarshaller(threadHeaderItem) - case promptItem: PromptItem => promptItemMarshaller(promptItem) - case spellingItem: SpellingItem => spellingItemMarshaller(spellingItem) - case momentAnnotationItem: MomentAnnotationItem => - momentAnnotationItemMarshaller(momentAnnotationItem) - case commerceProductItem: CommerceProductItem => - commerceProductItemMarshaller(commerceProductItem) - case commerceProductGroupItem: CommerceProductGroupItem => - commerceProductGroupItemMarshaller(commerceProductGroupItem) - case trendItem: TrendItem => trendItemMarshaller(trendItem) - case _: Cover => throw TimelineCoverNotFilteredException - case _ => throw new UnsupportedTimelineItemException(item) - } -} - -class UnsupportedTimelineItemException(timelineItem: TimelineItem) - extends UnsupportedOperationException( - "Unsupported timeline item " + TransportMarshaller.getSimpleName(timelineItem.getClass)) - -object TimelineCoverNotFilteredException - extends UnsupportedOperationException("AddEntriesInstructionBuilder does not support Cover. " + - "ShowCoverInstructionBuilder should be used with AddEntriesWithShowCoverInstructionBuilder " + - "in order to filter out the Cover.") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala deleted file mode 100644 index 242fdc522..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineItemMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineItemMarshaller @Inject() ( - timelineItemContentMarshaller: TimelineItemContentMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - feedbackInfoMarshaller: FeedbackInfoMarshaller) { - - def apply(item: TimelineItem): urt.TimelineItem = urt.TimelineItem( - content = timelineItemContentMarshaller(item), - clientEventInfo = item.clientEventInfo.map(clientEventInfoMarshaller(_)), - feedbackInfo = item.feedbackActionInfo.map(feedbackInfoMarshaller(_)), - prompt = None - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala deleted file mode 100644 index 792859941..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineMetadataMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineMetadataMarshaller @Inject() ( - timelineScribeConfigMarshaller: TimelineScribeConfigMarshaller, - readerModeConfigMarshaller: ReaderModeConfigMarshaller) { - - def apply(timelineMetadata: TimelineMetadata): urt.TimelineMetadata = urt.TimelineMetadata( - title = timelineMetadata.title, - scribeConfig = timelineMetadata.scribeConfig.map(timelineScribeConfigMarshaller(_)), - readerModeConfig = timelineMetadata.readerModeConfig.map(readerModeConfigMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala deleted file mode 100644 index 4de8d6164..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineModuleMarshaller.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleFooterMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleHeaderMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module.ModuleShowMoreBehaviorMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineModuleMarshaller @Inject() ( - moduleItemMarshaller: ModuleItemMarshaller, - moduleDisplayTypeMarshaller: ModuleDisplayTypeMarshaller, - moduleHeaderMarshaller: ModuleHeaderMarshaller, - moduleFooterMarshaller: ModuleFooterMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - feedbackInfoMarshaller: FeedbackInfoMarshaller, - moduleMetadataMarshaller: ModuleMetadataMarshaller, - moduleShowMoreBehaviorMarshaller: ModuleShowMoreBehaviorMarshaller) { - - def apply(timelineModule: TimelineModule): urt.TimelineModule = urt.TimelineModule( - items = timelineModule.items.map(moduleItemMarshaller(_, timelineModule.entryIdentifier)), - displayType = moduleDisplayTypeMarshaller(timelineModule.displayType), - header = timelineModule.header.map(moduleHeaderMarshaller(_)), - footer = timelineModule.footer.map(moduleFooterMarshaller(_)), - clientEventInfo = timelineModule.clientEventInfo.map(clientEventInfoMarshaller(_)), - feedbackInfo = timelineModule.feedbackActionInfo.map(feedbackInfoMarshaller(_)), - metadata = timelineModule.metadata.map(moduleMetadataMarshaller(_)), - showMoreBehavior = timelineModule.showMoreBehavior.map(moduleShowMoreBehaviorMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala deleted file mode 100644 index 85d506766..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineOperationMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorOperationMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineOperationMarshaller @Inject() ( - cursorOperationMarshaller: CursorOperationMarshaller) { - - def apply(operation: TimelineOperation): urt.TimelineOperation = operation match { - case cursorOperation: CursorOperation => cursorOperationMarshaller(cursorOperation) - case _ => - throw new UnsupportedTimelineOperationException(operation) - } -} - -class UnsupportedTimelineOperationException(operation: TimelineOperation) - extends UnsupportedOperationException( - "Unsupported timeline operation " + TransportMarshaller.getSimpleName(operation.getClass)) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala deleted file mode 100644 index a3f495510..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/TimelineScribeConfigMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineScribeConfigMarshaller @Inject() () { - - def apply(timelineScribeConfig: TimelineScribeConfig): urt.TimelineScribeConfig = - urt.TimelineScribeConfig( - page = timelineScribeConfig.page, - section = timelineScribeConfig.section, - entityToken = timelineScribeConfig.entityToken - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala deleted file mode 100644 index d270c3848..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshaller.scala +++ /dev/null @@ -1,101 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ChildFeedbackActionMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackActionMarshaller -import com.twitter.product_mixer.core.model.common.identifier.TransportMarshallerIdentifier -import com.twitter.product_mixer.core.model.marshalling.response.urt.Timeline -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineInstruction -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ContainsFeedbackActionInfos -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction -import com.twitter.timelines.render.thriftscala.TimelineResponse -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -/** - * [[TransportMarshaller]] for URT types - * - * @note to make an instance of a [[UrtTransportMarshaller]] you can use [[UrtTransportMarshallerBuilder.marshaller]] - */ -@Singleton -class UrtTransportMarshaller @Inject() ( - timelineInstructionMarshaller: TimelineInstructionMarshaller, - feedbackActionMarshaller: FeedbackActionMarshaller, - childFeedbackActionMarshaller: ChildFeedbackActionMarshaller, - timelineMetadataMarshaller: TimelineMetadataMarshaller) - extends TransportMarshaller[Timeline, urt.TimelineResponse] { - - override val identifier: TransportMarshallerIdentifier = - TransportMarshallerIdentifier("UnifiedRichTimeline") - - override def apply(timeline: Timeline): urt.TimelineResponse = { - val feedbackActions: Option[Map[String, urt.FeedbackAction]] = { - collectAndMarshallFeedbackActions(timeline.instructions) - } - urt.TimelineResponse( - state = urt.TimelineState.Ok, - timeline = urt.Timeline( - id = timeline.id, - instructions = timeline.instructions.map(timelineInstructionMarshaller(_)), - responseObjects = - feedbackActions.map(actions => urt.ResponseObjects(feedbackActions = Some(actions))), - metadata = timeline.metadata.map(timelineMetadataMarshaller(_)) - ) - ) - } - - // Currently, feedbackActionInfo at the URT TimelineItem level is supported, which covers almost all - // existing use cases. However, if additional feedbackActionInfos are defined on the URT - // TimelineItemContent level for "compound" URT types (see deprecated TopicCollection / - // TopicCollectionData), this is not supported. If "compound" URT types are added in the future, - // support must be added within that type (see ModuleItem) to handle the collection and marshalling - // of these feedbackActionInfos. - - private[this] def collectAndMarshallFeedbackActions( - instructions: Seq[TimelineInstruction] - ): Option[Map[String, urt.FeedbackAction]] = { - val feedbackActions: Seq[FeedbackAction] = for { - feedbackActionInfos <- instructions.collect { - case c: ContainsFeedbackActionInfos => c.feedbackActionInfos - } - feedbackInfoOpt <- feedbackActionInfos - feedbackInfo <- feedbackInfoOpt.toSeq - feedbackAction <- feedbackInfo.feedbackActions - } yield feedbackAction - - if (feedbackActions.nonEmpty) { - val urtFeedbackActions = feedbackActions.map(feedbackActionMarshaller(_)) - - val urtChildFeedbackActions: Seq[urt.FeedbackAction] = for { - feedbackAction <- feedbackActions - childFeedbackActions <- feedbackAction.childFeedbackActions.toSeq - childFeedbackAction <- childFeedbackActions - } yield childFeedbackActionMarshaller(childFeedbackAction) - - val allUrtFeedbackActions = urtFeedbackActions ++ urtChildFeedbackActions - - Some( - allUrtFeedbackActions.map { urtAction => - FeedbackActionMarshaller.generateKey(urtAction) -> urtAction - }.toMap - ) - } else { - None - } - } -} - -object UrtTransportMarshaller { - def unavailable(timelineId: String): TimelineResponse = { - urt.TimelineResponse( - state = urt.TimelineState.Unavailable, - timeline = urt.Timeline( - id = timelineId, - instructions = Seq.empty, - responseObjects = None, - metadata = None - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala deleted file mode 100644 index 18447aa35..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/UrtTransportMarshallerBuilder.scala +++ /dev/null @@ -1,711 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.ContextualTweetRefMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.OuterTweetContextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.TweetHydrationContextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.rtf.safety_level.SafetyLevelMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertColorConfigurationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertDisplayLocationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertIconDisplayInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertNavigationMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert.ShowAlertTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.ButtonStyleMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.CtaButtonMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.IconCtaButtonMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.TextCtaButtonMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.ColorMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.ColorPaletteMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductGroupItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce.CommerceProductItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverCtaBehaviorMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverCtaMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.CoverImageMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.FullCoverContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.FullCoverDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.HalfCoverContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover.HalfCoverDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article.ArticleSeedTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.audio_space.AudioSpaceItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card.CardDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card.CardItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation.ConversationAnnotationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation.ConversationAnnotationTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event.EventSummaryDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event.EventSummaryItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.ForwardPivotDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.ForwardPivotMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.SoftInterventionDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryActionMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryContextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item.GenericSummaryItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight.HighlightedSectionMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.icon_label.IconLabelItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label.LabelDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label.LabelItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message._ -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.moment.MomentAnnotationItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt._ -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.SpellingActionTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.SpellingItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion.TextResultMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread.ThreadHeaderContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread.ThreadHeaderItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.CallToActionTileContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.StandardTileContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.TileContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile.TileItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFollowPromptDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFollowPromptItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicFunctionalityTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic.TopicItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.trend.TrendItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TimelinesScoreInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetHighlightsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer.TweetComposerDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer.TweetComposerItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list.TwitterListDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list.TwitterListItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user.UserReactiveTriggersMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemContentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemTileStyleMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemTopicFunctionalityTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item.VerticalGridItemTopicTileMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.AspectRatioMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.BroadcastIdMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaEntityMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaKeyMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.RectMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.TweetMediaMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata._ -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorDisplayTreatmentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorItemMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorOperationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation.CursorTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.AdMetadataContainerMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.CallToActionMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.ClickTrackingInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.DisclaimerTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.DisclosureTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.DynamicPrerollTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.MediaInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PrerollMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PrerollMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.SkAdNetworkDataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.SponsorshipTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.UrlOverrideTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.VideoVariantsMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.reaction.TimelineReactionMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.ReferenceObjectMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextAlignmentMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextEntityMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextFormatMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module._ - -/** - * Convenience constructor for services not using dependency injection and unit tests. If using - * dependency injection, instead `@Inject` an instance of [[UrtTransportMarshaller]] to construct. - */ -object UrtTransportMarshallerBuilder { - val conversationSectionMarshaller = new ConversationSectionMarshaller - val conversationDetailsMarshaller = new ConversationDetailsMarshaller( - conversationSectionMarshaller) - val timelinesDetailsMarshaller = new TimelinesDetailsMarshaller - val articleDetailsMarshaller = new ArticleDetailsMarshaller - val liveEventDetailsMarshaller = new LiveEventDetailsMarshaller - val commerceDetailsMarshaller = new CommerceDetailsMarshaller - val clientEventDetailsMarshaller = - new ClientEventDetailsMarshaller( - conversationDetailsMarshaller, - timelinesDetailsMarshaller, - articleDetailsMarshaller, - liveEventDetailsMarshaller, - commerceDetailsMarshaller) - val clientEventInfoMarshaller = new ClientEventInfoMarshaller(clientEventDetailsMarshaller) - - val feedbackTypeMarshaller = new FeedbackTypeMarshaller - val confirmationDisplayTypeMarshaller = new ConfirmationDisplayTypeMarshaller - val horizonIconMarshaller = new HorizonIconMarshaller - val richFeedbackBehaviorMarshaller = new RichFeedbackBehaviorMarshaller - val childFeedbackActionMarshaller = new ChildFeedbackActionMarshaller( - feedbackTypeMarshaller = feedbackTypeMarshaller, - confirmationDisplayTypeMarshaller = confirmationDisplayTypeMarshaller, - clientEventInfoMarshaller = clientEventInfoMarshaller, - horizonIconMarshaller = horizonIconMarshaller, - richFeedbackBehaviorMarshaller = richFeedbackBehaviorMarshaller - ) - val feedbackActionMarshaller = new FeedbackActionMarshaller( - childFeedbackActionMarshaller = childFeedbackActionMarshaller, - feedbackTypeMarshaller = feedbackTypeMarshaller, - confirmationDisplayTypeMarshaller = confirmationDisplayTypeMarshaller, - clientEventInfoMarshaller = clientEventInfoMarshaller, - horizonIconMarshaller = horizonIconMarshaller, - richFeedbackBehaviorMarshaller = richFeedbackBehaviorMarshaller - ) - val feedbackDisplayContextMarshaller = new FeedbackDisplayContextMarshaller - val feedbackInfoMarshaller = new FeedbackInfoMarshaller( - feedbackActionMarshaller = feedbackActionMarshaller, - feedbackDisplayContextMarshaller = feedbackDisplayContextMarshaller, - clientEventInfoMarshaller = clientEventInfoMarshaller - ) - - val urlTypeMarshaller = new UrlTypeMarshaller - val urtEndpointOptionsMarshaller = new UrtEndpointOptionsMarshaller - val urlMarshaller = new UrlMarshaller( - urlTypeMarshaller = urlTypeMarshaller, - urtEndpointOptionsMarshaller = urtEndpointOptionsMarshaller - ) - val referenceObjectMarshaller = new ReferenceObjectMarshaller(urlMarshaller) - val richTextFormatMarshaller = new RichTextFormatMarshaller - val richTextEntityMarshaller = - new RichTextEntityMarshaller(referenceObjectMarshaller, richTextFormatMarshaller) - val richTextAlignmentMarshaller = new RichTextAlignmentMarshaller - val richTextMarshaller = - new RichTextMarshaller(richTextEntityMarshaller, richTextAlignmentMarshaller) - - val tombstoneInfoMarshaller = new TombstoneInfoMarshaller(richTextMarshaller = richTextMarshaller) - - val generalContextTypeMarshaller = new GeneralContextTypeMarshaller - val generalContextMarshaller = new GeneralContextMarshaller( - generalContextTypeMarshaller = generalContextTypeMarshaller, - urlMarshaller = urlMarshaller - ) - - val timelineReactionMarshaller = new TimelineReactionMarshaller - - val topicContextMarshaller = new TopicContextMarshaller() - - val socialContextMarshaller = new SocialContextMarshaller( - generalContextMarshaller = generalContextMarshaller, - topicContextMarshaller = topicContextMarshaller - ) - - val highlightedSectionMarshaller = new HighlightedSectionMarshaller() - val tweetHighlightsMarshaller = new TweetHighlightsMarshaller(highlightedSectionMarshaller) - - val topicDisplayTypeMarshaller = new TopicDisplayTypeMarshaller - val topicFunctionalityTypeMarshaller = new TopicFunctionalityTypeMarshaller - val topicItemMarshaller = new TopicItemMarshaller( - displayTypeMarshaller = topicDisplayTypeMarshaller, - functionalityTypeMarshaller = topicFunctionalityTypeMarshaller - ) - - val topicFollowPromptDisplayTypeMarshaller = new TopicFollowPromptDisplayTypeMarshaller - val topicFollowPromptItemMarshaller = new TopicFollowPromptItemMarshaller( - displayTypeMarshaller = topicFollowPromptDisplayTypeMarshaller - ) - - val rosettaColorMarshaller = new RosettaColorMarshaller() - val badgeMarshaller = new BadgeMarshaller( - rosettaColorMarshaller = rosettaColorMarshaller - ) - val iconCtaButtonMarshaller = new IconCtaButtonMarshaller(horizonIconMarshaller, urlMarshaller) - val textCtaButtonMarshaller = new TextCtaButtonMarshaller(urlMarshaller) - val ctaButtonMarshaller = - new CtaButtonMarshaller(iconCtaButtonMarshaller, textCtaButtonMarshaller) - - val standardTileContentMarshaller = new StandardTileContentMarshaller( - badgeMarshaller = badgeMarshaller - ) - val callToActionTileContentMarshaller = new CallToActionTileContentMarshaller( - ctaButtonMarshaller = ctaButtonMarshaller, - richTextMarshaller = richTextMarshaller - ) - - val tileContentMarshaller = new TileContentMarshaller( - standardTileContentMarshaller = standardTileContentMarshaller, - callToActionTileContentMarshaller = callToActionTileContentMarshaller - ) - val colorMarshaller = new ColorMarshaller() - val colorPaletteMarshaller = new ColorPaletteMarshaller( - colorMarshaller = colorMarshaller - ) - val imageVariantMarshaller = new ImageVariantMarshaller( - colorPaletteMarshaller = colorPaletteMarshaller - ) - val imageDisplayTypeMarshaller = new ImageDisplayTypeMarshaller() - val imageAnimationTypeMarshaller = new ImageAnimationTypeMarshaller() - - val softInterventionDisplayTypeMarshaller = new SoftInterventionDisplayTypeMarshaller - val forwardPivotDisplayTypeMarshaller = new ForwardPivotDisplayTypeMarshaller - val forwardPivotMarshaller = new ForwardPivotMarshaller( - urlMarshaller = urlMarshaller, - richTextMarshaller = richTextMarshaller, - forwardPivotDisplayTypeMarshaller = forwardPivotDisplayTypeMarshaller, - imageVariantMarshaller = imageVariantMarshaller, - badgeMarshaller = badgeMarshaller, - rosettaColorMarshaller = rosettaColorMarshaller, - softInterventionDisplayTypeMarshaller = softInterventionDisplayTypeMarshaller - ) - - val tweetDisplayTypeMarshaller = new TweetDisplayTypeMarshaller - val timelinesScoreInfoMarshaller = new TimelinesScoreInfoMarshaller - val disclosureTypeMarshaller = new DisclosureTypeMarshaller - val dynamicPrerollTypeMarshaller = new DynamicPrerollTypeMarshaller - val callToActionMarshaller = new CallToActionMarshaller - val videoVariantsMarshaller = new VideoVariantsMarshaller - val mediaInfoMarshaller = new MediaInfoMarshaller( - callToActionMarshaller = callToActionMarshaller, - videoVariantsMarshaller = videoVariantsMarshaller - ) - val prerollMarshaller = new PrerollMarshaller( - dynamicPrerollTypeMarshaller = dynamicPrerollTypeMarshaller, - mediaInfoMarshaller = mediaInfoMarshaller - ) - val sponsorshipTypeMarshaller = new SponsorshipTypeMarshaller - val disclaimerTypeMarshaller = new DisclaimerTypeMarshaller - val skAdNetworkDataMarshaller = new SkAdNetworkDataMarshaller - val adMetadataContainerMarshaller = new AdMetadataContainerMarshaller( - sponsorshipTypeMarshaller = sponsorshipTypeMarshaller, - disclaimerTypeMarshaller = disclaimerTypeMarshaller, - skAdNetworkDataMarshaller = skAdNetworkDataMarshaller - ) - val urlOverrideTypeMarshaller = new UrlOverrideTypeMarshaller - val clickTrackingInfoMarshaller = new ClickTrackingInfoMarshaller( - urlOverrideTypeMarshaller = urlOverrideTypeMarshaller - ) - val promotedMetadataMarshaller = new PromotedMetadataMarshaller( - disclosureTypeMarshaller = disclosureTypeMarshaller, - adMetadataContainerMarshaller = adMetadataContainerMarshaller, - clickTrackingInfoMarshaller = clickTrackingInfoMarshaller - ) - - val conversationAnnotationTypeMarshaller = new ConversationAnnotationTypeMarshaller - val conversationAnnotationMarshaller = new ConversationAnnotationMarshaller( - conversationAnnotationTypeMarshaller = conversationAnnotationTypeMarshaller, - richTextMarshaller = richTextMarshaller - ) - - val safetyLevelMarshaller = new SafetyLevelMarshaller - val outerTweetContextMarshaller = new OuterTweetContextMarshaller - val tweetHydrationContextMarshaller = new TweetHydrationContextMarshaller( - safetyLevelMarshaller = safetyLevelMarshaller, - outerTweetContextMarshaller = outerTweetContextMarshaller - ) - val contextualTweetRefMarshaller = new ContextualTweetRefMarshaller( - tweetHydrationContextMarshaller = tweetHydrationContextMarshaller - ) - val prerollMetadataMarshaller = new PrerollMetadataMarshaller( - prerollMarshaller = prerollMarshaller - ) - - val rectMarshaller = new RectMarshaller - val mediaKeyMarshaller = new MediaKeyMarshaller - val broadcastIdMarshaller = new BroadcastIdMarshaller - val tweetMediaMarshaller = new TweetMediaMarshaller - val mediaEntityMarshaller = new MediaEntityMarshaller( - tweetMediaMarshaller = tweetMediaMarshaller, - broadcastIdMarshaller = broadcastIdMarshaller, - imageVariantMarshaller = imageVariantMarshaller) - val aspectRatioMarshaller = new AspectRatioMarshaller - val mediaMarshaller = new MediaMarshaller( - mediaEntityMarshaller = mediaEntityMarshaller, - mediaKeyMarshaller = mediaKeyMarshaller, - rectMarshaller = rectMarshaller, - aspectRatioMarshaller = aspectRatioMarshaller) - - val tweetItemMarshaller = new TweetItemMarshaller( - tweetDisplayTypeMarshaller = tweetDisplayTypeMarshaller, - socialContextMarshaller = socialContextMarshaller, - tweetHighlightsMarshaller = tweetHighlightsMarshaller, - tombstoneInfoMarshaller = tombstoneInfoMarshaller, - timelinesScoreInfoMarshaller = timelinesScoreInfoMarshaller, - forwardPivotMarshaller = forwardPivotMarshaller, - promotedMetadataMarshaller = promotedMetadataMarshaller, - conversationAnnotationMarshaller = conversationAnnotationMarshaller, - contextualTweetRefMarshaller = contextualTweetRefMarshaller, - prerollMetadataMarshaller = prerollMetadataMarshaller, - badgeMarshaller = badgeMarshaller, - urlMarshaller = urlMarshaller - ) - - val eventSummaryDisplayTypeMarshaller = new EventSummaryDisplayTypeMarshaller - val eventSummaryItemMarshaller = new EventSummaryItemMarshaller( - eventSummaryDisplayTypeMarshaller = eventSummaryDisplayTypeMarshaller, - imageVariantMarshaller = imageVariantMarshaller, - urlMarshaller = urlMarshaller - ) - - val trendItemMarshaller = new TrendItemMarshaller( - promotedMetadataMarshaller = promotedMetadataMarshaller, - urlMarshaller = urlMarshaller - ) - - val userDisplayTypeMarshaller = new UserDisplayTypeMarshaller - val userReactiveTriggersMarshaller = new UserReactiveTriggersMarshaller( - timelineReactionMarshaller) - val userItemMarshaller = new UserItemMarshaller( - userDisplayTypeMarshaller = userDisplayTypeMarshaller, - promotedMetadataMarshaller = promotedMetadataMarshaller, - socialContextMarshaller = socialContextMarshaller, - userReactiveTriggersMarshaller = userReactiveTriggersMarshaller, - ) - - val verticalGridItemTileStyleMarshaller = new VerticalGridItemTileStyleMarshaller - val verticalGridItemTopicFunctionalityTypeMarshaller = - new VerticalGridItemTopicFunctionalityTypeMarshaller - - val verticalGridItemTopicTileMarshaller = new VerticalGridItemTopicTileMarshaller( - styleMarshaller = verticalGridItemTileStyleMarshaller, - functionalityTypeMarshaller = verticalGridItemTopicFunctionalityTypeMarshaller, - urlMarshaller = urlMarshaller - ) - - val verticalGridItemContentMarshaller = new VerticalGridItemContentMarshaller( - verticalGridItemTopicTileMarshaller) - - val verticalGridItemMarshaller = new VerticalGridItemMarshaller(verticalGridItemContentMarshaller) - - val tombstoneDisplayTypeMarshaller = new TombstoneDisplayTypeMarshaller - val tombstoneItemMarshaller = new TombstoneItemMarshaller( - displayTypeMarshaller = tombstoneDisplayTypeMarshaller, - tombstoneInfoMarshaller = tombstoneInfoMarshaller, - tweetItemMarshaller = tweetItemMarshaller) - - val iconLabelItemMarshaller = new IconLabelItemMarshaller( - richTextMarshaller, - horizonIconMarshaller - ) - - val labelDisplayTypeMarshaller = new LabelDisplayTypeMarshaller - val labelItemMarshaller = new LabelItemMarshaller( - displayTypeMarshaller = labelDisplayTypeMarshaller, - urlMarshaller = urlMarshaller - ) - - val tileItemMarshaller = new TileItemMarshaller( - tileContentMarshaller = tileContentMarshaller, - urlMarshaller = urlMarshaller, - imageVariantMarshaller = imageVariantMarshaller - ) - - val callbackMarshaller = new CallbackMarshaller - val messageActionMarshaller = new MessageActionMarshaller( - callbackMarshaller, - clientEventInfoMarshaller - ) - val messageTextActionMarshaller = new MessageTextActionMarshaller(messageActionMarshaller) - val messageImageMarshaller = new MessageImageMarshaller( - imageVariantMarshaller - ) - val userFacepileDisplayTypeMarshaller = new UserFacepileDisplayTypeMarshaller() - val messageActionTypeMarshaller = new MessageActionTypeMarshaller() - val userFacepileMarshaller = new UserFacepileMarshaller( - messageActionTypeMarshaller, - messageTextActionMarshaller, - userFacepileDisplayTypeMarshaller - ) - val inlinePromptMessageContentMarshaller = new InlinePromptMessageContentMarshaller( - messageTextActionMarshaller = messageTextActionMarshaller, - richTextMarshaller = richTextMarshaller, - socialContextMarshaller = socialContextMarshaller, - userFacepileMarshaller = userFacepileMarshaller - ) - val headerImagePromptMessageContentMarshaller = new HeaderImagePromptMessageContentMarshaller( - messageImageMarshaller = messageImageMarshaller, - messageTextActionMarshaller = messageTextActionMarshaller, - messageActionMarshaller = messageActionMarshaller, - richTextMarshaller = richTextMarshaller - ) - val compactPromptMessageContentMarshaller = new CompactPromptMessageContentMarshaller( - messageTextActionMarshaller = messageTextActionMarshaller, - messageActionMarshaller = messageActionMarshaller, - richTextMarshaller = richTextMarshaller - ) - val messageContentMarshaller = new MessageContentMarshaller( - inlinePromptMessageContentMarshaller = inlinePromptMessageContentMarshaller, - headerImagePromptMessageContentMarshaller = headerImagePromptMessageContentMarshaller, - compactPromptMessageContentMarshaller = compactPromptMessageContentMarshaller - ) - val messagePromptItemMarshaller = new MessagePromptItemMarshaller( - messageContentMarshaller = messageContentMarshaller, - callbackMarshaller = callbackMarshaller - ) - - val tweetComposerDisplayTypeMarshaller = new TweetComposerDisplayTypeMarshaller - val tweetComposerItemMarshaller = new TweetComposerItemMarshaller( - tweetComposerDisplayTypeMarshaller = tweetComposerDisplayTypeMarshaller, - urlMarshaller = urlMarshaller - ) - - val cursorTypeMarshaller = new CursorTypeMarshaller - val cursorDisplayTreatmentMarshaller = new CursorDisplayTreatmentMarshaller - val cursorItemMarshaller = new CursorItemMarshaller( - cursorTypeMarshaller = cursorTypeMarshaller, - cursorDisplayTreatmentMarshaller = cursorDisplayTreatmentMarshaller) - val articleDisplayTypeMarshaller = new ArticleDisplayTypeMarshaller - val articleSeedTypeMarshaller = new ArticleSeedTypeMarshaller - val articleItemMarshaller = - new ArticleItemMarshaller( - articleDisplayTypeMarshaller, - socialContextMarshaller, - articleSeedTypeMarshaller) - val audioSpaceItemMarshaller = new AudioSpaceItemMarshaller - val cardDisplayTypeMarshaller = new CardDisplayTypeMarshaller - val cardItemMarshaller = new CardItemMarshaller( - cardDisplayTypeMarshaller = cardDisplayTypeMarshaller, - urlMarshaller = urlMarshaller - ) - - val twitterListDisplayTypeMarshaller = new TwitterListDisplayTypeMarshaller - val twitterListItemMarshaller = new TwitterListItemMarshaller( - twitterListDisplayTypeMarshaller = twitterListDisplayTypeMarshaller) - - val threadHeaderItemMarshaller = new ThreadHeaderItemMarshaller( - threadHeaderContentMarshaller = new ThreadHeaderContentMarshaller - ) - - val relevancePromptFollowUpTextInputMarshaller = new RelevancePromptFollowUpTextInputMarshaller( - callbackMarshaller = callbackMarshaller - ) - val relevancePromptFollowUpFeedbackTypeMarshaller = - new RelevancePromptFollowUpFeedbackTypeMarshaller( - relevancePromptFollowUpTextInputMarshaller = relevancePromptFollowUpTextInputMarshaller - ) - val relevancePromptDisplayTypeMarshaller = new RelevancePromptDisplayTypeMarshaller - val relevancePromptContentMarshaller = new RelevancePromptContentMarshaller( - callbackMarshaller = callbackMarshaller, - relevancePromptDisplayTypeMarshaller = relevancePromptDisplayTypeMarshaller, - relevancePromptFollowUpFeedbackTypeMarshaller = relevancePromptFollowUpFeedbackTypeMarshaller - ) - val promptContentMarshaller = new PromptContentMarshaller( - relevancePromptContentMarshaller = relevancePromptContentMarshaller - ) - val promptItemMarshaller = new PromptItemMarshaller( - promptContentMarshaller = promptContentMarshaller, - clientEventInfoMarshaller = clientEventInfoMarshaller, - callbackMarshaller = callbackMarshaller - ) - - val textResultMarshaller = new TextResultMarshaller(highlightedSectionMarshaller) - val spellingActionTypeMarshaller = new SpellingActionTypeMarshaller() - val spellingItemMarshaller = new SpellingItemMarshaller( - textResultMarshaller = textResultMarshaller, - spellingActionTypeMarshaller = spellingActionTypeMarshaller) - - val momentAnnotationItemMarshaller = new MomentAnnotationItemMarshaller(richTextMarshaller) - - val genericSummaryDisplayTypeMarshaller = new GenericSummaryDisplayTypeMarshaller - val genericSummaryActionMarshaller = new GenericSummaryActionMarshaller( - urlMarshaller = urlMarshaller, - clientEventInfoMarshaller = clientEventInfoMarshaller) - val genericSummaryContextMarshaller = new GenericSummaryContextMarshaller( - richTextMarshaller = richTextMarshaller, - horizonIconMarshaller = horizonIconMarshaller - ) - val genericSummaryItemMarshaller = new GenericSummaryItemMarshaller( - genericSummaryDisplayTypeMarshaller = genericSummaryDisplayTypeMarshaller, - genericSummaryContextMarshaller = genericSummaryContextMarshaller, - genericSummaryActionMarshaller = genericSummaryActionMarshaller, - mediaMarshaller = mediaMarshaller, - promotedMetadataMarshaller = promotedMetadataMarshaller, - richTextMarshaller = richTextMarshaller - ) - - val commerceProductItemMarshaller = new CommerceProductItemMarshaller - val commerceProductGroupItemMarshaller = new CommerceProductGroupItemMarshaller - - val timelineItemMarshaller = new TimelineItemMarshaller( - timelineItemContentMarshaller = new TimelineItemContentMarshaller( - articleItemMarshaller = articleItemMarshaller, - audioSpaceItemMarshaller = audioSpaceItemMarshaller, - cardItemMarshaller = cardItemMarshaller, - cursorItemMarshaller = cursorItemMarshaller, - eventSummaryItemMarshaller = eventSummaryItemMarshaller, - iconLabelItemMarshaller = iconLabelItemMarshaller, - labelItemMarshaller = labelItemMarshaller, - messagePromptItemMarshaller = messagePromptItemMarshaller, - tileItemMarshaller = tileItemMarshaller, - tombstoneItemMarshaller = tombstoneItemMarshaller, - topicFollowPromptItemMarshaller = topicFollowPromptItemMarshaller, - topicItemMarshaller = topicItemMarshaller, - tweetComposerItemMarshaller = tweetComposerItemMarshaller, - tweetItemMarshaller = tweetItemMarshaller, - twitterListItemMarshaller = twitterListItemMarshaller, - userItemMarshaller = userItemMarshaller, - verticalGridItemMarshaller = verticalGridItemMarshaller, - threadHeaderItemMarshaller = threadHeaderItemMarshaller, - promptItemMarshaller = promptItemMarshaller, - spellingItemMarshaller = spellingItemMarshaller, - momentAnnotationItemMarshaller = momentAnnotationItemMarshaller, - genericSummaryItemMarshaller = genericSummaryItemMarshaller, - commerceProductItemMarshaller = commerceProductItemMarshaller, - commerceProductGroupItemMarshaller = commerceProductGroupItemMarshaller, - trendItemMarshaller = trendItemMarshaller - ), - clientEventInfoMarshaller = clientEventInfoMarshaller, - feedbackInfoMarshaller = feedbackInfoMarshaller - ) - - val moduleDisplayTypeMarshaller = new ModuleDisplayTypeMarshaller - val moduleItemTreeDisplayMarshaller = - new ModuleItemTreeDisplayMarshaller(moduleDisplayTypeMarshaller) - - val moduleItemMarshaller = new ModuleItemMarshaller( - timelineItemMarshaller = timelineItemMarshaller, - moduleItemTreeDisplayMarshaller = moduleItemTreeDisplayMarshaller) - - val moduleHeaderDisplayTypeMarshaller = new ModuleHeaderDisplayTypeMarshaller - val moduleHeaderMarshaller = new ModuleHeaderMarshaller( - horizonIconMarshaller = horizonIconMarshaller, - imageVariantMarshaller = imageVariantMarshaller, - socialContextMarshaller = socialContextMarshaller, - moduleHeaderDisplayTypeMarshaller = moduleHeaderDisplayTypeMarshaller - ) - val moduleFooterMarshaller = new ModuleFooterMarshaller(urlMarshaller = urlMarshaller) - val adsMetadataMarshaller = new AdsMetadataMarshaller - val moduleConversationMetadataMarshaller = new ModuleConversationMetadataMarshaller( - socialContextMarshaller = socialContextMarshaller) - val gridCarouselMetadataMarshaller = new GridCarouselMetadataMarshaller - val moduleMetadataMarshaller = new ModuleMetadataMarshaller( - adsMetadataMarshaller = adsMetadataMarshaller, - moduleConversationMetadataMarshaller = moduleConversationMetadataMarshaller, - gridCarouselMetadataMarshaller = gridCarouselMetadataMarshaller - ) - val moduleShowMoreBehaviorRevealByCountMarshaller = - new ModuleShowMoreBehaviorRevealByCountMarshaller - val moduleShowMoreBehaviorMarshaller = new ModuleShowMoreBehaviorMarshaller( - moduleShowMoreBehaviorRevealByCountMarshaller = moduleShowMoreBehaviorRevealByCountMarshaller - ) - val timelineModuleMarshaller = new TimelineModuleMarshaller( - moduleItemMarshaller = moduleItemMarshaller, - moduleDisplayTypeMarshaller = moduleDisplayTypeMarshaller, - moduleHeaderMarshaller = moduleHeaderMarshaller, - moduleFooterMarshaller = moduleFooterMarshaller, - clientEventInfoMarshaller = clientEventInfoMarshaller, - feedbackInfoMarshaller = feedbackInfoMarshaller, - moduleMetadataMarshaller = moduleMetadataMarshaller, - moduleShowMoreBehaviorMarshaller = moduleShowMoreBehaviorMarshaller - ) - - val halfCoverDisplayTypeMarshaller = new HalfCoverDisplayTypeMarshaller() - val fullCoverDisplayTypeMarshaller = new FullCoverDisplayTypeMarshaller() - val coverCtaBehaviorMarshaller = new CoverCtaBehaviorMarshaller(richTextMarshaller, urlMarshaller) - val buttonStyleMarshaller = new ButtonStyleMarshaller() - val coverCtaMarshaller = new CoverCtaMarshaller( - coverCtaBehaviorMarshaller, - callbackMarshaller, - clientEventInfoMarshaller, - horizonIconMarshaller, - buttonStyleMarshaller) - val coverImageMarshaller = - new CoverImageMarshaller( - imageVariantMarshaller, - imageDisplayTypeMarshaller, - imageAnimationTypeMarshaller) - val dismissInfoMarshaller = new DismissInfoMarshaller(callbackMarshaller) - - val halfCoverContentMarshaller = new HalfCoverContentMarshaller( - halfCoverDisplayTypeMarshaller, - coverCtaMarshaller, - richTextMarshaller, - coverImageMarshaller, - dismissInfoMarshaller, - callbackMarshaller) - val fullCoverContentMarshaller = new FullCoverContentMarshaller( - fullCoverDisplayTypeMarshaller, - coverCtaMarshaller, - richTextMarshaller, - imageVariantMarshaller, - dismissInfoMarshaller, - imageDisplayTypeMarshaller, - callbackMarshaller) - val coverContentMarshaller = - new CoverContentMarshaller(fullCoverContentMarshaller, halfCoverContentMarshaller) - val coverMarshaller = new CoverMarshaller(coverContentMarshaller, clientEventInfoMarshaller) - - val cursorOperationMarshaller = new CursorOperationMarshaller( - cursorTypeMarshaller = cursorTypeMarshaller, - cursorDisplayTreatmentMarshaller = cursorDisplayTreatmentMarshaller) - val timelineOperationMarshaller = new TimelineOperationMarshaller( - cursorOperationMarshaller = cursorOperationMarshaller) - - val timelineEntryMarshaller = new TimelineEntryMarshaller( - timelineEntryContentMarshaller = new TimelineEntryContentMarshaller( - timelineItemMarshaller = timelineItemMarshaller, - timelineModuleMarshaller = timelineModuleMarshaller, - timelineOperationMarshaller = timelineOperationMarshaller)) - - val addEntriesInstructionMarshaller = new AddEntriesInstructionMarshaller( - timelineEntryMarshaller = timelineEntryMarshaller) - - val markEntriesUnreadInstructionMarshaller = new MarkEntriesUnreadInstructionMarshaller() - - val addToModuleInstructionMarshaller = new AddToModuleInstructionMarshaller( - moduleItemMarshaller = moduleItemMarshaller) - - val replaceEntryInstructionMarshaller = new ReplaceEntryInstructionMarshaller( - timelineEntryMarshaller = timelineEntryMarshaller - ) - - val pinEntryInstructionMarshaller = new PinEntryInstructionMarshaller( - timelineEntryMarshaller = timelineEntryMarshaller - ) - - val showAlertTypeMarshaller = new ShowAlertTypeMarshaller() - val showAlertIconMarshaller = new ShowAlertIconMarshaller() - val showAlertIconDisplayInfoMarshaller = new ShowAlertIconDisplayInfoMarshaller( - showAlertIconMarshaller = showAlertIconMarshaller, - rosettaColorMarshaller = rosettaColorMarshaller - ) - val showAlertColorConfigurationMarshaller = new ShowAlertColorConfigurationMarshaller( - rosettaColorMarshaller = rosettaColorMarshaller - ) - val showAlertDisplayLocationMarshaller = new ShowAlertDisplayLocationMarshaller() - val showAlertNavigationMetadataMarshaller = new ShowAlertNavigationMetadataMarshaller() - val showAlertInstructionMarshaller = new ShowAlertInstructionMarshaller( - showAlertTypeMarshaller = new ShowAlertTypeMarshaller(), - clientEventInfoMarshaller = clientEventInfoMarshaller, - richTextMarshaller = richTextMarshaller, - showAlertIconDisplayInfoMarshaller = showAlertIconDisplayInfoMarshaller, - showAlertColorConfigurationMarshaller = showAlertColorConfigurationMarshaller, - showAlertDisplayLocationMarshaller = showAlertDisplayLocationMarshaller, - showAlertNavigationMetadataMarshaller = showAlertNavigationMetadataMarshaller - ) - - val timelineInstructionMarshaller = new TimelineInstructionMarshaller( - addEntriesInstructionMarshaller = addEntriesInstructionMarshaller, - addToModuleInstructionMarshaller = addToModuleInstructionMarshaller, - markEntriesUnreadInstructionMarshaller = markEntriesUnreadInstructionMarshaller, - pinEntryInstructionMarshaller = pinEntryInstructionMarshaller, - replaceEntryInstructionMarshaller = replaceEntryInstructionMarshaller, - showAlertInstructionMarshaller = showAlertInstructionMarshaller, - terminateTimelineInstructionMarshaller = new TerminateTimelineInstructionMarshaller, - coverMarshaller = coverMarshaller, - ) - - val timelineScribeConfigMarshaller = new TimelineScribeConfigMarshaller - - val readerModeConfigMarshaller = new ReaderModeConfigMarshaller(urlMarshaller) - - val timelineMetadataMarshaller = new TimelineMetadataMarshaller( - timelineScribeConfigMarshaller = timelineScribeConfigMarshaller, - readerModeConfigMarshaller = readerModeConfigMarshaller - ) - - val marshaller: UrtTransportMarshaller = - new UrtTransportMarshaller( - timelineInstructionMarshaller = timelineInstructionMarshaller, - feedbackActionMarshaller = feedbackActionMarshaller, - childFeedbackActionMarshaller = childFeedbackActionMarshaller, - timelineMetadataMarshaller = timelineMetadataMarshaller - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD deleted file mode 100644 index 62f1b9de1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "src/thrift/com/twitter/timelines/render:thrift-scala", - "util/util-core:util-core-util", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "src/thrift/com/twitter/timelines/render:thrift-scala", - "util/util-core:util-core-util", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala deleted file mode 100644 index e1b5cb7f1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertColorConfigurationMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class ShowAlertColorConfigurationMarshaller @Inject() ( - rosettaColorMarshaller: RosettaColorMarshaller) { - - def apply(colorConfiguration: ShowAlertColorConfiguration): urt.ShowAlertColorConfiguration = - urt.ShowAlertColorConfiguration( - background = rosettaColorMarshaller(colorConfiguration.background), - text = rosettaColorMarshaller(colorConfiguration.text), - border = colorConfiguration.border.map(rosettaColorMarshaller(_)), - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala deleted file mode 100644 index 8e7c979cb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertDisplayLocationMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert - -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.Top -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.Bottom -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class ShowAlertDisplayLocationMarshaller @Inject() () { - - def apply(alertDisplayLocation: ShowAlertDisplayLocation): urt.ShowAlertDisplayLocation = - alertDisplayLocation match { - case Top => urt.ShowAlertDisplayLocation.Top - case Bottom => urt.ShowAlertDisplayLocation.Bottom - } - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala deleted file mode 100644 index 9be91f48b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconDisplayInfoMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo - -@Singleton -class ShowAlertIconDisplayInfoMarshaller @Inject() ( - showAlertIconMarshaller: ShowAlertIconMarshaller, - rosettaColorMarshaller: RosettaColorMarshaller, -) { - - def apply(alertIconDisplayInfo: ShowAlertIconDisplayInfo): urt.ShowAlertIconDisplayInfo = - urt.ShowAlertIconDisplayInfo( - icon = showAlertIconMarshaller(alertIconDisplayInfo.icon), - tint = rosettaColorMarshaller(alertIconDisplayInfo.tint), - ) - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala deleted file mode 100644 index 91cef4d86..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertIconMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert - -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.DownArrow -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.UpArrow -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class ShowAlertIconMarshaller @Inject() () { - - def apply(alertIcon: ShowAlertIcon): urt.ShowAlertIcon = alertIcon match { - case UpArrow => urt.ShowAlertIcon.UpArrow - case DownArrow => urt.ShowAlertIcon.DownArrow - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala deleted file mode 100644 index f8daff191..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertNavigationMetadataMarshaller.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert - -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertNavigationMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ShowAlertNavigationMetadataMarshaller @Inject() () { - - def apply(alertNavigationMetadata: ShowAlertNavigationMetadata): urt.ShowAlertNavigationMetadata = - urt.ShowAlertNavigationMetadata(navigateToEntryId = - Some(alertNavigationMetadata.navigateToEntryId)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala deleted file mode 100644 index 83ae14c3f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/alert/ShowAlertTypeMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.alert - -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.Navigate -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.NewTweets -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ShowAlertTypeMarshaller @Inject() () { - - def apply(alertType: ShowAlertType): urt.AlertType = alertType match { - case NewTweets => urt.AlertType.NewTweets - case Navigate => urt.AlertType.Navigate - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD deleted file mode 100644 index 43ea49f65..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala deleted file mode 100644 index 3676b2d56..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/ButtonStyleMarshaller.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button - -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.ButtonStyle -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Default -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Primary -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Secondary -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Text -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Destructive -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.Neutral -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveSecondary -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.DestructiveText -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ButtonStyleMarshaller @Inject() () { - def apply(buttonStyle: ButtonStyle): urt.ButtonStyle = - buttonStyle match { - case Default => urt.ButtonStyle.Default - case Primary => urt.ButtonStyle.Primary - case Secondary => urt.ButtonStyle.Secondary - case Text => urt.ButtonStyle.Text - case Destructive => urt.ButtonStyle.Destructive - case Neutral => urt.ButtonStyle.Neutral - case DestructiveSecondary => urt.ButtonStyle.DestructiveSecondary - case DestructiveText => urt.ButtonStyle.DestructiveText - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala deleted file mode 100644 index 936b9073e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/CtaButtonMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button - -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.CtaButton -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.IconCtaButton -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.TextCtaButton -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CtaButtonMarshaller @Inject() ( - iconCtaButtonMarshaller: IconCtaButtonMarshaller, - textCtaButtonMarshaller: TextCtaButtonMarshaller) { - - def apply(ctaButton: CtaButton): urt.CtaButton = ctaButton match { - case button: TextCtaButton => urt.CtaButton.Text(textCtaButtonMarshaller(button)) - case button: IconCtaButton => urt.CtaButton.Icon(iconCtaButtonMarshaller(button)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala deleted file mode 100644 index c22c3666a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/IconCtaButtonMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.IconCtaButton -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class IconCtaButtonMarshaller @Inject() ( - horizonIconMarshaller: HorizonIconMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(iconCtaButton: IconCtaButton): urt.IconCtaButton = - urt.IconCtaButton( - buttonIcon = horizonIconMarshaller(iconCtaButton.buttonIcon), - accessibilityLabel = iconCtaButton.accessibilityLabel, - url = urlMarshaller(iconCtaButton.url) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala deleted file mode 100644 index f805a1758..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button/TextCtaButtonMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.TextCtaButton -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TextCtaButtonMarshaller @Inject() ( - urlMarshaller: UrlMarshaller) { - - def apply(textCtaButton: TextCtaButton): urt.TextCtaButton = - urt.TextCtaButton( - buttonText = textCtaButton.buttonText, - url = urlMarshaller(textCtaButton.url) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD deleted file mode 100644 index 7e72e4f60..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala deleted file mode 100644 index 98eacd8d8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.Color -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Singleton - -@Singleton -class ColorMarshaller { - - def apply(color: Color): urt.Color = urt.Color( - red = color.red, - green = color.green, - blue = color.blue, - opacity = color.opacity - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala deleted file mode 100644 index 22a932aa3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/ColorPaletteMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.ColorPalette -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ColorPaletteMarshaller @Inject() ( - colorMarshaller: ColorMarshaller) { - - def apply(colorPalette: ColorPalette): urt.ColorPaletteItem = urt.ColorPaletteItem( - rgb = colorMarshaller(colorPalette.rgb), - percentage = colorPalette.percentage - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala deleted file mode 100644 index 91926673e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color/RosettaColorMarshaller.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RosettaColorMarshaller @Inject() () { - - def apply(rosettaColor: RosettaColor): urt.RosettaColor = rosettaColor match { - case WhiteRosettaColor => urt.RosettaColor.White - case BlackRosettaColor => urt.RosettaColor.Black - case ClearRosettaColor => urt.RosettaColor.Clear - case TextBlackRosettaColor => urt.RosettaColor.TextBlack - case TextBlueRosettaColor => urt.RosettaColor.TextBlue - case DeepGrayRosettaColor => urt.RosettaColor.DeepGray - case MediumGrayRosettaColor => urt.RosettaColor.MediumGray - case LightGrayRosettaColor => urt.RosettaColor.LightGray - case FadedGrayRosettaColor => urt.RosettaColor.FadedGray - case FaintGrayRosettaColor => urt.RosettaColor.FaintGray - case DeepOrangeRosettaColor => urt.RosettaColor.DeepOrange - case MediumOrangeRosettaColor => urt.RosettaColor.MediumOrange - case LightOrangeRosettaColor => urt.RosettaColor.LightOrange - case FadedOrangeRosettaColor => urt.RosettaColor.FadedOrange - case DeepYellowRosettaColor => urt.RosettaColor.DeepYellow - case MediumYellowRosettaColor => urt.RosettaColor.MediumYellow - case LightYellowRosettaColor => urt.RosettaColor.LightYellow - case FadedYellowRosettaColor => urt.RosettaColor.FadedYellow - case DeepGreenRosettaColor => urt.RosettaColor.DeepGreen - case MediumGreenRosettaColor => urt.RosettaColor.MediumGreen - case LightGreenRosettaColor => urt.RosettaColor.LightGreen - case FadedGreenRosettaColor => urt.RosettaColor.FadedGreen - case DeepBlueRosettaColor => urt.RosettaColor.DeepBlue - case TwitterBlueRosettaColor => urt.RosettaColor.TwitterBlue - case LightBlueRosettaColor => urt.RosettaColor.LightBlue - case FadedBlueRosettaColor => urt.RosettaColor.FadedBlue - case FaintBlueRosettaColor => urt.RosettaColor.FaintBlue - case DeepPurpleRosettaColor => urt.RosettaColor.DeepPurple - case MediumPurpleRosettaColor => urt.RosettaColor.MediumPurple - case LightPurpleRosettaColor => urt.RosettaColor.LightPurple - case FadedPurpleRosettaColor => urt.RosettaColor.FadedPurple - case DeepRedRosettaColor => urt.RosettaColor.DeepRed - case MediumRedRosettaColor => urt.RosettaColor.MediumRed - case LightRedRosettaColor => urt.RosettaColor.LightRed - case FadedRedRosettaColor => urt.RosettaColor.FadedRed - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD deleted file mode 100644 index abb1600e9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala deleted file mode 100644 index 3841420e9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverContentMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CoverContentMarshaller @Inject() ( - fullCoverContentMarshaller: FullCoverContentMarshaller, - halfCoverContentMarshaller: HalfCoverContentMarshaller) { - - def apply(coverContent: CoverContent): urt.Cover = coverContent match { - case fullCover: FullCoverContent => fullCoverContentMarshaller(fullCover) - case halfCover: HalfCoverContent => halfCoverContentMarshaller(halfCover) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala deleted file mode 100644 index ae5c49228..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaBehaviorMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCtaBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorDismiss -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverBehaviorNavigate -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller - -@Singleton -class CoverCtaBehaviorMarshaller @Inject() ( - richTextMarshaller: RichTextMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(coverCtaBehavior: CoverCtaBehavior): urt.CoverCtaBehavior = - coverCtaBehavior match { - case dismiss: CoverBehaviorDismiss => - urt.CoverCtaBehavior.Dismiss( - urt.CoverBehaviorDismiss(dismiss.feedbackMessage.map(richTextMarshaller(_)))) - case nav: CoverBehaviorNavigate => - urt.CoverCtaBehavior.Navigate(urt.CoverBehaviorNavigate(urlMarshaller(nav.url))) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala deleted file mode 100644 index c46196cfa..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverCtaMarshaller.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.ButtonStyleMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverCta -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CoverCtaMarshaller @Inject() ( - coverCtaBehaviorMarshaller: CoverCtaBehaviorMarshaller, - callbackMarshaller: CallbackMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - horizonIconMarshaller: HorizonIconMarshaller, - buttonStyleMarshaller: ButtonStyleMarshaller) { - - def apply(coverCta: CoverCta): urt.CoverCta = urt.CoverCta( - text = coverCta.text, - ctaBehavior = coverCtaBehaviorMarshaller(coverCta.ctaBehavior), - callbacks = coverCta.callbacks.map(_.map(callbackMarshaller(_))), - clientEventInfo = coverCta.clientEventInfo.map(clientEventInfoMarshaller(_)), - icon = coverCta.icon.map(horizonIconMarshaller(_)), - buttonStyle = coverCta.buttonStyle.map(buttonStyleMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala deleted file mode 100644 index b04fa0faf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/CoverImageMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageAnimationTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverImage -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CoverImageMarshaller @Inject() ( - imageVariantMarshaller: ImageVariantMarshaller, - imageDisplayTypeMarshaller: ImageDisplayTypeMarshaller, - imageAnimationTypeMarshaller: ImageAnimationTypeMarshaller) { - - def apply(coverImage: CoverImage): urt.CoverImage = - urt.CoverImage( - image = imageVariantMarshaller(coverImage.imageVariant), - imageDisplayType = imageDisplayTypeMarshaller(coverImage.imageDisplayType), - imageAnimationType = coverImage.imageAnimationType.map(imageAnimationTypeMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala deleted file mode 100644 index 3ec88a87a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverContentMarshaller.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.DismissInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageDisplayTypeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FullCoverContentMarshaller @Inject() ( - fullCoverDisplayTypeMarshaller: FullCoverDisplayTypeMarshaller, - coverCtaMarshaller: CoverCtaMarshaller, - richTextMarshaller: RichTextMarshaller, - imageVariantMarshaller: ImageVariantMarshaller, - dismissInfoMarshaller: DismissInfoMarshaller, - imageDisplayTypeMarshaller: ImageDisplayTypeMarshaller, - callbackMarshaller: CallbackMarshaller) { - - def apply(fullCover: FullCoverContent): urt.Cover = - urt.Cover.FullCover( - urt.FullCover( - displayType = fullCoverDisplayTypeMarshaller(fullCover.displayType), - primaryText = richTextMarshaller(fullCover.primaryText), - primaryCoverCta = coverCtaMarshaller(fullCover.primaryCoverCta), - secondaryCoverCta = fullCover.secondaryCoverCta.map(coverCtaMarshaller(_)), - secondaryText = fullCover.secondaryText.map(richTextMarshaller(_)), - image = fullCover.imageVariant.map(imageVariantMarshaller(_)), - details = fullCover.details.map(richTextMarshaller(_)), - dismissInfo = fullCover.dismissInfo.map(dismissInfoMarshaller(_)), - imageDisplayType = fullCover.imageDisplayType.map(imageDisplayTypeMarshaller(_)), - impressionCallbacks = fullCover.impressionCallbacks.map(_.map(callbackMarshaller(_))) - )) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala deleted file mode 100644 index 9a961c925..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/FullCoverDisplayTypeMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverFullCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCoverDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FullCoverDisplayTypeMarshaller @Inject() () { - - def apply(halfCoverDisplayType: FullCoverDisplayType): urt.FullCoverDisplayType = - halfCoverDisplayType match { - case CoverFullCoverDisplayType => urt.FullCoverDisplayType.Cover - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala deleted file mode 100644 index 35f45b27e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverContentMarshaller.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.DismissInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HalfCoverContentMarshaller @Inject() ( - halfCoverDisplayTypeMarshaller: HalfCoverDisplayTypeMarshaller, - coverCtaMarshaller: CoverCtaMarshaller, - richTextMarshaller: RichTextMarshaller, - coverImageMarshaller: CoverImageMarshaller, - dismissInfoMarshaller: DismissInfoMarshaller, - callbackMarshaller: CallbackMarshaller) { - - def apply(halfCover: HalfCoverContent): urt.Cover = - urt.Cover.HalfCover( - urt.HalfCover( - displayType = halfCoverDisplayTypeMarshaller(halfCover.displayType), - primaryText = richTextMarshaller(halfCover.primaryText), - primaryCoverCta = coverCtaMarshaller(halfCover.primaryCoverCta), - secondaryCoverCta = halfCover.secondaryCoverCta.map(coverCtaMarshaller(_)), - secondaryText = halfCover.secondaryText.map(richTextMarshaller(_)), - impressionCallbacks = halfCover.impressionCallbacks.map(_.map(callbackMarshaller(_))), - dismissible = halfCover.dismissible, - coverImage = halfCover.coverImage.map(coverImageMarshaller(_)), - dismissInfo = halfCover.dismissInfo.map(dismissInfoMarshaller(_)) - )) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala deleted file mode 100644 index 537d2faf2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/cover/HalfCoverDisplayTypeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CenterCoverHalfCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.CoverHalfCoverDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCoverDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HalfCoverDisplayTypeMarshaller @Inject() () { - - def apply(halfCoverDisplayType: HalfCoverDisplayType): urt.HalfCoverDisplayType = - halfCoverDisplayType match { - case CenterCoverHalfCoverDisplayType => urt.HalfCoverDisplayType.CenterCover - case CoverHalfCoverDisplayType => urt.HalfCoverDisplayType.Cover - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD deleted file mode 100644 index 83a9b306f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala deleted file mode 100644 index e3d71ff5c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon/HorizonIconMarshaller.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon - -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HorizonIconMarshaller @Inject() () { - - def apply(icon: HorizonIcon): urt.HorizonIcon = icon match { - case Bookmark => urt.HorizonIcon.Bookmark - case Moment => urt.HorizonIcon.Moment - case Debug => urt.HorizonIcon.Debug - case Error => urt.HorizonIcon.Error - case Follow => urt.HorizonIcon.Follow - case Unfollow => urt.HorizonIcon.Unfollow - case Smile => urt.HorizonIcon.Smile - case Frown => urt.HorizonIcon.Frown - case Help => urt.HorizonIcon.Help - case Link => urt.HorizonIcon.Link - case Message => urt.HorizonIcon.Message - case No => urt.HorizonIcon.No - case Outgoing => urt.HorizonIcon.Outgoing - case Pin => urt.HorizonIcon.Pin - case Retweet => urt.HorizonIcon.Retweet - case Speaker => urt.HorizonIcon.Speaker - case Trashcan => urt.HorizonIcon.Trashcan - case Feedback => urt.HorizonIcon.Feedback - case FeedbackClose => urt.HorizonIcon.FeedbackClose - case EyeOff => urt.HorizonIcon.EyeOff - case Moderation => urt.HorizonIcon.Moderation - case Topic => urt.HorizonIcon.Topic - case TopicClose => urt.HorizonIcon.TopicClose - case Flag => urt.HorizonIcon.Flag - case TopicFilled => urt.HorizonIcon.TopicFilled - case NotificationsFollow => urt.HorizonIcon.NotificationsFollow - case Person => urt.HorizonIcon.Person - case BalloonStroke => urt.HorizonIcon.BalloonStroke - case Calendar => urt.HorizonIcon.Calendar - case LocationStroke => urt.HorizonIcon.LocationStroke - case PersonStroke => urt.HorizonIcon.PersonStroke - case Safety => urt.HorizonIcon.Safety - case Logo => urt.HorizonIcon.Logo - case SparkleOn => urt.HorizonIcon.SparkleOn - case StarRising => urt.HorizonIcon.StarRising - case CameraVideo => urt.HorizonIcon.CameraVideo - case ShoppingClock => urt.HorizonIcon.ShoppingClock - case ArrowRight => urt.HorizonIcon.ArrowRight - case SpeakerOff => urt.HorizonIcon.SpeakerOff - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD deleted file mode 100644 index c0ffc860c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -scala_library( - sources = ["**/*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/graphql/contextual_ref", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala deleted file mode 100644 index 8ff49b5e2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleDisplayTypeMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.Default -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ArticleDisplayTypeMarshaller @Inject() () { - def apply(articleDisplayType: ArticleDisplayType): urt.ArticleDisplayType = - articleDisplayType match { - case Default => urt.ArticleDisplayType.Default - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala deleted file mode 100644 index 35c931d79..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleItemMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ArticleItemMarshaller @Inject() ( - articleDisplayTypeMarshaller: ArticleDisplayTypeMarshaller, - socialContextMarshaller: SocialContextMarshaller, - articleSeedTypeMarshaller: ArticleSeedTypeMarshaller) { - def apply(articleItem: ArticleItem): urt.TimelineItemContent = - urt.TimelineItemContent.Article( - urt.Article( - id = articleItem.id, - displayType = articleItem.displayType.map(articleDisplayTypeMarshaller(_)), - socialContext = articleItem.socialContext.map(socialContextMarshaller(_)), - articleSeedType = Some(articleSeedTypeMarshaller(articleItem.articleSeedType)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala deleted file mode 100644 index 0227f8057..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/article/ArticleSeedTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.article - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ArticleSeedType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FollowingListSeed -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.FriendsOfFriendsSeed -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.article.ListIdSeed -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ArticleSeedTypeMarshaller @Inject() () { - - def apply(articleSeedType: ArticleSeedType): urt.ArticleSeedType = - articleSeedType match { - case FollowingListSeed => urt.ArticleSeedType.FollowingList - case FriendsOfFriendsSeed => urt.ArticleSeedType.FriendsOfFriends - case ListIdSeed => urt.ArticleSeedType.ListId - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala deleted file mode 100644 index b9a75756b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/audio_space/AudioSpaceItemMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.audio_space - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space.AudioSpaceItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AudioSpaceItemMarshaller @Inject() () { - - def apply(audioSpaceItem: AudioSpaceItem): urt.TimelineItemContent = - urt.TimelineItemContent.AudioSpace( - urt.AudioSpace( - id = audioSpaceItem.id - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala deleted file mode 100644 index 3565b6aba..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardDisplayTypeMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card - -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card._ -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class CardDisplayTypeMarshaller @Inject() () { - - def apply(cardDisplayType: CardDisplayType): urt.CardDisplayType = cardDisplayType match { - case HeroDisplayType => urt.CardDisplayType.Hero - case CellDisplayType => urt.CardDisplayType.Cell - case TweetCardDisplayType => urt.CardDisplayType.TweetCard - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala deleted file mode 100644 index 2ae8008bf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/card/CardItemMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.card - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.card.CardItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CardItemMarshaller @Inject() ( - cardDisplayTypeMarshaller: CardDisplayTypeMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(cardItem: CardItem): urt.TimelineItemContent = { - urt.TimelineItemContent.Card( - urt.Card( - cardUrl = cardItem.cardUrl, - text = cardItem.text, - subtext = cardItem.subtext, - url = cardItem.url.map(urlMarshaller(_)), - cardDisplayType = cardItem.displayType.map(cardDisplayTypeMarshaller(_)) - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala deleted file mode 100644 index 5fd0b9d56..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductGroupItemMarshaller.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CommerceProductGroupItemMarshaller @Inject() () { - - def apply(commerceProductGroupItem: CommerceProductGroupItem): urt.TimelineItemContent = - urt.TimelineItemContent.CommerceProductGroup( - urt.CommerceProductGroup(commerceProductGroupItem.id)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala deleted file mode 100644 index 8bc08beae..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/commerce/CommerceProductItemMarshaller.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.commerce - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CommerceProductItemMarshaller @Inject() () { - - def apply(commerceProductItem: CommerceProductItem): urt.TimelineItemContent = - urt.TimelineItemContent.CommerceProduct(urt.CommerceProduct(commerceProductItem.id)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala deleted file mode 100644 index bed51192e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotation -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConversationAnnotationMarshaller @Inject() ( - conversationAnnotationTypeMarshaller: ConversationAnnotationTypeMarshaller, - richTextMarshaller: RichTextMarshaller) { - - def apply(conversationAnnotation: ConversationAnnotation): urt.ConversationAnnotation = { - urt.ConversationAnnotation( - conversationAnnotationType = - conversationAnnotationTypeMarshaller(conversationAnnotation.conversationAnnotationType), - header = conversationAnnotation.header.map(richTextMarshaller(_)), - description = conversationAnnotation.description.map(richTextMarshaller(_)) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala deleted file mode 100644 index 85488d061..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/conversation_annotation/ConversationAnnotationTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotationType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.Large -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.Political - -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConversationAnnotationTypeMarshaller @Inject() () { - - def apply( - conversationAnnotationType: ConversationAnnotationType - ): urt.ConversationAnnotationType = conversationAnnotationType match { - case Large => urt.ConversationAnnotationType.Large - case Political => urt.ConversationAnnotationType.Political - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala deleted file mode 100644 index 3b325d822..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryDisplayTypeMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.CellEventSummaryDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.HeroEventSummaryDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.CellWithProminentSocialContextEventSummaryDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class EventSummaryDisplayTypeMarshaller @Inject() () { - - def apply( - eventSummaryDisplayType: EventSummaryDisplayType - ): urt.EventSummaryDisplayType = eventSummaryDisplayType match { - case CellEventSummaryDisplayType => - urt.EventSummaryDisplayType.Cell - case HeroEventSummaryDisplayType => - urt.EventSummaryDisplayType.Hero - case CellWithProminentSocialContextEventSummaryDisplayType => - urt.EventSummaryDisplayType.CellWithProminentSocialContext - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala deleted file mode 100644 index 0aa7b2471..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/event/EventSummaryItemMarshaller.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.event - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.event.EventSummaryItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class EventSummaryItemMarshaller @Inject() ( - eventSummaryDisplayTypeMarshaller: EventSummaryDisplayTypeMarshaller, - imageVariantMarshaller: ImageVariantMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(eventSummary: EventSummaryItem): urt.TimelineItemContent = - urt.TimelineItemContent.EventSummary( - urt.EventSummary( - id = eventSummary.id, - title = eventSummary.title, - displayType = eventSummaryDisplayTypeMarshaller(eventSummary.displayType), - url = urlMarshaller(eventSummary.url), - image = eventSummary.image.map(imageVariantMarshaller(_)), - timeString = eventSummary.timeString - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala deleted file mode 100644 index 648d8fb87..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotDisplayTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.CommunityNotes -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivotDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.LiveEvent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.SoftIntervention -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ForwardPivotDisplayTypeMarshaller @Inject() () { - - def apply(forwardPivotDisplayType: ForwardPivotDisplayType): urt.ForwardPivotDisplayType = - forwardPivotDisplayType match { - case LiveEvent => urt.ForwardPivotDisplayType.LiveEvent - case SoftIntervention => urt.ForwardPivotDisplayType.SoftIntervention - case CommunityNotes => urt.ForwardPivotDisplayType.CommunityNotes - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala deleted file mode 100644 index 6ef392c95..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/ForwardPivotMarshaller.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.BadgeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivot -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ForwardPivotMarshaller @Inject() ( - urlMarshaller: UrlMarshaller, - richTextMarshaller: RichTextMarshaller, - forwardPivotDisplayTypeMarshaller: ForwardPivotDisplayTypeMarshaller, - softInterventionDisplayTypeMarshaller: SoftInterventionDisplayTypeMarshaller, - imageVariantMarshaller: ImageVariantMarshaller, - badgeMarshaller: BadgeMarshaller, - rosettaColorMarshaller: RosettaColorMarshaller) { - - def apply(forwardPivot: ForwardPivot): urt.ForwardPivot = urt.ForwardPivot( - text = richTextMarshaller(forwardPivot.text), - landingUrl = urlMarshaller(forwardPivot.landingUrl), - displayType = forwardPivotDisplayTypeMarshaller(forwardPivot.displayType), - iconImageVariant = forwardPivot.iconImageVariant.map(imageVariantMarshaller(_)), - stateBadge = forwardPivot.stateBadge.map(badgeMarshaller(_)), - subtext = forwardPivot.subtext.map(richTextMarshaller(_)), - backgroundColorName = forwardPivot.backgroundColorName.map(rosettaColorMarshaller(_)), - engagementNudge = forwardPivot.engagementNudge, - softInterventionDisplayType = - forwardPivot.softInterventionDisplayType.map(softInterventionDisplayTypeMarshaller(_)), - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala deleted file mode 100644 index e2bf9dc34..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/forward_pivot/SoftInterventionDisplayTypeMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.GetTheLatest -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.GovernmentRequested -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.Misleading -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.SoftInterventionDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.StayInformed -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SoftInterventionDisplayTypeMarshaller @Inject() () { - - def apply( - softInterventionDisplayType: SoftInterventionDisplayType - ): urt.SoftInterventionDisplayType = - softInterventionDisplayType match { - case GetTheLatest => urt.SoftInterventionDisplayType.GetTheLatest - case StayInformed => urt.SoftInterventionDisplayType.StayInformed - case Misleading => urt.SoftInterventionDisplayType.Misleading - case GovernmentRequested => urt.SoftInterventionDisplayType.GovernmentRequested - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala deleted file mode 100644 index ff5ff44d6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryActionMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryAction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GenericSummaryActionMarshaller @Inject() ( - urlMarshaller: UrlMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller) { - - def apply(genericSummaryItemAction: GenericSummaryAction): urt.GenericSummaryAction = - urt.GenericSummaryAction( - url = urlMarshaller(genericSummaryItemAction.url), - clientEventInfo = genericSummaryItemAction.clientEventInfo.map(clientEventInfoMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala deleted file mode 100644 index 67401cbba..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryContextMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryContext -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GenericSummaryContextMarshaller @Inject() ( - richTextMarshaller: RichTextMarshaller, - horizonIconMarshaller: HorizonIconMarshaller) { - - def apply(genericSummaryItemContext: GenericSummaryContext): urt.GenericSummaryContext = - urt.GenericSummaryContext( - text = richTextMarshaller(genericSummaryItemContext.text), - icon = genericSummaryItemContext.icon.map(horizonIconMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala deleted file mode 100644 index 293736390..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryDisplayTypeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItemDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.HeroDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GenericSummaryDisplayTypeMarshaller @Inject() () { - - def apply( - genericSummaryItemDisplayType: GenericSummaryItemDisplayType - ): urt.GenericSummaryDisplayType = - genericSummaryItemDisplayType match { - case HeroDisplayType => urt.GenericSummaryDisplayType.Hero - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala deleted file mode 100644 index 0717a5c34..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/generic_summary_item/GenericSummaryItemMarshaller.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.generic_summary_item - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media.MediaMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary.GenericSummaryItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GenericSummaryItemMarshaller @Inject() ( - genericSummaryDisplayTypeMarshaller: GenericSummaryDisplayTypeMarshaller, - genericSummaryContextMarshaller: GenericSummaryContextMarshaller, - genericSummaryActionMarshaller: GenericSummaryActionMarshaller, - mediaMarshaller: MediaMarshaller, - promotedMetadataMarshaller: PromotedMetadataMarshaller, - richTextMarshaller: RichTextMarshaller) { - - def apply(genericSummaryItem: GenericSummaryItem): urt.TimelineItemContent = - urt.TimelineItemContent.GenericSummary( - urt.GenericSummary( - headline = richTextMarshaller(genericSummaryItem.headline), - displayType = genericSummaryDisplayTypeMarshaller(genericSummaryItem.displayType), - userAttributionIds = genericSummaryItem.userAttributionIds, - media = genericSummaryItem.media.map(mediaMarshaller(_)), - context = genericSummaryItem.context.map(genericSummaryContextMarshaller(_)), - timestamp = genericSummaryItem.timestamp.map(_.inMilliseconds), - onClickAction = genericSummaryItem.onClickAction.map(genericSummaryActionMarshaller(_)), - promotedMetadata = genericSummaryItem.promotedMetadata.map(promotedMetadataMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala deleted file mode 100644 index a370e7a9b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/highlight/HighlightedSectionMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HighlightedSectionMarshaller @Inject() () { - - def apply(highlightedSection: HighlightedSection): urt.HighlightedSection = - urt.HighlightedSection( - startIndex = highlightedSection.startIndex, - endIndex = highlightedSection.endIndex - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala deleted file mode 100644 index c6830185c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/icon_label/IconLabelItemMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.icon_label - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label.IconLabelItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class IconLabelItemMarshaller @Inject() ( - richTextMarshaller: RichTextMarshaller, - horizonIconMarshaller: HorizonIconMarshaller) { - - def apply(iconLabelItem: IconLabelItem): urt.TimelineItemContent = - urt.TimelineItemContent.IconLabel( - urt.IconLabel( - text = richTextMarshaller(iconLabelItem.text), - icon = iconLabelItem.icon.map(horizonIconMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala deleted file mode 100644 index 119c6adf7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelDisplayTypeMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.label._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LabelDisplayTypeMarshaller @Inject() () { - - def apply(labelDisplayType: LabelDisplayType): urt.LabelDisplayType = labelDisplayType match { - case InlineHeaderLabelDisplayType => urt.LabelDisplayType.InlineHeader - case OtherRepliesSectionHeaderLabelDisplayType => urt.LabelDisplayType.OtherRepliesSectionHeader - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala deleted file mode 100644 index 10dae7f8a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/label/LabelItemMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.label - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.label.LabelItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LabelItemMarshaller @Inject() ( - displayTypeMarshaller: LabelDisplayTypeMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(labelItem: LabelItem): urt.TimelineItemContent = { - urt.TimelineItemContent.Label( - urt.Label( - text = labelItem.text, - subtext = labelItem.subtext, - disclosureIndicator = labelItem.disclosureIndicator, - url = labelItem.url.map(urlMarshaller(_)), - displayType = labelItem.displayType.map(displayTypeMarshaller(_)) - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala deleted file mode 100644 index c40867874..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/CompactPromptMessageContentMarshaller.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactPromptMessageContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CompactPromptMessageContentMarshaller @Inject() ( - messageTextActionMarshaller: MessageTextActionMarshaller, - messageActionMarshaller: MessageActionMarshaller, - richTextMarshaller: RichTextMarshaller) { - - def apply(compactPromptMessageContent: CompactPromptMessageContent): urt.MessageContent = - urt.MessageContent.CompactPrompt( - urt.CompactPrompt( - headerText = compactPromptMessageContent.headerText, - bodyText = compactPromptMessageContent.bodyText, - primaryButtonAction = - compactPromptMessageContent.primaryButtonAction.map(messageTextActionMarshaller(_)), - secondaryButtonAction = - compactPromptMessageContent.secondaryButtonAction.map(messageTextActionMarshaller(_)), - action = compactPromptMessageContent.action.map(messageActionMarshaller(_)), - headerRichText = compactPromptMessageContent.headerRichText.map(richTextMarshaller(_)), - bodyRichText = compactPromptMessageContent.bodyRichText.map(richTextMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala deleted file mode 100644 index ba3abac35..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/HeaderImagePromptMessageContentMarshaller.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.HeaderImagePromptMessageContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class HeaderImagePromptMessageContentMarshaller @Inject() ( - messageImageMarshaller: MessageImageMarshaller, - messageTextActionMarshaller: MessageTextActionMarshaller, - messageActionMarshaller: MessageActionMarshaller, - richTextMarshaller: RichTextMarshaller) { - - def apply( - headerImagePromptMessageContent: HeaderImagePromptMessageContent - ): urt.MessageContent = - urt.MessageContent.HeaderImagePrompt( - urt.HeaderImagePrompt( - headerImage = messageImageMarshaller(headerImagePromptMessageContent.headerImage), - headerText = headerImagePromptMessageContent.headerText, - bodyText = headerImagePromptMessageContent.bodyText, - primaryButtonAction = - headerImagePromptMessageContent.primaryButtonAction.map(messageTextActionMarshaller(_)), - secondaryButtonAction = - headerImagePromptMessageContent.secondaryButtonAction.map(messageTextActionMarshaller(_)), - action = headerImagePromptMessageContent.action.map(messageActionMarshaller(_)), - headerRichText = headerImagePromptMessageContent.headerRichText.map(richTextMarshaller(_)), - bodyRichText = headerImagePromptMessageContent.bodyRichText.map(richTextMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala deleted file mode 100644 index e33830dbb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/InlinePromptMessageContentMarshaller.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class InlinePromptMessageContentMarshaller @Inject() ( - messageTextActionMarshaller: MessageTextActionMarshaller, - richTextMarshaller: RichTextMarshaller, - socialContextMarshaller: SocialContextMarshaller, - userFacepileMarshaller: UserFacepileMarshaller) { - - def apply(inlinePromptMessageContent: InlinePromptMessageContent): urt.MessageContent = - urt.MessageContent.InlinePrompt( - urt.InlinePrompt( - headerText = inlinePromptMessageContent.headerText, - bodyText = inlinePromptMessageContent.bodyText, - primaryButtonAction = - inlinePromptMessageContent.primaryButtonAction.map(messageTextActionMarshaller(_)), - secondaryButtonAction = - inlinePromptMessageContent.secondaryButtonAction.map(messageTextActionMarshaller(_)), - headerRichText = inlinePromptMessageContent.headerRichText.map(richTextMarshaller(_)), - bodyRichText = inlinePromptMessageContent.bodyRichText.map(richTextMarshaller(_)), - socialContext = inlinePromptMessageContent.socialContext.map(socialContextMarshaller(_)), - userFacepile = inlinePromptMessageContent.userFacepile.map(userFacepileMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala deleted file mode 100644 index ca8612585..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageAction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageActionMarshaller @Inject() ( - callbackMarshaller: CallbackMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller) { - - def apply(messageAction: MessageAction): urt.MessageAction = { - - urt.MessageAction( - dismissOnClick = messageAction.dismissOnClick, - url = messageAction.url, - clientEventInfo = messageAction.clientEventInfo.map(clientEventInfoMarshaller(_)), - onClickCallbacks = - messageAction.onClickCallbacks.map(callbackList => callbackList.map(callbackMarshaller(_))) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala deleted file mode 100644 index dde02b150..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageActionTypeMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.FollowAllMessageActionType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageActionType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageActionTypeMarshaller @Inject() () { - - def apply(messageActionType: MessageActionType): urt.MessageActionType = messageActionType match { - case FollowAllMessageActionType => urt.MessageActionType.FollowAll - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala deleted file mode 100644 index 01f1501ad..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageContentMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactPromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.InlinePromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.HeaderImagePromptMessageContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageContentMarshaller @Inject() ( - inlinePromptMessageContentMarshaller: InlinePromptMessageContentMarshaller, - headerImagePromptMessageContentMarshaller: HeaderImagePromptMessageContentMarshaller, - compactPromptMessageContentMarshaller: CompactPromptMessageContentMarshaller) { - - def apply(messageContent: MessageContent): urt.MessageContent = messageContent match { - case inlinePromptMessageContent: InlinePromptMessageContent => - inlinePromptMessageContentMarshaller(inlinePromptMessageContent) - case headerImagePromptMessageContent: HeaderImagePromptMessageContent => - headerImagePromptMessageContentMarshaller(headerImagePromptMessageContent) - case compactPromptMessageContent: CompactPromptMessageContent => - compactPromptMessageContentMarshaller(compactPromptMessageContent) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala deleted file mode 100644 index c10a26903..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageImageMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageImage -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageImageMarshaller @Inject() ( - imageVariantMarshaller: ImageVariantMarshaller) { - - def apply(messageImage: MessageImage): urt.MessageImage = { - urt.MessageImage( - imageVariants = messageImage.imageVariants.map(imageVariantMarshaller(_)), - backgroundColor = messageImage.backgroundColor - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala deleted file mode 100644 index a5a4a3a77..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessagePromptItemMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessagePromptItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessagePromptItemMarshaller @Inject() ( - messageContentMarshaller: MessageContentMarshaller, - callbackMarshaller: CallbackMarshaller) { - - def apply(messagePromptItem: MessagePromptItem): urt.TimelineItemContent = - urt.TimelineItemContent.Message( - urt.MessagePrompt( - content = messageContentMarshaller(messagePromptItem.content), - impressionCallbacks = messagePromptItem.impressionCallbacks.map { callbackList => - callbackList.map(callbackMarshaller(_)) - } - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala deleted file mode 100644 index f7a21d6e1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/MessageTextActionMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.MessageTextAction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MessageTextActionMarshaller @Inject() ( - messageActionMarshaller: MessageActionMarshaller) { - - def apply(messageTextAction: MessageTextAction): urt.MessageTextAction = - urt.MessageTextAction( - text = messageTextAction.text, - action = messageActionMarshaller(messageTextAction.action) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala deleted file mode 100644 index 9c7d39f0c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileDisplayTypeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.LargeUserFacepileDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.CompactUserFacepileDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepileDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UserFacepileDisplayTypeMarshaller @Inject() () { - - def apply(userFacepileDisplayType: UserFacepileDisplayType): urt.UserFacepileDisplayType = - userFacepileDisplayType match { - case LargeUserFacepileDisplayType => urt.UserFacepileDisplayType.Large - case CompactUserFacepileDisplayType => urt.UserFacepileDisplayType.Compact - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala deleted file mode 100644 index c6f5dabc8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/message/UserFacepileMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.message.UserFacepile -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UserFacepileMarshaller @Inject() ( - messageActionTypeMarshaller: MessageActionTypeMarshaller, - messageTextActionMarshaller: MessageTextActionMarshaller, - userFacepileDisplayTypeMarshaller: UserFacepileDisplayTypeMarshaller) { - - def apply(userFacepile: UserFacepile): urt.UserFacepile = - urt.UserFacepile( - userIds = userFacepile.userIds, - featuredUserIds = userFacepile.featuredUserIds, - action = userFacepile.action.map(messageTextActionMarshaller(_)), - actionType = userFacepile.actionType.map(messageActionTypeMarshaller(_)), - displaysFeaturingText = userFacepile.displaysFeaturingText, - displayType = userFacepile.displayType.map(userFacepileDisplayTypeMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala deleted file mode 100644 index 59f33f3d1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/moment/MomentAnnotationItemMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.moment - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment.MomentAnnotationItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MomentAnnotationItemMarshaller @Inject() (richTextMarshaller: RichTextMarshaller) { - def apply(momentAnnotationItem: MomentAnnotationItem): urt.TimelineItemContent = { - urt.TimelineItemContent.MomentAnnotation( - urt.MomentAnnotation( - annotationId = momentAnnotationItem.id, - text = momentAnnotationItem.text.map(richTextMarshaller(_)), - header = momentAnnotationItem.header.map(richTextMarshaller(_)), - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala deleted file mode 100644 index 9b669dd04..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptContentMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PromptContentMarshaller @Inject() ( - relevancePromptContentMarshaller: RelevancePromptContentMarshaller) { - - def apply(promptContent: PromptContent): urt.PromptContent = promptContent match { - case relevancePromptContent: RelevancePromptContent => - urt.PromptContent.RelevancePrompt(relevancePromptContentMarshaller(relevancePromptContent)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala deleted file mode 100644 index ccefd082b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/PromptItemMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ClientEventInfoMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.PromptItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PromptItemMarshaller @Inject() ( - promptContentMarshaller: PromptContentMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - callbackMarshaller: CallbackMarshaller) { - - def apply(relevancePromptItem: PromptItem): urt.TimelineItemContent = { - urt.TimelineItemContent.Prompt( - urt.Prompt( - content = promptContentMarshaller(relevancePromptItem.content), - clientEventInfo = relevancePromptItem.clientEventInfo.map(clientEventInfoMarshaller(_)), - impressionCallbacks = relevancePromptItem.impressionCallbacks.map { callbackList => - callbackList.map(callbackMarshaller(_)) - } - )) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala deleted file mode 100644 index be5d87003..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptContentMarshaller.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RelevancePromptContentMarshaller @Inject() ( - callbackMarshaller: CallbackMarshaller, - relevancePromptDisplayTypeMarshaller: RelevancePromptDisplayTypeMarshaller, - relevancePromptFollowUpFeedbackTypeMarshaller: RelevancePromptFollowUpFeedbackTypeMarshaller) { - - def apply(relevancePromptContent: RelevancePromptContent): urt.RelevancePrompt = - urt.RelevancePrompt( - title = relevancePromptContent.title, - confirmation = relevancePromptContent.confirmation, - isRelevantText = relevancePromptContent.isRelevantText, - notRelevantText = relevancePromptContent.notRelevantText, - isRelevantCallback = callbackMarshaller(relevancePromptContent.isRelevantCallback), - notRelevantCallback = callbackMarshaller(relevancePromptContent.notRelevantCallback), - displayType = relevancePromptDisplayTypeMarshaller(relevancePromptContent.displayType), - isRelevantFollowUp = relevancePromptContent.isRelevantFollowUp.map( - relevancePromptFollowUpFeedbackTypeMarshaller(_)), - notRelevantFollowUp = relevancePromptContent.notRelevantFollowUp.map( - relevancePromptFollowUpFeedbackTypeMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala deleted file mode 100644 index f81247e95..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptDisplayTypeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Singleton - -@Singleton -class RelevancePromptDisplayTypeMarshaller { - - def apply( - relevancePromptDisplayType: RelevancePromptDisplayType - ): urt.RelevancePromptDisplayType = relevancePromptDisplayType match { - case Normal => urt.RelevancePromptDisplayType.Normal - case Compact => urt.RelevancePromptDisplayType.Compact - case Large => urt.RelevancePromptDisplayType.Large - case ThumbsUpAndDown => urt.RelevancePromptDisplayType.ThumbsUpAndDown - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala deleted file mode 100644 index 8b01c14f6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpFeedbackTypeMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RelevancePromptFollowUpFeedbackTypeMarshaller @Inject() ( - relevancePromptFollowUpTextInputMarshaller: RelevancePromptFollowUpTextInputMarshaller) { - - def apply( - relevancePromptFollowUpFeedbackType: RelevancePromptFollowUpFeedbackType - ): urt.RelevancePromptFollowUpFeedbackType = relevancePromptFollowUpFeedbackType match { - case relevancePromptFollowUpTextInput: RelevancePromptFollowUpTextInput => - urt.RelevancePromptFollowUpFeedbackType.FollowUpTextInput( - relevancePromptFollowUpTextInputMarshaller(relevancePromptFollowUpTextInput)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala deleted file mode 100644 index d244e628f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/prompt/RelevancePromptFollowUpTextInputMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.prompt - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.CallbackMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt.RelevancePromptFollowUpTextInput -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RelevancePromptFollowUpTextInputMarshaller @Inject() ( - callbackMarshaller: CallbackMarshaller) { - - def apply( - relevancePromptFollowUpTextInput: RelevancePromptFollowUpTextInput - ): urt.RelevancePromptFollowUpTextInput = urt.RelevancePromptFollowUpTextInput( - context = relevancePromptFollowUpTextInput.context, - textFieldPlaceholder = relevancePromptFollowUpTextInput.textFieldPlaceholder, - sendTextCallback = callbackMarshaller(relevancePromptFollowUpTextInput.sendTextCallback) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala deleted file mode 100644 index 737c8e3ff..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingActionTypeMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Singleton - -@Singleton -class SpellingActionTypeMarshaller { - - def apply(spellingActionType: SpellingActionType): urt.SpellingActionType = - spellingActionType match { - case ReplaceSpellingActionType => urt.SpellingActionType.Replace - case ExpandSpellingActionType => urt.SpellingActionType.Expand - case SuggestSpellingActionType => urt.SpellingActionType.Suggest - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala deleted file mode 100644 index 4e0afe10c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/SpellingItemMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.SpellingItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SpellingItemMarshaller @Inject() ( - textResultMarshaller: TextResultMarshaller, - spellingActionTypeMarshaller: SpellingActionTypeMarshaller) { - - def apply(spellingItem: SpellingItem): urt.TimelineItemContent = { - urt.TimelineItemContent.Spelling( - urt.Spelling( - spellingResult = textResultMarshaller(spellingItem.textResult), - spellingAction = spellingItem.spellingActionType.map(spellingActionTypeMarshaller(_)), - originalQuery = spellingItem.originalQuery - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala deleted file mode 100644 index 44c353b48..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/suggestion/TextResultMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.suggestion - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight.HighlightedSectionMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion.TextResult -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TextResultMarshaller @Inject() (highlightedSectionMarshaller: HighlightedSectionMarshaller) { - - def apply(textResult: TextResult): urt.TextResult = { - val hitHighlights = textResult.hitHighlights.map { - highlightedSections: Seq[HighlightedSection] => - highlightedSections.map(highlightedSectionMarshaller(_)) - } - - urt.TextResult( - text = textResult.text, - hitHighlights = hitHighlights, - score = textResult.score, - querySource = textResult.querySource) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala deleted file mode 100644 index de79fe4e8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderContentMarshaller.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ThreadHeaderContentMarshaller @Inject() () { - def apply(content: ThreadHeaderContent): urt.ThreadHeaderContent = content match { - case UserThreadHeader(userId) => - urt.ThreadHeaderContent.UserThreadHeader(urt.UserThreadHeader(userId)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala deleted file mode 100644 index 8d88d7d33..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/thread/ThreadHeaderItemMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.thread - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread.ThreadHeaderItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ThreadHeaderItemMarshaller @Inject() ( - threadHeaderContentMarshaller: ThreadHeaderContentMarshaller) { - - def apply(threadHeaderItem: ThreadHeaderItem): urt.TimelineItemContent.ThreadHeader = - urt.TimelineItemContent.ThreadHeader( - urt.ThreadHeaderItem( - content = threadHeaderContentMarshaller(threadHeaderItem.content) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala deleted file mode 100644 index 52e92691b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/CallToActionTileContentMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.button.CtaButtonMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.CallToActionTileContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CallToActionTileContentMarshaller @Inject() ( - ctaButtonMarshaller: CtaButtonMarshaller, - richTextMarshaller: RichTextMarshaller) { - - def apply(callToActionTileContent: CallToActionTileContent): urt.TileContentCallToAction = - urt.TileContentCallToAction( - text = callToActionTileContent.text, - richText = callToActionTileContent.richText.map(richTextMarshaller(_)), - ctaButton = callToActionTileContent.ctaButton.map(ctaButtonMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala deleted file mode 100644 index 042f9dc69..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/StandardTileContentMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.BadgeMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class StandardTileContentMarshaller @Inject() ( - badgeMarshaller: BadgeMarshaller) { - - def apply(standardTileContent: StandardTileContent): urt.TileContentStandard = - urt.TileContentStandard( - title = standardTileContent.title, - supportingText = standardTileContent.supportingText, - badge = standardTileContent.badge.map(badgeMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala deleted file mode 100644 index 2688a9e4d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileContentMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.CallToActionTileContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.StandardTileContent -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileContent -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TileContentMarshaller @Inject() ( - standardTileContentMarshaller: StandardTileContentMarshaller, - callToActionTileContentMarshaller: CallToActionTileContentMarshaller) { - - def apply(tileContent: TileContent): urt.TileContent = tileContent match { - case tileCont: StandardTileContent => - urt.TileContent.Standard(standardTileContentMarshaller(tileCont)) - case tileCont: CallToActionTileContent => - urt.TileContent.CallToAction(callToActionTileContentMarshaller(tileCont)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala deleted file mode 100644 index e926568cc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tile/TileItemMarshaller.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tile - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile.TileItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TileItemMarshaller @Inject() ( - tileContentMarshaller: TileContentMarshaller, - urlMarshaller: UrlMarshaller, - imageVariantMarshaller: ImageVariantMarshaller) { - - def apply(tileItem: TileItem): urt.TimelineItemContent = { - urt.TimelineItemContent.Tile( - urt.Tile( - title = tileItem.title, - supportingText = tileItem.supportingText, - url = tileItem.url.map(urlMarshaller(_)), - image = tileItem.image.map(imageVariantMarshaller(_)), - badge = None, - content = tileContentMarshaller(tileItem.content) - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala deleted file mode 100644 index 323e2a429..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneDisplayTypeMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.DisconnectedRepliesAncestor -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.DisconnectedRepliesDescendant -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.Inline -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.NonCompliant -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TweetUnavailable -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TombstoneDisplayTypeMarshaller @Inject() () { - - def apply(tombstoneDisplayType: TombstoneDisplayType): urt.TombstoneDisplayType = - tombstoneDisplayType match { - case TweetUnavailable => urt.TombstoneDisplayType.TweetUnavailable - case DisconnectedRepliesAncestor => urt.TombstoneDisplayType.DisconnectedRepliesAncestor - case DisconnectedRepliesDescendant => urt.TombstoneDisplayType.DisconnectedRepliesDescendant - case Inline => urt.TombstoneDisplayType.Inline - case NonCompliant => urt.TombstoneDisplayType.NonCompliant - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala deleted file mode 100644 index 0a996eee6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneInfoMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext.RichTextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TombstoneInfoMarshaller @Inject() ( - richTextMarshaller: RichTextMarshaller) { - - def apply(tombstoneInfo: TombstoneInfo): urt.TombstoneInfo = urt.TombstoneInfo( - text = tombstoneInfo.text, - richText = tombstoneInfo.richText.map(richTextMarshaller(_)), - richRevealText = tombstoneInfo.richRevealText.map(richTextMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala deleted file mode 100644 index 6cc94b38c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tombstone/TombstoneItemMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet.TweetItemMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TombstoneItemMarshaller @Inject() ( - displayTypeMarshaller: TombstoneDisplayTypeMarshaller, - tombstoneInfoMarshaller: TombstoneInfoMarshaller, - tweetItemMarshaller: TweetItemMarshaller) { - - def apply(tombstoneItem: TombstoneItem): urt.TimelineItemContent = - urt.TimelineItemContent.Tombstone( - urt.Tombstone( - displayType = displayTypeMarshaller(tombstoneItem.tombstoneDisplayType), - tombstoneInfo = tombstoneItem.tombstoneInfo.map(tombstoneInfoMarshaller(_)), - tweet = tombstoneItem.tweet.map(tweetItemMarshaller(_).tweet) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala deleted file mode 100644 index eb8d0187e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicDisplayTypeMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.NoIconTopicDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillTopicDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PillWithoutActionIconDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicDisplayTypeMarshaller @Inject() () { - - def apply(topicDisplayType: TopicDisplayType): urt.TopicDisplayType = topicDisplayType match { - case BasicTopicDisplayType => urt.TopicDisplayType.Basic - case PillTopicDisplayType => urt.TopicDisplayType.Pill - case NoIconTopicDisplayType => urt.TopicDisplayType.NoIcon - case PillWithoutActionIconDisplayType => urt.TopicDisplayType.PillWithoutActionIcon - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala deleted file mode 100644 index 97bed21f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptDisplayTypeMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.IncentiveFocusTopicFollowPromptDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFocusTopicFollowPromptDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFollowPromptDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicFollowPromptDisplayTypeMarshaller @Inject() () { - - def apply( - topicFollowPromptDisplayType: TopicFollowPromptDisplayType - ): urt.TopicFollowPromptDisplayType = - topicFollowPromptDisplayType match { - case IncentiveFocusTopicFollowPromptDisplayType => - urt.TopicFollowPromptDisplayType.IncentiveFocus - case TopicFocusTopicFollowPromptDisplayType => urt.TopicFollowPromptDisplayType.TopicFocus - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala deleted file mode 100644 index 05ebe46f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFollowPromptItemMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFollowPromptItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicFollowPromptItemMarshaller @Inject() ( - displayTypeMarshaller: TopicFollowPromptDisplayTypeMarshaller) { - - def apply(topicFollowPromptItem: TopicFollowPromptItem): urt.TimelineItemContent = { - urt.TimelineItemContent.TopicFollowPrompt( - urt.TopicFollowPrompt( - topicId = topicFollowPromptItem.id.toString, - displayType = displayTypeMarshaller(topicFollowPromptItem.topicFollowPromptDisplayType), - followIncentiveTitle = topicFollowPromptItem.followIncentiveTitle, - followIncentiveText = topicFollowPromptItem.followIncentiveText - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala deleted file mode 100644 index 4646c37a1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicFunctionalityTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.BasicTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.PivotTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.RecommendationTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicFunctionalityType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicFunctionalityTypeMarshaller @Inject() () { - - def apply(topicFunctionalityType: TopicFunctionalityType): urt.TopicFunctionalityType = - topicFunctionalityType match { - case BasicTopicFunctionalityType => urt.TopicFunctionalityType.Basic - case RecommendationTopicFunctionalityType => urt.TopicFunctionalityType.Recommendation - case PivotTopicFunctionalityType => urt.TopicFunctionalityType.Pivot - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala deleted file mode 100644 index ad43d16a7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/topic/TopicItemMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic.TopicItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicItemMarshaller @Inject() ( - displayTypeMarshaller: TopicDisplayTypeMarshaller, - functionalityTypeMarshaller: TopicFunctionalityTypeMarshaller) { - - def apply(topicItem: TopicItem): urt.TimelineItemContent = { - urt.TimelineItemContent.Topic( - urt.Topic( - topicId = topicItem.id.toString, - topicDisplayType = topicItem.topicDisplayType - .map(displayTypeMarshaller(_)).getOrElse(urt.TopicDisplayType.Basic), - topicFunctionalityType = topicItem.topicFunctionalityType - .map(functionalityTypeMarshaller(_)).getOrElse(urt.TopicFunctionalityType.Basic), - // This is currently not required by users of this library - reactiveTriggers = None - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala deleted file mode 100644 index 0386c5fa8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/trend/TrendItemMarshaller.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.trend - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend.TrendItem -import com.twitter.timelines.render.thriftscala.GroupedTrend -import com.twitter.timelines.render.thriftscala.TrendMetadata -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class TrendItemMarshaller @Inject() ( - promotedMetadataMarshaller: PromotedMetadataMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(trendItem: TrendItem): urt.TimelineItemContent = - urt.TimelineItemContent.Trend( - urt.Trend( - name = trendItem.trendName, - url = urlMarshaller(trendItem.url), - promotedMetadata = trendItem.promotedMetadata.map(promotedMetadataMarshaller(_)), - description = trendItem.description, - trendMetadata = Some( - TrendMetadata( - metaDescription = trendItem.metaDescription, - url = Some(urlMarshaller(trendItem.url)), - domainContext = trendItem.domainContext - )), - groupedTrends = trendItem.groupedTrends.map { trends => - trends.map { trend => - GroupedTrend(name = trend.trendName, url = urlMarshaller(trend.url)) - } - } - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala deleted file mode 100644 index 53f75b716..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TimelinesScoreInfoMarshaller.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TimelinesScoreInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelinesScoreInfoMarshaller @Inject() () { - - def apply(timelinesScoreInfo: TimelinesScoreInfo): urt.TimelinesScoreInfo = - urt.TimelinesScoreInfo(score = timelinesScoreInfo.score) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala deleted file mode 100644 index 734dec577..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetDisplayTypeMarshaller.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetDisplayTypeMarshaller @Inject() () { - - def apply(tweetDisplayType: TweetDisplayType): urt.TweetDisplayType = tweetDisplayType match { - case Tweet => urt.TweetDisplayType.Tweet - case TweetFollowOnly => urt.TweetDisplayType.TweetFollowOnly - case Media => urt.TweetDisplayType.Media - case MomentTimelineTweet => urt.TweetDisplayType.MomentTimelineTweet - case EmphasizedPromotedTweet => urt.TweetDisplayType.EmphasizedPromotedTweet - case QuotedTweet => urt.TweetDisplayType.QuotedTweet - case SelfThread => urt.TweetDisplayType.SelfThread - case CompactPromotedTweet => urt.TweetDisplayType.CompactPromotedTweet - case TweetWithoutCard => urt.TweetDisplayType.TweetWithoutCard - case ReaderModeRoot => urt.TweetDisplayType.ReaderModeRoot - case ReaderMode => urt.TweetDisplayType.ReaderMode - case CondensedTweet => urt.TweetDisplayType.CondensedTweet - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala deleted file mode 100644 index 10026f7ac..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetHighlightsMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.highlight.HighlightedSectionMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetHighlights -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetHighlightsMarshaller @Inject() ( - highlightedSectionMarshaller: HighlightedSectionMarshaller) { - - def apply(tweetHighlights: TweetHighlights): urt.TweetHighlights = - urt.TweetHighlights( - textHighlights = tweetHighlights.textHighlights - .map(_.map(highlightedSectionMarshaller(_))), - cardTitleHighlights = tweetHighlights.cardTitleHighlights - .map(_.map(highlightedSectionMarshaller(_))), - cardDescriptionHighlights = tweetHighlights.cardDescriptionHighlights - .map(_.map(highlightedSectionMarshaller(_))) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala deleted file mode 100644 index ee5222e4f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet/TweetItemMarshaller.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet - -import com.twitter.product_mixer.core.functional_component.marshaller.response.graphql.contextual_ref.ContextualTweetRefMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.conversation_annotation.ConversationAnnotationMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.forward_pivot.ForwardPivotMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tombstone.TombstoneInfoMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PrerollMetadataMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.BadgeMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetItemMarshaller @Inject() ( - tweetDisplayTypeMarshaller: TweetDisplayTypeMarshaller, - socialContextMarshaller: SocialContextMarshaller, - tweetHighlightsMarshaller: TweetHighlightsMarshaller, - tombstoneInfoMarshaller: TombstoneInfoMarshaller, - timelinesScoreInfoMarshaller: TimelinesScoreInfoMarshaller, - forwardPivotMarshaller: ForwardPivotMarshaller, - promotedMetadataMarshaller: PromotedMetadataMarshaller, - conversationAnnotationMarshaller: ConversationAnnotationMarshaller, - contextualTweetRefMarshaller: ContextualTweetRefMarshaller, - prerollMetadataMarshaller: PrerollMetadataMarshaller, - badgeMarshaller: BadgeMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(tweetItem: TweetItem): urt.TimelineItemContent.Tweet = urt.TimelineItemContent.Tweet( - urt.Tweet( - id = tweetItem.id, - displayType = tweetDisplayTypeMarshaller(tweetItem.displayType), - socialContext = tweetItem.socialContext.map(socialContextMarshaller(_)), - highlights = tweetItem.highlights.map(tweetHighlightsMarshaller(_)), - innerTombstoneInfo = tweetItem.innerTombstoneInfo.map(tombstoneInfoMarshaller(_)), - timelinesScoreInfo = tweetItem.timelinesScoreInfo.map(timelinesScoreInfoMarshaller(_)), - hasModeratedReplies = tweetItem.hasModeratedReplies, - forwardPivot = tweetItem.forwardPivot.map(forwardPivotMarshaller(_)), - innerForwardPivot = tweetItem.innerForwardPivot.map(forwardPivotMarshaller(_)), - promotedMetadata = tweetItem.promotedMetadata.map(promotedMetadataMarshaller(_)), - conversationAnnotation = - tweetItem.conversationAnnotation.map(conversationAnnotationMarshaller(_)), - contextualTweetRef = tweetItem.contextualTweetRef.map(contextualTweetRefMarshaller(_)), - prerollMetadata = tweetItem.prerollMetadata.map(prerollMetadataMarshaller(_)), - replyBadge = tweetItem.replyBadge.map(badgeMarshaller(_)), - destination = tweetItem.destination.map(urlMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala deleted file mode 100644 index 1d0817ea4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerDisplayTypeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.Reply -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerSelfThread -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetComposerDisplayTypeMarshaller @Inject() () { - - def apply(displayType: TweetComposerDisplayType): urt.TweetComposerDisplayType = - displayType match { - case TweetComposerSelfThread => urt.TweetComposerDisplayType.SelfThread - case Reply => urt.TweetComposerDisplayType.Reply - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala deleted file mode 100644 index 8d018a9b6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/tweet_composer/TweetComposerItemMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.tweet_composer - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer.TweetComposerItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetComposerItemMarshaller @Inject() ( - tweetComposerDisplayTypeMarshaller: TweetComposerDisplayTypeMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(tweetComposer: TweetComposerItem): urt.TimelineItemContent = - urt.TimelineItemContent.TweetComposer( - urt.TweetComposer( - displayType = tweetComposerDisplayTypeMarshaller(tweetComposer.displayType), - text = tweetComposer.text, - url = urlMarshaller(tweetComposer.url) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala deleted file mode 100644 index 3ee2e3611..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListDisplayTypeMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.List -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.ListTile -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.ListWithPin -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.ListWithSubscribe -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TwitterListDisplayTypeMarshaller @Inject() () { - - def apply(twitterListDisplayType: TwitterListDisplayType): urt.TwitterListDisplayType = - twitterListDisplayType match { - case List => urt.TwitterListDisplayType.List - case ListTile => urt.TwitterListDisplayType.ListTile - case ListWithPin => urt.TwitterListDisplayType.ListWithPin - case ListWithSubscribe => urt.TwitterListDisplayType.ListWithSubscribe - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala deleted file mode 100644 index 9331ce0f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/twitter_list/TwitterListItemMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.twitter_list - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list.TwitterListItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TwitterListItemMarshaller @Inject() ( - twitterListDisplayTypeMarshaller: TwitterListDisplayTypeMarshaller) { - - def apply(twitterListItem: TwitterListItem): urt.TimelineItemContent = - urt.TimelineItemContent.TwitterList( - urt.TwitterList( - id = twitterListItem.id, - displayType = twitterListItem.displayType.map(twitterListDisplayTypeMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala deleted file mode 100644 index 2f2c18da2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserDisplayTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.PendingFollowUser -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.User -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserDetailed -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UserDisplayTypeMarshaller @Inject() () { - - def apply(userDisplayType: UserDisplayType): urt.UserDisplayType = - userDisplayType match { - case User => urt.UserDisplayType.User - case UserDetailed => urt.UserDisplayType.UserDetailed - case PendingFollowUser => urt.UserDisplayType.PendingFollowUser - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala deleted file mode 100644 index d48b59d02..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserItemMarshaller.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted.PromotedMetadataMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UserItemMarshaller @Inject() ( - userDisplayTypeMarshaller: UserDisplayTypeMarshaller, - promotedMetadataMarshaller: PromotedMetadataMarshaller, - socialContextMarshaller: SocialContextMarshaller, - userReactiveTriggersMarshaller: UserReactiveTriggersMarshaller) { - - def apply(userItem: UserItem): urt.TimelineItemContent = - urt.TimelineItemContent.User( - urt.User( - id = userItem.id, - displayType = userDisplayTypeMarshaller(userItem.displayType), - promotedMetadata = userItem.promotedMetadata.map(promotedMetadataMarshaller(_)), - socialContext = userItem.socialContext.map(socialContextMarshaller(_)), - enableReactiveBlending = userItem.enableReactiveBlending, - reactiveTriggers = userItem.reactiveTriggers.map(userReactiveTriggersMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala deleted file mode 100644 index 35eb891d8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/user/UserReactiveTriggersMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.user - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.reaction.TimelineReactionMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.user.UserReactiveTriggers -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UserReactiveTriggersMarshaller @Inject() ( - timelineReactionMarshaller: TimelineReactionMarshaller) { - - def apply(userReactiveTriggers: UserReactiveTriggers): urt.UserReactiveTriggers = { - urt.UserReactiveTriggers( - onFollow = userReactiveTriggers.onFollow.map(timelineReactionMarshaller(_))) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala deleted file mode 100644 index 396df8570..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemContentMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicTile -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class VerticalGridItemContentMarshaller @Inject() ( - verticalGridItemTopicTileMarshaller: VerticalGridItemTopicTileMarshaller) { - - def apply(item: VerticalGridItem): urt.VerticalGridItemContent = item match { - case verticalGridItemTopicTile: VerticalGridItemTopicTile => - verticalGridItemTopicTileMarshaller(verticalGridItemTopicTile) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala deleted file mode 100644 index 4955fae5c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class VerticalGridItemMarshaller @Inject() ( - verticalGridItemContentMarshaller: VerticalGridItemContentMarshaller) { - - def apply(verticalGridItem: VerticalGridItem): urt.TimelineItemContent = - urt.TimelineItemContent.VerticalGridItem( - urt.VerticalGridItem( - content = verticalGridItemContentMarshaller(verticalGridItem) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala deleted file mode 100644 index b0db79567..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTileStyleMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.SingleStateDefaultVerticalGridItemTileStyle -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.DoubleStateDefaultVerticalGridItemTileStyle -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTileStyle -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class VerticalGridItemTileStyleMarshaller @Inject() () { - - def apply(verticalGridItemTileStyle: VerticalGridItemTileStyle): urt.VerticalGridItemTileStyle = - verticalGridItemTileStyle match { - case SingleStateDefaultVerticalGridItemTileStyle => - urt.VerticalGridItemTileStyle.SingleStateDefault - case DoubleStateDefaultVerticalGridItemTileStyle => - urt.VerticalGridItemTileStyle.DoubleStateDefault - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala deleted file mode 100644 index e31a11d14..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityTypeMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.PivotVerticalGridItemTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.RecommendationVerticalGridItemTopicFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicFunctionalityType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class VerticalGridItemTopicFunctionalityTypeMarshaller @Inject() () { - - def apply( - verticalGridItemTopicFunctionalityType: VerticalGridItemTopicFunctionalityType - ): urt.VerticalGridItemTopicFunctionalityType = verticalGridItemTopicFunctionalityType match { - case PivotVerticalGridItemTopicFunctionalityType => - urt.VerticalGridItemTopicFunctionalityType.Pivot - case RecommendationVerticalGridItemTopicFunctionalityType => - urt.VerticalGridItemTopicFunctionalityType.Recommendation - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala deleted file mode 100644 index 4a67ad0ed..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/item/vertical_grid_item/VerticalGridItemTopicTileMarshaller.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.item.vertical_grid_item - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item.VerticalGridItemTopicTile -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class VerticalGridItemTopicTileMarshaller @Inject() ( - styleMarshaller: VerticalGridItemTileStyleMarshaller, - functionalityTypeMarshaller: VerticalGridItemTopicFunctionalityTypeMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(verticalGridItemTopicTile: VerticalGridItemTopicTile): urt.VerticalGridItemContent = - urt.VerticalGridItemContent.TopicTile( - urt.VerticalGridItemTopicTile( - topicId = verticalGridItemTopicTile.id.toString, - style = verticalGridItemTopicTile.style - .map(styleMarshaller(_)).getOrElse(urt.VerticalGridItemTileStyle.SingleStateDefault), - functionalityType = verticalGridItemTopicTile.functionalityType - .map(functionalityTypeMarshaller(_)).getOrElse( - urt.VerticalGridItemTopicFunctionalityType.Pivot), - url = verticalGridItemTopicTile.url.map(urlMarshaller(_)) - ) - ) - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala deleted file mode 100644 index 816327cc6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/AspectRatioMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.AspectRatio -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class AspectRatioMarshaller @Inject() () { - - def apply(aspectRatio: AspectRatio): urt.AspectRatio = urt.AspectRatio( - numerator = aspectRatio.numerator, - denominator = aspectRatio.denominator - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD deleted file mode 100644 index 76deb3159..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala deleted file mode 100644 index c1abb20f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/BroadcastIdMarshaller.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.BroadcastId -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BroadcastIdMarshaller @Inject() () { - - def apply(broadcastId: BroadcastId): urt.BroadcastId = urt.BroadcastId( - id = broadcastId.id - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala deleted file mode 100644 index b662e0a8b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaEntityMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.BroadcastId -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Image -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.MediaEntity -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.TweetMedia -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MediaEntityMarshaller @Inject() ( - tweetMediaMarshaller: TweetMediaMarshaller, - broadcastIdMarshaller: BroadcastIdMarshaller, - imageVariantMarshaller: ImageVariantMarshaller) { - - def apply(mediaEntity: MediaEntity): urt.MediaEntity = mediaEntity match { - case tweetMedia: TweetMedia => urt.MediaEntity.TweetMedia(tweetMediaMarshaller(tweetMedia)) - case broadcastId: BroadcastId => urt.MediaEntity.BroadcastId(broadcastIdMarshaller(broadcastId)) - case image: Image => urt.MediaEntity.Image(imageVariantMarshaller(image.image)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala deleted file mode 100644 index 0ab4e36d5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaKeyMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.MediaKey -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MediaKeyMarshaller @Inject() () { - - def apply(mediaKey: MediaKey): urt.MediaKey = urt.MediaKey( - id = mediaKey.id, - category = mediaKey.category - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala deleted file mode 100644 index 1a1f18f04..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/MediaMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Media -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MediaMarshaller @Inject() ( - mediaEntityMarshaller: MediaEntityMarshaller, - mediaKeyMarshaller: MediaKeyMarshaller, - rectMarshaller: RectMarshaller, - aspectRatioMarshaller: AspectRatioMarshaller) { - - def apply(media: Media): urt.Media = urt.Media( - mediaEntity = media.mediaEntity.map(mediaEntityMarshaller(_)), - mediaKey = media.mediaKey.map(mediaKeyMarshaller(_)), - imagePossibleCropping = media.imagePossibleCropping.map { rects => - rects.map(rectMarshaller(_)) - }, - aspectRatio = media.aspectRatio.map(aspectRatioMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala deleted file mode 100644 index 155243393..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/RectMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Rect -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class RectMarshaller @Inject() () { - - def apply(rect: Rect): urt.Rect = urt.Rect( - left = rect.left, - top = rect.top, - width = rect.width, - height = rect.height - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala deleted file mode 100644 index 0c4183c73..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/media/TweetMediaMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.TweetMedia -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TweetMediaMarshaller @Inject() () { - - def apply(tweetMedia: TweetMedia): urt.TweetMedia = urt.TweetMedia( - tweetId = tweetMedia.tweetId, - momentId = tweetMedia.momentId - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala deleted file mode 100644 index d5e356ad9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ArticleDetailsMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ArticleDetails -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ArticleDetailsMarshaller @Inject() () { - - def apply(articleDetails: ArticleDetails): urt.ArticleDetails = urt.ArticleDetails( - articlePosition = articleDetails.articlePosition, - shareCount = articleDetails.shareCount - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD deleted file mode 100644 index e516fc9b4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala deleted file mode 100644 index 569cd6a81..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/BadgeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.RosettaColorMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BadgeMarshaller @Inject() ( - rosettaColorMarshaller: RosettaColorMarshaller) { - - def apply(badge: Badge): urt.Badge = urt.Badge( - text = badge.text, - textColorName = badge.textColorName.map(rosettaColorMarshaller(_)), - backgroundColorName = badge.backgroundColorName.map(rosettaColorMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala deleted file mode 100644 index f1cbddfe5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CallbackMarshaller.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CallbackMarshaller @Inject() () { - - def apply(callback: Callback): urt.Callback = urt.Callback( - endpoint = callback.endpoint - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala deleted file mode 100644 index 6a3df4dbc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ChildFeedbackActionMarshaller.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ChildFeedbackAction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ChildFeedbackActionMarshaller @Inject() ( - feedbackTypeMarshaller: FeedbackTypeMarshaller, - confirmationDisplayTypeMarshaller: ConfirmationDisplayTypeMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - horizonIconMarshaller: HorizonIconMarshaller, - richFeedbackBehaviorMarshaller: RichFeedbackBehaviorMarshaller) { - - def apply(feedbackAction: ChildFeedbackAction): urt.FeedbackAction = { - urt.FeedbackAction( - feedbackType = feedbackTypeMarshaller(feedbackAction.feedbackType), - prompt = feedbackAction.prompt, - confirmation = feedbackAction.confirmation, - childKeys = None, - feedbackUrl = feedbackAction.feedbackUrl, - hasUndoAction = feedbackAction.hasUndoAction, - confirmationDisplayType = - feedbackAction.confirmationDisplayType.map(confirmationDisplayTypeMarshaller(_)), - clientEventInfo = feedbackAction.clientEventInfo.map(clientEventInfoMarshaller(_)), - icon = feedbackAction.icon.map(horizonIconMarshaller(_)), - richBehavior = feedbackAction.richBehavior.map(richFeedbackBehaviorMarshaller(_)), - subprompt = feedbackAction.subprompt - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala deleted file mode 100644 index 6d24a048a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventDetailsMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventDetails -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ClientEventDetailsMarshaller @Inject() ( - conversationDetailsMarshaller: ConversationDetailsMarshaller, - timelinesDetailsMarshaller: TimelinesDetailsMarshaller, - articleDetailsMarshaller: ArticleDetailsMarshaller, - liveEventDetailsMarshaller: LiveEventDetailsMarshaller, - commerceDetailsMarshaller: CommerceDetailsMarshaller) { - - def apply(clientEventDetails: ClientEventDetails): urt.ClientEventDetails = { - urt.ClientEventDetails( - conversationDetails = - clientEventDetails.conversationDetails.map(conversationDetailsMarshaller(_)), - timelinesDetails = clientEventDetails.timelinesDetails.map(timelinesDetailsMarshaller(_)), - articleDetails = clientEventDetails.articleDetails.map(articleDetailsMarshaller(_)), - liveEventDetails = clientEventDetails.liveEventDetails.map(liveEventDetailsMarshaller(_)), - commerceDetails = clientEventDetails.commerceDetails.map(commerceDetailsMarshaller(_)) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala deleted file mode 100644 index aff10b9ed..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ClientEventInfoMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ClientEventInfoMarshaller @Inject() ( - clientEventDetailsMarshaller: ClientEventDetailsMarshaller) { - - def apply(clientEventInfo: ClientEventInfo): urt.ClientEventInfo = { - urt.ClientEventInfo( - component = clientEventInfo.component, - element = clientEventInfo.element, - details = clientEventInfo.details.map(clientEventDetailsMarshaller(_)), - action = clientEventInfo.action, - entityToken = clientEventInfo.entityToken - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala deleted file mode 100644 index 3b14c7a05..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/CommerceDetailsMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.CommerceDetails -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CommerceDetailsMarshaller @Inject() () { - - def apply(commerceDetails: CommerceDetails): urt.CommerceDetails = urt.CommerceDetails( - dropId = commerceDetails.dropId, - shopV2Id = commerceDetails.shopV2Id, - productKey = commerceDetails.productKey, - merchantId = commerceDetails.merchantId, - productIndex = commerceDetails.productIndex, - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala deleted file mode 100644 index 78a74254f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConfirmationDisplayTypeMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.BottomSheet -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ConfirmationDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Inline -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConfirmationDisplayTypeMarshaller @Inject() () { - - def apply(confirmationDisplayType: ConfirmationDisplayType): urt.ConfirmationDisplayType = - confirmationDisplayType match { - case Inline => urt.ConfirmationDisplayType.Inline - case BottomSheet => urt.ConfirmationDisplayType.BottomSheet - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala deleted file mode 100644 index 88889bb5f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationDetailsMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ConversationDetails -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConversationDetailsMarshaller @Inject() (sectionMarshaller: ConversationSectionMarshaller) { - - def apply(conversationDetails: ConversationDetails): urt.ConversationDetails = - urt.ConversationDetails( - conversationSection = conversationDetails.conversationSection.map(sectionMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala deleted file mode 100644 index 0ae3e5bf0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ConversationSectionMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.AbusiveQuality -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ConversationSection -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HighQuality -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.LowQuality -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RelatedTweet -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ConversationSectionMarshaller @Inject() () { - - def apply(section: ConversationSection): urt.ConversationSection = section match { - case HighQuality => urt.ConversationSection.HighQuality - case LowQuality => urt.ConversationSection.LowQuality - case AbusiveQuality => urt.ConversationSection.AbusiveQuality - case RelatedTweet => urt.ConversationSection.RelatedTweet - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala deleted file mode 100644 index 61bcdec68..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/DismissInfoMarshaller.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DismissInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class DismissInfoMarshaller @Inject() (callbackMarshaller: CallbackMarshaller) { - - def apply(dismissInfo: DismissInfo): urt.DismissInfo = - urt.DismissInfo(dismissInfo.callbacks.map(_.map(callbackMarshaller(_)))) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala deleted file mode 100644 index 5be361b30..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackActionMarshaller.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.FeedbackActionMarshaller.generateKey -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackAction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -object FeedbackActionMarshaller { - def generateKey(feedbackAction: urt.FeedbackAction): String = { - feedbackAction.hashCode.toString - } -} - -@Singleton -class FeedbackActionMarshaller @Inject() ( - childFeedbackActionMarshaller: ChildFeedbackActionMarshaller, - feedbackTypeMarshaller: FeedbackTypeMarshaller, - confirmationDisplayTypeMarshaller: ConfirmationDisplayTypeMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller, - horizonIconMarshaller: HorizonIconMarshaller, - richFeedbackBehaviorMarshaller: RichFeedbackBehaviorMarshaller) { - - def apply(feedbackAction: FeedbackAction): urt.FeedbackAction = { - val childKeys = feedbackAction.childFeedbackActions - .map(_.map { childFeedbackAction => - val urtChildFeedbackAction = childFeedbackActionMarshaller(childFeedbackAction) - generateKey(urtChildFeedbackAction) - }) - - urt.FeedbackAction( - feedbackType = feedbackTypeMarshaller(feedbackAction.feedbackType), - prompt = feedbackAction.prompt, - confirmation = feedbackAction.confirmation, - childKeys = childKeys, - feedbackUrl = feedbackAction.feedbackUrl, - hasUndoAction = feedbackAction.hasUndoAction, - confirmationDisplayType = - feedbackAction.confirmationDisplayType.map(confirmationDisplayTypeMarshaller(_)), - clientEventInfo = feedbackAction.clientEventInfo.map(clientEventInfoMarshaller(_)), - icon = feedbackAction.icon.map(horizonIconMarshaller(_)), - richBehavior = feedbackAction.richBehavior.map(richFeedbackBehaviorMarshaller(_)), - subprompt = feedbackAction.subprompt, - encodedFeedbackRequest = feedbackAction.encodedFeedbackRequest - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala deleted file mode 100644 index 068450e02..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackDisplayContextMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackDisplayContext -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FeedbackDisplayContextMarshaller @Inject() () { - - def apply(displayContext: FeedbackDisplayContext): urt.FeedbackDisplayContext = - urt.FeedbackDisplayContext( - reason = displayContext.reason - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala deleted file mode 100644 index 5f8b4b988..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackInfoMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FeedbackInfoMarshaller @Inject() ( - feedbackActionMarshaller: FeedbackActionMarshaller, - feedbackDisplayContextMarshaller: FeedbackDisplayContextMarshaller, - clientEventInfoMarshaller: ClientEventInfoMarshaller) { - - def apply(feedbackActionInfo: FeedbackActionInfo): urt.FeedbackInfo = urt.FeedbackInfo( - // Generate key from the hashcode of the marshalled feedback action URT - feedbackKeys = feedbackActionInfo.feedbackActions - .map(feedbackActionMarshaller(_)).map(FeedbackActionMarshaller.generateKey), - feedbackMetadata = feedbackActionInfo.feedbackMetadata, - displayContext = feedbackActionInfo.displayContext.map(feedbackDisplayContextMarshaller(_)), - clientEventInfo = feedbackActionInfo.clientEventInfo.map(clientEventInfoMarshaller(_)), - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala deleted file mode 100644 index 6b76c31e0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/FeedbackTypeMarshaller.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class FeedbackTypeMarshaller @Inject() () { - - def apply(feedbackType: FeedbackType): urt.FeedbackType = feedbackType match { - case Dismiss => urt.FeedbackType.Dismiss - case SeeFewer => urt.FeedbackType.SeeFewer - case DontLike => urt.FeedbackType.DontLike - case NotRelevant => urt.FeedbackType.NotRelevant - case SeeMore => urt.FeedbackType.SeeMore - case NotCredible => urt.FeedbackType.NotCredible - case GiveFeedback => urt.FeedbackType.GiveFeedback - case NotRecent => urt.FeedbackType.NotRecent - case UnfollowEntity => urt.FeedbackType.UnfollowEntity - case Relevant => urt.FeedbackType.Relevant - case Moderate => urt.FeedbackType.Moderate - case RichBehavior => urt.FeedbackType.RichBehavior - case NotAboutTopic => urt.FeedbackType.NotAboutTopic - case Generic => urt.FeedbackType.Generic - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala deleted file mode 100644 index 91c2033cc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GeneralContextMarshaller @Inject() ( - generalContextTypeMarshaller: GeneralContextTypeMarshaller, - urlMarshaller: UrlMarshaller) { - - def apply(generalContext: GeneralContext): urt.SocialContext = { - urt.SocialContext.GeneralContext( - urt.GeneralContext( - contextType = generalContextTypeMarshaller(generalContext.contextType), - text = generalContext.text, - url = generalContext.url, - contextImageUrls = generalContext.contextImageUrls, - landingUrl = generalContext.landingUrl.map(urlMarshaller(_)) - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala deleted file mode 100644 index 982be27ab..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/GeneralContextTypeMarshaller.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GeneralContextTypeMarshaller @Inject() () { - - def apply(generalContextType: GeneralContextType): urt.ContextType = generalContextType match { - case LikeGeneralContextType => urt.ContextType.Like - case FollowGeneralContextType => urt.ContextType.Follow - case MomentGeneralContextType => urt.ContextType.Moment - case ReplyGeneralContextType => urt.ContextType.Reply - case ConversationGeneralContextType => urt.ContextType.Conversation - case PinGeneralContextType => urt.ContextType.Pin - case TextOnlyGeneralContextType => urt.ContextType.TextOnly - case FacePileGeneralContextType => urt.ContextType.Facepile - case MegaPhoneGeneralContextType => urt.ContextType.Megaphone - case BirdGeneralContextType => urt.ContextType.Bird - case FeedbackGeneralContextType => urt.ContextType.Feedback - case TopicGeneralContextType => urt.ContextType.Topic - case ListGeneralContextType => urt.ContextType.List - case RetweetGeneralContextType => urt.ContextType.Retweet - case LocationGeneralContextType => urt.ContextType.Location - case CommunityGeneralContextType => urt.ContextType.Community - case NewUserGeneralContextType => urt.ContextType.NewUser - case SmartblockExpirationGeneralContextType => urt.ContextType.SmartBlockExpiration - case TrendingGeneralContextType => urt.ContextType.Trending - case SparkleGeneralContextType => urt.ContextType.Sparkle - case SpacesGeneralContextType => urt.ContextType.Spaces - case ReplyPinGeneralContextType => urt.ContextType.ReplyPin - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala deleted file mode 100644 index 50c0c2519..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageAnimationTypeMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageAnimationType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Bounce -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ImageAnimationTypeMarshaller @Inject() () { - - def apply(imageAnimationType: ImageAnimationType): urt.ImageAnimationType = - imageAnimationType match { - case Bounce => urt.ImageAnimationType.Bounce - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala deleted file mode 100644 index 6021f26e8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageDisplayTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Icon -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FullWidth -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.IconSmall -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ImageDisplayTypeMarshaller @Inject() () { - - def apply(imageDisplayType: ImageDisplayType): urt.ImageDisplayType = - imageDisplayType match { - case Icon => urt.ImageDisplayType.Icon - case FullWidth => urt.ImageDisplayType.FullWidth - case IconSmall => urt.ImageDisplayType.IconSmall - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala deleted file mode 100644 index a5711cf43..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/ImageVariantMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.color.ColorPaletteMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ImageVariantMarshaller @Inject() ( - colorPaletteMarshaller: ColorPaletteMarshaller) { - - def apply(imageVariant: ImageVariant): urt.ImageVariant = urt.ImageVariant( - url = imageVariant.url, - width = imageVariant.width, - height = imageVariant.height, - palette = imageVariant.palette.map { paletteList => paletteList.map(colorPaletteMarshaller(_)) } - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala deleted file mode 100644 index e07d20251..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/LiveEventDetailsMarshaller.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.LiveEventDetails -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LiveEventDetailsMarshaller @Inject() () { - - def apply(liveEventDetails: LiveEventDetails): urt.LiveEventDetails = urt.LiveEventDetails( - eventId = liveEventDetails.eventId - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala deleted file mode 100644 index 43ec36fe4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/RichFeedbackBehaviorMarshaller.scala +++ /dev/null @@ -1,55 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.NotPinnableReplyPinState -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnableReplyPinState -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnedReplyPinState -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorBlockUser -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorMarkNotInterestedTopic -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorReplyPinState -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorReportList -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorReportTweet -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleFollowTopic -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleFollowTopicV2 -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleFollowUser -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleMuteList -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RichFeedbackBehaviorToggleMuteUser -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RichFeedbackBehaviorMarshaller @Inject() () { - - def apply(richFeedbackBehavior: RichFeedbackBehavior): urt.RichFeedbackBehavior = - richFeedbackBehavior match { - case RichFeedbackBehaviorReportList(listId, userId) => - urt.RichFeedbackBehavior.ReportList(urt.RichFeedbackBehaviorReportList(listId, userId)) - case RichFeedbackBehaviorBlockUser(userId) => - urt.RichFeedbackBehavior.BlockUser(urt.RichFeedbackBehaviorBlockUser(userId)) - case RichFeedbackBehaviorToggleFollowTopic(topicId) => - urt.RichFeedbackBehavior.ToggleFollowTopic( - urt.RichFeedbackBehaviorToggleFollowTopic(topicId)) - case RichFeedbackBehaviorToggleFollowTopicV2(topicId) => - urt.RichFeedbackBehavior.ToggleFollowTopicV2( - urt.RichFeedbackBehaviorToggleFollowTopicV2(topicId)) - case RichFeedbackBehaviorToggleMuteList(listId) => - urt.RichFeedbackBehavior.ToggleMuteList(urt.RichFeedbackBehaviorToggleMuteList(listId)) - case RichFeedbackBehaviorMarkNotInterestedTopic(topicId) => - urt.RichFeedbackBehavior.MarkNotInterestedTopic( - urt.RichFeedbackBehaviorMarkNotInterestedTopic(topicId)) - case RichFeedbackBehaviorReplyPinState(replyPinState) => - val pinState: urt.ReplyPinState = replyPinState match { - case PinnedReplyPinState => urt.ReplyPinState.Pinned - case PinnableReplyPinState => urt.ReplyPinState.Pinnable - case NotPinnableReplyPinState => urt.ReplyPinState.NotPinnable - } - urt.RichFeedbackBehavior.ReplyPinState(urt.RichFeedbackBehaviorReplyPinState(pinState)) - case RichFeedbackBehaviorToggleMuteUser(userId) => - urt.RichFeedbackBehavior.ToggleMuteUser(urt.RichFeedbackBehaviorToggleMuteUser(userId)) - case RichFeedbackBehaviorToggleFollowUser(userId) => - urt.RichFeedbackBehavior.ToggleFollowUser(urt.RichFeedbackBehaviorToggleFollowUser(userId)) - case RichFeedbackBehaviorReportTweet(entryId) => - urt.RichFeedbackBehavior.ReportTweet(urt.RichFeedbackBehaviorReportTweet(entryId)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala deleted file mode 100644 index 7d43812ea..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/SocialContextMarshaller.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.timelines.render.{thriftscala => urt} -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.GeneralContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TopicContext -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SocialContextMarshaller @Inject() ( - generalContextMarshaller: GeneralContextMarshaller, - topicContextMarshaller: TopicContextMarshaller) { - - def apply(socialContext: SocialContext): urt.SocialContext = - socialContext match { - case generalContextBanner: GeneralContext => - generalContextMarshaller(generalContextBanner) - case topicContextBanner: TopicContext => - topicContextMarshaller(topicContextBanner) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala deleted file mode 100644 index 657f49e75..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TimelinesDetailsMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TimelinesDetails -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelinesDetailsMarshaller @Inject() () { - - def apply(timelinesDetails: TimelinesDetails): urt.TimelinesDetails = urt.TimelinesDetails( - injectionType = timelinesDetails.injectionType, - controllerData = timelinesDetails.controllerData, - sourceData = timelinesDetails.sourceData - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala deleted file mode 100644 index e46f64614..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextFunctionalityTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.BasicTopicContextFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RecWithEducationTopicContextFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.RecommendationTopicContextFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TopicContextFunctionalityType -import com.twitter.timelines.render.{thriftscala => urt} - -object TopicContextFunctionalityTypeMarshaller { - - def apply( - topicContextFunctionalityType: TopicContextFunctionalityType - ): urt.TopicContextFunctionalityType = topicContextFunctionalityType match { - case BasicTopicContextFunctionalityType => urt.TopicContextFunctionalityType.Basic - case RecommendationTopicContextFunctionalityType => - urt.TopicContextFunctionalityType.Recommendation - case RecWithEducationTopicContextFunctionalityType => - urt.TopicContextFunctionalityType.RecWithEducation - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala deleted file mode 100644 index 0c067e299..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/TopicContextMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.BasicTopicContextFunctionalityType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.TopicContext -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TopicContextMarshaller @Inject() () { - - def apply(topicContext: TopicContext): urt.SocialContext = { - urt.SocialContext.TopicContext( - urt.TopicContext( - topicId = topicContext.topicId, - functionalityType = TopicContextFunctionalityTypeMarshaller( - topicContext.functionalityType.getOrElse(BasicTopicContextFunctionalityType)) - ) - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala deleted file mode 100644 index 65c8ba30d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UrlMarshaller @Inject() ( - urlTypeMarshaller: UrlTypeMarshaller, - urtEndpointOptionsMarshaller: UrtEndpointOptionsMarshaller) { - - def apply(url: Url): urt.Url = urt.Url( - urlType = urlTypeMarshaller(url.urlType), - url = url.url, - urtEndpointOptions = url.urtEndpointOptions.map(urtEndpointOptionsMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala deleted file mode 100644 index 4d2796535..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrlTypeMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DeepLink -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ExternalUrl -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrlType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpoint -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UrlTypeMarshaller @Inject() () { - - def apply(urlType: UrlType): urt.UrlType = urlType match { - case ExternalUrl => urt.UrlType.ExternalUrl - case DeepLink => urt.UrlType.DeepLink - case UrtEndpoint => urt.UrlType.UrtEndpoint - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala deleted file mode 100644 index d9d5c80ce..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata/UrtEndpointOptionsMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.UrtEndpointOptions -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UrtEndpointOptionsMarshaller @Inject() () { - - def apply(urtEndpointOptions: UrtEndpointOptions): urt.UrtEndpointOptions = - urt.UrtEndpointOptions( - requestParams = urtEndpointOptions.requestParams, - title = urtEndpointOptions.title, - cacheId = urtEndpointOptions.cacheId, - subtitle = urtEndpointOptions.subtitle - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD deleted file mode 100644 index 7d10b934c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala deleted file mode 100644 index 881891183..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorDisplayTreatmentMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorDisplayTreatment -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CursorDisplayTreatmentMarshaller @Inject() () { - - def apply(treatment: CursorDisplayTreatment): urt.CursorDisplayTreatment = - urt.CursorDisplayTreatment( - actionText = treatment.actionText, - labelText = treatment.labelText - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala deleted file mode 100644 index 00d83fad1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorItemMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorItem -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CursorItemMarshaller @Inject() ( - cursorTypeMarshaller: CursorTypeMarshaller, - cursorDisplayTreatmentMarshaller: CursorDisplayTreatmentMarshaller) { - - def apply(cursorItem: CursorItem): urt.TimelineItemContent.TimelineCursor = - urt.TimelineItemContent.TimelineCursor( - urt.TimelineCursor( - value = cursorItem.value, - cursorType = cursorTypeMarshaller(cursorItem.cursorType), - displayTreatment = cursorItem.displayTreatment.map(cursorDisplayTreatmentMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala deleted file mode 100644 index fedf19c65..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorOperationMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CursorOperationMarshaller @Inject() ( - cursorTypeMarshaller: CursorTypeMarshaller, - cursorDisplayTreatmentMarshaller: CursorDisplayTreatmentMarshaller) { - - def apply(cursorOperation: CursorOperation): urt.TimelineOperation.Cursor = - urt.TimelineOperation.Cursor( - urt.TimelineCursor( - value = cursorOperation.value, - cursorType = cursorTypeMarshaller(cursorOperation.cursorType), - displayTreatment = cursorOperation.displayTreatment.map(cursorDisplayTreatmentMarshaller(_)) - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala deleted file mode 100644 index 9359b069c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/operation/CursorTypeMarshaller.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation._ -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CursorTypeMarshaller @Inject() () { - - def apply(cursorType: CursorType): urt.CursorType = cursorType match { - case TopCursor => urt.CursorType.Top - case BottomCursor => urt.CursorType.Bottom - case GapCursor => urt.CursorType.Gap - case PivotCursor => urt.CursorType.Pivot - case SubBranchCursor => urt.CursorType.Subbranch - case ShowMoreCursor => urt.CursorType.ShowMore - case ShowMoreThreadsCursor => urt.CursorType.ShowMoreThreads - case ShowMoreThreadsPromptCursor => urt.CursorType.ShowMoreThreadsPrompt - case SecondRepliesSectionCursor => urt.CursorType.SecondRepliesSection - case ThirdRepliesSectionCursor => urt.CursorType.ThirdRepliesSection - } - - def unmarshall(cursorType: urt.CursorType): CursorType = cursorType match { - case urt.CursorType.Top => TopCursor - case urt.CursorType.Bottom => BottomCursor - case urt.CursorType.Gap => GapCursor - case urt.CursorType.Pivot => PivotCursor - case urt.CursorType.Subbranch => SubBranchCursor - case urt.CursorType.ShowMore => ShowMoreCursor - case urt.CursorType.ShowMoreThreads => ShowMoreThreadsCursor - case urt.CursorType.ShowMoreThreadsPrompt => ShowMoreThreadsPromptCursor - case urt.CursorType.SecondRepliesSection => SecondRepliesSectionCursor - case urt.CursorType.ThirdRepliesSection => ThirdRepliesSectionCursor - case urt.CursorType.EnumUnknownCursorType(id) => - throw new UnsupportedOperationException(s"Unexpected cursor enum field: $id") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala deleted file mode 100644 index e525e3495..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/AdMetadataContainerMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.AdMetadataContainer -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdMetadataContainerMarshaller @Inject() ( - sponsorshipTypeMarshaller: SponsorshipTypeMarshaller, - disclaimerTypeMarshaller: DisclaimerTypeMarshaller, - skAdNetworkDataMarshaller: SkAdNetworkDataMarshaller) { - - def apply(adMetadataContainer: AdMetadataContainer): urt.AdMetadataContainer = - urt.AdMetadataContainer( - removePromotedAttributionForPreroll = adMetadataContainer.removePromotedAttributionForPreroll, - sponsorshipCandidate = adMetadataContainer.sponsorshipCandidate, - sponsorshipOrganization = adMetadataContainer.sponsorshipOrganization, - sponsorshipOrganizationWebsite = adMetadataContainer.sponsorshipOrganizationWebsite, - sponsorshipType = adMetadataContainer.sponsorshipType.map(sponsorshipTypeMarshaller(_)), - disclaimerType = adMetadataContainer.disclaimerType.map(disclaimerTypeMarshaller(_)), - skAdNetworkDataList = - adMetadataContainer.skAdNetworkDataList.map(_.map(skAdNetworkDataMarshaller(_))), - unifiedCardOverride = adMetadataContainer.unifiedCardOverride - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD deleted file mode 100644 index 6ac0230f9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala deleted file mode 100644 index 5c55b1a59..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/CallToActionMarshaller.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.CallToAction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Singleton - -@Singleton -class CallToActionMarshaller { - def apply(callToAction: CallToAction): urt.CallToAction = { - urt.CallToAction( - callToActionType = callToAction.callToActionType, - url = callToAction.url - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala deleted file mode 100644 index c174b4107..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/ClickTrackingInfoMarshaller.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.ClickTrackingInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ClickTrackingInfoMarshaller @Inject() ( - urlOverrideTypeMarshaller: UrlOverrideTypeMarshaller) { - - def apply(clickTrackingInfo: ClickTrackingInfo): urt.ClickTrackingInfo = - urt.ClickTrackingInfo( - urlParams = clickTrackingInfo.urlParams, - urlOverride = clickTrackingInfo.urlOverride, - urlOverrideType = clickTrackingInfo.urlOverrideType.map(urlOverrideTypeMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala deleted file mode 100644 index 764eefa04..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclaimerTypeMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerIssue -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerPolitical -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclaimerType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class DisclaimerTypeMarshaller @Inject() () { - - def apply(disclaimerType: DisclaimerType): urt.DisclaimerType = disclaimerType match { - case DisclaimerPolitical => urt.DisclaimerType.Political - case DisclaimerIssue => urt.DisclaimerType.Issue - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala deleted file mode 100644 index dfabdd6d9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DisclosureTypeMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DisclosureType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Earned -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Issue -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoDisclosure -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Political -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class DisclosureTypeMarshaller @Inject() () { - - def apply(disclosureType: DisclosureType): urt.DisclosureType = disclosureType match { - case NoDisclosure => urt.DisclosureType.NoDisclosure - case Political => urt.DisclosureType.Political - case Earned => urt.DisclosureType.Earned - case Issue => urt.DisclosureType.Issue - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala deleted file mode 100644 index f009b89a3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/DynamicPrerollTypeMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Amplify -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DynamicPrerollType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.LiveTvEvent -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Marketplace -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class DynamicPrerollTypeMarshaller @Inject() () { - - def apply(dynamicPrerollType: DynamicPrerollType): urt.DynamicPrerollType = - dynamicPrerollType match { - case Amplify => urt.DynamicPrerollType.Amplify - case Marketplace => urt.DynamicPrerollType.Marketplace - case LiveTvEvent => urt.DynamicPrerollType.LiveTvEvent - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala deleted file mode 100644 index e9ce5b414..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/MediaInfoMarshaller.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.MediaInfo -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MediaInfoMarshaller @Inject() ( - callToActionMarshaller: CallToActionMarshaller, - videoVariantsMarshaller: VideoVariantsMarshaller) { - def apply(mediaInfo: MediaInfo): urt.MediaInfo = { - urt.MediaInfo( - uuid = mediaInfo.uuid, - publisherId = mediaInfo.publisherId, - callToAction = mediaInfo.callToAction.map(callToActionMarshaller(_)), - durationMillis = mediaInfo.durationMillis, - videoVariants = mediaInfo.videoVariants.map(videoVariantsMarshaller(_)), - advertiserName = mediaInfo.advertiserName, - renderAdByAdvertiserName = mediaInfo.renderAdByAdvertiserName, - advertiserProfileImageUrl = mediaInfo.advertiserProfileImageUrl - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala deleted file mode 100644 index 184540489..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.Preroll -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PrerollMarshaller @Inject() ( - dynamicPrerollTypeMarshaller: DynamicPrerollTypeMarshaller, - mediaInfoMarshaller: MediaInfoMarshaller) { - - def apply(preroll: Preroll): urt.Preroll = - urt.Preroll( - prerollId = preroll.prerollId, - dynamicPrerollType = preroll.dynamicPrerollType.map(dynamicPrerollTypeMarshaller(_)), - mediaInfo = preroll.mediaInfo.map(mediaInfoMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala deleted file mode 100644 index 65197a8cd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PrerollMetadataMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PrerollMetadataMarshaller @Inject() ( - prerollMarshaller: PrerollMarshaller) { - def apply(prerollMetadata: PrerollMetadata): urt.PrerollMetadata = - urt.PrerollMetadata( - preroll = prerollMetadata.preroll.map(prerollMarshaller(_)), - videoAnalyticsScribePassthrough = prerollMetadata.videoAnalyticsScribePassthrough - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala deleted file mode 100644 index 6a1e1750e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/PromotedMetadataMarshaller.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PromotedMetadataMarshaller @Inject() ( - disclosureTypeMarshaller: DisclosureTypeMarshaller, - adMetadataContainerMarshaller: AdMetadataContainerMarshaller, - clickTrackingInfoMarshaller: ClickTrackingInfoMarshaller) { - - /** See comments on [[com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata]] - * regarding impressionId and impressionString - * - * TL;DR the domain model only has impressionString (the newer version) an this marshaller sets both - * impressionId (the older) and impressionString based on it for compatibility. - * */ - def apply(promotedMetadata: PromotedMetadata): urt.PromotedMetadata = - urt.PromotedMetadata( - advertiserId = promotedMetadata.advertiserId, - impressionId = promotedMetadata.impressionString, - disclosureType = promotedMetadata.disclosureType.map(disclosureTypeMarshaller(_)), - experimentValues = promotedMetadata.experimentValues, - promotedTrendId = promotedMetadata.promotedTrendId, - promotedTrendName = promotedMetadata.promotedTrendName, - promotedTrendQueryTerm = promotedMetadata.promotedTrendQueryTerm, - adMetadataContainer = - promotedMetadata.adMetadataContainer.map(adMetadataContainerMarshaller(_)), - promotedTrendDescription = promotedMetadata.promotedTrendDescription, - impressionString = promotedMetadata.impressionString, - clickTrackingInfo = promotedMetadata.clickTrackingInfo.map(clickTrackingInfoMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala deleted file mode 100644 index cd1813508..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SkAdNetworkDataMarshaller.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SkAdNetworkData -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class SkAdNetworkDataMarshaller @Inject() () { - - def apply(skAdNetworkData: SkAdNetworkData): urt.SkAdNetworkData = - urt.SkAdNetworkData( - version = skAdNetworkData.version, - srcAppId = skAdNetworkData.srcAppId, - dstAppId = skAdNetworkData.dstAppId, - adNetworkId = skAdNetworkData.adNetworkId, - campaignId = skAdNetworkData.campaignId, - impressionTimeInMillis = skAdNetworkData.impressionTimeInMillis, - nonce = skAdNetworkData.nonce, - signature = skAdNetworkData.signature, - fidelityType = skAdNetworkData.fidelityType - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala deleted file mode 100644 index 7c892eef1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/SponsorshipTypeMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DirectSponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.IndirectSponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.NoSponsorshipSponsorshipType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.SponsorshipType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class SponsorshipTypeMarshaller @Inject() () { - - def apply(sponsorshipType: SponsorshipType): urt.SponsorshipType = sponsorshipType match { - case DirectSponsorshipType => urt.SponsorshipType.Direct - case IndirectSponsorshipType => urt.SponsorshipType.Indirect - case NoSponsorshipSponsorshipType => urt.SponsorshipType.NoSponsorship - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala deleted file mode 100644 index ea76457c1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/UrlOverrideTypeMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.DcmUrlOverrideType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.UnknownUrlOverrideType -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.UrlOverrideType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class UrlOverrideTypeMarshaller @Inject() () { - - def apply(urlOverrideType: UrlOverrideType): urt.UrlOverrideType = urlOverrideType match { - case UnknownUrlOverrideType => urt.UrlOverrideType.Unknown - case DcmUrlOverrideType => urt.UrlOverrideType.Dcm - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala deleted file mode 100644 index d3ab9188d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/promoted/VideoVariantsMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.promoted - -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.VideoVariant -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Singleton - -@Singleton -class VideoVariantsMarshaller { - def apply(videoVariants: Seq[VideoVariant]): Seq[urt.VideoVariant] = { - videoVariants.map(videoVariant => - urt.VideoVariant( - url = videoVariant.url, - contentType = videoVariant.contentType, - bitrate = videoVariant.bitrate - )) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD deleted file mode 100644 index 527e20c0c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala deleted file mode 100644 index 56a2d53ad..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/reaction/TimelineReactionMarshaller.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.reaction - -import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.ImmediateTimelineReaction -import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.RemoteTimelineReaction -import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.TimelineReaction -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TimelineReactionMarshaller @Inject() () { - def apply(timelineReaction: TimelineReaction): urt.TimelineReaction = { - val execution = timelineReaction.execution match { - case ImmediateTimelineReaction(key) => - urt.TimelineReactionExecution.Immediate(urt.ImmediateTimelineReaction(key)) - case RemoteTimelineReaction(requestParams, timeoutInSeconds) => - urt.TimelineReactionExecution.Remote( - urt.RemoteTimelineReaction( - requestParams, - timeoutInSeconds - )) - } - urt.TimelineReaction( - execution = execution, - maxExecutionCount = timelineReaction.maxExecutionCount - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD deleted file mode 100644 index cdc73d8c4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala deleted file mode 100644 index 217b9d9d1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/ReferenceObjectMarshaller.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextCashtag -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextHashtag -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextList -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextMention -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextUser -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ReferenceObjectMarshaller @Inject() (urlMarshaller: UrlMarshaller) { - - def apply(ref: ReferenceObject): urt.ReferenceObject = ref match { - case url: Url => urt.ReferenceObject.Url(urlMarshaller(url)) - case user: RichTextUser => urt.ReferenceObject.User(urt.RichTextUser(id = user.id)) - case mention: RichTextMention => - urt.ReferenceObject.Mention( - urt.RichTextMention(id = mention.id, screenName = mention.screenName)) - case hashtag: RichTextHashtag => - urt.ReferenceObject.Hashtag(urt.RichTextHashtag(text = hashtag.text)) - case cashtag: RichTextCashtag => - urt.ReferenceObject.Cashtag(urt.RichTextCashtag(text = cashtag.text)) - case twitterList: RichTextList => - urt.ReferenceObject.TwitterList(urt.RichTextList(id = twitterList.id, url = twitterList.url)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala deleted file mode 100644 index 24bbf07af..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextAlignmentMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Center -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Natural -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextAlignment -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RichTextAlignmentMarshaller @Inject() () { - - def apply(alignment: RichTextAlignment): urt.RichTextAlignment = alignment match { - case Natural => urt.RichTextAlignment.Natural - case Center => urt.RichTextAlignment.Center - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala deleted file mode 100644 index a2c7d2a6d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextEntityMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextEntity -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RichTextEntityMarshaller @Inject() ( - referenceObjectMarshaller: ReferenceObjectMarshaller, - richTextFormatMarshaller: RichTextFormatMarshaller) { - - def apply(entity: RichTextEntity): urt.RichTextEntity = urt.RichTextEntity( - fromIndex = entity.fromIndex, - toIndex = entity.toIndex, - ref = entity.ref.map(referenceObjectMarshaller(_)), - format = entity.format.map(richTextFormatMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala deleted file mode 100644 index cd24a4013..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextFormatMarshaller.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Plain -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichTextFormat -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.Strong -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RichTextFormatMarshaller @Inject() () { - - def apply(format: RichTextFormat): urt.RichTextFormat = format match { - case Plain => urt.RichTextFormat.Plain - case Strong => urt.RichTextFormat.Strong - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala deleted file mode 100644 index a86b90fd4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/richtext/RichTextMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.richtext - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RichTextMarshaller @Inject() ( - richTextEntityMarshaller: RichTextEntityMarshaller, - richTextAlignmentMarshaller: RichTextAlignmentMarshaller) { - - def apply(richText: RichText): urt.RichText = urt.RichText( - text = richText.text, - entities = richText.entities.map(richTextEntityMarshaller(_)), - rtl = richText.rtl, - alignment = richText.alignment.map(richTextAlignmentMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala deleted file mode 100644 index 9dda91373..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/AdsMetadataMarshaller.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.AdsMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AdsMetadataMarshaller @Inject() () { - - def apply(adsMetadata: AdsMetadata): urt.AdsMetadata = - urt.AdsMetadata(carouselId = adsMetadata.carouselId) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD deleted file mode 100644 index 04000837b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module", - "src/thrift/com/twitter/timelines/render:thrift-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala deleted file mode 100644 index d86cb0462..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/GridCarouselMetadataMarshaller.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarouselMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class GridCarouselMetadataMarshaller @Inject() () { - - def apply(gridCarouselMetadata: GridCarouselMetadata): urt.GridCarouselMetadata = - urt.GridCarouselMetadata(numRows = gridCarouselMetadata.numRows) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala deleted file mode 100644 index b816f91e8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleConversationMetadataMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleConversationMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleConversationMetadataMarshaller @Inject() ( - socialContextMarshaller: SocialContextMarshaller) { - - def apply( - moduleConversationMetadata: ModuleConversationMetadata - ): urt.ModuleConversationMetadata = urt.ModuleConversationMetadata( - allTweetIds = moduleConversationMetadata.allTweetIds, - socialContext = moduleConversationMetadata.socialContext.map(socialContextMarshaller(_)), - enableDeduplication = moduleConversationMetadata.enableDeduplication - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala deleted file mode 100644 index e2ce757f4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleDisplayTypeMarshaller.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Carousel -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.CompactCarousel -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ConversationTree -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.GridCarousel -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Vertical -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalConversation -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalWithContextLine -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.VerticalGrid -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class ModuleDisplayTypeMarshaller @Inject() () { - - def apply(displayType: ModuleDisplayType): urt.ModuleDisplayType = displayType match { - case Vertical => urt.ModuleDisplayType.Vertical - case Carousel => urt.ModuleDisplayType.Carousel - case VerticalWithContextLine => urt.ModuleDisplayType.VerticalWithContextLine - case VerticalConversation => urt.ModuleDisplayType.VerticalConversation - case ConversationTree => urt.ModuleDisplayType.ConversationTree - case GridCarousel => urt.ModuleDisplayType.GridCarousel - case CompactCarousel => urt.ModuleDisplayType.CompactCarousel - case VerticalGrid => urt.ModuleDisplayType.VerticalGrid - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala deleted file mode 100644 index d7d485fd9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleFooterMarshaller.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.UrlMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter -import javax.inject.Inject -import javax.inject.Singleton -import com.twitter.timelines.render.{thriftscala => urt} - -@Singleton -class ModuleFooterMarshaller @Inject() (urlMarshaller: UrlMarshaller) { - - def apply(footer: ModuleFooter): urt.ModuleFooter = urt.ModuleFooter( - text = footer.text, - landingUrl = footer.landingUrl.map(urlMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala deleted file mode 100644 index 32cc5dc32..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderDisplayTypeMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.Classic -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ClassicNoDivider -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ContextEmphasis -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeaderDisplayType -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleHeaderDisplayTypeMarshaller @Inject() () { - - def apply(displayType: ModuleHeaderDisplayType): urt.ModuleHeaderDisplayType = - displayType match { - case Classic => urt.ModuleHeaderDisplayType.Classic - case ContextEmphasis => urt.ModuleHeaderDisplayType.ContextEmphasis - case ClassicNoDivider => urt.ModuleHeaderDisplayType.ClassicNoDivider - } - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala deleted file mode 100644 index 05ab3a13a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleHeaderMarshaller.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.icon.HorizonIconMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.ImageVariantMarshaller -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.metadata.SocialContextMarshaller -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleHeaderMarshaller @Inject() ( - horizonIconMarshaller: HorizonIconMarshaller, - imageVariantMarshaller: ImageVariantMarshaller, - socialContextMarshaller: SocialContextMarshaller, - moduleHeaderDisplayTypeMarshaller: ModuleHeaderDisplayTypeMarshaller) { - - def apply(header: ModuleHeader): urt.ModuleHeader = urt.ModuleHeader( - text = header.text, - sticky = header.sticky, - icon = header.icon.map(horizonIconMarshaller(_)), - customIcon = header.customIcon.map(imageVariantMarshaller(_)), - socialContext = header.socialContext.map(socialContextMarshaller(_)), - displayType = moduleHeaderDisplayTypeMarshaller(header.moduleHeaderDisplayType) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala deleted file mode 100644 index 8c6154186..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleMetadataMarshaller.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleMetadataMarshaller @Inject() ( - adsMetadataMarshaller: AdsMetadataMarshaller, - moduleConversationMetadataMarshaller: ModuleConversationMetadataMarshaller, - gridCarouselMetadataMarshaller: GridCarouselMetadataMarshaller) { - - def apply(moduleMetadata: ModuleMetadata): urt.ModuleMetadata = urt.ModuleMetadata( - adsMetadata = moduleMetadata.adsMetadata.map(adsMetadataMarshaller(_)), - conversationMetadata = - moduleMetadata.conversationMetadata.map(moduleConversationMetadataMarshaller(_)), - gridCarouselMetadata = - moduleMetadata.gridCarouselMetadata.map(gridCarouselMetadataMarshaller(_)) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala deleted file mode 100644 index f0df20b3b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorMarshaller.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleShowMoreBehaviorMarshaller @Inject() ( - moduleShowMoreBehaviorRevealByCountMarshaller: ModuleShowMoreBehaviorRevealByCountMarshaller) { - - def apply( - moduleShowMoreBehavior: ModuleShowMoreBehavior - ): urt.ModuleShowMoreBehavior = moduleShowMoreBehavior match { - case moduleShowMoreBehaviorRevealByCount: ModuleShowMoreBehaviorRevealByCount => - moduleShowMoreBehaviorRevealByCountMarshaller(moduleShowMoreBehaviorRevealByCount) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala deleted file mode 100644 index 1d36e979e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/timeline_module/ModuleShowMoreBehaviorRevealByCountMarshaller.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.marshaller.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehaviorRevealByCount -import com.twitter.timelines.render.{thriftscala => urt} -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ModuleShowMoreBehaviorRevealByCountMarshaller @Inject() () { - - def apply( - moduleShowMoreBehaviorRevealByCount: ModuleShowMoreBehaviorRevealByCount - ): urt.ModuleShowMoreBehavior = - urt.ModuleShowMoreBehavior.RevealByCount( - urt.ModuleShowMoreBehaviorRevealByCount( - initialItemsCount = moduleShowMoreBehaviorRevealByCount.initialItemsCount, - showMoreItemsCount = moduleShowMoreBehaviorRevealByCount.showMoreItemsCount - ) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD deleted file mode 100644 index a5bd6af7e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala deleted file mode 100644 index ea027f086..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller/DomainMarshaller.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.premarshaller - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.DomainMarshallerIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModulePresentation -import com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * Transforms the `selections` into a [[DomainResponseType]] object (often URT, Slice, etc) - * - * [[DomainMarshaller]]s may contain business logic - * - * @note This is different from `com.twitter.product_mixer.core.marshaller`s - * which transforms into a wire-compatible type - */ -trait DomainMarshaller[-Query <: PipelineQuery, DomainResponseType] extends Component { - - override val identifier: DomainMarshallerIdentifier - - /** Transforms the `selections` into a [[DomainResponseType]] object */ - def apply( - query: Query, - selections: Seq[CandidateWithDetails] - ): DomainResponseType -} - -class UnsupportedCandidateDomainMarshallerException( - candidate: Any, - candidateSource: ComponentIdentifier) - extends UnsupportedOperationException( - s"Domain marshaller does not support candidate ${TransportMarshaller.getSimpleName( - candidate.getClass)} from source $candidateSource") - -class UndecoratedCandidateDomainMarshallerException( - candidate: Any, - candidateSource: ComponentIdentifier) - extends UnsupportedOperationException( - s"Domain marshaller does not support undecorated candidate ${TransportMarshaller - .getSimpleName(candidate.getClass)} from source $candidateSource") - -class UnsupportedPresentationDomainMarshallerException( - candidate: Any, - presentation: UniversalPresentation, - candidateSource: ComponentIdentifier) - extends UnsupportedOperationException( - s"Domain marshaller does not support decorator presentation ${TransportMarshaller - .getSimpleName(presentation.getClass)} for candidate ${TransportMarshaller.getSimpleName( - candidate.getClass)} from source $candidateSource") - -class UnsupportedModuleDomainMarshallerException( - presentation: Option[ModulePresentation], - candidateSource: ComponentIdentifier) - extends UnsupportedOperationException( - s"Domain marshaller does not support module presentation ${presentation - .map(p => - TransportMarshaller - .getSimpleName(presentation.getClass)).getOrElse("")} but was given a module from source $candidateSource") - -class UndecoratedModuleDomainMarshallerException( - candidateSource: ComponentIdentifier) - extends UnsupportedOperationException( - s"Domain marshaller does not support undecorated module from source $candidateSource") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD deleted file mode 100644 index 994d481fd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala deleted file mode 100644 index 7d856c50f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/ScoredCandidateResult.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.scorer - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun - -/** A [[Candidate]] and it's [[FeatureMap]] after being processed by a [[Scorer]] */ -case class ScoredCandidateResult[Candidate <: UniversalNoun[Any]]( - candidate: Candidate, - scorerResult: FeatureMap) - extends CandidateWithFeatures[Candidate] { - override val features: FeatureMap = scorerResult -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala deleted file mode 100644 index e224cbc48..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer/Scorer.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.scorer - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseBulkCandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.SupportsConditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScorerIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch - -/** Scores the provided `candidates` */ -trait Scorer[-Query <: PipelineQuery, -Candidate <: UniversalNoun[Any]] - extends BaseBulkCandidateFeatureHydrator[Query, Candidate, Feature[_, _]] - with SupportsConditionally[Query] { - - /** @see [[ScorerIdentifier]] */ - override val identifier: ScorerIdentifier - - /** - * Features returned by the Scorer - */ - def features: Set[Feature[_, _]] - - /** - * Scores the provided `candidates` - * - * @note the returned Seq of [[FeatureMap]] must contain all the input 'candidates' - * and be in the same order as the input 'candidates' - **/ - def apply( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]] - ): Stitch[Seq[FeatureMap]] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD deleted file mode 100644 index b1fadc1f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala deleted file mode 100644 index aaae604dd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/Selector.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.selector - -import com.twitter.product_mixer.core.functional_component.common.CandidateScope -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** Selects some `remainingCandidates` and add them to the `result` */ -trait Selector[-Query <: PipelineQuery] { - - /** - * Specifies which [[com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails.source]]s - * this [[Selector]] will apply to. - * - * @note it is up to each [[Selector]] implementation to correctly handle this behavior - */ - def pipelineScope: CandidateScope - - /** Selects some `remainingCandidates` and add them to the `result` */ - def apply( - query: Query, - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails] - ): SelectorResult -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala deleted file mode 100644 index e20a8cd6e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector/SelectorResult.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.selector - -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -/** - * The result of a [[Selector]] where items that were added - * to the [[result]] are removed from the [[remainingCandidates]] - */ -case class SelectorResult( - remainingCandidates: Seq[CandidateWithDetails], - result: Seq[CandidateWithDetails]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD deleted file mode 100644 index 95ff9136a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala deleted file mode 100644 index 924aa89b6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/ExecuteSynchronously.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.side_effect - -/** - * A modifier for any [[SideEffect]] so that the request waits for it to complete before being returned - * - * @note this will make the [[SideEffect]]'s latency impact the overall request's latency - * - * @example {{{ - * class MySideEffect extends PipelineResultSideEffect[T] with ExecuteSynchronously {...} - * }}} - * - * @example {{{ - * class MySideEffect extends ScribeLogEventSideEffect[T] with ExecuteSynchronously {...} - * }}} - */ -trait ExecuteSynchronously { _: SideEffect[_] => } - -/** - * A modifier for any [[ExecuteSynchronously]] [[SideEffect]] that makes it so failures will be - * reported in the results but wont cause the request as a whole to fail. - */ -trait FailOpen { _: ExecuteSynchronously => } diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala deleted file mode 100644 index d0e66a05f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/PipelineResultSideEffect.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.side_effect - -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect.Inputs -import com.twitter.product_mixer.core.model.common -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -/** - * A side-effect that can be run with a pipeline result before transport marshalling - * - * @see SideEffect - * - * @tparam Query pipeline query - * @tparam ResultType response after domain marshalling - */ -trait PipelineResultSideEffect[-Query <: PipelineQuery, -ResultType <: HasMarshalling] - extends SideEffect[Inputs[Query, ResultType]] - with PipelineResultSideEffect.SupportsConditionally[Query, ResultType] - -object PipelineResultSideEffect { - - /** - * Mixin for when you want to conditionally run a [[PipelineResultSideEffect]] - * - * This is a thin wrapper around [[common.Conditionally]] exposing a nicer API for the [[PipelineResultSideEffect]] specific use-case. - */ - trait Conditionally[-Query <: PipelineQuery, -ResultType <: HasMarshalling] - extends common.Conditionally[Inputs[Query, ResultType]] { - _: PipelineResultSideEffect[Query, ResultType] => - - /** @see [[common.Conditionally.onlyIf]] */ - def onlyIf( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: ResultType - ): Boolean - - override final def onlyIf(input: Inputs[Query, ResultType]): Boolean = - onlyIf( - input.query, - input.selectedCandidates, - input.remainingCandidates, - input.droppedCandidates, - input.response) - - } - - type SupportsConditionally[-Query <: PipelineQuery, -ResultType <: HasMarshalling] = - common.SupportsConditionally[Inputs[Query, ResultType]] - - case class Inputs[+Query <: PipelineQuery, +ResultType <: HasMarshalling]( - query: Query, - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - response: ResultType) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala deleted file mode 100644 index b8a4d5a2b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect/SideEffect.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.side_effect - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier -import com.twitter.stitch.Stitch - -/** - * A side-effect is a ancillary action that doesn't affect the result of execution directly. - * - * For example: Logging, history stores - * - * Implementing components can express failures by throwing an exception. These exceptions - * will be caught and not affect the request processing. - * - * @note Side effects execute asynchronously in a fire-and-forget way, it's important to add alerts - * to the [[SideEffect]] component itself since a failures wont show up in metrics - * that just monitor your pipeline as a whole. - * - * @see [[ExecuteSynchronously]] for modifying a [[SideEffect]] to execute with synchronously with - * the request waiting on the side effect to complete, this will impact the overall request's latency - **/ -trait SideEffect[-Inputs] extends Component { - - /** @see [[SideEffectIdentifier]] */ - override val identifier: SideEffectIdentifier - - def apply(inputs: Inputs): Stitch[Unit] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD deleted file mode 100644 index 52cd7bd26..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala deleted file mode 100644 index 454970f78..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidateFeatureTransformer.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.transformer - -/** - * Populates a [[com.twitter.product_mixer.core.feature.featuremap.FeatureMap]] with Features - * that are available in the [[CandidateSourceResult]] - */ -trait CandidateFeatureTransformer[-CandidateSourceResult] - extends FeatureTransformer[CandidateSourceResult] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala deleted file mode 100644 index 58c4a8735..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineQueryTransformer.scala +++ /dev/null @@ -1,85 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.transformer - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.CandidatePipelineResults -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure - -/** - * A transformer for transforming a mixer or recommendation pipeline's query type into a candidate - * pipeline's query type. - * @tparam Query The parent pipeline's query type - * @tparam CandidateSourceQuery The Candidate Source's query type that the Query should be converted to - */ -protected[core] sealed trait BaseCandidatePipelineQueryTransformer[ - -Query <: PipelineQuery, - +CandidateSourceQuery] - extends Transformer[Query, CandidateSourceQuery] { - - override val identifier: TransformerIdentifier = - BaseCandidatePipelineQueryTransformer.DefaultTransformerId -} - -trait CandidatePipelineQueryTransformer[-Query <: PipelineQuery, CandidateSourceQuery] - extends BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] - -trait DependentCandidatePipelineQueryTransformer[-Query <: PipelineQuery, CandidateSourceQuery] - extends BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] { - def transform(query: Query, candidates: Seq[CandidateWithDetails]): CandidateSourceQuery - - final override def transform(query: Query): CandidateSourceQuery = { - val candidates = query.features - .map(_.get(CandidatePipelineResults)).getOrElse( - throw PipelineFailure( - IllegalStateFailure, - "Candidate Pipeline Results Feature missing from query features")) - transform(query, candidates) - } -} - -object BaseCandidatePipelineQueryTransformer { - private[core] val DefaultTransformerId: TransformerIdentifier = - TransformerIdentifier(ComponentIdentifier.BasedOnParentComponent) - private[core] val TransformerIdSuffix = "Query" - - /** - * For use when building a [[BaseCandidatePipelineQueryTransformer]] in a [[com.twitter.product_mixer.core.pipeline.PipelineBuilder]] - * to ensure that the identifier is updated with the parent [[com.twitter.product_mixer.core.pipeline.Pipeline.identifier]] - */ - private[core] def copyWithUpdatedIdentifier[Query <: PipelineQuery, CandidateSourceQuery]( - queryTransformer: BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery], - parentIdentifier: ComponentIdentifier - ): BaseCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] = { - if (queryTransformer.identifier == DefaultTransformerId) { - val transformerIdentifierFromParentName = TransformerIdentifier( - s"${parentIdentifier.name}$TransformerIdSuffix") - queryTransformer match { - case queryTransformer: CandidatePipelineQueryTransformer[Query, CandidateSourceQuery] => - new CandidatePipelineQueryTransformer[Query, CandidateSourceQuery] { - override val identifier: TransformerIdentifier = transformerIdentifierFromParentName - - override def transform(input: Query): CandidateSourceQuery = - queryTransformer.transform(input) - } - case queryTransformer: DependentCandidatePipelineQueryTransformer[ - Query, - CandidateSourceQuery - ] => - new DependentCandidatePipelineQueryTransformer[Query, CandidateSourceQuery] { - override val identifier: TransformerIdentifier = transformerIdentifierFromParentName - - override def transform( - input: Query, - candidates: Seq[CandidateWithDetails] - ): CandidateSourceQuery = - queryTransformer.transform(input, candidates) - } - } - } else { - queryTransformer - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala deleted file mode 100644 index 80c29d7fb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/CandidatePipelineResultsTransformer.scala +++ /dev/null @@ -1,45 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.transformer - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -/** - * A transformer for transforming a candidate pipeline's source result type into the parent's - * mixer ore recommendation pipeline's type. - * @tparam SourceResult The type of the result of the candidate source being used. - * @tparam PipelineResult The type of the parent pipeline's expected - */ -trait CandidatePipelineResultsTransformer[SourceResult, PipelineResult <: UniversalNoun[Any]] - extends Transformer[SourceResult, PipelineResult] { - - override val identifier: TransformerIdentifier = - CandidatePipelineResultsTransformer.DefaultTransformerId -} - -object CandidatePipelineResultsTransformer { - private[core] val DefaultTransformerId: TransformerIdentifier = - TransformerIdentifier(ComponentIdentifier.BasedOnParentComponent) - private[core] val TransformerIdSuffix = "Results" - - /** - * For use when building a [[CandidatePipelineResultsTransformer]] in a [[com.twitter.product_mixer.core.pipeline.PipelineBuilder]] - * to ensure that the identifier is updated with the parent [[com.twitter.product_mixer.core.pipeline.Pipeline.identifier]] - */ - private[core] def copyWithUpdatedIdentifier[SourceResult, PipelineResult <: UniversalNoun[Any]]( - resultTransformer: CandidatePipelineResultsTransformer[SourceResult, PipelineResult], - parentIdentifier: ComponentIdentifier - ): CandidatePipelineResultsTransformer[SourceResult, PipelineResult] = { - if (resultTransformer.identifier == DefaultTransformerId) { - new CandidatePipelineResultsTransformer[SourceResult, PipelineResult] { - override val identifier: TransformerIdentifier = TransformerIdentifier( - s"${parentIdentifier.name}$TransformerIdSuffix") - - override def transform(input: SourceResult): PipelineResult = - resultTransformer.transform(input) - } - } else { - resultTransformer - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala deleted file mode 100644 index 82d22d1d5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/FeatureTransformer.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.transformer - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -/** - * [[FeatureTransformer]] allow you to populate a [[com.twitter.product_mixer.core.feature.Feature]]s - * value which is already available or can be derived without making an RPC. - * - * A [[FeatureTransformer]] transforms a given [[Inputs]] into a [[FeatureMap]]. - * The transformer must specify which [[com.twitter.product_mixer.core.feature.Feature]]s it will populate using the `features` field - * and the returned [[FeatureMap]] must always have the specified [[com.twitter.product_mixer.core.feature.Feature]]s populated. - * - * @note Unlike [[com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator]] implementations, - * an exception thrown in a [[FeatureTransformer]] will not be added to the [[FeatureMap]] and will instead be - * bubble up to the calling pipeline's [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier]]. - */ -trait FeatureTransformer[-Inputs] extends Transformer[Inputs, FeatureMap] { - - def features: Set[Feature[_, _]] - - override val identifier: TransformerIdentifier - - /** Hydrates a [[FeatureMap]] for a given [[Inputs]] */ - override def transform(input: Inputs): FeatureMap -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala deleted file mode 100644 index 8dfe0b2c4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer/Transformer.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.functional_component.transformer - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -/** - * A transformer is a synchronous transformation that takes the provided [[Input]] and returns some - * defined [[Output]]. For example, extracting a score from from a scored candidates. - */ -trait Transformer[-Inputs, +Output] extends Component { - override val identifier: TransformerIdentifier - - /** Takes [[Inputs]] and transformers them into some [[Output]] of your choosing. */ - def transform(input: Inputs): Output -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD deleted file mode 100644 index fb0bf8981..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala deleted file mode 100644 index a4bfd9e8e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/DenyLoggedOutUsersGate.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.gate.DenyLoggedOutUsersGate.Suffix -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.Authentication -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.stitch.Stitch - -case class DenyLoggedOutUsersGate(pipelineIdentifier: ComponentIdentifier) - extends Gate[PipelineQuery] { - override val identifier: GateIdentifier = GateIdentifier(pipelineIdentifier + Suffix) - - override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = { - if (query.getUserOrGuestId.nonEmpty) { - Stitch.value(!query.isLoggedOut) - } else { - Stitch.exception( - PipelineFailure( - Authentication, - "Expected either a `userId` (for logged in users) or `guestId` (for logged out users) but found neither" - )) - } - } -} - -object DenyLoggedOutUsersGate { - val Suffix = "DenyLoggedOutUsers" -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala deleted file mode 100644 index bc58ed797..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamGate.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -case class ParamGate(name: String, param: Param[Boolean])(implicit file: sourcecode.File) - extends Gate[PipelineQuery] { - - // From a customer-perspective, it's more useful to see the file that created the ParamGate - override val identifier: GateIdentifier = GateIdentifier(name)(file) - - override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = - Stitch.value(query.params(param)) -} - -object ParamGate { - val EnabledGateSuffix = "Enabled" - val SupportedClientGateSuffix = "SupportedClient" -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala deleted file mode 100644 index 38d735a15..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate/ParamNotGate.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.gate - -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Param - -case class ParamNotGate(name: String, param: Param[Boolean]) extends Gate[PipelineQuery] { - override val identifier: GateIdentifier = GateIdentifier(name) - - override def shouldContinue(query: PipelineQuery): Stitch[Boolean] = - Stitch.value(!query.params(param)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD deleted file mode 100644 index e84333ff3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-core", - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-databind", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - ], - exports = [ - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-core", - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-databind", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala deleted file mode 100644 index b8c7a8e47..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/CandidateWithFeatures.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.model.common - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap - -/** [[Candidate]] and it's FeatureMap */ -trait CandidateWithFeatures[+Candidate <: UniversalNoun[Any]] { - val candidate: Candidate - val features: FeatureMap -} - -object CandidateWithFeatures { - def unapply[Candidate <: UniversalNoun[Any]]( - candidateWithFeatures: CandidateWithFeatures[Candidate] - ): Option[(Candidate, FeatureMap)] = - Some( - (candidateWithFeatures.candidate, candidateWithFeatures.features) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala deleted file mode 100644 index 2edeb220c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Component.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.model.common - -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.HasComponentIdentifier - -/** - * Components are very generically reusable composable pieces - * Components are uniquely identifiable and centrally registered - */ -trait Component extends HasComponentIdentifier { - - /** @see [[ComponentIdentifier]] */ - override val identifier: ComponentIdentifier - - /** the [[Alert]]s that will be used for this component. */ - val alerts: Seq[Alert] = Seq.empty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala deleted file mode 100644 index 3b6362849..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/Conditionally.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.product_mixer.core.model.common - -/** - * A mixin trait that can be added to a [[Component]] that's marked with [[SupportsConditionally]] - * A [[Component]] with [[SupportsConditionally]] and [[Conditionally]] will only be run when `onlyIf` returns true - * if `onlyIf` returns false, the [[Component]] is skipped and no stats are recorded for it. - * - * @note if an exception is thrown when evaluating `onlyIf`, it will bubble up to the containing `Pipeline`, - * however the [[Component]]'s stats will not be incremented. Because of this `onlyIf` should never throw. - * - * @note each [[Component]] that [[SupportsConditionally]] has an implementation with in the - * component library that will conditionally run the component based on a [[com.twitter.timelines.configapi.Param]] - * - * @note [[Conditionally]] functionality is wired into the Component's Executor. - * - * @tparam Input the input that is used to gate a component on or off - */ -trait Conditionally[-Input] { _: SupportsConditionally[Input] => - - /** - * if `onlyIf` returns true, the underling [[Component]] is run, otherwise it's skipped - * @note must not throw - */ - def onlyIf(query: Input): Boolean -} - -/** - * Marker trait added to the base type for each [[Component]] which supports the [[Conditionally]] mixin - * - * @note this is `private[core]` because it can only be added to the base implementation of components by the Product Mixer team - * - * @tparam Input the input that is used to gate a component on or off if [[Conditionally]] is mixed in - */ -private[core] trait SupportsConditionally[-Input] { _: Component => } - -object Conditionally { - - /** - * Helper method for combining the [[Conditionally.onlyIf]] of an underlying [[Component]] with an additional predicate - */ - def and[ComponentType <: Component, Input]( - query: Input, - component: ComponentType with SupportsConditionally[Input], - onlyIf: Boolean - ): Boolean = - onlyIf && { - component match { - // @unchecked is safe here because the type parameter is guaranteed by - // the `SupportsConditionally[Input]` type parameter - case underlying: Conditionally[Input @unchecked] => - underlying.onlyIf(query) - case _ => - true - } - } - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala deleted file mode 100644 index 68acda414..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/UniversalNoun.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.common - -import com.fasterxml.jackson.annotation.JsonTypeInfo - -@JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.NAME) -trait UniversalNoun[+T] extends Equals { - def id: T -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD deleted file mode 100644 index 16504ded3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/lihaoyi:sourcecode", - "util/util-core", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], - exports = [ - "3rdparty/jvm/com/lihaoyi:sourcecode", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala deleted file mode 100644 index 1ad6ec144..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidatePipelineIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Candidate Pipeline identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class CandidatePipelineIdentifier(override val name: String) - extends ComponentIdentifier("CandidatePipeline", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CandidatePipelineIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: CandidatePipelineIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object CandidatePipelineIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): CandidatePipelineIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new CandidatePipelineIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal CandidatePipelineIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala deleted file mode 100644 index b83cb011d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/CandidateSourceIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Candidate Source identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class CandidateSourceIdentifier(override val name: String) - extends ComponentIdentifier("CandidateSource", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[CandidateSourceIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: CandidateSourceIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object CandidateSourceIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): CandidateSourceIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new CandidateSourceIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal CandidateSourceIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala deleted file mode 100644 index a95973ea2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifier.scala +++ /dev/null @@ -1,111 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.twitter.conversions.StringOps -import scala.util.matching.Regex - -/** - * Component Identifiers are a type of identifier used in product mixer to identify - * unique components - products, pipelines, candidate sources. - * - * Each identifier has two parts - a type and a name. Subclasses of [[ComponentIdentifier]] - * should hardcode the `componentType`, and be declared in this file. - * - * For example, a [[ProductPipelineIdentifier]] has the type "ProductPipeline". - * - * Component identifiers are used in: - * - Logs - * - Tooling - * - Metrics - * - Feature Switches - * - * A component identifier name is restricted to: - * - 3 to 80 characters to ensure reasonable length - * - A-Z, a-z, and Digits - * - Must start with A-Z - * - Digits only on the ends of "words" - * - Examples include "AlphaSample" and "UsersLikeMe" - * - and "SimsV2" or "Test6" - * - * Avoid including types like "Pipeline", "MixerPipeline" etc in your identifier. these - * can be implied by the type itself, and will automatically be used where appropriate (logs etc). - */ -@JsonSerialize(using = classOf[ComponentIdentifierSerializer]) -abstract class ComponentIdentifier( - val componentType: String, - val name: String) - extends Equals { - - val file: sourcecode.File = "" - - override val toString: String = s"$name$componentType" - - val snakeCase: String = StringOps.toSnakeCase(toString) - - val toScopes: Seq[String] = Seq(componentType, name) -} - -object ComponentIdentifier { - // Allows for CamelCase and CamelCaseVer3 styles - val AllowedCharacters: Regex = "([A-Z][A-Za-z]*[0-9]*)+".r - val MinLength = 3 - val MaxLength = 80 - - /** - * When a [[ComponentIdentifier.name]] is [[BasedOnParentComponent]] - * then when operations that depend on the [[ComponentIdentifier]] - * are performed, like registering and stats, we will perform that - * operation by substituting the [[ComponentIdentifier.name]] with - * the parent component's [[ComponentIdentifier.name]]. - */ - private[core] val BasedOnParentComponent = "BasedOnParentComponent" - - def isValidName(name: String): Boolean = { - name match { - case n if n.length < MinLength => - false - case n if n.length > MaxLength => - false - case AllowedCharacters(_*) => - true - case _ => - false - } - } - - implicit val ordering: Ordering[ComponentIdentifier] = - Ordering.by { component => - val componentTypeRank = component match { - case _: ProductIdentifier => 0 - case _: ProductPipelineIdentifier => 1 - case _: MixerPipelineIdentifier => 2 - case _: RecommendationPipelineIdentifier => 3 - case _: ScoringPipelineIdentifier => 4 - case _: CandidatePipelineIdentifier => 5 - case _: PipelineStepIdentifier => 6 - case _: CandidateSourceIdentifier => 7 - case _: FeatureHydratorIdentifier => 8 - case _: GateIdentifier => 9 - case _: FilterIdentifier => 10 - case _: TransformerIdentifier => 11 - case _: ScorerIdentifier => 12 - case _: DecoratorIdentifier => 13 - case _: DomainMarshallerIdentifier => 14 - case _: TransportMarshallerIdentifier => 15 - case _: SideEffectIdentifier => 16 - case _: PlatformIdentifier => 17 - case _: SelectorIdentifier => 18 - case _ => Int.MaxValue - } - - // First rank by type, then by name for equivalent types for overall order stability - (componentTypeRank, component.name) - } -} - -/** - * HasComponentIdentifier indicates that component has a [[ComponentIdentifier]] - */ -trait HasComponentIdentifier { - val identifier: ComponentIdentifier -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala deleted file mode 100644 index a9c2cac6a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierSerializer.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.JsonSerializer -import com.fasterxml.jackson.databind.SerializerProvider - -private[identifier] class ComponentIdentifierSerializer() - extends JsonSerializer[ComponentIdentifier] { - - private case class SerializableComponentIdentifier( - identifier: String, - sourceFile: String) - - override def serialize( - componentIdentifier: ComponentIdentifier, - gen: JsonGenerator, - serializers: SerializerProvider - ): Unit = serializers.defaultSerializeValue( - SerializableComponentIdentifier(componentIdentifier.toString, componentIdentifier.file.value), - gen) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala deleted file mode 100644 index 663e3a3dd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStack.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -import com.fasterxml.jackson.databind.annotation.JsonSerialize - -/** - * A non-empty immutable stack of [[ComponentIdentifier]]s - * - * [[ComponentIdentifierStack]] does not support removing [[ComponentIdentifier]]s, - * instead a [[ComponentIdentifierStack]] should be used by adding new [[ComponentIdentifier]]s - * as processing enters a given `Component`, then discarded after. - * Think of this as similar to a let-scoped variable, where the let-scope is the given component. - */ -@JsonSerialize(using = classOf[ComponentIdentifierStackSerializer]) -class ComponentIdentifierStack private (val componentIdentifiers: List[ComponentIdentifier]) { - - /** Make a new [[ComponentIdentifierStack]] with the [[ComponentIdentifier]] added at the top */ - def push(newComponentIdentifier: ComponentIdentifier): ComponentIdentifierStack = - new ComponentIdentifierStack(newComponentIdentifier :: componentIdentifiers) - - /** Make a new [[ComponentIdentifierStack]] with the [[ComponentIdentifier]]s added at the top */ - def push(newComponentIdentifiers: ComponentIdentifierStack): ComponentIdentifierStack = - new ComponentIdentifierStack( - newComponentIdentifiers.componentIdentifiers ::: componentIdentifiers) - - /** Make a new [[ComponentIdentifierStack]] with the [[ComponentIdentifier]]s added at the top */ - def push(newComponentIdentifiers: Option[ComponentIdentifierStack]): ComponentIdentifierStack = { - newComponentIdentifiers match { - case Some(newComponentIdentifiers) => push(newComponentIdentifiers) - case None => this - } - } - - /** Return the top element of the [[ComponentIdentifierStack]] */ - val peek: ComponentIdentifier = componentIdentifiers.head - - /** Return the size of the [[ComponentIdentifierStack]] */ - def size: Int = componentIdentifiers.length - - override def toString: String = - s"ComponentIdentifierStack(componentIdentifiers = $componentIdentifiers)" - - override def equals(obj: Any): Boolean = { - obj match { - case componentIdentifierStack: ComponentIdentifierStack - if componentIdentifierStack.eq(this) || - componentIdentifierStack.componentIdentifiers == componentIdentifiers => - true - case _ => false - } - } -} - -object ComponentIdentifierStack { - - /** - * Returns a [[ComponentIdentifierStack]] from the given [[ComponentIdentifier]]s, - * where the top of the stack is the left-most [[ComponentIdentifier]] - */ - def apply( - componentIdentifier: ComponentIdentifier, - componentIdentifierStack: ComponentIdentifier* - ) = - new ComponentIdentifierStack(componentIdentifier :: componentIdentifierStack.toList) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala deleted file mode 100644 index da8855df1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ComponentIdentifierStackSerializer.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.JsonSerializer -import com.fasterxml.jackson.databind.SerializerProvider - -private[identifier] class ComponentIdentifierStackSerializer() - extends JsonSerializer[ComponentIdentifierStack] { - override def serialize( - componentIdentifierStack: ComponentIdentifierStack, - gen: JsonGenerator, - serializers: SerializerProvider - ): Unit = serializers.defaultSerializeValue(componentIdentifierStack.componentIdentifiers, gen) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala deleted file mode 100644 index 3a9cfef88..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DecoratorIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Decorator identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class DecoratorIdentifier(override val name: String) - extends ComponentIdentifier("Decorator", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[DecoratorIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: DecoratorIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object DecoratorIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): DecoratorIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new DecoratorIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal DecoratorIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala deleted file mode 100644 index b0b22bb16..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/DomainMarshallerIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Domain Marshaller identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class DomainMarshallerIdentifier(override val name: String) - extends ComponentIdentifier("DomainMarshaller", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[DomainMarshallerIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: DomainMarshallerIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object DomainMarshallerIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): DomainMarshallerIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new DomainMarshallerIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal DomainMarshallerIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala deleted file mode 100644 index 46ace3cbd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FeatureHydratorIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Feature Hydrator identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class FeatureHydratorIdentifier(override val name: String) - extends ComponentIdentifier("FeatureHydrator", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[FeatureHydratorIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: FeatureHydratorIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object FeatureHydratorIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): FeatureHydratorIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new FeatureHydratorIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal FeatureHydratorIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala deleted file mode 100644 index 2b5c2113e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/FilterIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Filter identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class FilterIdentifier(override val name: String) - extends ComponentIdentifier("Filter", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[FilterIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: FilterIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object FilterIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): FilterIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new FilterIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal FilterIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala deleted file mode 100644 index 19309aa21..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/GateIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Gate identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class GateIdentifier(override val name: String) - extends ComponentIdentifier("Gate", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[GateIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: GateIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object GateIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): GateIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new GateIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal GateIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala deleted file mode 100644 index 696dc4ff1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/MixerPipelineIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Mixer Pipeline identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class MixerPipelineIdentifier(override val name: String) - extends ComponentIdentifier("MixerPipeline", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[MixerPipelineIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: MixerPipelineIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object MixerPipelineIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): MixerPipelineIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new MixerPipelineIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal MixerPipelineIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala deleted file mode 100644 index 5df48e069..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PipelineStepIdentifier.scala +++ /dev/null @@ -1,90 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Pipeline Step identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class PipelineStepIdentifier( - override val name: String) - extends ComponentIdentifier("Step", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[PipelineStepIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: PipelineStepIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -class Person(val name: String, val age: Int) extends Equals { - override def canEqual(that: Any): Boolean = - that.isInstanceOf[Person] - - //Intentionally avoiding the call to super.equals because no ancestor has overridden equals (see note 7 below) - override def equals(that: Any): Boolean = - that match { - case person: Person => - (this eq person) || (hashCode == person.hashCode) && ((name == person.name) && (age == person.age)) - - case _ => - false - } - - //Intentionally avoiding the call to super.hashCode because no ancestor has overridden hashCode (see note 7 below) - override def hashCode(): Int = - 31 * ( - name.## - ) + age.## -} - -object PipelineStepIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): PipelineStepIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new PipelineStepIdentifier(name) { override val file: sourcecode.File = sourceFile } - else - throw new IllegalArgumentException(s"Illegal StepIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala deleted file mode 100644 index 47a0c57e2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/PlatformIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * [[ComponentIdentifier]] type used by internal parts of Product Mixer that need to be identified - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class PlatformIdentifier(override val name: String) - extends ComponentIdentifier("Platform", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[PlatformIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: PlatformIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object PlatformIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): PlatformIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new PlatformIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal PlatformIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala deleted file mode 100644 index 681be8c9d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Product identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class ProductIdentifier(override val name: String) - extends ComponentIdentifier("Product", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[ProductIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: ProductIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object ProductIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): ProductIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new ProductIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal ProductIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala deleted file mode 100644 index 21a8ca26d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ProductPipelineIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Product Pipeline identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class ProductPipelineIdentifier(override val name: String) - extends ComponentIdentifier("ProductPipeline", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[ProductPipelineIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: ProductPipelineIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object ProductPipelineIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): ProductPipelineIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new ProductPipelineIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal ProductPipelineIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala deleted file mode 100644 index f10e6d28d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RecommendationPipelineIdentifier.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Recommendation Pipeline identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class RecommendationPipelineIdentifier(override val name: String) - extends ComponentIdentifier("RecommendationPipeline", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[RecommendationPipelineIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: RecommendationPipelineIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object RecommendationPipelineIdentifier { - def apply( - name: String - )( - implicit sourceFile: sourcecode.File - ): RecommendationPipelineIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new RecommendationPipelineIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal RecommendationPipelineIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala deleted file mode 100644 index 5d55c6422..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/RootIdentifier.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Root identifier used as the root identifier for products during component registration - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class RootIdentifier extends ComponentIdentifier("Root", "") { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[RootIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: RootIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object RootIdentifier { - def apply()(implicit sourceFile: sourcecode.File): RootIdentifier = { - new RootIdentifier() { - override val file: sourcecode.File = sourceFile - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala deleted file mode 100644 index 3caee298f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScorerIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Scorer identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class ScorerIdentifier(override val name: String) - extends ComponentIdentifier("Scorer", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[ScorerIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: ScorerIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object ScorerIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): ScorerIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new ScorerIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal ScorerIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala deleted file mode 100644 index 3b2fbdb86..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/ScoringPipelineIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Scoring Pipeline identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class ScoringPipelineIdentifier(override val name: String) - extends ComponentIdentifier("ScoringPipeline", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[ScoringPipelineIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: ScoringPipelineIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object ScoringPipelineIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): ScoringPipelineIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new ScoringPipelineIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal ScoringPipelineIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala deleted file mode 100644 index 5e04d394b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SelectorIdentifier.scala +++ /dev/null @@ -1,79 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Selector identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class SelectorIdentifier(override val name: String) - extends ComponentIdentifier("Selector", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[SelectorIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: SelectorIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -/** - * Used in `SelectorExecutor` to give an ID to each selector in the `ComponentIdentifierStack` - * - * These are often generated automatically in the executor and are dependent on the class names - * so we skip validation to avoid issues. Since we dont record stats for Selectors this is okay. - */ -private[core] object SelectorIdentifier { - def apply( - name: String, - index: Int - )( - implicit sourceFile: sourcecode.File - ): SelectorIdentifier = { - val capitalizedWithoutSpecialCharacters = name.replace("$", "").capitalize - new SelectorIdentifier(index.toString + capitalizedWithoutSpecialCharacters) { - override val file: sourcecode.File = sourceFile - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala deleted file mode 100644 index 4775721b6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/SideEffectIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Side Effect identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class SideEffectIdentifier(override val name: String) - extends ComponentIdentifier("SideEffect", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[SideEffectIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: SideEffectIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object SideEffectIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): SideEffectIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new SideEffectIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal SideEffectIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala deleted file mode 100644 index e336c4460..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransformerIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Transformer identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class TransformerIdentifier(override val name: String) - extends ComponentIdentifier("Transformer", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TransformerIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: TransformerIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object TransformerIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): TransformerIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new TransformerIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal TransformerIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala deleted file mode 100644 index 07f7d8d76..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier/TransportMarshallerIdentifier.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.model.common.identifier - -/** - * Transport Marshaller identifier - * - * @note This class should always remain effectively `final`. If for any reason the `sealed` - * modifier is removed, the equals() implementation must be updated in order to handle class - * inheritor equality (see note on the equals method below) - */ -sealed abstract class TransportMarshallerIdentifier(override val name: String) - extends ComponentIdentifier("TransportMarshaller", name) { - - /** - * @inheritdoc - */ - override def canEqual(that: Any): Boolean = that.isInstanceOf[TransportMarshallerIdentifier] - - /** - * High performance implementation of equals method that leverages: - * - Referential equality short circuit - * - Cached hashcode equality short circuit - * - Field values are only checked if the hashCodes are equal to handle the unlikely case - * of a hashCode collision - * - Removal of check for `that` being an equals-compatible descendant since this class is final - * - * @note `candidate.canEqual(this)` is not necessary because this class is final - * @see [[http://www.artima.com/pins1ed/object-equality.html Programming in Scala, - * Chapter 28]] for discussion and design. - */ - override def equals(that: Any): Boolean = - that match { - case identifier: TransportMarshallerIdentifier => - // Note identifier.canEqual(this) is not necessary because this class is effectively final - ((this eq identifier) - || ((hashCode == identifier.hashCode) && ((componentType == identifier.componentType) && (name == identifier.name)))) - case _ => - false - } - - /** - * Leverage domain-specific constraints (see notes below) to safely construct and cache the - * hashCode as a val, such that it is instantiated once on object construction. This prevents the - * need to recompute the hashCode on each hashCode() invocation, which is the behavior of the - * Scala compiler case class-generated hashCode() since it cannot make assumptions regarding field - * object mutability and hashCode implementations. - * - * @note Caching the hashCode is only safe if all of the fields used to construct the hashCode - * are immutable. This includes: - * - Inability to mutate the object reference on for an existing instantiated identifier - * (i.e. each field is a val) - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * - Inability to mutate the field object instance itself (i.e. each field is an immutable - * data structure), assuming stable hashCode implementations for these objects - * - * @note In order for the hashCode to be consistent with object equality, `##` must be used for - * boxed numeric types and null. As such, always prefer `.##` over `.hashCode()`. - */ - override val hashCode: Int = 31 * componentType.## + name.## -} - -object TransportMarshallerIdentifier { - def apply(name: String)(implicit sourceFile: sourcecode.File): TransportMarshallerIdentifier = { - if (ComponentIdentifier.isValidName(name)) - new TransportMarshallerIdentifier(name) { - override val file: sourcecode.File = sourceFile - } - else - throw new IllegalArgumentException(s"Illegal TransportMarshallerIdentifier: $name") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD deleted file mode 100644 index 506c23b1b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala deleted file mode 100644 index 65f476af5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateFeatures.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import scala.collection.immutable.ListSet - -/** - * A list set of all the candidate pipelines a candidate originated from. This is typically a - * single element set, but merging candidates across pipelines using - * [[com.twitter.product_mixer.component_library.selector.CombineFeatureMapsCandidateMerger]] - * will merge sets for the candidate. The last element of the set is the first pipeline identifier - * as we prepend new ones since we want O(1) access for the last element. - */ -object CandidatePipelines extends Feature[UniversalNoun[Any], ListSet[CandidatePipelineIdentifier]] - -/** - * A list set of all the candidate sources a candidate originated from. This is typically a - * single element set, but merging candidates across pipelines using - * [[com.twitter.product_mixer.component_library.selector.CombineFeatureMapsCandidateMerger]] - * will merge sets for the candidate. The last element of the set is the first source identifier - * as we prepend new ones since we want O(1) access for the last element. - */ -object CandidateSources extends Feature[UniversalNoun[Any], ListSet[CandidateSourceIdentifier]] - -/** - * The source position relative to all candidates the originating candidate source a candidate - * came from. When merged with other candidates, the position from the first candidate source - * takes priority. - */ -object CandidateSourcePosition extends Feature[UniversalNoun[Any], Int] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala deleted file mode 100644 index ff6297a92..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/CandidateWithDetails.scala +++ /dev/null @@ -1,140 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult -import scala.collection.immutable.ListSet -import scala.reflect.ClassTag - -sealed trait CandidateWithDetails { self => - def presentation: Option[UniversalPresentation] - def features: FeatureMap - - // last of the set because in ListSet, the last element is the first inserted one with O(1) - // access - lazy val source: CandidatePipelineIdentifier = features.get(CandidatePipelines).last - lazy val sourcePosition: Int = features.get(CandidateSourcePosition) - - /** - * @see [[getCandidateId]] - */ - def candidateIdLong: Long = getCandidateId[Long] - - /** - * @see [[getCandidateId]] - */ - def candidateIdString: String = getCandidateId[String] - - /** - * Convenience method for retrieving a candidate ID off of the base [[CandidateWithDetails]] trait - * without manually pattern matching. - * - * @throws PipelineFailure if CandidateIdType does not match the expected Item Candidate Id type, - * or if invoked on a Module Candidate - */ - def getCandidateId[CandidateIdType]( - )( - implicit tag: ClassTag[CandidateIdType] - ): CandidateIdType = - self match { - case item: ItemCandidateWithDetails => - item.candidate.id match { - case id: CandidateIdType => id - case _ => - throw PipelineFailure( - UnexpectedCandidateResult, - s"Invalid Item Candidate ID type expected $tag for Item Candidate type ${item.candidate.getClass}") - } - case _: ModuleCandidateWithDetails => - throw PipelineFailure( - UnexpectedCandidateResult, - "Cannot retrieve Item Candidate ID for a Module") - } - - /** - * Convenience method for retrieving a candidate off of the base [[CandidateWithDetails]] trait - * without manually pattern matching. - * - * @throws PipelineFailure if CandidateType does not match the expected Item Candidate type, or - * if invoked on a Module Candidate - */ - def getCandidate[CandidateType <: UniversalNoun[_]]( - )( - implicit tag: ClassTag[CandidateType] - ): CandidateType = - self match { - case ItemCandidateWithDetails(candidate: CandidateType, _, _) => candidate - case item: ItemCandidateWithDetails => - throw PipelineFailure( - UnexpectedCandidateResult, - s"Invalid Item Candidate type expected $tag for Item Candidate type ${item.candidate.getClass}") - case _: ModuleCandidateWithDetails => - throw PipelineFailure( - UnexpectedCandidateResult, - "Cannot retrieve Item Candidate for a Module") - } - - /** - * Convenience method for checking if this contains a certain candidate type - * - * @throws PipelineFailure if CandidateType does not match the expected Item Candidate type, or - * if invoked on a Module Candidate - */ - def isCandidateType[CandidateType <: UniversalNoun[_]]( - )( - implicit tag: ClassTag[CandidateType] - ): Boolean = self match { - case ItemCandidateWithDetails(_: CandidateType, _, _) => true - case _ => false - } -} - -case class ItemCandidateWithDetails( - override val candidate: UniversalNoun[Any], - presentation: Option[UniversalPresentation], - override val features: FeatureMap) - extends CandidateWithDetails - with CandidateWithFeatures[UniversalNoun[Any]] - -case class ModuleCandidateWithDetails( - candidates: Seq[ItemCandidateWithDetails], - presentation: Option[ModulePresentation], - override val features: FeatureMap) - extends CandidateWithDetails - -object ItemCandidateWithDetails { - def apply( - candidate: UniversalNoun[Any], - presentation: Option[UniversalPresentation], - source: CandidatePipelineIdentifier, - sourcePosition: Int, - features: FeatureMap - ): ItemCandidateWithDetails = { - val newFeatureMap = - FeatureMapBuilder() - .add(CandidateSourcePosition, sourcePosition) - .add(CandidatePipelines, ListSet.empty + source).build() ++ features - ItemCandidateWithDetails(candidate, presentation, newFeatureMap) - } -} - -object ModuleCandidateWithDetails { - def apply( - candidates: Seq[ItemCandidateWithDetails], - presentation: Option[ModulePresentation], - source: CandidatePipelineIdentifier, - sourcePosition: Int, - features: FeatureMap - ): ModuleCandidateWithDetails = { - val newFeatureMap = - FeatureMapBuilder() - .add(CandidateSourcePosition, sourcePosition) - .add(CandidatePipelines, ListSet.empty + source).build() ++ features - - ModuleCandidateWithDetails(candidates, presentation, newFeatureMap) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala deleted file mode 100644 index 93f86e2b4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ItemPresentation.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation - -trait ItemPresentation extends UniversalPresentation { - // Optional field which if populated, will group the items into the specified module - def modulePresentation: Option[ModulePresentation] = None -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala deleted file mode 100644 index dff815c8a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/ModulePresentation.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation - -trait ModulePresentation extends UniversalPresentation diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala deleted file mode 100644 index d206c5b23..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/UniversalPresentation.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation - -/** - * Encapsulates information about how to present a Candidate - * - * Implementations of a [[UniversalPresentation]] contain information about how to present the Candidate. - * This extra information can be in fields in the implementations or in their types. - * - * For instance, a Tweet candidate that will be displayed as a URT Tweet Item will be decorated with a - * [[UniversalPresentation]] implementation that reflects the presentation such as - * [[com.twitter.product_mixer.component_library.model.presentation.urt.UrtItemPresentation]] - * - * @see [[com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator]] for associating a - * [[UniversalPresentation]] with a Candidate. - */ -trait UniversalPresentation diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD deleted file mode 100644 index 67ebe01c4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala deleted file mode 100644 index dedb450ce..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/slice/BaseSliceItemPresentation.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation.slice - -import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation -import com.twitter.product_mixer.core.model.marshalling.response.slice.SliceItem - -trait BaseSliceItemPresentation extends ItemPresentation { - def sliceItem: SliceItem -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD deleted file mode 100644 index b9923428d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala deleted file mode 100644 index 7e1f87bef..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtItemPresentation.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -trait BaseUrtItemPresentation extends ItemPresentation { - - def timelineItem: TimelineItem -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala deleted file mode 100644 index d1a774499..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtModulePresentation.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.ModulePresentation -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineModule - -trait BaseUrtModulePresentation extends ModulePresentation { - def timelineModule: TimelineModule -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala deleted file mode 100644 index 0d0a74da3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/BaseUrtOperationPresentation.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation.urt - -import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation - -trait BaseUrtOperationPresentation extends ItemPresentation { - - def timelineOperation: TimelineOperation -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala deleted file mode 100644 index 33ff69c21..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/IsDispensable.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation.urt - -/** - * Whether an item is considered dispensable within a module. - * Dispensable module items should never be left as the final remaining - * items within a module. Whenever a module would be left with only - * dispensable contents (through removal or dismissal of other items) the - * entire module should be discarded as if contained 0 items. - * - * @see http://go/urtDispensableModuleItems - */ -trait IsDispensable { self: BaseUrtItemPresentation => - def dispensable: Boolean -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala deleted file mode 100644 index 0235a20de..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation/urt/WithItemTreeDisplay.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.model.common.presentation.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ModuleItemTreeDisplay - -/* - * Tree state declaring item’s parent relationship with any other items in - * the module, any display indentation information, and/or collapsed display state. - */ -trait WithItemTreeDisplay { self: BaseUrtItemPresentation => - def treeDisplay: Option[ModuleItemTreeDisplay] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD deleted file mode 100644 index c9ed8c7eb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/BUILD +++ /dev/null @@ -1,8 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala deleted file mode 100644 index 5158523ee..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/HasMarshalling.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling - -trait HasMarshalling diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD deleted file mode 100644 index 790abac6d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/fasterxml/jackson:jackson-module-scala", - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "configapi/configapi-core/src/main/scala/com/twitter/timelines/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "util/util-core:util-core-util", - ], - exports = [ - "3rdparty/jvm/com/fasterxml/jackson:jackson-module-scala", - "3rdparty/jvm/com/fasterxml/jackson/core:jackson-annotations", - "configapi/configapi-core/src/main/scala/com/twitter/timelines/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "util/util-core:util-core-util", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala deleted file mode 100644 index 31ba2ad04..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ClientContext.scala +++ /dev/null @@ -1,94 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -import com.fasterxml.jackson.annotation.JsonIgnore -import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure - -/** - * ClientContext contains fields related to the client making the request. - */ -case class ClientContext( - userId: Option[Long], - guestId: Option[Long], - guestIdAds: Option[Long], - guestIdMarketing: Option[Long], - appId: Option[Long], - ipAddress: Option[String], - userAgent: Option[String], - countryCode: Option[String], - languageCode: Option[String], - isTwoffice: Option[Boolean], - userRoles: Option[Set[String]], - deviceId: Option[String], - mobileDeviceId: Option[String], - mobileDeviceAdId: Option[String], - limitAdTracking: Option[Boolean]) - -object ClientContext { - val empty: ClientContext = ClientContext( - userId = None, - guestId = None, - guestIdAds = None, - guestIdMarketing = None, - appId = None, - ipAddress = None, - userAgent = None, - countryCode = None, - languageCode = None, - isTwoffice = None, - userRoles = None, - deviceId = None, - mobileDeviceId = None, - mobileDeviceAdId = None, - limitAdTracking = None - ) -} - -/** - * HasClientContext indicates that a request has [[ClientContext]] and adds helper functions for - * accessing [[ClientContext]] fields. - */ -trait HasClientContext { - def clientContext: ClientContext - - /** - * getRequiredUserId returns a userId and throw if it's missing. - * - * @note logged out requests are disabled by default so this is safe for most products - */ - @JsonIgnore /** Jackson tries to serialize this method, throwing an exception for guest products */ - def getRequiredUserId: Long = clientContext.userId.getOrElse( - throw PipelineFailure(BadRequest, "Missing required field: userId")) - - /** - * getOptionalUserId returns a userId if one is set - */ - def getOptionalUserId: Option[Long] = clientContext.userId - - /** - * getUserIdLoggedOutSupport returns a userId and falls back to 0 if none is set - */ - def getUserIdLoggedOutSupport: Long = clientContext.userId.getOrElse(0L) - - /** - * getUserOrGuestId returns a userId or a guestId if no userId has been set - */ - def getUserOrGuestId: Option[Long] = clientContext.userId.orElse(clientContext.guestId) - - /** - * getCountryCode returns a country code if one is set - */ - def getCountryCode: Option[String] = clientContext.countryCode - - /** - * getLanguageCode returns a language code if one is set - */ - def getLanguageCode: Option[String] = clientContext.languageCode - - /** - * isLoggedOut returns true if the user is logged out (no userId present). - * - * @note this can be useful in conjunction with [[getUserIdLoggedOutSupport]] - */ - def isLoggedOut: Boolean = clientContext.userId.isEmpty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala deleted file mode 100644 index 7347e333b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugOptions.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -import com.twitter.util.Time - -trait DebugOptions { - // Manually override the request time which is useful for writing deterministic Feature tests, - // since Feature tests do not support mocking Time. For example, URT sort indexes start with a - // Snowflake ID based on request time if no initialSortIndex is set on the request cursor, so to - // write a Feature test for this scenario, we can manually set the request time to use here. - def requestTimeOverride: Option[Time] = None -} - -trait HasDebugOptions { - def debugOptions: Option[DebugOptions] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala deleted file mode 100644 index 1c951cbf3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/DebugParams.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -import com.twitter.timelines.configapi.{FeatureValue => ConfigApiFeatureValue} - -case class DebugParams( - featureOverrides: Option[Map[String, ConfigApiFeatureValue]], - override val debugOptions: Option[DebugOptions]) - extends HasDebugOptions diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala deleted file mode 100644 index 40f60fc7c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasExcludedIds.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -/** - * Allow clients to pass in a set of IDs that would be excluded from the results. - */ -trait HasExcludedIds { - val excludedIds: Set[Long] = Set.empty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala deleted file mode 100644 index e52f2bcde..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/HasSerializedRequestCursor.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -/** - * serializedRequestCursor is any serialized representation of a cursor. - * - * The serialized representation is implementation-specific but will often be a base 64 - * representation of a Thrift struct. Cursors should not be deserialized in the unmarshaller. - */ -trait HasSerializedRequestCursor { - def serializedRequestCursor: Option[String] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala deleted file mode 100644 index 7afb2eefe..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Product.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.ProductIdentifier - -trait Product extends Component { - - /** - * Identifier names on products can be used to create Feature Switch rules by product, - * which useful if bucketing occurs in a component shared by multiple products. - * - * @see [[com.twitter.product_mixer.core.product.ProductParamConfig.supportedClientFSName]] - */ - override val identifier: ProductIdentifier - - /** - * To support StringCenter, override this val to `Some("name-of-string-center-project")` and - * include the `ProductScopeStringCenterModule` in the server's modules list - */ - val stringCenterProject: Option[String] = None -} - -trait HasProduct { - def product: Product -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala deleted file mode 100644 index 71a0d66ea..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/ProductContext.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -trait ProductContext - -trait HasProductContext { - def productContext: Option[ProductContext] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala deleted file mode 100644 index 7dfcf4e4d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request/Request.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.request - -trait Request - extends HasClientContext - with HasProduct - with HasProductContext - with HasSerializedRequestCursor { - def maxResults: Option[Int] - def debugParams: Option[DebugParams] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD deleted file mode 100644 index e37672b5c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala deleted file mode 100644 index b0709285a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level/SafetyLevel.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level - -/* - These are model objects for the thrift enum - src/thrift/com/twitter/spam/rtf/safety_level.thrift - Please add new objects as needed for the marhallers - */ -sealed trait SafetyLevel - -case object ConversationFocalTweetSafetyLevel extends SafetyLevel -case object ConversationReplySafetyLevel extends SafetyLevel -case object ConversationInjectedTweetSafetyLevel extends SafetyLevel -case object TimelineFocalTweetSafetyLevel extends SafetyLevel -case object TimelineHomePromotedHydrationSafetyLevel extends SafetyLevel diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD deleted file mode 100644 index e37672b5c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala deleted file mode 100644 index 5891027a6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/slice/SliceItem.scala +++ /dev/null @@ -1,84 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.slice - -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling - -/** - * These are the Ad Types exposed on AdUnits - * - * They are to be kept in sync with strato/config/src/thrift/com/twitter/strato/graphql/hubble.thrift - */ -sealed trait AdType -object AdType { - case object Tweet extends AdType - case object Account extends AdType - case object InStreamVideo extends AdType - case object DisplayCreative extends AdType - case object Trend extends AdType - case object Spotlight extends AdType - case object Takeover extends AdType -} - -trait SliceItem -case class TweetItem(id: Long) extends SliceItem -case class UserItem(id: Long) extends SliceItem -case class TwitterListItem(id: Long) extends SliceItem -case class DMConvoSearchItem(id: String, lastReadableEventId: Option[Long]) extends SliceItem -case class DMEventItem(id: Long) extends SliceItem -case class DMConvoItem(id: String, lastReadableEventId: Option[Long]) extends SliceItem -case class DMMessageSearchItem(id: Long) extends SliceItem -case class TopicItem(id: Long) extends SliceItem -case class TypeaheadEventItem(eventId: Long, metadata: Option[TypeaheadMetadata]) extends SliceItem -case class TypeaheadQuerySuggestionItem(query: String, metadata: Option[TypeaheadMetadata]) - extends SliceItem -case class TypeaheadUserItem( - userId: Long, - metadata: Option[TypeaheadMetadata], - badges: Seq[UserBadge]) - extends SliceItem -case class AdItem(adUnitId: Long, adAccountId: Long) extends SliceItem -case class AdCreativeItem(creativeId: Long, adType: AdType, adAccountId: Long) extends SliceItem -case class AdGroupItem(adGroupId: Long, adAccountId: Long) extends SliceItem -case class CampaignItem(campaignId: Long, adAccountId: Long) extends SliceItem -case class FundingSourceItem(fundingSourceId: Long, adAccountId: Long) extends SliceItem - -sealed trait CursorType -case object PreviousCursor extends CursorType -case object NextCursor extends CursorType -@deprecated( - "GapCursors are not supported by Product Mixer Slice marshallers, if you need support for these reach out to #product-mixer") -case object GapCursor extends CursorType - -// CursorItem extends SliceItem to enable support for GapCursors -case class CursorItem(value: String, cursorType: CursorType) extends SliceItem - -case class SliceInfo( - previousCursor: Option[String], - nextCursor: Option[String]) - -case class Slice( - items: Seq[SliceItem], - sliceInfo: SliceInfo) - extends HasMarshalling - -sealed trait TypeaheadResultContextType -case object You extends TypeaheadResultContextType -case object Location extends TypeaheadResultContextType -case object NumFollowers extends TypeaheadResultContextType -case object FollowRelationship extends TypeaheadResultContextType -case object Bio extends TypeaheadResultContextType -case object NumTweets extends TypeaheadResultContextType -case object Trending extends TypeaheadResultContextType -case object HighlightedLabel extends TypeaheadResultContextType - -case class TypeaheadResultContext( - contextType: TypeaheadResultContextType, - displayString: String, - iconUrl: Option[String]) - -case class TypeaheadMetadata( - score: Double, - source: Option[String], - context: Option[TypeaheadResultContext]) - -// Used to render badges in Typeahead, such as Business-affiliated badges -case class UserBadge(badgeType: String, badgeUrl: String, description: String) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD deleted file mode 100644 index b0c058fe3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala deleted file mode 100644 index df9656f85..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/Page.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig - -case class Page( - id: String, - pageBody: PageBody, - scribeConfig: Option[TimelineScribeConfig] = None, - pageHeader: Option[PageHeader] = None, - pageNavBar: Option[PageNavBar] = None) - extends HasMarshalling diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala deleted file mode 100644 index 8f3a0ff96..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageBody.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -sealed trait PageBody - -case class TimelineKeyPageBody(timeline: TimelineKey) extends PageBody - -case class SegmentedTimelinesPageBody( - initialTimeline: SegmentedTimeline, - timelines: Seq[SegmentedTimeline]) - extends PageBody diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala deleted file mode 100644 index b39b36a99..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageHeader.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasClientEventInfo - -sealed trait PageHeader - -case class TopicPageHeader( - topicId: String, - facepile: Option[TopicPageHeaderFacepile] = None, - override val clientEventInfo: Option[ClientEventInfo] = None, - landingContext: Option[String] = None, - displayType: Option[TopicPageHeaderDisplayType] = Some(BasicTopicPageHeaderDisplayType)) - extends PageHeader - with HasClientEventInfo diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala deleted file mode 100644 index ee1d4d554..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/PageNavBar.scala +++ /dev/null @@ -1,19 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasClientEventInfo - -sealed trait PageNavBar - -case class TopicPageNavBar( - topicId: String, - override val clientEventInfo: Option[ClientEventInfo] = None) - extends PageNavBar - with HasClientEventInfo - -case class TitleNavBar( - title: String, - subtitle: Option[String] = None, - override val clientEventInfo: Option[ClientEventInfo] = None) - extends PageNavBar - with HasClientEventInfo diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala deleted file mode 100644 index a727376f4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/SegmentedTimeline.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineScribeConfig - -case class SegmentedTimeline( - id: String, - labelText: String, - timeline: TimelineKey, - scribeConfig: Option[TimelineScribeConfig] = None, - refreshIntervalSec: Option[Long] = None) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala deleted file mode 100644 index 6146693d1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TimelineKey.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -sealed trait TimelineKey - -case class TopicsLandingTimeline(topicId: Option[String]) extends TimelineKey - -case class NoteworthyAccountsTimeline(topicId: Option[String]) extends TimelineKey - -case class TopicsPickerTimeline(topicId: Option[String]) extends TimelineKey - -case class NotInterestedTopicsMeTimeline() extends TimelineKey - -case class FollowedTopicsMeTimeline() extends TimelineKey - -case class FollowedTopicsOtherTimeline(userId: Long) extends TimelineKey - -case class NuxUserRecommendationsTimeline() extends TimelineKey - -case class NuxForYouCategoryUserRecommendationsTimeline() extends TimelineKey - -case class NuxPymkCategoryUserRecommendationsTimeline() extends TimelineKey - -case class NuxGeoCategoryUserRecommendationsTimeline() extends TimelineKey - -case class NuxSingleInterestCategoryUserRecommendationsTimeline(topicId: Option[String]) - extends TimelineKey - -case class ShoppingHomeTimeline() extends TimelineKey - -case class ForYouExploreMixerTimeline() extends TimelineKey - -case class TrendingExploreMixerTimeline() extends TimelineKey diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala deleted file mode 100644 index 3ef6e3851..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -sealed trait TopicPageHeaderDisplayType - -case object BasicTopicPageHeaderDisplayType extends TopicPageHeaderDisplayType -case object PersonalizedTopicPageHeaderDisplayType extends TopicPageHeaderDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala deleted file mode 100644 index ce6599028..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp/TopicPageHeaderFacepile.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urp - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url - -case class TopicPageHeaderFacepile( - userIds: Seq[Long], - facepileUrl: Option[Url] = None) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD deleted file mode 100644 index 683520b2c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module", - "util/util-core:util-core-util", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module", - "util/util-core:util-core-util", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala deleted file mode 100644 index 568fa103f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Cover.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -trait Cover extends TimelineItem diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala deleted file mode 100644 index 53838658b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/EntryNamespace.scala +++ /dev/null @@ -1,50 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import scala.util.matching.Regex - -/** - * Entry Identifiers (commonly entry ids) are a type of identifier used in URT to identify - * unique timeline entries - tweets, users, modules, etc. - * - * Entry Identifiers are formed from two parts - a namespace (EntryNamespace) and an underlying - * id. - * - * A Entry Namespace is restricted to: - * - 3 to 60 characters to ensure reasonable length - * - a-z and dashes (kebab-case) - * - Examples include "user" and "tweet" - * - * When specific entries identifiers are created, they will be appended with a dash and their - * own id, like user-12 or tweet-20 - */ - -trait HasEntryNamespace { - val entryNamespace: EntryNamespace -} - -// sealed abstract case class is basically a scala 2.12 opaque type - -// you can only create them via the factory method on the companion -// allowing us to enforce validation -sealed abstract case class EntryNamespace(override val toString: String) - -object EntryNamespace { - val AllowedCharacters: Regex = "[a-z-]+".r // Allows for kebab-case - - def apply(str: String): EntryNamespace = { - val isValid = str match { - case n if n.length < 3 => - false - case n if n.length > 60 => - false - case AllowedCharacters() => - true - case _ => - false - } - - if (isValid) - new EntryNamespace(str) {} - else - throw new IllegalArgumentException(s"Illegal EntryNamespace: $str") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala deleted file mode 100644 index 6008172c5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasEntryIdentifier.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -trait HasEntryIdentifier extends UniversalNoun[Any] with HasEntryNamespace { - // Distinctly identifies this entry and must be unique relative to other entries within a response - lazy val entryIdentifier: String = s"$entryNamespace-$id" -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala deleted file mode 100644 index e20c75131..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasExpirationTime.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.util.Time - -trait HasExpirationTime { - def expirationTime: Option[Time] = None - - final def expirationTimeInMillis: Option[Long] = expirationTime.map(_.inMillis) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala deleted file mode 100644 index e3a9f6d55..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/HasSortIndex.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -trait HasSortIndex { timelineEntry: TimelineEntry => - def sortIndex: Option[Long] - - def withSortIndex(sortIndex: Long): TimelineEntry -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala deleted file mode 100644 index c1d612f3d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ModuleItemTreeDisplay.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType - -case class ModuleItemTreeDisplay( - parentModuleEntryItemId: Option[String], - indentFromParent: Option[Boolean], - displayType: Option[ModuleDisplayType], - isAnchorChild: Option[Boolean]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala deleted file mode 100644 index 412e6aa67..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ReaderModeConfig.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import metadata.Url - -case class ReaderModeConfig(isReaderModeAvailable: Boolean, landingUrl: Url) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala deleted file mode 100644 index 602af7498..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/ShowAlert.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.ShowAlert.ShowAlertEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertColorConfiguration -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertDisplayLocation -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertIconDisplayInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertNavigationMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.alert.ShowAlertType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.util.Duration - -/** - * Domain model for the URT ShowAlert [[https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/ShowAlert.html]] - * - * @note the text field (id: 2) has been deliberately excluded as it's been deprecated since 2018. Use RichText instead. - */ -case class ShowAlert( - override val id: String, - override val sortIndex: Option[Long], - alertType: ShowAlertType, - triggerDelay: Option[Duration], - displayDuration: Option[Duration], - clientEventInfo: Option[ClientEventInfo], - collapseDelay: Option[Duration], - userIds: Option[Seq[Long]], - richText: Option[RichText], - iconDisplayInfo: Option[ShowAlertIconDisplayInfo], - colorConfig: ShowAlertColorConfiguration, - displayLocation: ShowAlertDisplayLocation, - navigationMetadata: Option[ShowAlertNavigationMetadata], -) extends TimelineItem { - override val entryNamespace: EntryNamespace = ShowAlertEntryNamespace - - // Note that sort index is not used for ShowAlerts, as they are not TimelineEntry and do not have entryId - override def withSortIndex(newSortIndex: Long): TimelineEntry = - copy(sortIndex = Some(newSortIndex)) - - // Not used for ShowAlerts - override def feedbackActionInfo: Option[FeedbackActionInfo] = None -} - -object ShowAlert { - val ShowAlertEntryNamespace: EntryNamespace = EntryNamespace("show-alert") -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala deleted file mode 100644 index 83c46cb9f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/Timeline.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling - -case class Timeline( - id: String, - instructions: Seq[TimelineInstruction], - // responseObjects::feedbackActions actions are populated implicitly, see UrtTransportMarshaller - metadata: Option[TimelineMetadata] = None) - extends HasMarshalling diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala deleted file mode 100644 index 70163f3a8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineEntry.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ContainsFeedbackActionInfos -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasFeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.PinnableEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ReplaceableEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.MarkUnreadableEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleFooter -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleHeader -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module.ModuleShowMoreBehavior - -sealed trait TimelineEntry - extends HasEntryIdentifier - with HasSortIndex - with HasExpirationTime - with PinnableEntry - with ReplaceableEntry - with MarkUnreadableEntry - -trait TimelineItem extends TimelineEntry with HasClientEventInfo with HasFeedbackActionInfo - -case class ModuleItem( - item: TimelineItem, - dispensable: Option[Boolean], - treeDisplay: Option[ModuleItemTreeDisplay]) - -case class TimelineModule( - override val id: Long, - override val sortIndex: Option[Long], - override val entryNamespace: EntryNamespace, - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - override val isPinned: Option[Boolean], - items: Seq[ModuleItem], - displayType: ModuleDisplayType, - header: Option[ModuleHeader], - footer: Option[ModuleFooter], - metadata: Option[ModuleMetadata], - showMoreBehavior: Option[ModuleShowMoreBehavior]) - extends TimelineEntry - with HasClientEventInfo - with HasFeedbackActionInfo - with ContainsFeedbackActionInfos { - override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] = { - items.map(_.item.feedbackActionInfo) :+ feedbackActionInfo - } - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} - -trait TimelineOperation extends TimelineEntry diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala deleted file mode 100644 index 9b89750cb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineInstruction.scala +++ /dev/null @@ -1,65 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ContainsFeedbackActionInfos -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.HasFeedbackActionInfo - -sealed trait TimelineInstruction - -case class AddEntriesTimelineInstruction(entries: Seq[TimelineEntry]) - extends TimelineInstruction - with ContainsFeedbackActionInfos { - override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] = - entries.flatMap { - // Order is important, as entries that implement both ContainsFeedbackActionInfos and - // HasFeedbackActionInfo are expected to include both when implementing ContainsFeedbackActionInfos - case containsFeedbackActionInfos: ContainsFeedbackActionInfos => - containsFeedbackActionInfos.feedbackActionInfos - case hasFeedbackActionInfo: HasFeedbackActionInfo => - Seq(hasFeedbackActionInfo.feedbackActionInfo) - case _ => Seq.empty - } -} - -case class ReplaceEntryTimelineInstruction(entry: TimelineEntry) - extends TimelineInstruction - with ContainsFeedbackActionInfos { - override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] = - entry match { - // Order is important, as entries that implement both ContainsFeedbackActionInfos and - // HasFeedbackActionInfo are expected to include both when implementing ContainsFeedbackActionInfos - case containsFeedbackActionInfos: ContainsFeedbackActionInfos => - containsFeedbackActionInfos.feedbackActionInfos - case hasFeedbackActionInfo: HasFeedbackActionInfo => - Seq(hasFeedbackActionInfo.feedbackActionInfo) - case _ => Seq.empty - } -} - -case class AddToModuleTimelineInstruction( - moduleItems: Seq[ModuleItem], - moduleEntryId: String, - moduleItemEntryId: Option[String], - prepend: Option[Boolean]) - extends TimelineInstruction - with ContainsFeedbackActionInfos { - override def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] = - moduleItems.map(_.item.feedbackActionInfo) -} - -case class PinEntryTimelineInstruction(entry: TimelineEntry) extends TimelineInstruction - -case class MarkEntriesUnreadInstruction(entryIds: Seq[String]) extends TimelineInstruction - -case class ClearCacheTimelineInstruction() extends TimelineInstruction - -sealed trait TimelineTerminationDirection -case object TopTermination extends TimelineTerminationDirection -case object BottomTermination extends TimelineTerminationDirection -case object TopAndBottomTermination extends TimelineTerminationDirection -case class TerminateTimelineInstruction(terminateTimelineDirection: TimelineTerminationDirection) - extends TimelineInstruction - -case class ShowCoverInstruction(cover: Cover) extends TimelineInstruction - -case class ShowAlertInstruction(showAlert: ShowAlert) extends TimelineInstruction diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala deleted file mode 100644 index 88b74ea41..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineMetadata.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -case class TimelineMetadata( - title: Option[String], - scribeConfig: Option[TimelineScribeConfig], - readerModeConfig: Option[ReaderModeConfig] = None) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala deleted file mode 100644 index 6a7c46bbc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/TimelineScribeConfig.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt - -case class TimelineScribeConfig( - page: Option[String], - section: Option[String], - entityToken: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD deleted file mode 100644 index d5a4881bd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "util/util-core:scala", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - "util/util-core:scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala deleted file mode 100644 index e8378270d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertColorConfiguration.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.alert - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor - -case class ShowAlertColorConfiguration( - background: RosettaColor, - text: RosettaColor, - border: Option[RosettaColor], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala deleted file mode 100644 index adf797f9b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertDisplayLocation.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.alert - -sealed trait ShowAlertDisplayLocation -case object Top extends ShowAlertDisplayLocation -case object Bottom extends ShowAlertDisplayLocation diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala deleted file mode 100644 index 0405ca0ba..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIcon.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.alert - -sealed trait ShowAlertIcon -case object UpArrow extends ShowAlertIcon -case object DownArrow extends ShowAlertIcon diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala deleted file mode 100644 index e55498c10..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertIconDisplayInfo.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.alert - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor - -case class ShowAlertIconDisplayInfo(icon: ShowAlertIcon, tint: RosettaColor) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala deleted file mode 100644 index 5cef1453f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertNavigationMetadata.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.alert - -case class ShowAlertNavigationMetadata(navigateToEntryId: String) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala deleted file mode 100644 index 191ebed40..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/alert/ShowAlertType.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.alert - -sealed trait ShowAlertType -case object NewTweets extends ShowAlertType -case object Navigate extends ShowAlertType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD deleted file mode 100644 index 5e528fdc8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala deleted file mode 100644 index 241a9c78e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/ButtonStyle.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.button - -sealed trait ButtonStyle - -case object Default extends ButtonStyle -case object Primary extends ButtonStyle -case object Secondary extends ButtonStyle -case object Text extends ButtonStyle -case object Destructive extends ButtonStyle -case object Neutral extends ButtonStyle -case object DestructiveSecondary extends ButtonStyle -case object DestructiveText extends ButtonStyle diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala deleted file mode 100644 index 9820c52ab..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button/CtaButton.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.button - -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url - -sealed trait CtaButton - -case class TextCtaButton(buttonText: String, url: Url) extends CtaButton - -case class IconCtaButton(buttonIcon: HorizonIcon, accessibilityLabel: String, url: Url) - extends CtaButton diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD deleted file mode 100644 index c9ed8c7eb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/BUILD +++ /dev/null @@ -1,8 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala deleted file mode 100644 index 6dc9f1869..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/Color.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.color - -case class Color( - red: Short, - green: Short, - blue: Short, - opacity: Option[Short]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala deleted file mode 100644 index 36486ee43..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/ColorPalette.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.color - -case class ColorPalette( - rgb: Color, - percentage: Double) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala deleted file mode 100644 index cbc36d9bb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color/RosettaColor.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.color - -sealed trait RosettaColor - -case object WhiteRosettaColor extends RosettaColor -case object BlackRosettaColor extends RosettaColor -case object ClearRosettaColor extends RosettaColor - -case object TextBlackRosettaColor extends RosettaColor -case object TextBlueRosettaColor extends RosettaColor - -case object DeepGrayRosettaColor extends RosettaColor -case object MediumGrayRosettaColor extends RosettaColor -case object LightGrayRosettaColor extends RosettaColor -case object FadedGrayRosettaColor extends RosettaColor -case object FaintGrayRosettaColor extends RosettaColor - -case object DeepOrangeRosettaColor extends RosettaColor -case object MediumOrangeRosettaColor extends RosettaColor -case object LightOrangeRosettaColor extends RosettaColor -case object FadedOrangeRosettaColor extends RosettaColor - -case object DeepYellowRosettaColor extends RosettaColor -case object MediumYellowRosettaColor extends RosettaColor -case object LightYellowRosettaColor extends RosettaColor -case object FadedYellowRosettaColor extends RosettaColor - -case object DeepGreenRosettaColor extends RosettaColor -case object MediumGreenRosettaColor extends RosettaColor -case object LightGreenRosettaColor extends RosettaColor -case object FadedGreenRosettaColor extends RosettaColor - -case object DeepBlueRosettaColor extends RosettaColor -case object TwitterBlueRosettaColor extends RosettaColor -case object LightBlueRosettaColor extends RosettaColor -case object FadedBlueRosettaColor extends RosettaColor -case object FaintBlueRosettaColor extends RosettaColor - -case object DeepPurpleRosettaColor extends RosettaColor -case object MediumPurpleRosettaColor extends RosettaColor -case object LightPurpleRosettaColor extends RosettaColor -case object FadedPurpleRosettaColor extends RosettaColor - -case object DeepRedRosettaColor extends RosettaColor -case object MediumRedRosettaColor extends RosettaColor -case object LightRedRosettaColor extends RosettaColor -case object FadedRedRosettaColor extends RosettaColor diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD deleted file mode 100644 index b58811811..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/rtf/safety_level", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala deleted file mode 100644 index 9936003b6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/ContextualTweetRef.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref - -case class ContextualTweetRef( - id: Long, - hydrationContext: Option[TweetHydrationContext]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala deleted file mode 100644 index c3dd55a0f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/OuterTweetContext.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref - -sealed trait OuterTweetContext - -case class QuoteTweetId(id: Long) extends OuterTweetContext -case class RetweetId(id: Long) extends OuterTweetContext diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala deleted file mode 100644 index 9104faf7d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref/TweetHydrationContext.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref - -import com.twitter.product_mixer.core.model.marshalling.response.rtf.safety_level.SafetyLevel - -case class TweetHydrationContext( - safetyLevelOverride: Option[SafetyLevel], - outerTweetContext: Option[OuterTweetContext]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD deleted file mode 100644 index 699f48119..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala deleted file mode 100644 index 0753432c0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverContent.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.DismissInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -sealed trait CoverContent - -case class FullCoverContent( - displayType: FullCoverDisplayType, - primaryText: RichText, - primaryCoverCta: CoverCta, - secondaryCoverCta: Option[CoverCta], - secondaryText: Option[RichText], - imageVariant: Option[ImageVariant], - details: Option[RichText], - dismissInfo: Option[DismissInfo], - imageDisplayType: Option[ImageDisplayType], - impressionCallbacks: Option[List[Callback]]) - extends CoverContent - -case class HalfCoverContent( - displayType: HalfCoverDisplayType, - primaryText: RichText, - primaryCoverCta: CoverCta, - secondaryCoverCta: Option[CoverCta], - secondaryText: Option[RichText], - impressionCallbacks: Option[List[Callback]], - dismissible: Option[Boolean], - coverImage: Option[CoverImage], - dismissInfo: Option[DismissInfo]) - extends CoverContent diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala deleted file mode 100644 index 2b4bfe706..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCta.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.ButtonStyle -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo - -case class CoverCta( - text: String, - ctaBehavior: CoverCtaBehavior, - callbacks: Option[List[Callback]], - clientEventInfo: Option[ClientEventInfo], - icon: Option[HorizonIcon], - buttonStyle: Option[ButtonStyle]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala deleted file mode 100644 index 07e2d6c84..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverCtaBehavior.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -sealed trait CoverCtaBehavior - -case class CoverBehaviorNavigate(url: Url) extends CoverCtaBehavior -case class CoverBehaviorDismiss(feedbackMessage: Option[RichText]) extends CoverCtaBehavior diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala deleted file mode 100644 index 45d4b702e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/CoverImage.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageAnimationType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageDisplayType -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant - -case class CoverImage( - imageVariant: ImageVariant, - imageDisplayType: ImageDisplayType, - imageAnimationType: Option[ImageAnimationType]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala deleted file mode 100644 index 6c0ef1ec0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/FullCoverDisplayType.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -sealed trait FullCoverDisplayType - -case object CoverFullCoverDisplayType extends FullCoverDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala deleted file mode 100644 index 2160bc3a7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/HalfCoverDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -sealed trait HalfCoverDisplayType - -case object CoverHalfCoverDisplayType extends HalfCoverDisplayType -case object CenterCoverHalfCoverDisplayType extends HalfCoverDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala deleted file mode 100644 index 8062d23a6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/cover/ShowCover.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.cover - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.Cover -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.FullCover.FullCoverEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.cover.HalfCover.HalfCoverEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo - -object HalfCover { - val HalfCoverEntryNamespace = EntryNamespace("half-cover") -} -case class HalfCover( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - content: HalfCoverContent) - extends Cover { - - override val entryNamespace: EntryNamespace = HalfCoverEntryNamespace - - // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId - override def withSortIndex(newSortIndex: Long): TimelineEntry = - copy(sortIndex = Some(newSortIndex)) - - // Not used for covers - override def feedbackActionInfo: Option[FeedbackActionInfo] = None -} - -object FullCover { - val FullCoverEntryNamespace = EntryNamespace("full-cover") -} -case class FullCover( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - content: FullCoverContent) - extends Cover { - - override val entryNamespace: EntryNamespace = FullCoverEntryNamespace - - // Note that sort index is not used for Covers, as they are not TimelineEntry and do not have entryId - override def withSortIndex(newSortIndex: Long): TimelineEntry = - copy(sortIndex = Some(newSortIndex)) - - // Not used for covers - override def feedbackActionInfo: Option[FeedbackActionInfo] = None -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD deleted file mode 100644 index f2657f7bf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/BUILD +++ /dev/null @@ -1,9 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [], - exports = [], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala deleted file mode 100644 index dbabdaa46..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon/HorizonIcon.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.icon - -sealed trait HorizonIcon - -case object Bookmark extends HorizonIcon -case object Moment extends HorizonIcon -case object Debug extends HorizonIcon -case object Error extends HorizonIcon -case object Follow extends HorizonIcon -case object Unfollow extends HorizonIcon -case object Smile extends HorizonIcon -case object Frown extends HorizonIcon -case object Help extends HorizonIcon -case object Link extends HorizonIcon -case object Message extends HorizonIcon -case object No extends HorizonIcon -case object Outgoing extends HorizonIcon -case object Pin extends HorizonIcon -case object Retweet extends HorizonIcon -case object Speaker extends HorizonIcon -case object Trashcan extends HorizonIcon -case object Feedback extends HorizonIcon -case object FeedbackClose extends HorizonIcon -case object EyeOff extends HorizonIcon -case object Moderation extends HorizonIcon -case object Topic extends HorizonIcon -case object TopicClose extends HorizonIcon -case object Flag extends HorizonIcon -case object TopicFilled extends HorizonIcon -case object NotificationsFollow extends HorizonIcon -case object Person extends HorizonIcon -case object BalloonStroke extends HorizonIcon -case object Calendar extends HorizonIcon -case object LocationStroke extends HorizonIcon -case object PersonStroke extends HorizonIcon -case object Safety extends HorizonIcon -case object Logo extends HorizonIcon -case object SparkleOn extends HorizonIcon -case object StarRising extends HorizonIcon -case object CameraVideo extends HorizonIcon -case object ShoppingClock extends HorizonIcon -case object ArrowRight extends HorizonIcon -case object SpeakerOff extends HorizonIcon diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD deleted file mode 100644 index 1b67082a3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["**/*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/button", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/contextual_ref", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala deleted file mode 100644 index 401c5f879..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleDisplayType.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.article - -sealed trait ArticleDisplayType - -case object Default extends ArticleDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala deleted file mode 100644 index 1f892bea3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleItem.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.article - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object ArticleItem { - val ArticleEntryNamespace = EntryNamespace("article") -} - -case class ArticleItem( - override val id: Int, - articleSeedType: ArticleSeedType, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - displayType: Option[ArticleDisplayType], - socialContext: Option[SocialContext]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = ArticleItem.ArticleEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala deleted file mode 100644 index c08ce74ec..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/article/ArticleSeedType.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.article - -sealed trait ArticleSeedType - -/** - * Seed UTEG with a user's following list (1st degree network) - */ -case object FollowingListSeed extends ArticleSeedType - -/** - * Seed UTEG with a user's friends of friends (follow graph + 1) list - */ -case object FriendsOfFriendsSeed extends ArticleSeedType - -/** - * Seed UTEG with a given lists' members - */ -case object ListIdSeed extends ArticleSeedType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala deleted file mode 100644 index a4699ebd9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/audio_space/AudioSpaceItem.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.audio_space - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object AudioSpaceItem { - val SpaceEntryNamespace = EntryNamespace("audiospace") -} - -case class AudioSpaceItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = AudioSpaceItem.SpaceEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala deleted file mode 100644 index 4ec0b6216..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardDisplayType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.card - -sealed trait CardDisplayType - -case object HeroDisplayType extends CardDisplayType -case object CellDisplayType extends CardDisplayType -case object TweetCardDisplayType extends CardDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala deleted file mode 100644 index b8ebc0240..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/card/CardItem.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.card - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url - -object CardItem { - val CardEntryNamespace = EntryNamespace("card") -} - -case class CardItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - cardUrl: String, - text: Option[String], - subtext: Option[String], - url: Option[Url], - displayType: Option[CardDisplayType]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = CardItem.CardEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala deleted file mode 100644 index b77fde3fc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductGroupItem.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductGroupItem.CommerceProductGroupEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo - -object CommerceProductGroupItem { - val CommerceProductGroupEntryNamespace: EntryNamespace = EntryNamespace("commerce-product-group") -} - -case class CommerceProductGroupItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo]) - extends TimelineItem { - - val entryNamespace: EntryNamespace = CommerceProductGroupEntryNamespace - def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala deleted file mode 100644 index a7f3820bc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/commerce/CommerceProductItem.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.commerce.CommerceProductItem.CommerceProductEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo - -object CommerceProductItem { - val CommerceProductEntryNamespace: EntryNamespace = EntryNamespace("commerce-product") -} - -case class CommerceProductItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo]) - extends TimelineItem { - - val entryNamespace: EntryNamespace = CommerceProductEntryNamespace - def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala deleted file mode 100644 index 5fa93a9d1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotation.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -case class ConversationAnnotation( - conversationAnnotationType: ConversationAnnotationType, - header: Option[RichText], - description: Option[RichText]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala deleted file mode 100644 index ed8d6573a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/conversation_annotation/ConversationAnnotationType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation - -sealed trait ConversationAnnotationType - -case object Political extends ConversationAnnotationType -case object Large extends ConversationAnnotationType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala deleted file mode 100644 index 4b6e0b161..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryDisplayType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.event - -sealed trait EventSummaryDisplayType - -case object CellEventSummaryDisplayType extends EventSummaryDisplayType -case object HeroEventSummaryDisplayType extends EventSummaryDisplayType -case object CellWithProminentSocialContextEventSummaryDisplayType extends EventSummaryDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala deleted file mode 100644 index f011d72ab..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/event/EventSummaryItem.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.event - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object EventSummaryItem { - val EventSummaryItemEntryNamespace = EntryNamespace("eventsummary") -} - -case class EventSummaryItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - title: String, - displayType: EventSummaryDisplayType, - url: Url, - image: Option[ImageVariant], - timeString: Option[String]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = - EventSummaryItem.EventSummaryItemEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala deleted file mode 100644 index ad75952c0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivot.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -case class ForwardPivot( - text: RichText, - landingUrl: Url, - displayType: ForwardPivotDisplayType, - iconImageVariant: Option[ImageVariant], - stateBadge: Option[Badge], - subtext: Option[RichText], - backgroundColorName: Option[RosettaColor], - engagementNudge: Option[Boolean], - softInterventionDisplayType: Option[SoftInterventionDisplayType]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala deleted file mode 100644 index 7c13a05f0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/ForwardPivotDisplayType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot - -sealed trait ForwardPivotDisplayType - -case object LiveEvent extends ForwardPivotDisplayType -case object SoftIntervention extends ForwardPivotDisplayType -case object CommunityNotes extends ForwardPivotDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala deleted file mode 100644 index 1c07e95b8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/forward_pivot/SoftInterventionDisplayType.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot - -sealed trait SoftInterventionDisplayType - -case object GetTheLatest extends SoftInterventionDisplayType -case object StayInformed extends SoftInterventionDisplayType -case object Misleading extends SoftInterventionDisplayType -case object GovernmentRequested extends SoftInterventionDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala deleted file mode 100644 index ce3cebc55..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryAction.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url - -case class GenericSummaryAction( - url: Url, - clientEventInfo: Option[ClientEventInfo]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala deleted file mode 100644 index fe1a87749..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryContext.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary - -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -case class GenericSummaryContext( - text: RichText, - icon: Option[HorizonIcon]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala deleted file mode 100644 index b4c15baac..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryDisplayType.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary - -sealed trait GenericSummaryItemDisplayType - -case object HeroDisplayType extends GenericSummaryItemDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala deleted file mode 100644 index 74cc6b1c1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/generic_summary/GenericSummaryItem.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.generic_summary - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.media.Media -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.util.Time - -object GenericSummaryItem { - val GenericSummaryItemNamespace: EntryNamespace = EntryNamespace("genericsummary") -} - -case class GenericSummaryItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - headline: RichText, - displayType: GenericSummaryItemDisplayType, - userAttributionIds: Seq[Long], - media: Option[Media], - context: Option[GenericSummaryContext], - timestamp: Option[Time], - onClickAction: Option[GenericSummaryAction], - promotedMetadata: Option[PromotedMetadata]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = GenericSummaryItem.GenericSummaryItemNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala deleted file mode 100644 index 5f9263de5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/highlight/HighlightedSection.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight - -case class HighlightedSection(startIndex: Int, endIndex: Int) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala deleted file mode 100644 index 63f6d29c9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/icon_label/IconLabelItem.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.icon_label - -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object IconLabelItem { - val IconLabelEntryNamespace = EntryNamespace("iconlabel") -} - -case class IconLabelItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - text: RichText, - icon: Option[HorizonIcon]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = IconLabelItem.IconLabelEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala deleted file mode 100644 index 3b3a7cedf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.label - -sealed trait LabelDisplayType - -case object InlineHeaderLabelDisplayType extends LabelDisplayType -case object OtherRepliesSectionHeaderLabelDisplayType extends LabelDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala deleted file mode 100644 index 890a9ea92..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/label/LabelItem.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.label - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object LabelItem { - val LabelEntryNamespace = EntryNamespace("label") -} - -case class LabelItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - text: String, - subtext: Option[String], - disclosureIndicator: Option[Boolean], - url: Option[Url], - displayType: Option[LabelDisplayType]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = LabelItem.LabelEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala deleted file mode 100644 index 7939a2446..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageAction.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo - -case class MessageAction( - dismissOnClick: Boolean, - url: Option[String], - clientEventInfo: Option[ClientEventInfo], - onClickCallbacks: Option[Seq[Callback]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala deleted file mode 100644 index feeaab391..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageActionType.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -sealed trait MessageActionType - -case object FollowAllMessageActionType extends MessageActionType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala deleted file mode 100644 index b8c9c495f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageContent.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -sealed trait MessageContent - -case class InlinePromptMessageContent( - headerText: String, - bodyText: Option[String], - primaryButtonAction: Option[MessageTextAction], - secondaryButtonAction: Option[MessageTextAction], - headerRichText: Option[RichText], - bodyRichText: Option[RichText], - socialContext: Option[SocialContext], - userFacepile: Option[UserFacepile]) - extends MessageContent - -case class HeaderImagePromptMessageContent( - headerImage: MessageImage, - headerText: Option[String], - bodyText: Option[String], - primaryButtonAction: Option[MessageTextAction], - secondaryButtonAction: Option[MessageTextAction], - action: Option[MessageAction], - headerRichText: Option[RichText], - bodyRichText: Option[RichText]) - extends MessageContent - -case class CompactPromptMessageContent( - headerText: String, - bodyText: Option[String], - primaryButtonAction: Option[MessageTextAction], - secondaryButtonAction: Option[MessageTextAction], - action: Option[MessageAction], - headerRichText: Option[RichText], - bodyRichText: Option[RichText]) - extends MessageContent diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala deleted file mode 100644 index a8ac940e4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageImage.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant - -case class MessageImage( - imageVariants: Set[ImageVariant], - backgroundColor: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala deleted file mode 100644 index df8d1cc4e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessagePromptItem.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object MessagePromptItem { - val MessagePromptEntryNamespace = EntryNamespace("messageprompt") -} - -case class MessagePromptItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - override val isPinned: Option[Boolean], - content: MessageContent, - impressionCallbacks: Option[List[Callback]]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = - MessagePromptItem.MessagePromptEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala deleted file mode 100644 index fc1b793f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/MessageTextAction.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -case class MessageTextAction( - text: String, - action: MessageAction) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala deleted file mode 100644 index 91757a0fe..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepile.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -case class UserFacepile( - userIds: Seq[Long], - featuredUserIds: Seq[Long], - action: Option[MessageTextAction], - actionType: Option[MessageActionType], - displaysFeaturingText: Option[Boolean], - displayType: Option[UserFacepileDisplayType]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala deleted file mode 100644 index f592ee1ca..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/message/UserFacepileDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.message - -sealed trait UserFacepileDisplayType - -case object LargeUserFacepileDisplayType extends UserFacepileDisplayType -case object CompactUserFacepileDisplayType extends UserFacepileDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala deleted file mode 100644 index de057c0a0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/moment/MomentAnnotationItem.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.moment - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -object MomentAnnotationItem { - val MomentAnnotationEntryNamespace = EntryNamespace("momentannotation") -} - -/** - * Represents a MomentAnnotation URT item. - * This is primarily used by Trends Searth Result Page for displaying Trends Title or Description - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/MomentAnnotation.html - */ -case class MomentAnnotationItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - override val isPinned: Option[Boolean], - text: Option[RichText], - header: Option[RichText], -) extends TimelineItem { - - override val entryNamespace: EntryNamespace = - MomentAnnotationItem.MomentAnnotationEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala deleted file mode 100644 index d665c5c94..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptContent.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback - -/** - * Represents different types of URT Prompts supported such as the Relevance Prompt. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/PromptContent.html - */ -sealed trait PromptContent - -/** - * Relevance Prompt is a Yes-No style prompt that can be used for collecting feedback from a User - * about a part of their timeline. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/RelevancePrompt.html - */ -case class RelevancePromptContent( - title: String, - confirmation: String, - isRelevantText: String, - notRelevantText: String, - isRelevantCallback: Callback, - notRelevantCallback: Callback, - displayType: RelevancePromptDisplayType, - isRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType], - notRelevantFollowUp: Option[RelevancePromptFollowUpFeedbackType]) - extends PromptContent diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala deleted file mode 100644 index 59ef60bce..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/PromptItem.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback - -object PromptItem { - val PromptEntryNamespace = EntryNamespace("relevanceprompt") -} - -case class PromptItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo] = None, - content: PromptContent, - impressionCallbacks: Option[List[Callback]]) - extends TimelineItem { - - override val entryNamespace: EntryNamespace = PromptItem.PromptEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala deleted file mode 100644 index f4c04dd15..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptDisplayType.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt - -/** - * Represents the different ways to display the Relevance Prompt in a timeline. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/RelevancePromptDisplayType.html - */ -sealed trait RelevancePromptDisplayType - -case object Normal extends RelevancePromptDisplayType -case object Compact extends RelevancePromptDisplayType -case object Large extends RelevancePromptDisplayType -case object ThumbsUpAndDown extends RelevancePromptDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala deleted file mode 100644 index a8b6d59a5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/prompt/RelevancePromptFollowUpFeedbackType.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.prompt - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Callback - -/** - * Different kinds of follow-ups after a positive-negative feedback on a prompt button. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/RelevancePromptFollowUpFeedbackType.html - */ -sealed trait RelevancePromptFollowUpFeedbackType - -case class RelevancePromptFollowUpTextInput( - context: String, - textFieldPlaceholder: String, - sendTextCallback: Callback) - extends RelevancePromptFollowUpFeedbackType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala deleted file mode 100644 index a686f1f94..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingActionType.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion - -/** - * Represents the different types of Spelling Suggestion items. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/SpellingActionType.html - */ -sealed trait SpellingActionType - -/** - * Used when the original query is replaced completed by another query in the backend. - * Clients use the text 'Searching instead for …' to display this suggestion. - */ -case object ReplaceSpellingActionType extends SpellingActionType - -/** - * Used when the original query is expanded by a suggestion when performing the search. - * Clients use the text 'Including results for …' to display this suggestion. - */ -case object ExpandSpellingActionType extends SpellingActionType - -/** - * Used when the search query is not changed and a suggestion is displayed as an alternative query. - * Clients use the text 'Did you mean … ?' to display the suggestion. - */ -case object SuggestSpellingActionType extends SpellingActionType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala deleted file mode 100644 index 439c2023f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/SpellingItem.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo - -object SpellingItem { - val SpellingEntryNamespace = EntryNamespace("spelling") -} - -/** - * Represents a Spelling Suggestion URT item. This is primary used by Search timelines for - * displaying Spelling correction information. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/Spelling.html - */ -case class SpellingItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - textResult: TextResult, - spellingActionType: Option[SpellingActionType], - originalQuery: Option[String]) - extends TimelineItem { - - override val entryNamespace: EntryNamespace = SpellingItem.SpellingEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala deleted file mode 100644 index b6d0afb8a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/suggestion/TextResult.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.suggestion - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection - -/** - * Represents text with hit-highlights used for returning search query suggestions. - * - * URT API Reference: https://docbird.twitter.biz/unified_rich_timelines_urt/gen/com/twitter/timelines/render/thriftscala/TextResult.html - */ -case class TextResult( - text: String, - hitHighlights: Option[Seq[HighlightedSection]], - score: Option[Double], - querySource: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala deleted file mode 100644 index bd2a5a7d8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderContent.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread - -sealed trait ThreadHeaderContent - -case class UserThreadHeader(userId: Long) extends ThreadHeaderContent diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala deleted file mode 100644 index 074d81ec3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/thread/ThreadHeaderItem.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.thread - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo - -object ThreadHeaderItem { - val ThreadHeaderEntryNamespace = EntryNamespace("threadheader") -} - -case class ThreadHeaderItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - override val isPinned: Option[Boolean], - content: ThreadHeaderContent) - extends TimelineItem { - override val entryNamespace: EntryNamespace = ThreadHeaderItem.ThreadHeaderEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala deleted file mode 100644 index 85c212c76..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileContent.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile - -import com.twitter.product_mixer.core.model.marshalling.response.urt.button.CtaButton -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -sealed trait TileContent - -case class StandardTileContent( - title: String, - supportingText: String, - badge: Option[Badge]) - extends TileContent - -case class CallToActionTileContent( - text: String, - richText: Option[RichText], - ctaButton: Option[CtaButton]) - extends TileContent - -//todo: Add other TileContent types later diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala deleted file mode 100644 index 8d6498c69..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tile/TileItem.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tile - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object TileItem { - val TileEntryNamespace = EntryNamespace("tile") -} - -case class TileItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - title: String, - supportingText: String, - url: Option[Url], - image: Option[ImageVariant], - content: TileContent) - extends TimelineItem { - override val entryNamespace: EntryNamespace = TileItem.TileEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala deleted file mode 100644 index 1fa166559..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneDisplayType.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone - -sealed trait TombstoneDisplayType - -case object TweetUnavailable extends TombstoneDisplayType -case object DisconnectedRepliesAncestor extends TombstoneDisplayType -case object DisconnectedRepliesDescendant extends TombstoneDisplayType -case object Inline extends TombstoneDisplayType -case object NonCompliant extends TombstoneDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala deleted file mode 100644 index 12e030af4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneInfo.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.RichText - -case class TombstoneInfo( - text: String, - richText: Option[RichText], - richRevealText: Option[RichText]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala deleted file mode 100644 index 00c053439..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tombstone/TombstoneItem.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet.TweetItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object TombstoneItem { - val TombstoneEntryNamespace = EntryNamespace("tombstone") -} - -case class TombstoneItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - tombstoneDisplayType: TombstoneDisplayType, - tombstoneInfo: Option[TombstoneInfo], - tweet: Option[TweetItem]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = TombstoneItem.TombstoneEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala deleted file mode 100644 index ea6941f9b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicDisplayType.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic - -sealed trait TopicDisplayType - -case object BasicTopicDisplayType extends TopicDisplayType -case object PillTopicDisplayType extends TopicDisplayType -case object NoIconTopicDisplayType extends TopicDisplayType -case object PillWithoutActionIconDisplayType extends TopicDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala deleted file mode 100644 index 1774abf40..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic - -sealed trait TopicFollowPromptDisplayType - -case object IncentiveFocusTopicFollowPromptDisplayType extends TopicFollowPromptDisplayType -case object TopicFocusTopicFollowPromptDisplayType extends TopicFollowPromptDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala deleted file mode 100644 index ac9466939..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFollowPromptItem.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object TopicFollowPromptItem { - val TopicFollowPromptEntryNamespace = EntryNamespace("topicfollowprompt") -} - -case class TopicFollowPromptItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - topicFollowPromptDisplayType: TopicFollowPromptDisplayType, - followIncentiveTitle: Option[String], - followIncentiveText: Option[String]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = - TopicFollowPromptItem.TopicFollowPromptEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala deleted file mode 100644 index 6ba979b66..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicFunctionalityType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic - -sealed trait TopicFunctionalityType - -case object BasicTopicFunctionalityType extends TopicFunctionalityType -case object PivotTopicFunctionalityType extends TopicFunctionalityType -case object RecommendationTopicFunctionalityType extends TopicFunctionalityType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala deleted file mode 100644 index bd2467abd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/topic/TopicItem.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.topic - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object TopicItem { - val TopicEntryNamespace = EntryNamespace("topic") -} - -case class TopicItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - topicFunctionalityType: Option[TopicFunctionalityType], - topicDisplayType: Option[TopicDisplayType]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = TopicItem.TopicEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala deleted file mode 100644 index 86e7fac48..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/trend/TrendItem.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.trend - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata - -object TrendItem { - val TrendItemEntryNamespace = EntryNamespace("trend") -} - -case class GroupedTrend(trendName: String, url: Url) - -case class TrendItem( - override val id: String, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - normalizedTrendName: String, - trendName: String, - url: Url, - description: Option[String], - metaDescription: Option[String], - tweetCount: Option[Int], - domainContext: Option[String], - promotedMetadata: Option[PromotedMetadata], - groupedTrends: Option[Seq[GroupedTrend]]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = TrendItem.TrendItemEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala deleted file mode 100644 index 168dd47a9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TimelinesScoreInfo.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet - -case class TimelinesScoreInfo(score: Double) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala deleted file mode 100644 index d54512f6a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetDisplayType.scala +++ /dev/null @@ -1,16 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet - -sealed trait TweetDisplayType - -case object Tweet extends TweetDisplayType -case object TweetFollowOnly extends TweetDisplayType -case object Media extends TweetDisplayType -case object MomentTimelineTweet extends TweetDisplayType -case object EmphasizedPromotedTweet extends TweetDisplayType -case object QuotedTweet extends TweetDisplayType -case object SelfThread extends TweetDisplayType -case object CompactPromotedTweet extends TweetDisplayType -case object TweetWithoutCard extends TweetDisplayType -case object ReaderModeRoot extends TweetDisplayType -case object ReaderMode extends TweetDisplayType -case object CondensedTweet extends TweetDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala deleted file mode 100644 index e2c1caa4f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetHighlights.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet - -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.highlight.HighlightedSection - -case class TweetHighlights( - textHighlights: Option[List[HighlightedSection]], - cardTitleHighlights: Option[List[HighlightedSection]], - cardDescriptionHighlights: Option[List[HighlightedSection]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala deleted file mode 100644 index 15690bd2d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet/TweetItem.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.contextual_ref.ContextualTweetRef -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.conversation_annotation.ConversationAnnotation -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.forward_pivot.ForwardPivot -import com.twitter.product_mixer.core.model.marshalling.response.urt.item.tombstone.TombstoneInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Badge -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PrerollMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url - -object TweetItem { - val TweetEntryNamespace = EntryNamespace("tweet") - val PromotedTweetEntryNamespace = EntryNamespace("promoted-tweet") -} - -case class TweetItem( - override val id: Long, - override val entryNamespace: EntryNamespace, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - override val isPinned: Option[Boolean], - override val entryIdToReplace: Option[String], - socialContext: Option[SocialContext], - highlights: Option[TweetHighlights], - displayType: TweetDisplayType, - innerTombstoneInfo: Option[TombstoneInfo], - timelinesScoreInfo: Option[TimelinesScoreInfo], - hasModeratedReplies: Option[Boolean], - forwardPivot: Option[ForwardPivot], - innerForwardPivot: Option[ForwardPivot], - promotedMetadata: Option[PromotedMetadata], - conversationAnnotation: Option[ConversationAnnotation], - contextualTweetRef: Option[ContextualTweetRef], - prerollMetadata: Option[PrerollMetadata], - replyBadge: Option[Badge], - destination: Option[Url]) - extends TimelineItem { - - /** - * Promoted tweets need to include the impression ID in the entry ID since some clients have - * client-side logic that deduplicates ads impression callbacks based on a combination of the - * tweet and impression IDs. Not including the impression ID will lead to over deduplication. - */ - override lazy val entryIdentifier: String = promotedMetadata - .map { metadata => - val impressionId = metadata.impressionString match { - case Some(impressionString) if impressionString.nonEmpty => impressionString - case _ => throw new IllegalStateException(s"Promoted Tweet $id missing impression ID") - } - s"$entryNamespace-$id-$impressionId" - }.getOrElse(s"$entryNamespace-$id") - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala deleted file mode 100644 index a477bb239..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer - -sealed trait TweetComposerDisplayType - -case object TweetComposerSelfThread extends TweetComposerDisplayType -case object Reply extends TweetComposerDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala deleted file mode 100644 index 4340c5328..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/tweet_composer/TweetComposerItem.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.tweet_composer - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object TweetComposerItem { - val TweetComposerEntryNameSpace = EntryNamespace("tweetcomposer") -} - -case class TweetComposerItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - displayType: TweetComposerDisplayType, - text: String, - url: Url) - extends TimelineItem { - override val entryNamespace: EntryNamespace = TweetComposerItem.TweetComposerEntryNameSpace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala deleted file mode 100644 index b80e8cc05..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListDisplayType.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list - -sealed trait TwitterListDisplayType - -case object List extends TwitterListDisplayType -case object ListTile extends TwitterListDisplayType -case object ListWithPin extends TwitterListDisplayType -case object ListWithSubscribe extends TwitterListDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala deleted file mode 100644 index c585b145b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/twitter_list/TwitterListItem.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.twitter_list - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -object TwitterListItem { - val ListEntryNamespace = EntryNamespace("list") -} - -case class TwitterListItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - displayType: Option[TwitterListDisplayType]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = TwitterListItem.ListEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala deleted file mode 100644 index a73e76d54..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserDisplayType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.user - -sealed trait UserDisplayType - -case object User extends UserDisplayType -case object UserDetailed extends UserDisplayType -case object PendingFollowUser extends UserDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala deleted file mode 100644 index 5bb1209c9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserItem.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.user - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem -import com.twitter.product_mixer.core.model.marshalling.response.urt.promoted.PromotedMetadata - -object UserItem { - val UserEntryNamespace: EntryNamespace = EntryNamespace("user") -} - -case class UserItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - override val isMarkUnread: Option[Boolean], - displayType: UserDisplayType, - promotedMetadata: Option[PromotedMetadata], - socialContext: Option[SocialContext], - reactiveTriggers: Option[UserReactiveTriggers], - enableReactiveBlending: Option[Boolean]) - extends TimelineItem { - override val entryNamespace: EntryNamespace = UserItem.UserEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala deleted file mode 100644 index 87bdda4b9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/user/UserReactiveTriggers.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.user - -import com.twitter.product_mixer.core.model.marshalling.response.urt.reaction.TimelineReaction - -case class UserReactiveTriggers(onFollow: Option[TimelineReaction]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala deleted file mode 100644 index d96416a1f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItem.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -sealed trait VerticalGridItem extends TimelineItem - -object VerticalGridItemTopicTile { - val VerticalGridItemTopicTileEntryNamespace = EntryNamespace("verticalgriditemtopictile") -} - -case class VerticalGridItemTopicTile( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - style: Option[VerticalGridItemTileStyle], - functionalityType: Option[VerticalGridItemTopicFunctionalityType], - url: Option[Url]) - extends VerticalGridItem { - override val entryNamespace: EntryNamespace = - VerticalGridItemTopicTile.VerticalGridItemTopicTileEntryNamespace - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala deleted file mode 100644 index 869322ebc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTileStyle.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item - -sealed trait VerticalGridItemTileStyle - -case object SingleStateDefaultVerticalGridItemTileStyle extends VerticalGridItemTileStyle -case object DoubleStateDefaultVerticalGridItemTileStyle extends VerticalGridItemTileStyle diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala deleted file mode 100644 index 961aadc27..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/item/vertical_grid_item/VerticalGridItemTopicFunctionalityType.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.item.vertical_grid_item - -sealed trait VerticalGridItemTopicFunctionalityType - -case object PivotVerticalGridItemTopicFunctionalityType - extends VerticalGridItemTopicFunctionalityType -case object RecommendationVerticalGridItemTopicFunctionalityType - extends VerticalGridItemTopicFunctionalityType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala deleted file mode 100644 index f81020c8b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/AspectRatio.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.media - -case class AspectRatio( - numerator: Short, - denominator: Short) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD deleted file mode 100644 index ae81ac4e2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt/metadata", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala deleted file mode 100644 index 82fcb3e9f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Media.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.media - -case class Media( - mediaEntity: Option[MediaEntity], - mediaKey: Option[MediaKey], - imagePossibleCropping: Option[List[Rect]], - aspectRatio: Option[AspectRatio]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala deleted file mode 100644 index 5def14bc6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaEntity.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.media - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant - -sealed trait MediaEntity - -case class TweetMedia( - tweetId: Long, - momentId: Option[Long]) - extends MediaEntity - -case class BroadcastId(id: String) extends MediaEntity - -case class Image(image: ImageVariant) extends MediaEntity diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala deleted file mode 100644 index 191a5d3f4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/MediaKey.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.media - -case class MediaKey( - id: Long, - category: Int) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala deleted file mode 100644 index ecd3d2c82..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/media/Rect.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.media - -case class Rect( - left: Int, - top: Int, - width: Int, - height: Int) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala deleted file mode 100644 index 135a5d2ad..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ArticleDetails.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class ArticleDetails( - articlePosition: Int, - shareCount: Int) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD deleted file mode 100644 index 669bbc52b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/color", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/icon", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala deleted file mode 100644 index 1c12ce262..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Badge.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.RosettaColor - -case class Badge( - text: Option[String], - textColorName: Option[RosettaColor], - backgroundColorName: Option[RosettaColor]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala deleted file mode 100644 index 9ab8c082c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Callback.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class Callback(endpoint: String) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala deleted file mode 100644 index f78750ca0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ClientEventInfo.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -trait HasClientEventInfo { - def clientEventInfo: Option[ClientEventInfo] -} - -/** - * Information used to build Client Events - * @see [[http://go/client-events]] - */ -case class ClientEventInfo( - component: Option[String], - element: Option[String], - details: Option[ClientEventDetails], - action: Option[String], - entityToken: Option[String]) - -/** - * Additional client events fields - * - * @note if a field from [[http://go/client_app.thrift]] is needed but is not here - * contact the `#product-mixer` team to have it added. - */ -case class ClientEventDetails( - conversationDetails: Option[ConversationDetails], - timelinesDetails: Option[TimelinesDetails], - articleDetails: Option[ArticleDetails], - liveEventDetails: Option[LiveEventDetails], - commerceDetails: Option[CommerceDetails]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala deleted file mode 100644 index 86cc9dc15..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/CommerceDetails.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class CommerceDetails( - dropId: Option[Long], - shopV2Id: Option[Long], - productKey: Option[Long], - merchantId: Option[Long], - productIndex: Option[Int]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala deleted file mode 100644 index 66aed65f5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConfirmationDisplayType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait ConfirmationDisplayType - -case object Inline extends ConfirmationDisplayType -case object BottomSheet extends ConfirmationDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala deleted file mode 100644 index be7a48935..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationDetails.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class ConversationDetails(conversationSection: Option[ConversationSection]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala deleted file mode 100644 index 0ba7a68b4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ConversationSection.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait ConversationSection - -case object HighQuality extends ConversationSection -case object LowQuality extends ConversationSection -case object AbusiveQuality extends ConversationSection -case object RelatedTweet extends ConversationSection diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala deleted file mode 100644 index 3f11122ad..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/DismissInfo.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class DismissInfo(callbacks: Option[Seq[Callback]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala deleted file mode 100644 index 753ae9ca8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackAction.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon - -case class FeedbackAction( - feedbackType: FeedbackType, - prompt: Option[String], - confirmation: Option[String], - childFeedbackActions: Option[Seq[ChildFeedbackAction]], - feedbackUrl: Option[String], - hasUndoAction: Option[Boolean], - confirmationDisplayType: Option[ConfirmationDisplayType], - clientEventInfo: Option[ClientEventInfo], - icon: Option[HorizonIcon], - richBehavior: Option[RichFeedbackBehavior], - subprompt: Option[String], - encodedFeedbackRequest: Option[String]) - -case class ChildFeedbackAction( - feedbackType: FeedbackType, - prompt: Option[String], - confirmation: Option[String], - feedbackUrl: Option[String], - hasUndoAction: Option[Boolean], - confirmationDisplayType: Option[ConfirmationDisplayType], - clientEventInfo: Option[ClientEventInfo], - icon: Option[HorizonIcon], - richBehavior: Option[RichFeedbackBehavior], - subprompt: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala deleted file mode 100644 index 1eebf6cf5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackActionInfo.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -trait HasFeedbackActionInfo { - def feedbackActionInfo: Option[FeedbackActionInfo] -} - -trait ContainsFeedbackActionInfos { - def feedbackActionInfos: Seq[Option[FeedbackActionInfo]] -} - -case class FeedbackActionInfo( - feedbackActions: Seq[FeedbackAction], - feedbackMetadata: Option[String], - displayContext: Option[FeedbackDisplayContext], - clientEventInfo: Option[ClientEventInfo]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala deleted file mode 100644 index e257b909b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackInfo.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -trait HasFeedbackInfo { - def feedbackInfo: Option[FeedbackInfo] -} - -case class FeedbackDisplayContext(reason: String) - -case class FeedbackInfo( - feedbackKeys: Seq[String], - feedbackMetadata: Option[String], - displayContext: Option[FeedbackDisplayContext], - clientEventInfo: Option[ClientEventInfo]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala deleted file mode 100644 index df2c274b5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/FeedbackType.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait FeedbackType - -case object Dismiss extends FeedbackType -case object SeeFewer extends FeedbackType -case object DontLike extends FeedbackType -case object NotRelevant extends FeedbackType -case object SeeMore extends FeedbackType -case object NotCredible extends FeedbackType -case object GiveFeedback extends FeedbackType -case object NotRecent extends FeedbackType -case object UnfollowEntity extends FeedbackType -case object Relevant extends FeedbackType -case object Moderate extends FeedbackType -case object RichBehavior extends FeedbackType -case object NotAboutTopic extends FeedbackType -case object Generic extends FeedbackType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala deleted file mode 100644 index 143af16c9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageAnimationType.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait ImageAnimationType - -case object Bounce extends ImageAnimationType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala deleted file mode 100644 index 79008df60..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageDisplayType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait ImageDisplayType - -case object Icon extends ImageDisplayType -case object FullWidth extends ImageDisplayType -case object IconSmall extends ImageDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala deleted file mode 100644 index 08b57a66e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ImageVariant.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.color.ColorPalette - -case class ImageVariant( - url: String, - width: Int, - height: Int, - palette: Option[List[ColorPalette]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala deleted file mode 100644 index 931c98bba..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/LiveEventDetails.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class LiveEventDetails(eventId: Option[Long]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala deleted file mode 100644 index f26eed533..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/MarkUnreadableEntry.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -// Track unread entries for the MarkUnread URT instruction. -trait MarkUnreadableEntry { - def isMarkUnread: Option[Boolean] = None -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala deleted file mode 100644 index f99565d8f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/PinnableEntry.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -trait PinnableEntry { - def isPinned: Option[Boolean] = None -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala deleted file mode 100644 index 2fc7442b5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplaceableEntry.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -trait ReplaceableEntry { - def entryIdToReplace: Option[String] = None -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala deleted file mode 100644 index 83a056bf7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/ReplyPinState.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait ReplyPinState - -object PinnedReplyPinState extends ReplyPinState -object PinnableReplyPinState extends ReplyPinState -object NotPinnableReplyPinState extends ReplyPinState diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala deleted file mode 100644 index 2ae86471f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/RichFeedbackBehavior.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait RichFeedbackBehavior - -case class RichFeedbackBehaviorReportList(listId: Long, userId: Long) extends RichFeedbackBehavior -case class RichFeedbackBehaviorBlockUser(userId: Long) extends RichFeedbackBehavior -case class RichFeedbackBehaviorToggleFollowTopic(topicId: Long) extends RichFeedbackBehavior -case class RichFeedbackBehaviorToggleFollowTopicV2(topicId: String) extends RichFeedbackBehavior -case class RichFeedbackBehaviorToggleMuteList(listId: Long) extends RichFeedbackBehavior -case class RichFeedbackBehaviorMarkNotInterestedTopic(topicId: String) extends RichFeedbackBehavior -case class RichFeedbackBehaviorReplyPinState(replyPinState: ReplyPinState) - extends RichFeedbackBehavior -case class RichFeedbackBehaviorToggleMuteUser(userId: Long) extends RichFeedbackBehavior -case class RichFeedbackBehaviorToggleFollowUser(userId: Long) extends RichFeedbackBehavior -case class RichFeedbackBehaviorReportTweet(entryId: Long) extends RichFeedbackBehavior diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala deleted file mode 100644 index ed6fc2652..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/SocialContext.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -sealed trait SocialContext - -trait HasSocialContext { - def socialContext: Option[SocialContext] -} - -sealed trait GeneralContextType -case object LikeGeneralContextType extends GeneralContextType -case object FollowGeneralContextType extends GeneralContextType -case object MomentGeneralContextType extends GeneralContextType -case object ReplyGeneralContextType extends GeneralContextType -case object ConversationGeneralContextType extends GeneralContextType -case object PinGeneralContextType extends GeneralContextType -case object TextOnlyGeneralContextType extends GeneralContextType -case object FacePileGeneralContextType extends GeneralContextType -case object MegaPhoneGeneralContextType extends GeneralContextType -case object BirdGeneralContextType extends GeneralContextType -case object FeedbackGeneralContextType extends GeneralContextType -case object TopicGeneralContextType extends GeneralContextType -case object ListGeneralContextType extends GeneralContextType -case object RetweetGeneralContextType extends GeneralContextType -case object LocationGeneralContextType extends GeneralContextType -case object CommunityGeneralContextType extends GeneralContextType -case object NewUserGeneralContextType extends GeneralContextType -case object SmartblockExpirationGeneralContextType extends GeneralContextType -case object TrendingGeneralContextType extends GeneralContextType -case object SparkleGeneralContextType extends GeneralContextType -case object SpacesGeneralContextType extends GeneralContextType -case object ReplyPinGeneralContextType extends GeneralContextType - -case class GeneralContext( - contextType: GeneralContextType, - text: String, - url: Option[String], - contextImageUrls: Option[List[String]], - landingUrl: Option[Url]) - extends SocialContext - -sealed trait TopicContextFunctionalityType -case object BasicTopicContextFunctionalityType extends TopicContextFunctionalityType -case object RecommendationTopicContextFunctionalityType extends TopicContextFunctionalityType -case object RecWithEducationTopicContextFunctionalityType extends TopicContextFunctionalityType - -case class TopicContext( - topicId: String, - functionalityType: Option[TopicContextFunctionalityType]) - extends SocialContext diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala deleted file mode 100644 index 57f6fd58a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/TimelinesDetails.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -case class TimelinesDetails( - injectionType: Option[String], - controllerData: Option[String], - sourceData: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala deleted file mode 100644 index 112b278d7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata/Url.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.metadata - -import com.twitter.product_mixer.core.model.marshalling.response.urt.richtext.ReferenceObject - -sealed trait UrlType -case object ExternalUrl extends UrlType -case object DeepLink extends UrlType -case object UrtEndpoint extends UrlType - -case class UrtEndpointOptions( - requestParams: Option[Map[String, String]], - title: Option[String], - cacheId: Option[String], - subtitle: Option[String]) - -case class Url(urlType: UrlType, url: String, urtEndpointOptions: Option[UrtEndpointOptions] = None) - extends ReferenceObject diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD deleted file mode 100644 index 25898763c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala deleted file mode 100644 index babf20ea6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorDisplayTreatment.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.operation - -case class CursorDisplayTreatment( - actionText: Option[String], - labelText: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala deleted file mode 100644 index 0ea733c08..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorItem.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ClientEventInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.FeedbackActionInfo -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation.CursorEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineItem - -/** - * CursorItem should only be used for Module cursors - * For timeline cursors, see - * [[com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation]] - */ -case class CursorItem( - override val id: Long, - override val sortIndex: Option[Long], - override val clientEventInfo: Option[ClientEventInfo], - override val feedbackActionInfo: Option[FeedbackActionInfo], - value: String, - cursorType: CursorType, - displayTreatment: Option[CursorDisplayTreatment]) - extends TimelineItem { - - override val entryNamespace: EntryNamespace = CursorEntryNamespace - - override lazy val entryIdentifier: String = - s"$entryNamespace-${cursorType.entryNamespace}-$id" - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala deleted file mode 100644 index 9bcf0a1d1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorOperation.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.operation.CursorOperation.CursorEntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineEntry -import com.twitter.product_mixer.core.model.marshalling.response.urt.TimelineOperation - -object CursorOperation { - val CursorEntryNamespace = EntryNamespace("cursor") - - private def entryIdentifier(cursorType: CursorType, identifier: Long): String = - s"$CursorEntryNamespace-${cursorType.entryNamespace.toString}-$identifier" -} - -case class CursorOperation( - override val id: Long, - override val sortIndex: Option[Long], - value: String, - cursorType: CursorType, - displayTreatment: Option[CursorDisplayTreatment], - idToReplace: Option[Long]) - extends TimelineOperation { - override val entryNamespace: EntryNamespace = CursorEntryNamespace - - override lazy val entryIdentifier: String = CursorOperation.entryIdentifier(cursorType, id) - - override def entryIdToReplace: Option[String] = - idToReplace.map(CursorOperation.entryIdentifier(cursorType, _)) - - override def withSortIndex(sortIndex: Long): TimelineEntry = copy(sortIndex = Some(sortIndex)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala deleted file mode 100644 index 298a24052..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/operation/CursorType.scala +++ /dev/null @@ -1,37 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.operation - -import com.twitter.product_mixer.core.model.marshalling.response.urt.EntryNamespace -import com.twitter.product_mixer.core.model.marshalling.response.urt.HasEntryNamespace - -sealed trait CursorType extends HasEntryNamespace - -case object TopCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("top") -} -case object BottomCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("bottom") -} -case object GapCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("gap") -} -case object PivotCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("pivot") -} -case object SubBranchCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("subbranch") -} -case object ShowMoreCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("showmore") -} -case object ShowMoreThreadsCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("showmorethreads") -} -case object ShowMoreThreadsPromptCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("showmorethreadsprompt") -} -case object SecondRepliesSectionCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("secondrepliessection") -} -case object ThirdRepliesSectionCursor extends CursorType { - override val entryNamespace: EntryNamespace = EntryNamespace("thirdrepliessection") -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala deleted file mode 100644 index 756c2ceb3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/AdMetadataContainer.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class AdMetadataContainer( - removePromotedAttributionForPreroll: Option[Boolean], - sponsorshipCandidate: Option[String], - sponsorshipOrganization: Option[String], - sponsorshipOrganizationWebsite: Option[String], - sponsorshipType: Option[SponsorshipType], - disclaimerType: Option[DisclaimerType], - skAdNetworkDataList: Option[Seq[SkAdNetworkData]], - unifiedCardOverride: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD deleted file mode 100644 index 7ef37be56..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/BUILD +++ /dev/null @@ -1,11 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ], - exports = [ - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala deleted file mode 100644 index 4cabb4855..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/CallToAction.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class CallToAction( - callToActionType: Option[String], - url: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala deleted file mode 100644 index a29da2634..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/ClickTrackingInfo.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -import scala.collection.Map - -case class ClickTrackingInfo( - urlParams: Map[String, String], - urlOverride: Option[String], - urlOverrideType: Option[UrlOverrideType]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala deleted file mode 100644 index 72508ccd4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclaimerType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -sealed trait DisclaimerType - -object DisclaimerPolitical extends DisclaimerType -object DisclaimerIssue extends DisclaimerType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala deleted file mode 100644 index 624c871b3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DisclosureType.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -sealed trait DisclosureType - -case object NoDisclosure extends DisclosureType -case object Political extends DisclosureType -case object Earned extends DisclosureType -case object Issue extends DisclosureType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala deleted file mode 100644 index c4a7c3306..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/DynamicPrerollType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -sealed trait DynamicPrerollType - -object Amplify extends DynamicPrerollType -object Marketplace extends DynamicPrerollType -object LiveTvEvent extends DynamicPrerollType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala deleted file mode 100644 index 5e2eb001d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/MediaInfo.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class MediaInfo( - uuid: Option[String], - publisherId: Option[Long], - callToAction: Option[CallToAction], - durationMillis: Option[Int], - videoVariants: Option[Seq[VideoVariant]], - advertiserName: Option[String], - renderAdByAdvertiserName: Option[Boolean], - advertiserProfileImageUrl: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala deleted file mode 100644 index 51e83da8b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/Preroll.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class Preroll( - prerollId: Option[String], - dynamicPrerollType: Option[DynamicPrerollType], - mediaInfo: Option[MediaInfo]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala deleted file mode 100644 index ee7a72940..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PrerollMetadata.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class PrerollMetadata( - preroll: Option[Preroll], - videoAnalyticsScribePassthrough: Option[String]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala deleted file mode 100644 index 1fa5ff04a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/PromotedMetadata.scala +++ /dev/null @@ -1,23 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -/* - * As per discussion with #revenue-serving on 9/22/2017, `impressionId` should be set from `impressionString`. - * impressionId often returns None from adserver, as it's been replaced with impressionString. - * - * However, Android (at least) crashes without impressionId filled out in the response. - * - * So, we've removed `impressionId` from this case class, and our marshaller will set both `impressionId` - * and `impressionString` in the render thrift from `impressionString`. - */ - -case class PromotedMetadata( - advertiserId: Long, - disclosureType: Option[DisclosureType], - experimentValues: Option[Map[String, String]], - promotedTrendId: Option[Long], - promotedTrendName: Option[String], - promotedTrendQueryTerm: Option[String], - adMetadataContainer: Option[AdMetadataContainer], - promotedTrendDescription: Option[String], - impressionString: Option[String], - clickTrackingInfo: Option[ClickTrackingInfo]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala deleted file mode 100644 index a5ab45755..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SkAdNetworkData.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class SkAdNetworkData( - version: Option[String], // version of the SKAdNetwork protocol - srcAppId: Option[String], // app showing the ad (Twitter app or app promoting through MOPUB) - dstAppId: Option[String], // app being promoted - adNetworkId: Option[String], // the ad-network-id being used - campaignId: Option[Long], // the sk-campaign-id - different from the Twitter campaign id - impressionTimeInMillis: Option[Long], // the timestamp of the impression - nonce: Option[String], // nonce used to generate the signature - signature: Option[String], // the signed payload - fidelityType: Option[Long] // th -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala deleted file mode 100644 index 5594450d5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/SponsorshipType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -sealed trait SponsorshipType - -case object DirectSponsorshipType extends SponsorshipType -case object IndirectSponsorshipType extends SponsorshipType -case object NoSponsorshipSponsorshipType extends SponsorshipType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala deleted file mode 100644 index 86730c18d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/UrlOverrideType.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -sealed trait UrlOverrideType - -object UnknownUrlOverrideType extends UrlOverrideType -object DcmUrlOverrideType extends UrlOverrideType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala deleted file mode 100644 index c4b56034a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/promoted/VideoVariant.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.promoted - -case class VideoVariant( - url: Option[String], - contentType: Option[String], - bitrate: Option[Int]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD deleted file mode 100644 index 7ef37be56..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/BUILD +++ /dev/null @@ -1,11 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ], - exports = [ - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala deleted file mode 100644 index 0dd5fe4a8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReaction.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.reaction - -case class TimelineReaction( - execution: TimelineReactionExecution, - maxExecutionCount: Option[Short]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala deleted file mode 100644 index d2785b2cb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/reaction/TimelineReactionExecution.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.reaction - -sealed abstract class TimelineReactionExecution - -case class ImmediateTimelineReaction(key: String) extends TimelineReactionExecution - -case class RemoteTimelineReaction( - requestParams: Map[String, String], - timeoutInSeconds: Option[Short]) - extends TimelineReactionExecution diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD deleted file mode 100644 index 7ef37be56..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/BUILD +++ /dev/null @@ -1,11 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ], - exports = [ - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala deleted file mode 100644 index 5f4d808a7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/ReferenceObject.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext - -trait ReferenceObject - -case class RichTextUser(id: Long) extends ReferenceObject -case class RichTextMention(id: Long, screenName: String) extends ReferenceObject -case class RichTextHashtag(text: String) extends ReferenceObject -case class RichTextCashtag(text: String) extends ReferenceObject -case class RichTextList(id: Long, url: String) extends ReferenceObject diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala deleted file mode 100644 index 8ff4a2788..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichText.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext - -case class RichText( - text: String, - entities: List[RichTextEntity], - rtl: Option[Boolean], - alignment: Option[RichTextAlignment]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala deleted file mode 100644 index fe18486bc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextAlignment.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext - -sealed trait RichTextAlignment - -case object Natural extends RichTextAlignment -case object Center extends RichTextAlignment diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala deleted file mode 100644 index a3a577a80..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextEntity.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext - -case class RichTextEntity( - fromIndex: Int, - toIndex: Int, - ref: Option[ReferenceObject], - format: Option[RichTextFormat]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala deleted file mode 100644 index da8afe13a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/richtext/RichTextFormat.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.richtext - -sealed trait RichTextFormat { - def name: String -} - -case object Plain extends RichTextFormat { - override val name: String = "Plain" -} - -case object Strong extends RichTextFormat { - override val name: String = "Strong" -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala deleted file mode 100644 index b1f77a489..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/AdsMetadata.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -case class AdsMetadata(carouselId: Option[Long]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD deleted file mode 100644 index bac59b4cb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/BUILD +++ /dev/null @@ -1,13 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/metadata", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala deleted file mode 100644 index f596e1b10..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/GridCarouselMetadata.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -case class GridCarouselMetadata(numRows: Option[Int]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala deleted file mode 100644 index 03826fb33..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleConversationMetadata.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext - -case class ModuleConversationMetadata( - allTweetIds: Option[Seq[Long]], - socialContext: Option[SocialContext], - enableDeduplication: Option[Boolean]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala deleted file mode 100644 index 9b5d3e5a0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleDisplayType.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -sealed trait ModuleDisplayType - -case object Carousel extends ModuleDisplayType -case object CompactCarousel extends ModuleDisplayType -case object ConversationTree extends ModuleDisplayType -case object GridCarousel extends ModuleDisplayType -case object Vertical extends ModuleDisplayType -case object VerticalConversation extends ModuleDisplayType -case object VerticalGrid extends ModuleDisplayType -case object VerticalWithContextLine extends ModuleDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala deleted file mode 100644 index 826df3bc0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleFooter.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.Url - -case class ModuleFooter( - text: String, - landingUrl: Option[Url]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala deleted file mode 100644 index 06f7bd14c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeader.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -import com.twitter.product_mixer.core.model.marshalling.response.urt.icon.HorizonIcon -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.ImageVariant -import com.twitter.product_mixer.core.model.marshalling.response.urt.metadata.SocialContext - -case class ModuleHeader( - text: String, - sticky: Option[Boolean], - icon: Option[HorizonIcon], - customIcon: Option[ImageVariant], - socialContext: Option[SocialContext], - moduleHeaderDisplayType: ModuleHeaderDisplayType) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala deleted file mode 100644 index 1f0088c4a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleHeaderDisplayType.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -sealed trait ModuleHeaderDisplayType - -case object Classic extends ModuleHeaderDisplayType -case object ContextEmphasis extends ModuleHeaderDisplayType -case object ClassicNoDivider extends ModuleHeaderDisplayType diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala deleted file mode 100644 index 5d840f3da..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleMetadata.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -object ModuleMetadata { - def isConversationModule(moduleMetadata: Option[ModuleMetadata]): Boolean = - moduleMetadata.map(_.conversationMetadata).isDefined -} - -case class ModuleMetadata( - adsMetadata: Option[AdsMetadata], - conversationMetadata: Option[ModuleConversationMetadata], - gridCarouselMetadata: Option[GridCarouselMetadata]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala deleted file mode 100644 index c7e3ae3f6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt/timeline_module/ModuleShowMoreBehavior.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.model.marshalling.response.urt.timeline_module - -sealed trait ModuleShowMoreBehavior - -case class ModuleShowMoreBehaviorRevealByCount( - initialItemsCount: Int, - showMoreItemsCount: Int) - extends ModuleShowMoreBehavior diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala deleted file mode 100644 index e695dcede..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ABDeciderModule.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.google.inject.Provides -import com.twitter.abdecider.ABDeciderFactory -import com.twitter.abdecider.LoggingABDecider -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.logging._ -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ScribeABImpressions -import javax.inject.Singleton - -object ABDeciderModule extends TwitterModule { - private val YmlPath = "/usr/local/config/abdecider/abdecider.yml" - - @Provides - @Singleton - def provideLoggingABDecider( - @Flag(ScribeABImpressions) isScribeAbImpressions: Boolean, - stats: StatsReceiver - ): LoggingABDecider = { - val clientEventsHandler: HandlerFactory = - if (isScribeAbImpressions) { - QueueingHandler( - maxQueueSize = 10000, - handler = ScribeHandler( - category = "client_event", - formatter = BareFormatter, - level = Some(Level.INFO), - statsReceiver = stats.scope("abdecider")) - ) - } else { () => - NullHandler - } - - val factory = LoggerFactory( - node = "abdecider", - level = Some(Level.INFO), - useParents = false, - handlers = clientEventsHandler :: Nil - ) - - val abDeciderFactory = ABDeciderFactory( - abDeciderYmlPath = YmlPath, - scribeLogger = Some(factory()), - environment = Some("production") - ) - - abDeciderFactory.buildWithLogging() - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD deleted file mode 100644 index 846bbbacc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/BUILD +++ /dev/null @@ -1,49 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/inject:guice", - "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject", - "3rdparty/jvm/net/codingwell:scala-guice", - "3rdparty/jvm/org/slf4j:slf4j-api", - "abdecider", - "decider", - "featureswitches/featureswitches-core/src/main/scala/com/twitter/featureswitches/v2/builder", - "finatra-internal/decider/src/main/scala", - "finatra-internal/international/src/main/scala/com/twitter/finatra/international/modules", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-thrift-client/src/main/scala", - "finatra/jackson/src/main/scala/com/twitter/finatra/jackson/modules", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "servo/decider", - "strato/src/main/scala/com/twitter/strato/client", - "timelines/src/main/scala/com/twitter/timelines/features/app", - "util-internal/scribe", - "util/util-slf4j-api/src/main/scala", - ], - exports = [ - "3rdparty/jvm/com/google/inject:guice", - "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject", - "3rdparty/jvm/net/codingwell:scala-guice", - "3rdparty/jvm/org/slf4j:slf4j-api", - "abdecider", - "decider", - "finatra-internal/decider/src/main/scala", - "finatra-internal/international/src/main/scala/com/twitter/finatra/international/modules", - "finatra-internal/mtls-thriftmux/src/main/scala", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-thrift-client/src/main/scala", - "finatra/jackson/src/main/scala/com/twitter/finatra/jackson/modules", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "servo/decider", - "timelines/src/main/scala/com/twitter/timelines/features/app", - "util-internal/scribe", - "util/util-slf4j-api/src/main/scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala deleted file mode 100644 index c7b1bec0b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ConfigApiModule.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.google.inject.Provides -import com.twitter.decider.Decider -import com.twitter.inject.TwitterModule -import com.twitter.product_mixer.core.functional_component.configapi.ConfigBuilder -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.Config -import javax.inject.Singleton - -object ConfigApiModule extends TwitterModule { - - @Provides - @Singleton - def providesDeciderGateBuilder(decider: Decider): DeciderGateBuilder = - new DeciderGateBuilder(decider) - - @Provides - @Singleton - def providesConfig(configBuilder: ConfigBuilder): Config = configBuilder.build() -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala deleted file mode 100644 index c2f615696..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/FeatureSwitchesModule.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.google.inject.Provides -import com.twitter.abdecider.LoggingABDecider -import com.twitter.featureswitches.v2.FeatureSwitches -import com.twitter.featureswitches.v2.builder.FeatureSwitchesBuilder -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ConfigRepoLocalPath -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.FeatureSwitchesPath -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.timelines.features.app.ForcibleFeatureValuesModule -import javax.inject.Singleton - -object FeatureSwitchesModule extends TwitterModule with ForcibleFeatureValuesModule { - private val DefaultConfigRepoPath = "/usr/local/config" - - @Provides - @Singleton - def providesFeatureSwitches( - abDecider: LoggingABDecider, - statsReceiver: StatsReceiver, - @Flag(ServiceLocal) isServiceLocal: Boolean, - @Flag(ConfigRepoLocalPath) localConfigRepoPath: String, - @Flag(FeatureSwitchesPath) featuresPath: String - ): FeatureSwitches = { - val configRepoPath = if (isServiceLocal) { - localConfigRepoPath - } else { - DefaultConfigRepoPath - } - - val baseBuilder = FeatureSwitchesBuilder - .createDefault(featuresPath, abDecider, Some(statsReceiver)) - .configRepoAbsPath(configRepoPath) - .forcedValues(getFeatureSwitchOverrides) - // Track stats when an experiment impression is made. For example: - // "experiment_impressions/test_experiment_1234/" - // "experiment_impressions/test_experiment_1234/control" - // "experiment_impressions/test_experiment_1234/treatment" - .experimentImpressionStatsEnabled(true) - .unitsOfDiversionEnable(true) - - val finalBuilder = if (isServiceLocal) { - baseBuilder - } else { - baseBuilder.serviceDetailsFromAurora() - } - - finalBuilder.build() - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala deleted file mode 100644 index 0332e9819..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/LoggingThrowableExceptionMapper.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.twitter.finatra.thrift.exceptions.ExceptionMapper -import com.twitter.inject.Logging -import com.twitter.util.Future -import javax.inject.Singleton -import scala.util.control.NonFatal - -/** - * Similar to [[com.twitter.finatra.thrift.internal.exceptions.ThrowableExceptionMapper]] - * - * But this one also logs the exceptions. - */ -@Singleton -class LoggingThrowableExceptionMapper extends ExceptionMapper[Throwable, Nothing] with Logging { - - override def handleException(throwable: Throwable): Future[Nothing] = { - error("Unhandled Exception", throwable) - - throwable match { - case NonFatal(e) => Future.exception(e) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala deleted file mode 100644 index 3047135fa..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/PipelineExecutionLoggerModule.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.twitter.inject.TwitterModule -import com.twitter.product_mixer.core.service.pipeline_execution_logger.AllowListedPipelineExecutionLogger -import com.twitter.product_mixer.core.service.pipeline_execution_logger.PipelineExecutionLogger - -object PipelineExecutionLoggerModule extends TwitterModule { - - override protected def configure(): Unit = { - bind[PipelineExecutionLogger].to[AllowListedPipelineExecutionLogger] - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala deleted file mode 100644 index 8c7f98eb8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/ProductMixerModule.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.twitter.inject.TwitterModule -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule -import com.twitter.finatra.decider.modules.DeciderModule -import com.twitter.finatra.international.modules.LanguagesModule -import com.twitter.product_mixer.core.product.guice.ProductScopeModule -import com.twitter.finatra.jackson.modules.ScalaObjectMapperModule -import com.twitter.inject.thrift.modules.ThriftClientIdModule - -/** - * ProductMixerModule provides modules required by all Product Mixer services. - * - * @note if your service calls Strato you will need to add the [[StratoClientModule]] yourself. - */ -object ProductMixerModule extends TwitterModule { - - override val modules = Seq( - ABDeciderModule, - ConfigApiModule, - DeciderModule, - FeatureSwitchesModule, - LanguagesModule, - PipelineExecutionLoggerModule, - ProductMixerFlagModule, - new ProductScopeModule(), - ScalaObjectMapperModule, - ThriftClientIdModule, - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala deleted file mode 100644 index fc5680aa1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/StratoClientModule.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.core.module - -import com.google.inject.Provides -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.ssl.OpportunisticTls -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.StratoLocalRequestTimeout -import com.twitter.strato.client.Client -import com.twitter.strato.client.Strato -import com.twitter.util.Duration -import javax.inject.Singleton - -/** - * Product Mixer prefers to use a single strato client module over having a variety with different - * timeouts. Latency Budgets in Product Mixer systems should be defined at the application layer. - */ -object StratoClientModule extends TwitterModule { - - @Provides - @Singleton - def providesStratoClient( - serviceIdentifier: ServiceIdentifier, - @Flag(ServiceLocal) isServiceLocal: Boolean, - @Flag(StratoLocalRequestTimeout) timeout: Option[Duration] - ): Client = { - val stratoClient = Strato.client.withMutualTls(serviceIdentifier, OpportunisticTls.Required) - - // For local development it can be useful to have a larger timeout than the Strato default of - // 280ms. We strongly discourage setting client-level timeouts outside of this use-case. We - // recommend setting an overall timeout for your pipeline's end-to-end running time. - if (isServiceLocal && timeout.isDefined) - stratoClient.withRequestTimeout(timeout.get).build() - else { - stratoClient.build() - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD deleted file mode 100644 index 00b2668ca..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/BUILD +++ /dev/null @@ -1,15 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - ], - exports = [ - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala deleted file mode 100644 index 6426928be..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags/ProductMixerFlagModule.scala +++ /dev/null @@ -1,74 +0,0 @@ -package com.twitter.product_mixer.core.module.product_mixer_flags - -import com.twitter.inject.annotations.Flags -import com.twitter.inject.Injector -import com.twitter.inject.TwitterModule -import com.twitter.util.Duration - -object ProductMixerFlagModule extends TwitterModule { - final val ServiceLocal = "service.local" - final val ConfigRepoLocalPath = "configrepo.local_path" - final val FeatureSwitchesPath = "feature_switches.path" - final val StratoLocalRequestTimeout = "strato.local.request_timeout" - final val ScribeABImpressions = "scribe.ab_impressions" - final val PipelineExecutionLoggerAllowList = "pipeline_execution_logger.allow_list" - - flag[Boolean]( - name = ServiceLocal, - default = false, - help = "Is the server running locally or in a DC") - - flag[String]( - name = ConfigRepoLocalPath, - default = System.getProperty("user.home") + "/workspace/config", - help = "Path to your local config repo" - ) - - flag[Boolean]( - name = ScribeABImpressions, - help = "Enable scribing of AB impressions" - ) - - flag[String]( - name = FeatureSwitchesPath, - help = "Path to your local config repo" - ) - - flag[Duration]( - name = StratoLocalRequestTimeout, - help = "Override the request timeout for Strato when running locally" - ) - - flag[Seq[String]]( - name = PipelineExecutionLoggerAllowList, - default = Seq.empty, - help = - "Specify user role(s) for which detailed log messages (containing PII) can be made. Accepts a single role or a comma separated list 'a,b,c'" - ) - - /** - * Invoked at the end of server startup. - * - * If we're running locally, we display a nice message and a link to the admin page - */ - override def singletonPostWarmupComplete(injector: Injector): Unit = { - val isLocalService = injector.instance[Boolean](Flags.named(ServiceLocal)) - if (isLocalService) { - // Extract service name from clientId since there isn't a specific flag for that - val clientId = injector.instance[String](Flags.named("thrift.clientId")) - val name = clientId.split("\\.")(0) - - val adminPort = injector.instance[String](Flags.named("admin.port")) - val url = s"http://localhost$adminPort/" - - // Print instead of log, so it goes on stdout and doesn't get the logging decorations. - // Update our local development recipe (local-development.rst) if making changes to this - // message. - println("===============================================================================") - println(s"Welcome to a Product Mixer Service, $name") - println(s"You can view the admin endpoint and thrift web forms at $url") - println("Looking for support? Have questions? #product-mixer on Slack.") - println("===============================================================================") - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD deleted file mode 100644 index ad9cb35b3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/inject:guice", - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client/sources", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client/sources/refreshing", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], - exports = [ - "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala deleted file mode 100644 index 3db236d9d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/stringcenter/ProductScopeStringCenterModule.scala +++ /dev/null @@ -1,135 +0,0 @@ -package com.twitter.product_mixer.core.module.stringcenter - -import com.google.inject.Provides -import com.twitter.abdecider.LoggingABDecider -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.util.jackson.ScalaObjectMapper -import com.twitter.inject.TwitterModule -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.core.product.guice.scope.ProductScoped -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.twitter.stringcenter.client.ExternalStringRegistry -import com.twitter.stringcenter.client.StringCenter -import com.twitter.stringcenter.client.StringCenterClientConfig -import com.twitter.stringcenter.client.sources.RefreshingStringSource -import com.twitter.stringcenter.client.sources.RefreshingStringSourceConfig -import com.twitter.stringcenter.client.sources.StringSource -import com.twitter.translation.Languages -import javax.inject.Singleton -import scala.collection.concurrent - -/* - * Fun trivia - this has to be a Class not an Object, otherwise when you ./bazel test blah/... - * and glob multiple feature tests together it'll reuse the concurrentMaps below across - * executions / different server objects. - */ -class ProductScopeStringCenterModule extends TwitterModule { - - private val loadNothing = - flag[Boolean](name = "stringcenter.dontload", default = false, help = "Avoid loading any files") - - flag[Boolean]( - name = "stringcenter.handle.language.fallback", - default = true, - help = "Handle language fallback for services that don't already handle it") - - flag[String]( - name = "stringcenter.default_bundle_path", - default = "stringcenter", - help = "The path on disk to the default bundle available at startup time") - - private val refreshingInterval = flag[Int]( - name = "stringcenter.refresh_interval_minutes", - default = 3, - help = "How often to poll the refreshing bundle path to check for new bundles") - - /* The Guice injector is single threaded, but out of a preponderance of caution we use a concurrent Map. - * - * We need to ensure that we only build one StringSource, StringCenter client, and External String - * Registry for each String Center Project. @ProductScoped doesn't ensure this on it's own as - * two products can have the same String Center Project set. - */ - val stringSources: concurrent.Map[String, StringSource] = concurrent.TrieMap.empty - val stringCenterClients: concurrent.Map[String, StringCenter] = concurrent.TrieMap.empty - val externalStringRegistries: concurrent.Map[String, ExternalStringRegistry] = - concurrent.TrieMap.empty - - @ProductScoped - @Provides - def providesStringCenterClients( - abDecider: LoggingABDecider, - stringSource: StringSource, - languages: Languages, - statsReceiver: StatsReceiver, - clientConfig: StringCenterClientConfig, - product: Product - ): StringCenter = { - stringCenterClients.getOrElseUpdate( - stringCenterForProduct(product), { - new StringCenter( - abDecider, - stringSource, - languages, - statsReceiver, - clientConfig - ) - }) - } - - @ProductScoped - @Provides - def providesExternalStringRegistries( - product: Product - ): ExternalStringRegistry = { - externalStringRegistries.getOrElseUpdate( - stringCenterForProduct(product), { - new ExternalStringRegistry() - }) - } - - @ProductScoped - @Provides - def providesStringCenterSources( - mapper: ScalaObjectMapper, - statsReceiver: StatsReceiver, - product: Product, - @Flag("stringcenter.default_bundle_path") defaultBundlePath: String - ): StringSource = { - if (loadNothing()) { - StringSource.Empty - } else { - val stringCenterProduct = stringCenterForProduct(product) - - stringSources.getOrElseUpdate( - stringCenterProduct, { - val config = RefreshingStringSourceConfig( - stringCenterProduct, - defaultBundlePath, - "stringcenter/downloaded/current/stringcenter", - refreshingInterval().minutes - ) - new RefreshingStringSource( - config, - mapper, - statsReceiver - .scope("StringCenter", "refreshing", "project", stringCenterProduct)) - } - ) - } - } - - private def stringCenterForProduct(product: Product): String = - product.stringCenterProject.getOrElse { - throw new UnsupportedOperationException( - s"No StringCenter project defined for Product ${product.identifier}") - } - - @Singleton - @Provides - def providesStringCenterClientConfig( - @Flag("stringcenter.handle.language.fallback") handleLanguageFallback: Boolean - ): StringCenterClientConfig = { - StringCenterClientConfig(handleLanguageFallback = handleLanguageFallback) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD deleted file mode 100644 index bbb46c4c3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/BUILD +++ /dev/null @@ -1,92 +0,0 @@ -scala_library( - name = "query", - sources = ["PipelineQuery.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - ], -) - -scala_library( - name = "executor", - sources = [ - "FailOpenPolicy.scala", - "PipelineResult.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "util/util-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "util/util-core", - ], -) - -scala_library( - sources = [ - "!FailOpenPolicy.scala", - "!PipelineQuery.scala", - "!PipelineResult.scala", - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - ":executor", - ":query", - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "scrooge/scrooge-serializer/src/main/scala", - "stitch/stitch-core", - ], - exports = [ - ":executor", - ":query", - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "scrooge/scrooge-serializer/src/main/scala", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala deleted file mode 100644 index 49a31cbec..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/CandidatePipelineFeatures.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -private[core] object CandidatePipelineResults - extends Feature[PipelineQuery, Seq[CandidateWithDetails]] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala deleted file mode 100644 index f36664e1d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/FailOpenPolicy.scala +++ /dev/null @@ -1,42 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory - -/** - * [[FailOpenPolicy]] determines what should happen in the event that a candidate pipeline fails - * to execute successfully. - * - * Exercise caution when creating new fail open policies. Product Mixer will fail open by default in - * certain error cases (e.g. closed gate on a candidate pipeline) but these might inadvertently be - * excluded by a new policy. - */ -trait FailOpenPolicy { - def apply(failureCategory: PipelineFailureCategory): Boolean -} - -object FailOpenPolicy { - - /** - * Always fail open on candidate pipeline failures except - * for [[MisconfiguredFeatureMapFailure]]s because it's a programmer error - * and should always fail loudly, even with an [[Always]] p[[FailOpenPolicy]] - */ - val Always: FailOpenPolicy = (category: PipelineFailureCategory) => { - category != MisconfiguredFeatureMapFailure - } - - /** - * Never fail open on candidate pipeline failures. - * - * @note this is more restrictive than the default behavior which is to allow gate closed - * failures. - */ - val Never: FailOpenPolicy = (_: PipelineFailureCategory) => false - - // Build a policy that will fail open for a given set of categories - def apply(categories: Set[PipelineFailureCategory]): FailOpenPolicy = - (failureCategory: PipelineFailureCategory) => - categories - .contains(failureCategory) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala deleted file mode 100644 index 889f1f8e4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/InvalidStepStateException.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier - -case class InvalidStepStateException(step: PipelineStepIdentifier, missingData: String) - extends Exception( - s"Invalid Step State: Step $step requires $missingData" - ) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala deleted file mode 100644 index 14e8b0778..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineArrowBuilder.scala +++ /dev/null @@ -1,181 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults -import com.twitter.product_mixer.core.pipeline.state.HasResult -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.Executor.Context -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow -import com.twitter.stitch.Arrow.Iso -import com.twitter.util.Return -import com.twitter.util.Throw - -/** - * Pipeline Arrow Builder used for constructing a final arrow for a pipeline after adding necessary - * steps. - * - * @param steps The kept non-empty Pipeline Steps - * @param addedSteps Steps that have been added, but not necessarily kept. - * @param statsReceiver Stats Receiver for metric book keeping - * @tparam Result sThe expected final result type of the pipeline. - * @tparam State The input state type, which should implement [[HasResult]]. - */ -case class NewPipelineArrowBuilder[ - Result, - State <: HasExecutorResults[State] with HasResult[Result] -] private ( - private val steps: Seq[PipelineStep[State, _, _, _]], - override val statsReceiver: StatsReceiver) - extends Executor { - - def add[Config, ExecutorInput, ExResult <: ExecutorResult]( - pipelineStepIdentifier: PipelineStepIdentifier, - step: Step[State, Config, ExecutorInput, ExResult], - executorConfig: Config - ): NewPipelineArrowBuilder[Result, State] = { - require( - !steps.contains(pipelineStepIdentifier), - s"Found duplicate step $pipelineStepIdentifier when building pipeline arrow") - - // If the step has nothing to execute, drop it for simplification but still added it to the - // "addedSteps" field for build time validation - if (step.isEmpty(executorConfig)) { - this - } else { - val newPipelineStep = - PipelineStep(pipelineStepIdentifier, executorConfig, step) - val newSteps = steps :+ newPipelineStep - this.copy(steps = newSteps) - } - } - - def buildArrow( - context: Executor.Context - ): Arrow[State, NewPipelineResult[Result]] = { - val initialArrow = Arrow - .map { input: State => NewStepData[State](input) } - val allStepArrows = steps.map { step => - Iso.onlyIf[NewStepData[State]] { stepData => !stepData.stopExecuting } { - wrapStepWithExecutorBookkeeping(step, context) - } - } - val combinedArrow = isoArrowsSequentially(allStepArrows) - val resultArrow = Arrow.map { stepData: NewStepData[State] => - stepData.pipelineFailure match { - case Some(failure) => - NewPipelineResult.Failure(failure, stepData.pipelineState.executorResultsByPipelineStep) - case None => - NewPipelineResult.Success( - stepData.pipelineState.buildResult, - stepData.pipelineState.executorResultsByPipelineStep) - } - } - initialArrow.andThen(combinedArrow).andThen(resultArrow) - } - - private[this] def wrapStepWithExecutorBookkeeping( - step: PipelineStep[State, _, _, _], - context: Context - ): Arrow.Iso[NewStepData[State]] = { - val wrapped = wrapStepWithExecutorBookkeeping[NewStepData[State], NewStepData[State]]( - context = context, - identifier = step.stepIdentifier, - arrow = step.arrow(context), - // extract the failure only if it's present. Not sure if this is needed??? - transformer = _.pipelineFailure.map(Throw(_)).getOrElse(Return.Unit) - ) - - Arrow - .zipWithArg(wrapped.liftToTry) - .map { - case (_: NewStepData[State], Return(result)) => - // if Step was successful, return the result - result - case (previous: NewStepData[State], Throw(pipelineFailure: PipelineFailure)) => - // if the Step failed in such a way that the failure was NOT captured - // in the result object, then update the State with the failure - previous.withFailure(pipelineFailure) - case (_, Throw(ex)) => - // an exception was thrown which was not handled by the failure classifier - // this only happens with cancellation exceptions which are re-thrown - throw ex - } - } - - /** - * Sets up stats [[com.twitter.finagle.stats.Gauge]]s for any [[QualityFactorStatus]] - * - * @note We use provideGauge so these gauges live forever even without a reference. - */ - private[pipeline] def buildGaugesForQualityFactor( - pipelineIdentifier: ComponentIdentifier, - qualityFactorStatus: QualityFactorStatus, - statsReceiver: StatsReceiver - ): Unit = { - qualityFactorStatus.qualityFactorByPipeline.foreach { - case (identifier, qualityFactor) => - // QF is a relative stat (since the parent pipeline is monitoring a child pipeline) - val scopes = pipelineIdentifier.toScopes ++ identifier.toScopes :+ "QualityFactor" - statsReceiver.provideGauge(scopes: _*) { qualityFactor.currentValue.toFloat } - } - } -} - -object NewPipelineArrowBuilder { - def apply[Result, InputState <: HasExecutorResults[InputState] with HasResult[Result]]( - statsReceiver: StatsReceiver - ): NewPipelineArrowBuilder[Result, InputState] = { - NewPipelineArrowBuilder( - Seq.empty, - statsReceiver - ) - } -} - -/** - * This is a pipeline specific instance of a step, i.e, a generic step with the step identifier - * within the pipeline and its executor configs. - * @param stepIdentifier Step identifier of the step within a pipeline - * @param executorConfig Config to execute the step with - * @param step The underlying step to be used - * @tparam InputState The input state object - * @tparam ExecutorConfig The config expected for the given step - * @tparam ExecutorInput Input for the underlying executor - * @tparam ExecResult The result type - */ -case class PipelineStep[ - State <: HasExecutorResults[State], - PipelineStepConfig, - ExecutorInput, - ExecResult <: ExecutorResult -]( - stepIdentifier: PipelineStepIdentifier, - executorConfig: PipelineStepConfig, - step: Step[State, PipelineStepConfig, ExecutorInput, ExecResult]) { - - def arrow( - context: Executor.Context - ): Arrow.Iso[NewStepData[State]] = { - val inputArrow = Arrow.map { stepData: NewStepData[State] => - step.adaptInput(stepData.pipelineState, executorConfig) - } - - Arrow - .zipWithArg(inputArrow.andThen(step.arrow(executorConfig, context))).map { - case (stepData: NewStepData[State], executorResult: ExecResult @unchecked) => - val updatedResultsByPipelineStep = - stepData.pipelineState.executorResultsByPipelineStep + (stepIdentifier -> executorResult) - val updatedPipelineState = step - .updateState(stepData.pipelineState, executorResult, executorConfig).setExecutorResults( - updatedResultsByPipelineStep) - - NewStepData(updatedPipelineState) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala deleted file mode 100644 index a93d735d4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineBuilder.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults -import com.twitter.product_mixer.core.pipeline.state.HasResult - -/** - * A pipeline builder that is responsible for taking a PipelineConfig and creating a final pipeline - * from it. It provides an [[NewPipelineArrowBuilder]] for composing the pipeline's underlying arrow - * from [[Step]]s. - * - * @tparam Config The Pipeline Config - * @tparam PipelineArrowResult The expected final result - * @tparam PipelineArrowState State object for maintaining state across the pipeline. - * @tparam OutputPipeline The final pipeline - */ -trait NewPipelineBuilder[ - Config <: PipelineConfig, - PipelineArrowResult, - PipelineArrowState <: HasExecutorResults[PipelineArrowState] with HasResult[PipelineArrowResult], - OutputPipeline <: Pipeline[_, _]] { - - type ArrowResult = PipelineArrowResult - type ArrowState = PipelineArrowState - - def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - arrowBuilder: NewPipelineArrowBuilder[ArrowResult, ArrowState], - config: Config - ): OutputPipeline -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala deleted file mode 100644 index 0e473dfc3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewPipelineResult.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.ExecutorResult -import scala.collection.immutable.ListMap - -sealed trait NewPipelineResult[-Result] { - def executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult] -} - -object NewPipelineResult { - case class Failure( - failure: PipelineFailure, - override val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult]) - extends NewPipelineResult[Any] - - case class Success[Result]( - result: Result, - override val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult]) - extends NewPipelineResult[Result] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala deleted file mode 100644 index 3981d316c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/NewStepData.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults - -case class NewStepData[State <: HasExecutorResults[State]]( - pipelineState: State, - pipelineFailure: Option[PipelineFailure] = None) { - - val stopExecuting = pipelineFailure.isDefined - def withFailure(failure: PipelineFailure): NewStepData[State] = - this.copy(pipelineFailure = Some(failure)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala deleted file mode 100644 index c53ec81ed..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/Pipeline.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch - -/** Base trait for all `pipeline` implementations */ -trait Pipeline[-Query, Result] extends Component { - - /** The [[PipelineConfig]] that was used to create this [[Pipeline]] */ - private[core] val config: PipelineConfig - - /** Returns the underlying arrow that represents the pipeline. This is a val because we want to ensure - * that the arrow is long-lived and consistent, not generated per-request. - * - * Directly using this arrow allows you to combine it with other arrows efficiently. - */ - val arrow: Arrow[Query, PipelineResult[Result]] - - /** all child [[Component]]s that this [[Pipeline]] contains which will be registered and monitored */ - val children: Seq[Component] - - /** - * A helper for executing a single query. - * - * toResultTry and lowerFromTry has the end result of adapting PipelineResult into either a - * successful result or a Stitch exception, which is a common use-case for callers, - * particularly in the case of [[com.twitter.product_mixer.core.pipeline.product.ProductPipeline]]. - */ - def process(query: Query): Stitch[Result] = arrow(query).map(_.toResultTry).lowerFromTry - - final override def toString = s"Pipeline(identifier=$identifier)" - - /** - * [[Pipeline]]s are equal to one another if they were generated from the same [[PipelineConfig]], - * we check this by doing a reference checks first then comparing the [[PipelineConfig]] instances. - * - * We can skip additional checks because the other fields (e.g. [[identifier]] and [[children]]) - * are derived from the [[PipelineConfig]]. - */ - final override def equals(obj: Any): Boolean = obj match { - case pipeline: Pipeline[_, _] => - pipeline.eq(this) || pipeline.config.eq(config) || pipeline.config == config - case _ => false - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala deleted file mode 100644 index 377c06233..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineBuilder.scala +++ /dev/null @@ -1,194 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.Executor.Context -import com.twitter.product_mixer.core.service -import com.twitter.stitch.Arrow -import com.twitter.util.Return -import com.twitter.util.Throw - -trait PipelineBuilder[Query] extends Executor { - - /** - * When a step is mostly the same, but only the result update changes, - * you can pass in a [[ResultUpdater]] to the [[Step]] to perform the update - * such as with multi-step hydration. - */ - trait ResultUpdater[R <: PipelineResult[_], ER <: service.ExecutorResult] { - def apply(existingResult: R, executorResult: ER): R - } - - type UnderlyingResultType - type PipelineResultType <: PipelineResult[UnderlyingResultType] - - /** the data that every step has as input and output - the query, and the in-progress result */ - case class StepData(query: Query, result: PipelineResultType) - - /** An [[Arrow.Iso]] [[Arrow]] is an arrow with the same input and output types. */ - type StepArrow = Arrow.Iso[StepData] - - /** - * We break pipeline execution into a linear sequence of [[Step]]s. The execution logic of each - * step is represented as an [[Executor]] (which is reusable between pipelines). - * - * Each step has access to the [[PipelineResult]] generated by previous steps, and can update it - * with some new data. - * - * We define a pipeline Step as having three parts: - * - * - An underlying [[Executor]] [[Arrow]], from the underlying executor - * - An input adaptor to extract the right data from the previous [[PipelineResult]] - * - A result updater to update the [[PipelineResult]] - * - * This keeps knowledge of [[PipelineResult]] out of the executors, so they're reusable. - * - * @tparam ExecutorInput The input type used by the executor - * @tparam ExecutorResult The output/result type used by the executor - */ - trait Step[ExecutorInput, ExecutorResult] { - def identifier: PipelineStepIdentifier - def executorArrow: Arrow[ExecutorInput, ExecutorResult] - def inputAdaptor(query: Query, previousResult: PipelineResultType): ExecutorInput - def resultUpdater( - previousPipelineResult: PipelineResultType, - executorResult: ExecutorResult - ): PipelineResultType - - /** - * Optionally, steps can define a function to update the Query - */ - def queryUpdater(query: Query, executorResult: ExecutorResult): Query = query - - /** - * Arrow that adapts the input, runs the underlying Executor, adapts the output, and updates the state - */ - val stepArrow: StepArrow = { - val inputAdaptorArrow: Arrow[StepData, ExecutorInput] = Arrow.map { stepData: StepData => - inputAdaptor(stepData.query, stepData.result) - } - val outputAdaptorArrow: Arrow[(StepData, ExecutorResult), StepData] = Arrow.map { - // abstract type pattern ExecutorResult is unchecked since it is eliminated by erasure - case (previousStepData: StepData, executorResult: ExecutorResult @unchecked) => - StepData( - query = queryUpdater(previousStepData.query, executorResult), - result = resultUpdater(previousStepData.result, executorResult) - ) - } - - Arrow - .zipWithArg(inputAdaptorArrow.andThen(executorArrow)) - .andThen(outputAdaptorArrow) - } - } - - /** - * Wraps a step with [[wrapStepWithExecutorBookkeeping]] - * - * When an error is encountered in execution, we update the [[PipelineResult.failure]] field, - * and we return the partial results from all previously executed steps. - */ - def wrapStepWithExecutorBookkeeping( - context: Context, - step: Step[_, _] - ): Arrow.Iso[StepData] = { - val wrapped = wrapStepWithExecutorBookkeeping[StepData, StepData]( - context = context, - identifier = step.identifier, - arrow = step.stepArrow, - // extract the failure only if it's present - transformer = _.result.failure match { - case Some(pipelineFailure) => Throw(pipelineFailure) - case None => Return.Unit - } - ) - - Arrow - .zipWithArg(wrapped.liftToTry) - .map { - case (_: StepData, Return(result)) => - // if Step was successful, return the result - result - case (StepData(query, previousResult), Throw(pipelineFailure: PipelineFailure)) => - // if the Step failed in such a way that the failure was NOT captured - // in the result object, then update the State with the failure - StepData( - query, - previousResult.withFailure(pipelineFailure).asInstanceOf[PipelineResultType]) - case (_, Throw(ex)) => - // an exception was thrown which was not handled by the failure classifier - // this only happens with cancellation exceptions which are re-thrown - throw ex - } - } - - /** - * Builds a combined arrow out of steps. - * - * Wraps them in error handling, and only executes each step if the previous step is successful. - */ - def buildCombinedArrowFromSteps( - steps: Seq[Step[_, _]], - context: Executor.Context, - initialEmptyResult: PipelineResultType, - stepsInOrderFromConfig: Seq[PipelineStepIdentifier] - ): Arrow[Query, PipelineResultType] = { - - validateConfigAndBuilderAreInSync(steps, stepsInOrderFromConfig) - - /** - * Prepare the step arrows. - * 1. Wrap them in executor bookkeeping - * 2. Wrap them in Iso.onlyIf - so we only execute them if we don't have a result or failure yet - * 3. Combine them using [[isoArrowsSequentially]] - * - * @note this results in no Executor bookkeeping actions for [[Step]]s after - * we reach a [[PipelineResult.stopExecuting]]. - */ - val stepArrows = isoArrowsSequentially(steps.map { step => - Arrow.Iso.onlyIf[StepData](stepData => !stepData.result.stopExecuting)( - wrapStepWithExecutorBookkeeping(context, step)) - }) - - Arrow - .identity[Query] - .map { query => StepData(query, initialEmptyResult) } - .andThen(stepArrows) - .map { case StepData(_, result) => result } - } - - /** - * Sets up stats [[com.twitter.finagle.stats.Gauge]]s for any [[QualityFactorStatus]] - * - * @note We use provideGauge so these gauges live forever even without a reference. - */ - private[pipeline] def buildGaugesForQualityFactor( - pipelineIdentifier: ComponentIdentifier, - qualityFactorStatus: QualityFactorStatus, - statsReceiver: StatsReceiver - ): Unit = { - qualityFactorStatus.qualityFactorByPipeline.foreach { - case (identifier, qualityFactor) => - // QF is a relative stat (since the parent pipeline is monitoring a child pipeline) - val scopes = pipelineIdentifier.toScopes ++ identifier.toScopes :+ "QualityFactor" - statsReceiver.provideGauge(scopes: _*) { qualityFactor.currentValue.toFloat } - } - } - - /** Validates that the [[PipelineConfigCompanion]] is in sync with the [[Step]]s a [[PipelineBuilder]] produces */ - private[this] def validateConfigAndBuilderAreInSync( - builtSteps: Seq[Step[_, _]], - stepsInOrder: Seq[PipelineStepIdentifier] - ): Unit = { - require( - builtSteps.map(_.identifier) == stepsInOrder, - s"Builder and Config are out of sync, bug in Product Mixer Core, `PipelineCompanion` and `PipelineBuilder` " + - s"have different definitions of what Steps are run in this Pipeline \n" + - s"${builtSteps.map(_.identifier).zip(stepsInOrder).mkString("\n")}" - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala deleted file mode 100644 index 5b99e32fc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineConfig.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.model.common.identifier.HasComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier - -trait PipelineConfig extends HasComponentIdentifier - -trait PipelineConfigCompanion { - - /** used to generate `AsyncFeaturesFor` [[PipelineStepIdentifier]]s for the internal Async Features Step */ - private[core] def asyncFeaturesStep( - stepToHydrateFor: PipelineStepIdentifier - ): PipelineStepIdentifier = - PipelineStepIdentifier("AsyncFeaturesFor" + stepToHydrateFor.name) - - /** All the Steps which are executed by a [[Pipeline]] in the order in which they are run */ - val stepsInOrder: Seq[PipelineStepIdentifier] - - val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set.empty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala deleted file mode 100644 index 3428939e4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursor.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -/** - * PipelineCursor represents any product-specific cursor model. Typically the PipelineCursor will be - * a de-serialized base 64 thrift struct from initial request. - */ -trait PipelineCursor - -/** - * HasPipelineCursor indicates that a [[PipelineQuery]] has a cursor - */ -trait HasPipelineCursor[+Cursor <: PipelineCursor] { - def pipelineCursor: Option[Cursor] - - /** - * If the cursor is not present, this typically means that we are on the first page - */ - def isFirstPage: Boolean = pipelineCursor.isEmpty -} - -/** - * UrtPipelineCursor represents a URT product-specific cursor model. Typically the UrtPipelineCursor - * will be a de-serialized base 64 thrift struct from initial request. - */ -trait UrtPipelineCursor extends PipelineCursor { - - /** See [[UrtCursorBuilder]] for background on building initialSortIndex */ - def initialSortIndex: Long -} - -object UrtPipelineCursor { - def getCursorInitialSortIndex(query: PipelineQuery with HasPipelineCursor[_]): Option[Long] = { - query.pipelineCursor match { - case Some(cursor: UrtPipelineCursor) => Some(cursor.initialSortIndex) - case _ => None - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala deleted file mode 100644 index 6ed6a9ce2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineCursorSerializer.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MalformedCursor -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.scrooge.BinaryThriftStructSerializer -import com.twitter.scrooge.ThriftStruct -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try - -/** - * Serializes a [[PipelineCursor]] into thrift and then into a base64 encoded string - */ -trait PipelineCursorSerializer[-Cursor <: PipelineCursor] { - def serializeCursor(cursor: Cursor): String -} - -object PipelineCursorSerializer { - - /** - * Deserializes a cursor string into thrift and then into a [[PipelineCursor]] - * - * @param cursorString to deserialize, which is base64 encoded thrift - * @param cursorThriftSerializer to deserialize the cursor string into thrift - * @param deserializePf specifies how to transform the serialized thrift into a [[PipelineCursor]] - * @return optional [[PipelineCursor]]. `None` may or may not be a failure depending on the - * implementation of deserializePf. - * - * @note The "A" type of deserializePf cannot be inferred due to the thrift type not being present - * on the PipelineCursorSerializer trait. Therefore invokers must often add an explicit type - * on the deserializeCursor call to help out the compiler when passing deserializePf inline. - * Alternatively, deserializePf can be declared as a val with a type annotation before it is - * passed into this method. - */ - def deserializeCursor[Thrift <: ThriftStruct, Cursor <: PipelineCursor]( - cursorString: String, - cursorThriftSerializer: BinaryThriftStructSerializer[Thrift], - deserializePf: PartialFunction[Option[Thrift], Option[Cursor]] - ): Option[Cursor] = { - val thriftCursor: Option[Thrift] = - Try { - cursorThriftSerializer.fromString(cursorString) - } match { - case Return(thriftCursor) => Some(thriftCursor) - case Throw(_) => None - } - - // Add type annotation to help out the compiler since the type is lost due to the _ match - val defaultDeserializePf: PartialFunction[Option[Thrift], Option[Cursor]] = { - case _ => - // This case is the result of the client submitting a cursor we do not expect - throw PipelineFailure(MalformedCursor, s"Unknown request cursor: $cursorString") - } - - (deserializePf orElse defaultDeserializePf)(thriftCursor) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala deleted file mode 100644 index ae6add7e1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineQuery.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.marshalling.request.HasClientContext -import com.twitter.product_mixer.core.model.marshalling.request.HasDebugOptions -import com.twitter.product_mixer.core.model.marshalling.request.HasProduct -import com.twitter.timelines.configapi.HasParams -import com.twitter.timelines.configapi.Param -import com.twitter.util.Time - -trait PipelineQuery extends HasParams with HasClientContext with HasProduct with HasDebugOptions { - self => - - /** Set a query time val that is constant for the duration of the query lifecycle */ - val queryTime: Time = self.debugOptions.flatMap(_.requestTimeOverride).getOrElse(Time.now) - - /** The requested max results is specified, or not specified, by the thrift client */ - def requestedMaxResults: Option[Int] - - /** Retrieves the max results with a default Param, if not specified by the thrift client */ - def maxResults(defaultRequestedMaxResultParam: Param[Int]): Int = - requestedMaxResults.getOrElse(params(defaultRequestedMaxResultParam)) - - /** Optional [[FeatureMap]], this may be updated later using [[withFeatureMap]] */ - def features: Option[FeatureMap] - - /** - * Since Query-Level features can be hydrated later, we need this method to update the PipelineQuery - * usually this will be implemented via `copy(features = Some(features))` - */ - def withFeatureMap(features: FeatureMap): PipelineQuery -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala deleted file mode 100644 index f7e378917..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/PipelineResult.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.core.pipeline - -import com.twitter.product_mixer.component_library.model.candidate.CursorCandidate -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ExecutionFailed -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try - -/** - * Pipelines return a PipelineResult. - * - * This allows us to return a single main result (optionally, incase the pipeline didn't execute successfully), but - * still have a detailed response object to show how that result was produced. - */ -trait PipelineResult[ResultType] { - val failure: Option[PipelineFailure] - val result: Option[ResultType] - - def withFailure(failure: PipelineFailure): PipelineResult[ResultType] - def withResult(result: ResultType): PipelineResult[ResultType] - - def resultSize(): Int - - private[pipeline] def stopExecuting: Boolean = failure.isDefined || result.isDefined - - final def toTry: Try[this.type] = (result, failure) match { - case (_, Some(failure)) => - Throw(failure) - case (_: Some[ResultType], _) => - Return(this) - // Pipelines should always finish with either a result or a failure - case _ => Throw(PipelineFailure(ExecutionFailed, "Pipeline did not execute")) - } - - final def toResultTry: Try[ResultType] = { - // `.get` is safe here because `toTry` guarantees a value in the `Return` case - toTry.map(_.result.get) - } -} - -object PipelineResult { - - /** - * Track number of candidates returned by a Pipeline. Cursors are excluded from this - * count and modules are counted as the sum of their candidates. - * - * @note this is a somewhat subjective measure of 'size' and it is spread across pipeline - * definitions as well as selectors. - */ - def resultSize(results: Seq[CandidateWithDetails]): Int = results.map { - case module: ModuleCandidateWithDetails => resultSize(module.candidates) - case ItemCandidateWithDetails(_: CursorCandidate, _, _) => 0 - case _ => 1 - }.sum -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD deleted file mode 100644 index 642e7c74f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/BUILD +++ /dev/null @@ -1,77 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "configapi/configapi-decider", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "configapi/configapi-decider", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala deleted file mode 100644 index 2c52636b6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipeline.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Arrow - -/** - * A Candidate Pipeline - * - * This is an abstract class, as we only construct these via the [[CandidatePipelineBuilder]]. - * - * A [[CandidatePipeline]] is capable of processing requests (queries) and returning candidates - * in the form of a [[CandidatePipelineResult]] - * - * @tparam Query the domain model for the query or request - */ -abstract class CandidatePipeline[-Query <: PipelineQuery] private[candidate] - extends Pipeline[CandidatePipeline.Inputs[Query], Seq[CandidateWithDetails]] { - override private[core] val config: BaseCandidatePipelineConfig[Query, _, _, _] - override val arrow: Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult] - override val identifier: CandidatePipelineIdentifier -} - -object CandidatePipeline { - case class Inputs[+Query <: PipelineQuery]( - query: Query, - existingCandidates: Seq[CandidateWithDetails]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala deleted file mode 100644 index 2d3df3440..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilder.scala +++ /dev/null @@ -1,735 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.transformer.BaseCandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.gate.ParamGate -import com.twitter.product_mixer.core.gate.ParamGate.EnabledGateSuffix -import com.twitter.product_mixer.core.gate.ParamGate.SupportedClientGateSuffix -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.InvalidStepStateException -import com.twitter.product_mixer.core.pipeline.PipelineBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutor -import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutorResult -import com.twitter.product_mixer.core.service.candidate_source_executor.FetchedCandidateWithFeatures -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutor -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorInput -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.stitch.Arrow -import com.twitter.util.logging.Logging -import javax.inject.Inject - -class CandidatePipelineBuilder[ - Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Result <: UniversalNoun[Any]] @Inject() ( - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor, - asyncFeatureMapExecutor: AsyncFeatureMapExecutor, - candidateDecoratorExecutor: CandidateDecoratorExecutor, - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor, - candidateSourceExecutor: CandidateSourceExecutor, - groupResultsExecutor: GroupResultsExecutor, - filterExecutor: FilterExecutor, - gateExecutor: GateExecutor, - override val statsReceiver: StatsReceiver) - extends PipelineBuilder[CandidatePipeline.Inputs[Query]] - with Logging { - - override type UnderlyingResultType = Seq[CandidateWithDetails] - override type PipelineResultType = IntermediateCandidatePipelineResult[Result] - - def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - config: BaseCandidatePipelineConfig[ - Query, - CandidateSourceQuery, - CandidateSourceResult, - Result - ] - ): CandidatePipeline[Query] = { - - val pipelineIdentifier = config.identifier - val candidateSourceIdentifier = config.candidateSource.identifier - - val context = Executor.Context( - PipelineFailureClassifier( - config.failureClassifier.orElse(StoppedGateException.classifier(ClosedGate))), - parentComponentIdentifierStack.push(pipelineIdentifier) - ) - - val enabledGateOpt = config.enabledDeciderParam.map { deciderParam => - ParamGate(pipelineIdentifier + EnabledGateSuffix, deciderParam) - } - val supportedClientGateOpt = config.supportedClientParam.map { param => - ParamGate(pipelineIdentifier + SupportedClientGateSuffix, param) - } - - /** - * Evaluate enabled decider gate first since if it's off, there is no reason to proceed - * Next evaluate supported client feature switch gate, followed by customer configured gates - */ - val allGates = enabledGateOpt.toSeq ++ supportedClientGateOpt.toSeq ++ config.gates - - // Dynamically replace the identifier of both transformers if config used the inline constructor - // which sets a default identifier. We need to do this to ensure uniqueness of identifiers. - val queryTransformer = BaseCandidatePipelineQueryTransformer.copyWithUpdatedIdentifier( - config.queryTransformer, - pipelineIdentifier) - - val resultsTransformer = CandidatePipelineResultsTransformer.copyWithUpdatedIdentifier( - config.resultTransformer, - pipelineIdentifier) - - val decorator = config.decorator.map(decorator => - CandidateDecorator.copyWithUpdatedIdentifier(decorator, pipelineIdentifier)) - - val GatesStep = new Step[Query, GateExecutorResult] { - override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.gatesStep - - override def executorArrow: Arrow[Query, GateExecutorResult] = { - gateExecutor.arrow(allGates, context) - } - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): Query = - query.query - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: GateExecutorResult - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy(underlyingResult = - previousPipelineResult.underlyingResult.copy(gateResult = Some(executorResult))) - } - - def queryFeatureHydrationStep( - queryFeatureHydrators: Seq[BaseQueryFeatureHydrator[Query, _]], - stepIdentifier: PipelineStepIdentifier, - updater: ResultUpdater[CandidatePipelineResult, QueryFeatureHydratorExecutor.Result] - ): Step[Query, QueryFeatureHydratorExecutor.Result] = - new Step[Query, QueryFeatureHydratorExecutor.Result] { - override def identifier: PipelineStepIdentifier = stepIdentifier - - override def executorArrow: Arrow[Query, QueryFeatureHydratorExecutor.Result] = - queryFeatureHydratorExecutor.arrow( - queryFeatureHydrators, - CandidatePipelineConfig.stepsAsyncFeatureHydrationCanBeCompletedBy, - context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): Query = query.query - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: QueryFeatureHydratorExecutor.Result - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy( - underlyingResult = updater(previousPipelineResult.underlyingResult, executorResult)) - - override def queryUpdater( - query: CandidatePipeline.Inputs[Query], - executorResult: QueryFeatureHydratorExecutor.Result - ): CandidatePipeline.Inputs[Query] = - CandidatePipeline.Inputs( - query.query - .withFeatureMap( - query.query.features.getOrElse( - FeatureMap.empty) ++ executorResult.featureMap).asInstanceOf[Query], - query.existingCandidates) - } - - def asyncFeaturesStep( - stepToHydrateFor: PipelineStepIdentifier, - context: Executor.Context - ): Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - new Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] { - override def identifier: PipelineStepIdentifier = - CandidatePipelineConfig.asyncFeaturesStep(stepToHydrateFor) - - override def executorArrow: Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - asyncFeatureMapExecutor.arrow(stepToHydrateFor, identifier, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): AsyncFeatureMap = - previousResult.underlyingResult.mergedAsyncQueryFeatures - .getOrElse( - throw InvalidStepStateException(identifier, "MergedAsyncQueryFeatures") - ) - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: AsyncFeatureMapExecutorResults - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy( - underlyingResult = - previousPipelineResult.underlyingResult.copy(asyncFeatureHydrationResults = - previousPipelineResult.underlyingResult.asyncFeatureHydrationResults match { - case Some(existingResults) => Some(existingResults ++ executorResult) - case None => Some(executorResult) - })) - - override def queryUpdater( - query: CandidatePipeline.Inputs[Query], - executorResult: AsyncFeatureMapExecutorResults - ): CandidatePipeline.Inputs[Query] = - if (executorResult.featureMapsByStep - .getOrElse(stepToHydrateFor, FeatureMap.empty).isEmpty) { - query - } else { - val updatedQuery = query.query - .withFeatureMap( - query.query.features - .getOrElse(FeatureMap.empty) ++ executorResult.featureMapsByStep( - stepToHydrateFor)).asInstanceOf[Query] - CandidatePipeline.Inputs(updatedQuery, query.existingCandidates) - } - } - - val CandidateSourceStep = - new Step[Query, CandidateSourceExecutorResult[Result]] { - override def identifier: PipelineStepIdentifier = - CandidatePipelineConfig.candidateSourceStep - - override def executorArrow: Arrow[ - Query, - CandidateSourceExecutorResult[Result] - ] = - candidateSourceExecutor - .arrow( - config.candidateSource, - queryTransformer, - resultsTransformer, - config.featuresFromCandidateSourceTransformers, - context - ) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): Query = - query.query - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: CandidateSourceExecutorResult[Result] - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy(underlyingResult = - previousPipelineResult.underlyingResult.copy( - candidateSourceResult = - Some(executorResult.asInstanceOf[CandidateSourceExecutorResult[UniversalNoun[Any]]]) - )) - - override def queryUpdater( - query: CandidatePipeline.Inputs[Query], - executorResult: CandidateSourceExecutorResult[Result] - ): CandidatePipeline.Inputs[Query] = { - val updatedFeatureMap = - query.query.features - .getOrElse(FeatureMap.empty) ++ executorResult.candidateSourceFeatureMap - val updatedQuery = query.query - .withFeatureMap(updatedFeatureMap).asInstanceOf[Query] - CandidatePipeline.Inputs(updatedQuery, query.existingCandidates) - } - } - - val PreFilterFeatureHydrationPhase1Step = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] { - override def identifier: PipelineStepIdentifier = - CandidatePipelineConfig.preFilterFeatureHydrationPhase1Step - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] = - candidateFeatureHydratorExecutor.arrow(config.preFilterFeatureHydrationPhase1, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = { - val candidateSourceExecutorResult = - previousResult.underlyingResult.candidateSourceResult.getOrElse { - throw InvalidStepStateException(identifier, "CandidateSourceResult") - } - CandidateFeatureHydratorExecutor.Inputs( - query.query, - candidateSourceExecutorResult.candidates - .asInstanceOf[Seq[CandidateWithFeatures[Result]]]) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: CandidateFeatureHydratorExecutorResult[Result] - ): IntermediateCandidatePipelineResult[Result] = { - val candidateSourceExecutorResult = - previousPipelineResult.underlyingResult.candidateSourceResult.getOrElse { - throw InvalidStepStateException(identifier, "CandidateSourceResult") - } - - val featureMapsFromPreFilter = executorResult.results.map { result => - result.candidate -> result.features - }.toMap - - val mergedFeatureMaps = candidateSourceExecutorResult.candidates.map { candidate => - val candidateFeatureMap = candidate.features - val preFilterFeatureMap = - featureMapsFromPreFilter.getOrElse( - candidate.candidate.asInstanceOf[Result], - FeatureMap.empty) - - candidate.candidate.asInstanceOf[Result] -> (candidateFeatureMap ++ preFilterFeatureMap) - }.toMap - - previousPipelineResult.copy( - underlyingResult = previousPipelineResult.underlyingResult.copy( - preFilterHydrationResult = Some( - executorResult - .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]]) - ), - featureMaps = Some(mergedFeatureMaps) - ) - } - } - - val PreFilterFeatureHydrationPhase2Step = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] { - override def identifier: PipelineStepIdentifier = - CandidatePipelineConfig.preFilterFeatureHydrationPhase2Step - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] = - candidateFeatureHydratorExecutor.arrow(config.preFilterFeatureHydrationPhase2, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = { - val candidates = previousResult.underlyingResult.preFilterHydrationResult.getOrElse { - throw InvalidStepStateException(identifier, "PreFilterHydrationResult") - }.results - CandidateFeatureHydratorExecutor.Inputs( - query.query, - candidates.asInstanceOf[Seq[CandidateWithFeatures[Result]]] - ) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: CandidateFeatureHydratorExecutorResult[Result] - ): IntermediateCandidatePipelineResult[Result] = { - - val featureMapsFromPreFilterPhase2 = executorResult.results.map { result => - result.candidate -> result.features - }.toMap - - val mergedFeatureMaps = previousPipelineResult.featureMaps - .getOrElse(throw InvalidStepStateException(identifier, "FeatureMaps")) - .map { - case (candidate, featureMap) => - val preFilterPhase2FeatureMap = - featureMapsFromPreFilterPhase2.getOrElse(candidate, FeatureMap.empty) - - candidate -> (featureMap ++ preFilterPhase2FeatureMap) - } - - previousPipelineResult.copy( - underlyingResult = previousPipelineResult.underlyingResult.copy( - preFilterHydrationResultPhase2 = Some( - executorResult - .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]]) - ), - featureMaps = Some(mergedFeatureMaps) - ) - } - } - - val FiltersStep = - new Step[(Query, Seq[CandidateWithFeatures[Result]]), FilterExecutorResult[Result]] { - override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.filtersStep - - override def executorArrow: Arrow[ - (Query, Seq[CandidateWithFeatures[Result]]), - FilterExecutorResult[ - Result - ] - ] = - filterExecutor.arrow(config.filters, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): (Query, Seq[CandidateWithFeatures[Result]]) = { - val candidates = - previousResult.underlyingResult.candidateSourceResult - .getOrElse { - throw InvalidStepStateException(identifier, "CandidateSourceResult") - }.candidates.map(_.candidate).asInstanceOf[Seq[Result]] - - val featureMaps = previousResult.featureMaps - .getOrElse(throw InvalidStepStateException(identifier, "FeatureMaps")) - - ( - query.query, - candidates.map(candidate => - CandidateWithFeaturesImpl( - candidate, - featureMaps.getOrElse(candidate, FeatureMap.empty)))) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: FilterExecutorResult[Result] - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy(underlyingResult = - previousPipelineResult.underlyingResult.copy( - filterResult = - Some(executorResult.asInstanceOf[FilterExecutorResult[UniversalNoun[Any]]]) - )) - } - - val PostFilterFeatureHydrationStep = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] { - override def identifier: PipelineStepIdentifier = - CandidatePipelineConfig.postFilterFeatureHydrationStep - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] = - candidateFeatureHydratorExecutor.arrow(config.postFilterFeatureHydration, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = { - val filterResult = previousResult.underlyingResult.filterResult - .getOrElse( - throw InvalidStepStateException(identifier, "FilterResult") - ).result.asInstanceOf[Seq[Result]] - - val featureMaps = previousResult.featureMaps.getOrElse( - throw InvalidStepStateException(identifier, "FeatureMaps") - ) - - val filteredCandidates = filterResult.map { candidate => - CandidateWithFeaturesImpl(candidate, featureMaps.getOrElse(candidate, FeatureMap.empty)) - } - CandidateFeatureHydratorExecutor.Inputs(query.query, filteredCandidates) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: CandidateFeatureHydratorExecutorResult[Result] - ): IntermediateCandidatePipelineResult[Result] = { - val filterResult = previousPipelineResult.underlyingResult.filterResult - .getOrElse( - throw InvalidStepStateException(identifier, "FilterResult") - ).result.asInstanceOf[Seq[Result]] - - val featureMaps = previousPipelineResult.featureMaps.getOrElse( - throw InvalidStepStateException(identifier, "FeatureMaps") - ) - - val postFilterFeatureMaps = executorResult.results.map { result => - result.candidate -> result.features - }.toMap - - val mergedFeatureMaps = filterResult.map { candidate => - candidate -> - (featureMaps - .getOrElse(candidate, FeatureMap.empty) ++ postFilterFeatureMaps.getOrElse( - candidate, - FeatureMap.empty)) - }.toMap - - previousPipelineResult.copy( - underlyingResult = previousPipelineResult.underlyingResult.copy( - postFilterHydrationResult = Some( - executorResult - .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]]) - ), - featureMaps = Some(mergedFeatureMaps) - ) - } - } - - val ScorersStep = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] { - override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.scorersStep - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] = - candidateFeatureHydratorExecutor.arrow(config.scorers, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Result] = { - val filterResult = previousResult.underlyingResult.filterResult - .getOrElse( - throw InvalidStepStateException(identifier, "FilterResult") - ).result.asInstanceOf[Seq[Result]] - - val featureMaps = previousResult.featureMaps.getOrElse( - throw InvalidStepStateException(identifier, "FeatureMaps") - ) - - val filteredCandidates = filterResult.map { candidate => - CandidateWithFeaturesImpl(candidate, featureMaps.getOrElse(candidate, FeatureMap.empty)) - } - CandidateFeatureHydratorExecutor.Inputs(query.query, filteredCandidates) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: CandidateFeatureHydratorExecutorResult[Result] - ): IntermediateCandidatePipelineResult[Result] = { - val filterResult = previousPipelineResult.underlyingResult.filterResult - .getOrElse( - throw InvalidStepStateException(identifier, "FilterResult") - ).result.asInstanceOf[Seq[Result]] - - val featureMaps = previousPipelineResult.featureMaps.getOrElse( - throw InvalidStepStateException(identifier, "FeatureMaps") - ) - - val scoringFeatureMaps = executorResult.results.map { result => - result.candidate -> result.features - }.toMap - - val mergedFeatureMaps = filterResult.map { candidate => - candidate -> - (featureMaps - .getOrElse(candidate, FeatureMap.empty) ++ scoringFeatureMaps.getOrElse( - candidate, - FeatureMap.empty)) - }.toMap - - previousPipelineResult.copy( - underlyingResult = previousPipelineResult.underlyingResult.copy( - scorersResult = Some( - executorResult - .asInstanceOf[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]]) - ), - featureMaps = Some(mergedFeatureMaps) - ) - } - } - - val DecorationStep = - new Step[(Query, Seq[CandidateWithFeatures[Result]]), CandidateDecoratorExecutorResult] { - override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.decoratorStep - - override def executorArrow: Arrow[ - (Query, Seq[CandidateWithFeatures[Result]]), - CandidateDecoratorExecutorResult - ] = - candidateDecoratorExecutor.arrow(decorator, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): (Query, Seq[CandidateWithFeatures[Result]]) = { - val keptCandidates = previousResult.underlyingResult.filterResult - .getOrElse { - throw InvalidStepStateException(identifier, "FilterResult") - }.result.asInstanceOf[Seq[Result]] - - val featureMaps = previousResult.featureMaps.getOrElse { - throw InvalidStepStateException(identifier, "FeatureMaps") - } - - ( - query.query, - keptCandidates.map(candidate => - CandidateWithFeaturesImpl( - candidate, - featureMaps.getOrElse(candidate, FeatureMap.empty)))) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: CandidateDecoratorExecutorResult - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy(underlyingResult = - previousPipelineResult.underlyingResult.copy( - candidateDecoratorResult = Some(executorResult) - )) - } - - /** - * ResultStep is a synchronous step that basically takes the outputs from the other steps, groups modules, - * and puts things into the final result object - */ - val ResultStep = new Step[GroupResultsExecutorInput[Result], GroupResultsExecutorResult] { - override def identifier: PipelineStepIdentifier = CandidatePipelineConfig.resultStep - - override def executorArrow: Arrow[ - GroupResultsExecutorInput[Result], - GroupResultsExecutorResult - ] = groupResultsExecutor.arrow(pipelineIdentifier, candidateSourceIdentifier, context) - - override def inputAdaptor( - query: CandidatePipeline.Inputs[Query], - previousResult: IntermediateCandidatePipelineResult[Result] - ): GroupResultsExecutorInput[Result] = { - - val underlying = previousResult.underlyingResult - - val keptCandidates = underlying.filterResult - .getOrElse( - throw InvalidStepStateException(identifier, "FilterResult") - ).result.asInstanceOf[Seq[Result]] - - val decorations = underlying.candidateDecoratorResult - .getOrElse( - throw InvalidStepStateException(identifier, "DecorationResult") - ).result.map(decoration => decoration.candidate -> decoration.presentation).toMap - - val combinedFeatureMaps: Map[Result, FeatureMap] = previousResult.featureMaps.getOrElse( - throw InvalidStepStateException(identifier, "FeatureMaps")) - - val filteredCandidates = keptCandidates.map { candidate => - val updatedMap = combinedFeatureMaps - .get(candidate).getOrElse(FeatureMap.empty) - FetchedCandidateWithFeatures(candidate, updatedMap) - } - - GroupResultsExecutorInput( - candidates = filteredCandidates, - decorations = decorations - ) - } - - override def resultUpdater( - previousPipelineResult: IntermediateCandidatePipelineResult[Result], - executorResult: GroupResultsExecutorResult - ): IntermediateCandidatePipelineResult[Result] = - previousPipelineResult.copy(underlyingResult = previousPipelineResult.underlyingResult - .copy(result = Some(executorResult.candidatesWithDetails))) - } - - val builtSteps = Seq( - GatesStep, - queryFeatureHydrationStep( - config.queryFeatureHydration, - CandidatePipelineConfig.fetchQueryFeaturesStep, - (pipelineResult, executorResult) => - pipelineResult.copy(queryFeatures = Some(executorResult)) - ), - queryFeatureHydrationStep( - config.queryFeatureHydrationPhase2, - CandidatePipelineConfig.fetchQueryFeaturesPhase2Step, - (pipelineResult, executorResult) => - pipelineResult.copy( - queryFeaturesPhase2 = Some(executorResult), - mergedAsyncQueryFeatures = Some( - pipelineResult.queryFeatures - .getOrElse( - throw InvalidStepStateException( - CandidatePipelineConfig.fetchQueryFeaturesPhase2Step, - "QueryFeatures") - ).asyncFeatureMap ++ executorResult.asyncFeatureMap) - ) - ), - asyncFeaturesStep(CandidatePipelineConfig.candidateSourceStep, context), - CandidateSourceStep, - asyncFeaturesStep(CandidatePipelineConfig.preFilterFeatureHydrationPhase1Step, context), - PreFilterFeatureHydrationPhase1Step, - asyncFeaturesStep(CandidatePipelineConfig.preFilterFeatureHydrationPhase2Step, context), - PreFilterFeatureHydrationPhase2Step, - asyncFeaturesStep(CandidatePipelineConfig.filtersStep, context), - FiltersStep, - asyncFeaturesStep(CandidatePipelineConfig.postFilterFeatureHydrationStep, context), - PostFilterFeatureHydrationStep, - asyncFeaturesStep(CandidatePipelineConfig.scorersStep, context), - ScorersStep, - asyncFeaturesStep(CandidatePipelineConfig.decoratorStep, context), - DecorationStep, - ResultStep - ) - - /** The main execution logic for this Candidate Pipeline. */ - val finalArrow: Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult] = - buildCombinedArrowFromSteps( - steps = builtSteps, - context = context, - initialEmptyResult = - IntermediateCandidatePipelineResult.empty[Result](config.candidateSource.identifier), - stepsInOrderFromConfig = CandidatePipelineConfig.stepsInOrder - ).map(_.underlyingResult) - - val configFromBuilder = config - new CandidatePipeline[Query] { - override private[core] val config: BaseCandidatePipelineConfig[Query, _, _, _] = - configFromBuilder - override val arrow: Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult] = - finalArrow - override val identifier: CandidatePipelineIdentifier = pipelineIdentifier - override val alerts: Seq[Alert] = config.alerts - override val children: Seq[Component] = - allGates ++ - config.queryFeatureHydration ++ - Seq(queryTransformer, config.candidateSource, resultsTransformer) ++ - config.featuresFromCandidateSourceTransformers ++ - decorator.toSeq ++ - config.preFilterFeatureHydrationPhase1 ++ - config.filters ++ - config.postFilterFeatureHydration ++ - config.scorers - } - } - - private case class CandidateWithFeaturesImpl(candidate: Result, features: FeatureMap) - extends CandidateWithFeatures[Result] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala deleted file mode 100644 index f488b341d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineBuilderFactory.scala +++ /dev/null @@ -1,56 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutor -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CandidatePipelineBuilderFactory @Inject() ( - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor, - asyncFeatureMapExecutor: AsyncFeatureMapExecutor, - candidateDecoratorExecutor: CandidateDecoratorExecutor, - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor, - candidateSourceExecutor: CandidateSourceExecutor, - groupResultsExecutor: GroupResultsExecutor, - filterExecutor: FilterExecutor, - gateExecutor: GateExecutor, - statsReceiver: StatsReceiver) { - def get[ - Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Result <: UniversalNoun[Any] - ]: CandidatePipelineBuilder[ - Query, - CandidateSourceQuery, - CandidateSourceResult, - Result - ] = { - new CandidatePipelineBuilder[ - Query, - CandidateSourceQuery, - CandidateSourceResult, - Result - ]( - queryFeatureHydratorExecutor, - asyncFeatureMapExecutor, - candidateDecoratorExecutor, - candidateFeatureHydratorExecutor, - candidateSourceExecutor, - groupResultsExecutor, - filterExecutor, - gateExecutor, - statsReceiver - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala deleted file mode 100644 index bbdcb2d50..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineConfig.scala +++ /dev/null @@ -1,264 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.functional_component.transformer._ -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineConfig -import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam - -sealed trait BaseCandidatePipelineConfig[ - -Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Result <: UniversalNoun[Any]] - extends PipelineConfig { - - val identifier: CandidatePipelineIdentifier - - /** - * A candidate pipeline can fetch query-level features for use within the candidate source. It's - * generally recommended to set a hydrator in the parent recos or mixer pipeline if multiple - * candidate pipelines share the same feature but if a specific query feature hydrator is used - * by one pipeline and you don't want to block the others, you could explicitly set it here. - * If a feature is hydrated both in the parent pipeline or here, this one takes priority. - */ - def queryFeatureHydration: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty - - /** - * For query-level features that are dependent on query-level features from [[queryFeatureHydration]] - */ - def queryFeatureHydrationPhase2: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty - - /** - * When these Params are defined, they will automatically be added as Gates in the pipeline - * by the CandidatePipelineBuilder - * - * The enabled decider param can to be used to quickly disable a Candidate Pipeline via Decider - */ - val enabledDeciderParam: Option[DeciderParam[Boolean]] = None - - /** - * This supported client feature switch param can be used with a Feature Switch to control the - * rollout of a new Candidate Pipeline from dogfood to experiment to production - */ - val supportedClientParam: Option[FSParam[Boolean]] = None - - /** [[Gate]]s that are applied sequentially, the pipeline will only run if all the Gates are open */ - def gates: Seq[BaseGate[Query]] = Seq.empty - - /** - * A pair of transforms to adapt the underlying candidate source to the pipeline's query and result types - * Complex use cases such as those that need access to features should construct their own transformer, but - * for simple use cases, you can pass in an anonymous function. - * @example - * {{{ override val queryTransformer: CandidatePipelineQueryTransformer[Query, CandidateSourceQuery] = { query => - * query.toExampleThrift - * } - * }}} - */ - def queryTransformer: BaseCandidatePipelineQueryTransformer[ - Query, - CandidateSourceQuery - ] - - /** Source for Candidates for this Pipeline */ - def candidateSource: BaseCandidateSource[CandidateSourceQuery, CandidateSourceResult] - - /** - * [[CandidateFeatureTransformer]] allow you to define [[com.twitter.product_mixer.core.feature.Feature]] extraction logic from your [[CandidateSource]] results. - * If your candidate sources return [[com.twitter.product_mixer.core.feature.Feature]]s alongside the candidate that might be useful later on, - * add transformers for constructing feature maps. - * - * @note If multiple transformers extract the same feature, the last one takes priority and is kept. - */ - def featuresFromCandidateSourceTransformers: Seq[ - CandidateFeatureTransformer[CandidateSourceResult] - ] = Seq.empty - - /** - * a result Transformer may throw PipelineFailure for candidates that are malformed and - * should be removed. This should be exceptional behavior, and not a replacement for adding a Filter. - * Complex use cases such as those that need access to features should construct their own transformer, but - * for simple use cases, you can pass in an anonymous function. - * @example - * {{{ override val queryTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Result] = { sourceResult => - * ExampleCandidate(sourceResult.id) - * } - * }}} - * - */ - val resultTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Result] - - /** - * Before filters are run, you can fetch features for each candidate. - * - * Uses Stitch, so you're encouraged to use a working Stitch Adaptor to batch between candidates. - * - * The existing features (from the candidate source) are passed in as an input. You are not expected - * to put them into the resulting feature map yourself - they will be merged for you by the platform. - * - * This API is likely to change when Product Mixer does managed feature hydration - */ - val preFilterFeatureHydrationPhase1: Seq[BaseCandidateFeatureHydrator[Query, Result, _]] = - Seq.empty - - /** - * A second phase of feature hydration that can be run before filtering and after the first phase - * of [[preFilterFeatureHydrationPhase1]]. You are not expected to put them into the resulting - * feature map yourself - they will be merged for you by the platform. - */ - val preFilterFeatureHydrationPhase2: Seq[BaseCandidateFeatureHydrator[Query, Result, _]] = - Seq.empty - - /** A list of filters to apply. Filters will be applied in sequential order. */ - def filters: Seq[Filter[Query, Result]] = Seq.empty - - /** - * After filters are run, you can fetch features for each candidate. - * - * Uses Stitch, so you're encouraged to use a working Stitch Adaptor to batch between candidates. - * - * The existing features (from the candidate source) & pre-filtering are passed in as an input. - * You are not expected to put them into the resulting feature map yourself - - * they will be merged for you by the platform. - * - * This API is likely to change when Product Mixer does managed feature hydration - */ - val postFilterFeatureHydration: Seq[BaseCandidateFeatureHydrator[Query, Result, _]] = Seq.empty - - /** - * Decorators allow for adding Presentations to candidates. While the Presentation can contain any - * arbitrary data, Decorators are often used to add a UrtItemPresentation for URT item support, or - * a UrtModulePresentation for grouping the candidates in a URT module. - */ - val decorator: Option[CandidateDecorator[Query, Result]] = None - - /** - * A candidate pipeline can define a partial function to rescue failures here. They will be treated as failures - * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here). - */ - def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty - - /** - * Scorers for candidates. Scorers are executed in parallel. Order does not matter. - */ - def scorers: Seq[Scorer[Query, Result]] = Seq.empty - - /** - * Alerts can be used to indicate the pipeline's service level objectives. Alerts and - * dashboards will be automatically created based on this information. - */ - val alerts: Seq[Alert] = Seq.empty - - /** - * This method is used by the product mixer framework to build the pipeline. - */ - private[core] final def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - factory: CandidatePipelineBuilderFactory - ): CandidatePipeline[Query] = { - factory.get.build(parentComponentIdentifierStack, this) - } -} - -trait CandidatePipelineConfig[ - -Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Result <: UniversalNoun[Any]] - extends BaseCandidatePipelineConfig[ - Query, - CandidateSourceQuery, - CandidateSourceResult, - Result - ] { - override val gates: Seq[Gate[Query]] = Seq.empty - - override val queryTransformer: CandidatePipelineQueryTransformer[ - Query, - CandidateSourceQuery - ] -} - -trait DependentCandidatePipelineConfig[ - -Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Result <: UniversalNoun[Any]] - extends BaseCandidatePipelineConfig[ - Query, - CandidateSourceQuery, - CandidateSourceResult, - Result - ] - -/** - * Contains [[PipelineStepIdentifier]]s for the Steps that are available for all [[BaseCandidatePipelineConfig]]s - */ -object CandidatePipelineConfig extends PipelineConfigCompanion { - val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates") - val fetchQueryFeaturesStep: PipelineStepIdentifier = PipelineStepIdentifier("FetchQueryFeatures") - val fetchQueryFeaturesPhase2Step: PipelineStepIdentifier = PipelineStepIdentifier( - "FetchQueryFeaturesPhase2") - val candidateSourceStep: PipelineStepIdentifier = PipelineStepIdentifier("CandidateSource") - val preFilterFeatureHydrationPhase1Step: PipelineStepIdentifier = - PipelineStepIdentifier("PreFilterFeatureHydration") - val preFilterFeatureHydrationPhase2Step: PipelineStepIdentifier = - PipelineStepIdentifier("PreFilterFeatureHydrationPhase2") - val filtersStep: PipelineStepIdentifier = PipelineStepIdentifier("Filters") - val postFilterFeatureHydrationStep: PipelineStepIdentifier = - PipelineStepIdentifier("PostFilterFeatureHydration") - val scorersStep: PipelineStepIdentifier = PipelineStepIdentifier("Scorer") - val decoratorStep: PipelineStepIdentifier = PipelineStepIdentifier("Decorator") - val resultStep: PipelineStepIdentifier = PipelineStepIdentifier("Result") - - /** All the steps which are executed by a [[CandidatePipeline]] in the order in which they are run */ - override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq( - gatesStep, - fetchQueryFeaturesStep, - fetchQueryFeaturesPhase2Step, - asyncFeaturesStep(candidateSourceStep), - candidateSourceStep, - asyncFeaturesStep(preFilterFeatureHydrationPhase1Step), - preFilterFeatureHydrationPhase1Step, - asyncFeaturesStep(preFilterFeatureHydrationPhase2Step), - preFilterFeatureHydrationPhase2Step, - asyncFeaturesStep(filtersStep), - filtersStep, - asyncFeaturesStep(postFilterFeatureHydrationStep), - postFilterFeatureHydrationStep, - asyncFeaturesStep(scorersStep), - scorersStep, - asyncFeaturesStep(decoratorStep), - decoratorStep, - resultStep - ) - - override val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set( - candidateSourceStep, - preFilterFeatureHydrationPhase1Step, - preFilterFeatureHydrationPhase2Step, - filtersStep, - postFilterFeatureHydrationStep, - scorersStep, - decoratorStep - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala deleted file mode 100644 index 7729cbcf8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/CandidatePipelineResult.scala +++ /dev/null @@ -1,93 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutorResult -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor - -case class CandidatePipelineResult( - candidateSourceIdentifier: CandidateSourceIdentifier, - gateResult: Option[GateExecutorResult], - queryFeatures: Option[QueryFeatureHydratorExecutor.Result], - queryFeaturesPhase2: Option[QueryFeatureHydratorExecutor.Result], - mergedAsyncQueryFeatures: Option[AsyncFeatureMap], - candidateSourceResult: Option[CandidateSourceExecutorResult[UniversalNoun[Any]]], - preFilterHydrationResult: Option[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]], - preFilterHydrationResultPhase2: Option[ - CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]] - ], - filterResult: Option[FilterExecutorResult[UniversalNoun[Any]]], - postFilterHydrationResult: Option[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]], - candidateDecoratorResult: Option[CandidateDecoratorExecutorResult], - scorersResult: Option[CandidateFeatureHydratorExecutorResult[UniversalNoun[Any]]], - asyncFeatureHydrationResults: Option[AsyncFeatureMapExecutorResults], - failure: Option[PipelineFailure], - result: Option[Seq[CandidateWithDetails]]) - extends PipelineResult[Seq[CandidateWithDetails]] { - - override def withFailure(failure: PipelineFailure): CandidatePipelineResult = - copy(failure = Some(failure)) - - override def withResult( - result: Seq[CandidateWithDetails] - ): CandidatePipelineResult = copy(result = Some(result)) - - override val resultSize: Int = result.map(PipelineResult.resultSize).getOrElse(0) -} - -private[candidate] object IntermediateCandidatePipelineResult { - def empty[Candidate <: UniversalNoun[Any]]( - candidateSourceIdentifier: CandidateSourceIdentifier - ): IntermediateCandidatePipelineResult[Candidate] = { - IntermediateCandidatePipelineResult( - CandidatePipelineResult( - candidateSourceIdentifier = candidateSourceIdentifier, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None - ), - None - ) - } -} - -private[candidate] case class IntermediateCandidatePipelineResult[Candidate <: UniversalNoun[Any]]( - underlyingResult: CandidatePipelineResult, - featureMaps: Option[Map[Candidate, FeatureMap]]) - extends PipelineResult[Seq[CandidateWithDetails]] { - override val failure: Option[PipelineFailure] = underlyingResult.failure - override val result: Option[Seq[CandidateWithDetails]] = underlyingResult.result - - override def withFailure( - failure: PipelineFailure - ): IntermediateCandidatePipelineResult[Candidate] = - copy(underlyingResult = underlyingResult.withFailure(failure)) - - override def withResult( - result: Seq[CandidateWithDetails] - ): IntermediateCandidatePipelineResult[Candidate] = - copy(underlyingResult = underlyingResult.withResult(result)) - - override def resultSize(): Int = underlyingResult.resultSize -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala deleted file mode 100644 index 73baa8abb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/PassthroughCandidatePipelineConfig.scala +++ /dev/null @@ -1,47 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.product_mixer.core.functional_component.candidate_source.PassthroughCandidateSource -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateExtractor -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -object PassthroughCandidatePipelineConfig { - - /** - * Build a [[PassthroughCandidatePipelineConfig]] with a [[PassthroughCandidateSource]] built from - * a [[CandidateExtractor]] - */ - def apply[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - identifier: CandidatePipelineIdentifier, - extractor: CandidateExtractor[Query, Candidate], - decorator: Option[CandidateDecorator[Query, Candidate]] = None - ): PassthroughCandidatePipelineConfig[Query, Candidate] = { - - // Renaming variables to keep the interface clean, but avoid naming collisions when creating - // the anonymous class. - val _identifier = identifier - val _extractor = extractor - val _decorator = decorator - - new PassthroughCandidatePipelineConfig[Query, Candidate] { - override val identifier = _identifier - override val candidateSource = - PassthroughCandidateSource(CandidateSourceIdentifier(_identifier.name), _extractor) - override val decorator = _decorator - } - } -} - -trait PassthroughCandidatePipelineConfig[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends CandidatePipelineConfig[Query, Query, Candidate, Candidate] { - - override val queryTransformer: CandidatePipelineQueryTransformer[Query, Query] = identity - - override val resultTransformer: CandidatePipelineResultsTransformer[Candidate, Candidate] = - identity -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala deleted file mode 100644 index 2829e8334..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate/StaticCandidatePipelineConfig.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.candidate - -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.candidate_source.StaticCandidateSource -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator - -object StaticCandidatePipelineConfig { - - /** - * Build a [[StaticCandidatePipelineConfig]] with a [[CandidateSource]] that returns the [[candidate]] - */ - def apply[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - identifier: CandidatePipelineIdentifier, - candidate: Candidate, - decorator: Option[CandidateDecorator[Query, Candidate]] = None - ): StaticCandidatePipelineConfig[Query, Candidate] = { - - // Renaming variables to keep the interface clean, but avoid naming collisions when creating - // the anonymous class. - val _identifier = identifier - val _candidate = candidate - val _decorator = decorator - - new StaticCandidatePipelineConfig[Query, Candidate] { - override val identifier = _identifier - override val candidate = _candidate - override val decorator = _decorator - } - } -} - -trait StaticCandidatePipelineConfig[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends CandidatePipelineConfig[Query, Unit, Unit, Candidate] { - - val candidate: Candidate - - override def candidateSource: CandidateSource[Unit, Unit] = StaticCandidateSource[Unit]( - identifier = CandidateSourceIdentifier(identifier.name), - result = Seq(())) - - override val queryTransformer: CandidatePipelineQueryTransformer[Query, Unit] = _ => Unit - - override val resultTransformer: CandidatePipelineResultsTransformer[Unit, Candidate] = _ => - candidate -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD deleted file mode 100644 index bbda52b47..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/BUILD +++ /dev/null @@ -1,62 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala deleted file mode 100644 index 645e20bea..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipeline.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.mixer - -import com.twitter.product_mixer.core.model.common.identifier.MixerPipelineIdentifier -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Arrow - -/** - * A Mixer Pipeline - * - * This is an abstract class, as we only construct these via the [[MixerPipelineBuilder]]. - * - * A [[MixerPipeline]] is capable of processing requests (queries) and returning responses (results) - * in the correct format to directly send to users. - * - * @tparam Query the domain model for the query or request - * @tparam Result the final marshalled result type - */ -abstract class MixerPipeline[Query <: PipelineQuery, Result] private[mixer] - extends Pipeline[Query, Result] { - override private[core] val config: MixerPipelineConfig[Query, _, Result] - override val arrow: Arrow[Query, MixerPipelineResult[Result]] - override val identifier: MixerPipelineIdentifier -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala deleted file mode 100644 index 4cdb44552..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilder.scala +++ /dev/null @@ -1,582 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.mixer - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.MixerPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.InvalidStepStateException -import com.twitter.product_mixer.core.pipeline.PipelineBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipeline -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor -import com.twitter.stitch.Arrow -import com.twitter.util.logging.Logging - -/** - * MixerPipelineBuilder builds [[MixerPipeline]]s from [[MixerPipelineConfig]]s. - * - * You should inject a [[MixerPipelineBuilderFactory]] and call `.get` to build these. - * - * @see [[MixerPipelineConfig]] for the description of the type parameters - */ -class MixerPipelineBuilder[Query <: PipelineQuery, DomainResultType <: HasMarshalling, Result]( - candidatePipelineExecutor: CandidatePipelineExecutor, - gateExecutor: GateExecutor, - selectorExecutor: SelectorExecutor, - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor, - asyncFeatureMapExecutor: AsyncFeatureMapExecutor, - domainMarshallerExecutor: DomainMarshallerExecutor, - transportMarshallerExecutor: TransportMarshallerExecutor, - pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor, - candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory, - override val statsReceiver: StatsReceiver) - extends PipelineBuilder[Query] - with Logging { - - override type UnderlyingResultType = Result - override type PipelineResultType = MixerPipelineResult[Result] - - def qualityFactorStep( - qualityFactorStatus: QualityFactorStatus - ): Step[Query, QualityFactorExecutorResult] = - new Step[Query, QualityFactorExecutorResult] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.qualityFactorStep - - override def executorArrow: Arrow[Query, QualityFactorExecutorResult] = - Arrow - .map[Query, QualityFactorExecutorResult] { _ => - QualityFactorExecutorResult( - pipelineQualityFactors = - qualityFactorStatus.qualityFactorByPipeline.mapValues(_.currentValue) - ) - } - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): Query = query - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: QualityFactorExecutorResult - ): MixerPipelineResult[Result] = - previousPipelineResult.copy(qualityFactorResult = Some(executorResult)) - - override def queryUpdater( - query: Query, - executorResult: QualityFactorExecutorResult - ): Query = { - query match { - case queryWithQualityFactor: HasQualityFactorStatus => - queryWithQualityFactor - .withQualityFactorStatus( - queryWithQualityFactor.qualityFactorStatus.getOrElse(QualityFactorStatus.empty) ++ - qualityFactorStatus - ).asInstanceOf[Query] - case _ => - query - } - } - } - - def gatesStep( - gates: Seq[Gate[Query]], - context: Executor.Context - ): Step[Query, GateExecutorResult] = new Step[Query, GateExecutorResult] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.gatesStep - - override def executorArrow: Arrow[Query, GateExecutorResult] = - gateExecutor.arrow(gates, context) - - override def inputAdaptor(query: Query, previousResult: MixerPipelineResult[Result]): Query = - query - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: GateExecutorResult - ): MixerPipelineResult[Result] = - previousPipelineResult.copy(gateResult = Some(executorResult)) - } - - def fetchQueryFeaturesStep( - queryFeatureHydrators: Seq[QueryFeatureHydrator[Query]], - stepIdentifier: PipelineStepIdentifier, - updater: ResultUpdater[MixerPipelineResult[Result], QueryFeatureHydratorExecutor.Result], - context: Executor.Context - ): Step[Query, QueryFeatureHydratorExecutor.Result] = - new Step[Query, QueryFeatureHydratorExecutor.Result] { - override def identifier: PipelineStepIdentifier = stepIdentifier - - override def executorArrow: Arrow[Query, QueryFeatureHydratorExecutor.Result] = - queryFeatureHydratorExecutor.arrow( - queryFeatureHydrators, - MixerPipelineConfig.stepsAsyncFeatureHydrationCanBeCompletedBy, - context) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): Query = query - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: QueryFeatureHydratorExecutor.Result - ): MixerPipelineResult[Result] = - updater(previousPipelineResult, executorResult) - - override def queryUpdater( - query: Query, - executorResult: QueryFeatureHydratorExecutor.Result - ): Query = - query - .withFeatureMap( - query.features - .getOrElse(FeatureMap.empty) ++ executorResult.featureMap).asInstanceOf[Query] - } - - def asyncFeaturesStep( - stepToHydrateFor: PipelineStepIdentifier, - context: Executor.Context - ): Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - new Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] { - override def identifier: PipelineStepIdentifier = - MixerPipelineConfig.asyncFeaturesStep(stepToHydrateFor) - - override def executorArrow: Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - asyncFeatureMapExecutor.arrow( - stepToHydrateFor, - identifier, - context - ) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): AsyncFeatureMap = - previousResult.mergedAsyncQueryFeatures - .getOrElse( - throw InvalidStepStateException(identifier, "MergedAsyncQueryFeatures") - ) - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: AsyncFeatureMapExecutorResults - ): MixerPipelineResult[Result] = previousPipelineResult.copy( - asyncFeatureHydrationResults = previousPipelineResult.asyncFeatureHydrationResults match { - case Some(existingResults) => Some(existingResults ++ executorResult) - case None => Some(executorResult) - }) - - override def queryUpdater( - query: Query, - executorResult: AsyncFeatureMapExecutorResults - ): Query = - if (executorResult.featureMapsByStep - .getOrElse(stepToHydrateFor, FeatureMap.empty).isEmpty) { - query - } else { - query - .withFeatureMap( - query.features - .getOrElse(FeatureMap.empty) ++ executorResult.featureMapsByStep( - stepToHydrateFor)).asInstanceOf[Query] - } - } - - def candidatePipelinesStep( - candidatePipelines: Seq[CandidatePipeline[Query]], - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] = - new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.candidatePipelinesStep - - override def executorArrow: Arrow[CandidatePipeline.Inputs[ - Query - ], CandidatePipelineExecutorResult] = - candidatePipelineExecutor - .arrow( - candidatePipelines, - defaultFailOpenPolicy, - failOpenPolicies, - qualityFactorObserverByPipeline, - context - ) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): CandidatePipeline.Inputs[Query] = CandidatePipeline.Inputs[Query](query, Seq.empty) - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: CandidatePipelineExecutorResult - ): MixerPipelineResult[Result] = - previousPipelineResult.copy(candidatePipelineResults = Some(executorResult)) - - override def queryUpdater( - query: Query, - executorResult: CandidatePipelineExecutorResult - ): Query = { - val updatedFeatureMap = query.features - .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap - query - .withFeatureMap(updatedFeatureMap).asInstanceOf[Query] - } - } - - def dependentCandidatePipelinesStep( - candidatePipelines: Seq[CandidatePipeline[Query]], - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] = - new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] { - override def identifier: PipelineStepIdentifier = - MixerPipelineConfig.dependentCandidatePipelinesStep - - override def executorArrow: Arrow[CandidatePipeline.Inputs[ - Query - ], CandidatePipelineExecutorResult] = - candidatePipelineExecutor - .arrow( - candidatePipelines, - defaultFailOpenPolicy, - failOpenPolicies, - qualityFactorObserverByPipeline, - context - ) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): CandidatePipeline.Inputs[Query] = { - val previousCandidates = previousResult.candidatePipelineResults - .getOrElse { - throw InvalidStepStateException(identifier, "Candidates") - }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty)) - CandidatePipeline.Inputs[Query](query, previousCandidates) - } - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: CandidatePipelineExecutorResult - ): MixerPipelineResult[Result] = - previousPipelineResult.copy(dependentCandidatePipelineResults = Some(executorResult)) - - override def queryUpdater( - query: Query, - executorResult: CandidatePipelineExecutorResult - ): Query = { - val updatedFeatureMap = query.features - .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap - query - .withFeatureMap(updatedFeatureMap).asInstanceOf[Query] - } - } - - def resultSelectorsStep( - selectors: Seq[Selector[Query]], - context: Executor.Context - ): Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = - new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.resultSelectorsStep - - override def executorArrow: Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = - selectorExecutor.arrow(selectors, context) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): SelectorExecutor.Inputs[Query] = { - val candidates = previousResult.candidatePipelineResults - .getOrElse { - throw InvalidStepStateException(identifier, "Candidates") - }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty)) - - val dependentCandidates = - previousResult.dependentCandidatePipelineResults - .getOrElse { - throw InvalidStepStateException(identifier, "DependentCandidates") - }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty)) - - SelectorExecutor.Inputs( - query = query, - candidatesWithDetails = candidates ++ dependentCandidates - ) - } - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: SelectorExecutorResult - ): MixerPipelineResult[Result] = - previousPipelineResult.copy(resultSelectorResults = Some(executorResult)) - } - - def domainMarshallingStep( - domainMarshaller: DomainMarshaller[Query, DomainResultType], - context: Executor.Context - ): Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[ - DomainResultType - ]] = - new Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[ - DomainResultType - ]] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.domainMarshallerStep - - override def executorArrow: Arrow[ - DomainMarshallerExecutor.Inputs[Query], - DomainMarshallerExecutor.Result[DomainResultType] - ] = - domainMarshallerExecutor.arrow(domainMarshaller, context) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): DomainMarshallerExecutor.Inputs[Query] = { - val selectorResults = previousResult.resultSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "SelectorResults") - } - - DomainMarshallerExecutor.Inputs( - query = query, - candidatesWithDetails = selectorResults.selectedCandidates - ) - } - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: DomainMarshallerExecutor.Result[DomainResultType] - ): MixerPipelineResult[Result] = previousPipelineResult.copy( - domainMarshallerResults = Some(executorResult) - ) - } - - def resultSideEffectsStep( - sideEffects: Seq[PipelineResultSideEffect[Query, DomainResultType]], - context: Executor.Context - ): Step[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] = new Step[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.resultSideEffectsStep - - override def executorArrow: Arrow[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] = pipelineResultSideEffectExecutor.arrow(sideEffects, context) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): PipelineResultSideEffect.Inputs[Query, DomainResultType] = { - - val selectorResults = previousResult.resultSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "SelectorResults") - } - - val domainMarshallerResults = previousResult.domainMarshallerResults.getOrElse { - throw InvalidStepStateException(identifier, "DomainMarshallerResults") - } - - PipelineResultSideEffect.Inputs[Query, DomainResultType]( - query = query, - selectedCandidates = selectorResults.selectedCandidates, - remainingCandidates = selectorResults.remainingCandidates, - droppedCandidates = selectorResults.droppedCandidates, - response = domainMarshallerResults.result.asInstanceOf[DomainResultType] - ) - } - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: PipelineResultSideEffectExecutor.Result - ): MixerPipelineResult[Result] = - previousPipelineResult.copy(resultSideEffectResults = Some(executorResult)) - } - - def transportMarshallingStep( - transportMarshaller: TransportMarshaller[DomainResultType, Result], - context: Executor.Context - ): Step[ - TransportMarshallerExecutor.Inputs[DomainResultType], - TransportMarshallerExecutor.Result[Result] - ] = new Step[TransportMarshallerExecutor.Inputs[ - DomainResultType - ], TransportMarshallerExecutor.Result[Result]] { - override def identifier: PipelineStepIdentifier = MixerPipelineConfig.transportMarshallerStep - - override def executorArrow: Arrow[TransportMarshallerExecutor.Inputs[ - DomainResultType - ], TransportMarshallerExecutor.Result[Result]] = - transportMarshallerExecutor.arrow(transportMarshaller, context) - - override def inputAdaptor( - query: Query, - previousResult: MixerPipelineResult[Result] - ): TransportMarshallerExecutor.Inputs[DomainResultType] = { - val domainMarshallingResults = previousResult.domainMarshallerResults.getOrElse { - throw InvalidStepStateException(identifier, "DomainMarshallerResults") - } - - // Since the PipelineResult just uses HasMarshalling - val domainResult = domainMarshallingResults.result.asInstanceOf[DomainResultType] - - TransportMarshallerExecutor.Inputs(domainResult) - } - - override def resultUpdater( - previousPipelineResult: MixerPipelineResult[Result], - executorResult: TransportMarshallerExecutor.Result[Result] - ): MixerPipelineResult[Result] = previousPipelineResult.copy( - transportMarshallerResults = Some(executorResult), - result = Some(executorResult.result) - ) - } - - def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - config: MixerPipelineConfig[Query, DomainResultType, Result] - ): MixerPipeline[Query, Result] = { - - val pipelineIdentifier = config.identifier - - val context = Executor.Context( - PipelineFailureClassifier( - config.failureClassifier.orElse(StoppedGateException.classifier(ProductDisabled))), - parentComponentIdentifierStack.push(pipelineIdentifier) - ) - - val qualityFactorStatus: QualityFactorStatus = - QualityFactorStatus.build(config.qualityFactorConfigs) - - val qualityFactorObserverByPipeline = - qualityFactorStatus.qualityFactorByPipeline.mapValues { qualityFactor => - qualityFactor.buildObserver() - } - - buildGaugesForQualityFactor(pipelineIdentifier, qualityFactorStatus, statsReceiver) - - val candidatePipelines: Seq[CandidatePipeline[Query]] = config.candidatePipelines.map { - pipelineConfig: CandidatePipelineConfig[Query, _, _, _] => - pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory) - } - - val dependentCandidatePipelines: Seq[CandidatePipeline[Query]] = - config.dependentCandidatePipelines.map { - pipelineConfig: DependentCandidatePipelineConfig[Query, _, _, _] => - pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory) - } - - val builtSteps = Seq( - qualityFactorStep(qualityFactorStatus), - gatesStep(config.gates, context), - fetchQueryFeaturesStep( - config.fetchQueryFeatures, - MixerPipelineConfig.fetchQueryFeaturesStep, - (previousPipelineResult, executorResult) => - previousPipelineResult.copy(queryFeatures = Some(executorResult)), - context - ), - fetchQueryFeaturesStep( - config.fetchQueryFeaturesPhase2, - MixerPipelineConfig.fetchQueryFeaturesPhase2Step, - (previousPipelineResult, executorResult) => - previousPipelineResult.copy( - queryFeaturesPhase2 = Some(executorResult), - mergedAsyncQueryFeatures = Some( - previousPipelineResult.queryFeatures - .getOrElse(throw InvalidStepStateException( - MixerPipelineConfig.fetchQueryFeaturesPhase2Step, - "QueryFeatures")) - .asyncFeatureMap ++ executorResult.asyncFeatureMap) - ), - context - ), - asyncFeaturesStep(MixerPipelineConfig.candidatePipelinesStep, context), - candidatePipelinesStep( - candidatePipelines, - config.defaultFailOpenPolicy, - config.failOpenPolicies, - qualityFactorObserverByPipeline, - context), - asyncFeaturesStep(MixerPipelineConfig.dependentCandidatePipelinesStep, context), - dependentCandidatePipelinesStep( - dependentCandidatePipelines, - config.defaultFailOpenPolicy, - config.failOpenPolicies, - qualityFactorObserverByPipeline, - context), - asyncFeaturesStep(MixerPipelineConfig.resultSelectorsStep, context), - resultSelectorsStep(config.resultSelectors, context), - domainMarshallingStep(config.domainMarshaller, context), - asyncFeaturesStep(MixerPipelineConfig.resultSideEffectsStep, context), - resultSideEffectsStep(config.resultSideEffects, context), - transportMarshallingStep(config.transportMarshaller, context) - ) - - val finalArrow = buildCombinedArrowFromSteps( - steps = builtSteps, - context = context, - initialEmptyResult = MixerPipelineResult.empty, - stepsInOrderFromConfig = MixerPipelineConfig.stepsInOrder - ) - - val configFromBuilder = config - new MixerPipeline[Query, Result] { - override private[core] val config: MixerPipelineConfig[Query, _, Result] = configFromBuilder - override val arrow: Arrow[Query, MixerPipelineResult[Result]] = finalArrow - override val identifier: MixerPipelineIdentifier = pipelineIdentifier - override val alerts: Seq[Alert] = config.alerts - override val children: Seq[Component] = - config.gates ++ - config.fetchQueryFeatures ++ - candidatePipelines ++ - dependentCandidatePipelines ++ - config.resultSideEffects ++ - Seq(config.domainMarshaller, config.transportMarshaller) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala deleted file mode 100644 index 4b8ebacbc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineBuilderFactory.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.mixer - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class MixerPipelineBuilderFactory @Inject() ( - candidatePipelineExecutor: CandidatePipelineExecutor, - gateExecutor: GateExecutor, - selectorExecutor: SelectorExecutor, - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor, - asyncFeatureMapExecutor: AsyncFeatureMapExecutor, - domainMarshallerExecutor: DomainMarshallerExecutor, - transportMarshallerExecutor: TransportMarshallerExecutor, - pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor, - candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory, - statsReceiver: StatsReceiver) { - def get[ - Query <: PipelineQuery, - DomainResultType <: HasMarshalling, - Result - ]: MixerPipelineBuilder[Query, DomainResultType, Result] = { - new MixerPipelineBuilder[Query, DomainResultType, Result]( - candidatePipelineExecutor, - gateExecutor, - selectorExecutor, - queryFeatureHydratorExecutor, - asyncFeatureMapExecutor, - domainMarshallerExecutor, - transportMarshallerExecutor, - pipelineResultSideEffectExecutor, - candidatePipelineBuilderFactory, - statsReceiver - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala deleted file mode 100644 index 238533143..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineConfig.scala +++ /dev/null @@ -1,175 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.mixer - -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.QueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.MixerPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.PipelineConfig -import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig - -/** - * This is the configuration necessary to generate a Mixer Pipeline. Product code should create a - * MixerPipelineConfig, and then use a MixerPipelineBuilder to get the final MixerPipeline which can - * process requests. - * - * @tparam Query - The domain model for the query or request - * @tparam UnmarshalledResultType - The result type of the pipeline, but before marshalling to a wire protocol like URT - * @tparam Result - The final result that will be served to users - */ -trait MixerPipelineConfig[Query <: PipelineQuery, UnmarshalledResultType <: HasMarshalling, Result] - extends PipelineConfig { - - override val identifier: MixerPipelineIdentifier - - /** - * Mixer Pipeline Gates will be executed before any other step (including retrieval from candidate - * pipelines). They're executed sequentially, and any "Stop" result will prevent pipeline execution. - */ - def gates: Seq[Gate[Query]] = Seq.empty - - /** - * A mixer pipeline can fetch query-level features before candidate pipelines are executed. - */ - def fetchQueryFeatures: Seq[QueryFeatureHydrator[Query]] = Seq.empty - - /** - * For query-level features that are dependent on query-level features from [[fetchQueryFeatures]] - */ - def fetchQueryFeaturesPhase2: Seq[QueryFeatureHydrator[Query]] = Seq.empty - - /** - * Candidate pipelines retrieve candidates for possible inclusion in the result - */ - def candidatePipelines: Seq[CandidatePipelineConfig[Query, _, _, _]] - - /** - * Dependent candidate pipelines to retrieve candidates that depend on the result of [[candidatePipelines]] - * [[DependentCandidatePipelineConfig]] have access to the list of previously retrieved & decorated - * candidates for use in constructing the query object. - */ - def dependentCandidatePipelines: Seq[DependentCandidatePipelineConfig[Query, _, _, _]] = Seq.empty - - /** - * [[defaultFailOpenPolicy]] is the [[FailOpenPolicy]] that will be applied to any candidate - * pipeline that isn't in the [[failOpenPolicies]] map. By default Candidate Pipelines will fail - * open for Closed Gates only. - */ - def defaultFailOpenPolicy: FailOpenPolicy = FailOpenPolicy(Set(ClosedGate)) - - /** - * [[failOpenPolicies]] associates [[FailOpenPolicy]]s to specific candidate pipelines using - * [[CandidatePipelineIdentifier]]. - * - * @note these [[FailOpenPolicy]]s override the [[defaultFailOpenPolicy]] for a mapped - * Candidate Pipeline. - */ - def failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy] = Map.empty - - /** - ** [[qualityFactorConfigs]] associates [[QualityFactorConfig]]s to specific candidate pipelines - * using [[CandidatePipelineIdentifier]]. - */ - def qualityFactorConfigs: Map[CandidatePipelineIdentifier, QualityFactorConfig] = - Map.empty - - /** - * Selectors are executed in sequential order to combine the candidates into a result - */ - def resultSelectors: Seq[Selector[Query]] - - /** - * Mixer result side effects that are executed after selection and domain marshalling - */ - def resultSideEffects: Seq[PipelineResultSideEffect[Query, UnmarshalledResultType]] = Seq() - - /** - * Domain marshaller transforms the selections into the model expected by the marshaller - */ - def domainMarshaller: DomainMarshaller[Query, UnmarshalledResultType] - - /** - * Transport marshaller transforms the model into our line-level API like URT or JSON - */ - def transportMarshaller: TransportMarshaller[UnmarshalledResultType, Result] - - /** - * A pipeline can define a partial function to rescue failures here. They will be treated as failures - * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here). - */ - def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty - - /** - * Alert can be used to indicate the pipeline's service level objectives. Alerts and - * dashboards will be automatically created based on this information. - */ - val alerts: Seq[Alert] = Seq.empty - - /** - * This method is used by the product mixer framework to build the pipeline. - */ - private[core] final def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - builder: MixerPipelineBuilderFactory - ): MixerPipeline[Query, Result] = - builder.get.build(parentComponentIdentifierStack, this) -} - -object MixerPipelineConfig extends PipelineConfigCompanion { - val qualityFactorStep: PipelineStepIdentifier = PipelineStepIdentifier("QualityFactor") - val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates") - val fetchQueryFeaturesStep: PipelineStepIdentifier = PipelineStepIdentifier("FetchQueryFeatures") - val fetchQueryFeaturesPhase2Step: PipelineStepIdentifier = - PipelineStepIdentifier("FetchQueryFeaturesPhase2") - val candidatePipelinesStep: PipelineStepIdentifier = PipelineStepIdentifier("CandidatePipelines") - val dependentCandidatePipelinesStep: PipelineStepIdentifier = - PipelineStepIdentifier("DependentCandidatePipelines") - val resultSelectorsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSelectors") - val domainMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier("DomainMarshaller") - val resultSideEffectsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSideEffects") - val transportMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier( - "TransportMarshaller") - - /** All the Steps which are executed by a [[MixerPipeline]] in the order in which they are run */ - override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq( - qualityFactorStep, - gatesStep, - fetchQueryFeaturesStep, - fetchQueryFeaturesPhase2Step, - asyncFeaturesStep(candidatePipelinesStep), - candidatePipelinesStep, - asyncFeaturesStep(dependentCandidatePipelinesStep), - dependentCandidatePipelinesStep, - asyncFeaturesStep(resultSelectorsStep), - resultSelectorsStep, - domainMarshallerStep, - asyncFeaturesStep(resultSideEffectsStep), - resultSideEffectsStep, - transportMarshallerStep - ) - - /** - * All the Steps which an [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator AsyncHydrator]] - * can be configured to [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator.hydrateBefore hydrateBefore]] - */ - override val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set( - candidatePipelinesStep, - dependentCandidatePipelinesStep, - resultSelectorsStep, - resultSideEffectsStep - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala deleted file mode 100644 index 1ddf00bd4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer/MixerPipelineResult.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.mixer - -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor - -/** - * A [[MixerPipelineResult]] includes both the user-visible [[PipelineResult]] and all the - * Execution details possible - intermediate results, what components did, etc. - */ -case class MixerPipelineResult[Result]( - qualityFactorResult: Option[QualityFactorExecutorResult], - gateResult: Option[GateExecutorResult], - queryFeatures: Option[QueryFeatureHydratorExecutor.Result], - queryFeaturesPhase2: Option[QueryFeatureHydratorExecutor.Result], - mergedAsyncQueryFeatures: Option[AsyncFeatureMap], - candidatePipelineResults: Option[CandidatePipelineExecutorResult], - dependentCandidatePipelineResults: Option[CandidatePipelineExecutorResult], - resultSelectorResults: Option[SelectorExecutorResult], - domainMarshallerResults: Option[DomainMarshallerExecutor.Result[HasMarshalling]], - resultSideEffectResults: Option[PipelineResultSideEffectExecutor.Result], - asyncFeatureHydrationResults: Option[AsyncFeatureMapExecutorResults], - transportMarshallerResults: Option[TransportMarshallerExecutor.Result[Result]], - failure: Option[PipelineFailure], - result: Option[Result]) - extends PipelineResult[Result] { - - override def withFailure(failure: PipelineFailure): PipelineResult[Result] = - copy(failure = Some(failure)) - - override def withResult(result: Result): PipelineResult[Result] = copy(result = Some(result)) - - /** - * resultSize is calculated based on the selector results rather than the marshalled results. The - * structure of the marshalled format is unknown, making operating on selector results more - * convenient. This will implicitly excluded cursors built during marshalling but cursors don't - * contribute to the result size anyway. - */ - override val resultSize: Int = - resultSelectorResults.map(_.selectedCandidates).map(PipelineResult.resultSize).getOrElse(0) -} - -object MixerPipelineResult { - def empty[A]: MixerPipelineResult[A] = MixerPipelineResult( - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD deleted file mode 100644 index 68dfa5b8f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala deleted file mode 100644 index eef0db9b4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailure.scala +++ /dev/null @@ -1,49 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.pipeline_failure - -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import scala.util.control.NoStackTrace - -/** - * Pipeline Failures represent pipeline requests that were not able to complete. - * - * A pipeline result will always define either a result or a failure. - * - * The reason field should not be displayed to end-users, and is free to change over time. - * It should always be free of private user data such that we can log it. - * - * The pipeline can classify it's own failures into categories (timeouts, invalid arguments, - * rate limited, etc) such that the caller can choose how to handle it. - * - * @note [[componentStack]] should only be set by the product mixer framework, - * it should **NOT** be set when making a [[PipelineFailure]] - */ -@JsonSerialize(using = classOf[PipelineFailureSerializer]) -case class PipelineFailure( - category: PipelineFailureCategory, - reason: String, - underlying: Option[Throwable] = None, - componentStack: Option[ComponentIdentifierStack] = None) - extends Exception( - "PipelineFailure(" + - s"category = $category, " + - s"reason = $reason, " + - s"underlying = $underlying, " + - s"componentStack = $componentStack)", - underlying.orNull - ) { - override def toString: String = getMessage - - /** Returns an updated copy of this [[PipelineFailure]] with the same exception stacktrace */ - def copy( - category: PipelineFailureCategory = this.category, - reason: String = this.reason, - underlying: Option[Throwable] = this.underlying, - componentStack: Option[ComponentIdentifierStack] = this.componentStack - ): PipelineFailure = { - val newPipelineFailure = - new PipelineFailure(category, reason, underlying, componentStack) with NoStackTrace - newPipelineFailure.setStackTrace(this.getStackTrace) - newPipelineFailure - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala deleted file mode 100644 index f0cb57fe0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureCategory.scala +++ /dev/null @@ -1,190 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.pipeline_failure - -/** - * Failures are grouped into categories based on which party is 'responsible' for the issue. This - * is important for generating accurate SLOs and ensuring that the correct team is alerted. - */ -sealed trait PipelineFailureCategory { - val categoryName: String - val failureName: String -} - -/** - * Client Failures are failures where the client is deemed responsible for the issue. Such as by - * issuing an invalid request or not having the right permissions. - * - * A failure might belong in this category if it relates to behaviour on the client and is not - * actionable by the team which owns the product. - */ -trait ClientFailure extends PipelineFailureCategory { - override val categoryName: String = "ClientFailure" -} - -/** - * The requested product is disabled so the request cannot be served. - */ -case object ProductDisabled extends ClientFailure { - override val failureName: String = "ProductDisabled" -} - -/** - * The request was deemed invalid by this or a backing service. - */ -case object BadRequest extends ClientFailure { - override val failureName: String = "BadRequest" -} - -/** - * Credentials proving the identity of the caller were missing, not trusted, or expired. - * For example, an auth cookie might be expired and in need of refreshing. - * - * Do not confuse this with Authorization, where the credentials are believed but not allowed to perform the operation. - */ -case object Authentication extends ClientFailure { - override val failureName: String = "Authentication" -} - -/** - * The operation was forbidden (often, but not always, by a Strato access control policy). - * - * Do not confuse this with Authentication, where the given credentials were missing, not trusted, or expired. - */ -case object Unauthorized extends ClientFailure { - override val failureName: String = "Unauthorized" -} - -/** - * The operation returned a Not Found response. - */ -case object NotFound extends ClientFailure { - override val failureName: String = "NotFound" -} - -/** - * An invalid input is included in a cursor field. - */ -case object MalformedCursor extends ClientFailure { - override val failureName: String = "MalformedCursor" -} - -/** - * The operation did not succeed due to a closed gate - */ -case object ClosedGate extends ClientFailure { - override val failureName: String = "ClosedGate" -} - -/** - * Server Failures are failures for which the owner of the product is responsible. Typically this - * means the request was valid but an issue within Product Mixer or a dependent service prevented - * it from succeeding. - * - * Server Failures contribute to the success rate SLO for the product. - */ -trait ServerFailure extends PipelineFailureCategory { - override val categoryName: String = "ServerFailure" -} - -/** - * Unclassified failures occur when product code throws an exception that Product Mixer does not - * know how to classify. - * - * They can be used in failOpen policies, etc - but it's always preferred to instead add additional - * classification logic and to keep Unclassified failures at 0. - */ -case object UncategorizedServerFailure extends ServerFailure { - override val failureName: String = "UncategorizedServerFailure" -} - -/** - * A hydrator or transformer returned a misconfigured feature map, this indicates a customer - * configuration error. The owner of the component should make sure the hydrator always returns a - * [[FeatureMap]] with the all features defined in the hydrator also set in the map, it should not have - * any unregistered features nor should registered features be absent. - */ -case object MisconfiguredFeatureMapFailure extends ServerFailure { - override val failureName: String = "MisconfiguredFeatureMapFailure" -} - -/** - * A PipelineSelector returned an invalid ComponentIdentifier. - * - * A pipeline selector should choose the identifier of a pipeline that is contained by the 'pipelines' - * sequence of the ProductPipelineConfig. - */ -case object InvalidPipelineSelected extends ServerFailure { - override val failureName: String = "InvalidPipelineSelected" -} - -/** - * Failures that occur when product code reaches an unexpected or otherwise illegal state. - */ -case object IllegalStateFailure extends ServerFailure { - override val failureName: String = "IllegalStateFailure" -} - -/** - * An unexpected candidate was returned in a candidate source that was unable to be transformed. - */ -case object UnexpectedCandidateResult extends ServerFailure { - override val failureName: String = "UnexpectedCandidateResult" -} - -/** - * An unexpected Candidate was returned in a marshaller - */ -case object UnexpectedCandidateInMarshaller extends ServerFailure { - override val failureName: String = "UnexpectedCandidateInMarshaller" -} - -/** - * Pipeline execution failed due to an incorrectly configured quality factor (e.g, accessing - * quality factor state for a pipeline that does not have quality factor configured) - */ -case object MisconfiguredQualityFactor extends ServerFailure { - override val failureName: String = "MisconfiguredQualityFactor" -} - -/** - * Pipeline execution failed due to an incorrectly configured decorator (e.g, decorator - * returned the wrong type or tried to decorate an already decorated candidate) - */ -case object MisconfiguredDecorator extends ServerFailure { - override val failureName: String = "MisconfiguredDecorator" -} - -/** - * Candidate Source Pipeline execution failed due to a timeout. - */ -case object CandidateSourceTimeout extends ServerFailure { - override val failureName: String = "CandidateSourceTimeout" -} - -/** - * Platform Failures are issues in the core Product Mixer logic itself which prevent a pipeline from - * properly executing. These failures are the responsibility of the Product Mixer team. - */ -trait PlatformFailure extends PipelineFailureCategory { - override val categoryName: String = "PlatformFailure" -} - -/** - * Pipeline execution failed due to an unexpected error in Product Mixer. - * - * ExecutionFailed indicates a bug with the core Product Mixer execution logic rather than with a - * specific product. For example, a bug in PipelineBuilder leading to us returning a - * ProductPipelineResult that neither succeeded nor failed. - */ -case object ExecutionFailed extends PlatformFailure { - override val failureName: String = "ExecutionFailed" -} - -/** - * Pipeline execution failed due to a feature hydration failure. - * - * FeatureHydrationFailed indicates that the underlying hydration for a feature defined in a hydrator - * failed (e.g, typically from a RPC call failing). - */ -case object FeatureHydrationFailed extends PlatformFailure { - override val failureName: String = "FeatureHydrationFailed" -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala deleted file mode 100644 index 449542ba9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureClassifier.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.pipeline_failure - -/** Represents a way to classify a given [[Throwable]] to a [[PipelineFailure]] */ -case class PipelineFailureClassifier( - classifier: PartialFunction[Throwable, PipelineFailure]) - extends PartialFunction[Throwable, PipelineFailure] { - override def isDefinedAt(throwable: Throwable): Boolean = classifier.isDefinedAt(throwable) - override def apply(throwable: Throwable): PipelineFailure = classifier.apply(throwable) -} - -private[core] object PipelineFailureClassifier { - val Empty: PipelineFailureClassifier = PipelineFailureClassifier(PartialFunction.empty) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala deleted file mode 100644 index 9e4607b4c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure/PipelineFailureSerializer.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.pipeline_failure - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.JsonSerializer -import com.fasterxml.jackson.databind.SerializerProvider -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack - -private[pipeline_failure] class PipelineFailureSerializer() - extends JsonSerializer[PipelineFailure] { - - private sealed trait BaseSerializableException - - private case class SerializableException( - `class`: String, - message: String, - stackTrace: Seq[String], - cause: Option[BaseSerializableException]) - extends BaseSerializableException - - private case class SerializablePipelineFailure( - category: String, - reason: String, - underlying: Option[BaseSerializableException], - componentStack: Option[ComponentIdentifierStack], - stackTrace: Seq[String]) - extends BaseSerializableException - - private def serializeStackTrace(stackTrace: Array[StackTraceElement]): Seq[String] = - stackTrace.map(stackTraceElement => "at " + stackTraceElement.toString) - - private def mkSerializableException( - t: Throwable, - recursionDepth: Int = 0 - ): Option[BaseSerializableException] = { - t match { - case _ if recursionDepth > 4 => - // in the unfortunate case of a super deep chain of exceptions, stop if we get too deep - None - case pipelineFailure: PipelineFailure => - Some( - SerializablePipelineFailure( - category = - pipelineFailure.category.categoryName + "/" + pipelineFailure.category.failureName, - reason = pipelineFailure.reason, - underlying = - pipelineFailure.underlying.flatMap(mkSerializableException(_, recursionDepth + 1)), - componentStack = pipelineFailure.componentStack, - stackTrace = serializeStackTrace(pipelineFailure.getStackTrace) - )) - case t => - Some( - SerializableException( - `class` = t.getClass.getName, - message = t.getMessage, - stackTrace = serializeStackTrace(t.getStackTrace), - cause = Option(t.getCause).flatMap(mkSerializableException(_, recursionDepth + 1)) - ) - ) - } - } - - override def serialize( - pipelineFailure: PipelineFailure, - gen: JsonGenerator, - serializers: SerializerProvider - ): Unit = serializers.defaultSerializeValue(mkSerializableException(pipelineFailure), gen) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD deleted file mode 100644 index 6a1c78097..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/BUILD +++ /dev/null @@ -1,51 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client", - "stringcenter/client/src/main/scala/com/twitter/stringcenter/client/stitch", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/access_policy", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala deleted file mode 100644 index 407379234..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipeline.scala +++ /dev/null @@ -1,28 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.product - -import com.twitter.product_mixer.core.functional_component.common.access_policy.WithDebugAccessPolicies -import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.stitch.Arrow - -/** - * A Product Pipeline - * - * This is an abstract class, as we only construct these via the [[ProductPipelineBuilder]]. - * - * A [[ProductPipeline]] is capable of processing a [[Request]] and returning a response. - * - * @tparam RequestType the domain model for the query or request - * @tparam ResponseType the final marshalled result type - */ -abstract class ProductPipeline[RequestType <: Request, ResponseType] private[product] - extends Pipeline[ProductPipelineRequest[RequestType], ResponseType] - with WithDebugAccessPolicies { - override private[core] val config: ProductPipelineConfig[RequestType, _, ResponseType] - override val arrow: Arrow[ - ProductPipelineRequest[RequestType], - ProductPipelineResult[ResponseType] - ] - override val identifier: ProductPipelineIdentifier -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala deleted file mode 100644 index 600a70eed..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilder.scala +++ /dev/null @@ -1,385 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.product - -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finagle.tracing.Trace -import com.twitter.finagle.transport.Transport -import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.gate.DenyLoggedOutUsersGate -import com.twitter.product_mixer.core.gate.ParamGate -import com.twitter.product_mixer.core.gate.ParamGate.EnabledGateSuffix -import com.twitter.product_mixer.core.gate.ParamGate.SupportedClientGateSuffix -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.InvalidStepStateException -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineConfig -import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled -import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineConfig -import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineResult -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException -import com.twitter.product_mixer.core.service.pipeline_execution_logger.PipelineExecutionLogger -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutor -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorRequest -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorResult -import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutor -import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutorResult -import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult -import com.twitter.stitch.Arrow -import com.twitter.stringcenter.client.StringCenterRequestContext -import com.twitter.stringcenter.client.stitch.StringCenterRequestContextLetter -import com.twitter.timelines.configapi.Params -import com.twitter.util.logging.Logging -import org.slf4j.MDC - -class ProductPipelineBuilder[TRequest <: Request, Query <: PipelineQuery, Response]( - gateExecutor: GateExecutor, - pipelineSelectorExecutor: PipelineSelectorExecutor, - pipelineExecutor: PipelineExecutor, - mixerPipelineBuilderFactory: MixerPipelineBuilderFactory, - recommendationPipelineBuilderFactory: RecommendationPipelineBuilderFactory, - override val statsReceiver: StatsReceiver, - pipelineExecutionLogger: PipelineExecutionLogger) - extends PipelineBuilder[ProductPipelineRequest[TRequest]] - with Logging { builder => - - override type UnderlyingResultType = Response - override type PipelineResultType = ProductPipelineResult[Response] - - /** - * Query Transformer Step is implemented inline instead of using an executor. - * - * It's a simple, synchronous step that executes the query transformer. - * - * Since the output of the transformer is used in multiple other steps (Gate, Pipeline Execution), - * we've promoted the transformer to a step so that it's outputs can be reused easily. - */ - def pipelineQueryTransformerStep( - queryTransformer: (TRequest, Params) => Query, - context: Executor.Context - ): Step[ProductPipelineRequest[TRequest], Query] = - new Step[ProductPipelineRequest[TRequest], Query] { - - override def identifier: PipelineStepIdentifier = - ProductPipelineConfig.pipelineQueryTransformerStep - - override def executorArrow: Arrow[ProductPipelineRequest[TRequest], Query] = { - wrapWithErrorHandling(context, identifier)( - Arrow.map[ProductPipelineRequest[TRequest], Query] { - case ProductPipelineRequest(request, params) => queryTransformer(request, params) - } - ) - } - - override def inputAdaptor( - query: ProductPipelineRequest[TRequest], - previousResult: ProductPipelineResult[Response] - ): ProductPipelineRequest[TRequest] = query - - override def resultUpdater( - previousPipelineResult: ProductPipelineResult[Response], - executorResult: Query - ): ProductPipelineResult[Response] = - previousPipelineResult.copy(transformedQuery = Some(executorResult)) - } - - def qualityFactorStep( - qualityFactorStatus: QualityFactorStatus - ): Step[Query, QualityFactorExecutorResult] = { - new Step[Query, QualityFactorExecutorResult] { - override def identifier: PipelineStepIdentifier = ProductPipelineConfig.qualityFactorStep - - override def executorArrow: Arrow[Query, QualityFactorExecutorResult] = - Arrow - .map[Query, QualityFactorExecutorResult] { _ => - QualityFactorExecutorResult( - pipelineQualityFactors = - qualityFactorStatus.qualityFactorByPipeline.mapValues(_.currentValue) - ) - } - - override def inputAdaptor( - query: ProductPipelineRequest[TRequest], - previousResult: ProductPipelineResult[Response] - ): Query = previousResult.transformedQuery - .getOrElse { - throw InvalidStepStateException(identifier, "TransformedQuery") - }.asInstanceOf[Query] - - override def resultUpdater( - previousPipelineResult: ProductPipelineResult[Response], - executorResult: QualityFactorExecutorResult - ): ProductPipelineResult[Response] = { - previousPipelineResult.copy( - transformedQuery = previousPipelineResult.transformedQuery.map { - case queryWithQualityFactor: HasQualityFactorStatus => - queryWithQualityFactor - .withQualityFactorStatus(qualityFactorStatus).asInstanceOf[Query] - case query => - query - }, - qualityFactorResult = Some(executorResult) - ) - } - } - } - - def gatesStep( - gates: Seq[Gate[Query]], - context: Executor.Context - ): Step[Query, GateExecutorResult] = new Step[Query, GateExecutorResult] { - override def identifier: PipelineStepIdentifier = ProductPipelineConfig.gatesStep - - override def executorArrow: Arrow[Query, GateExecutorResult] = { - gateExecutor.arrow(gates, context) - } - - override def inputAdaptor( - query: ProductPipelineRequest[TRequest], - previousResult: ProductPipelineResult[Response] - ): Query = previousResult.transformedQuery - .getOrElse { - throw InvalidStepStateException(identifier, "TransformedQuery") - }.asInstanceOf[Query] - - override def resultUpdater( - previousPipelineResult: ProductPipelineResult[Response], - executorResult: GateExecutorResult - ): ProductPipelineResult[Response] = - previousPipelineResult.copy(gateResult = Some(executorResult)) - } - - def pipelineSelectorStep( - pipelineByIdentifer: Map[ComponentIdentifier, Pipeline[Query, Response]], - pipelineSelector: Query => ComponentIdentifier, - context: Executor.Context - ): Step[Query, PipelineSelectorExecutorResult] = - new Step[Query, PipelineSelectorExecutorResult] { - override def identifier: PipelineStepIdentifier = ProductPipelineConfig.pipelineSelectorStep - - override def executorArrow: Arrow[ - Query, - PipelineSelectorExecutorResult - ] = pipelineSelectorExecutor.arrow(pipelineByIdentifer, pipelineSelector, context) - - override def inputAdaptor( - query: ProductPipelineRequest[TRequest], - previousResult: ProductPipelineResult[Response] - ): Query = - previousResult.transformedQuery - .getOrElse(throw InvalidStepStateException(identifier, "TransformedQuery")).asInstanceOf[ - Query] - - override def resultUpdater( - previousPipelineResult: ProductPipelineResult[Response], - executorResult: PipelineSelectorExecutorResult - ): ProductPipelineResult[Response] = - previousPipelineResult.copy(pipelineSelectorResult = Some(executorResult)) - } - - def pipelineExecutionStep( - pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Response]], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Step[PipelineExecutorRequest[Query], PipelineExecutorResult[Response]] = - new Step[PipelineExecutorRequest[Query], PipelineExecutorResult[Response]] { - override def identifier: PipelineStepIdentifier = ProductPipelineConfig.pipelineExecutionStep - - override def executorArrow: Arrow[ - PipelineExecutorRequest[Query], - PipelineExecutorResult[Response] - ] = { - pipelineExecutor.arrow(pipelineByIdentifier, qualityFactorObserverByPipeline, context) - } - - override def inputAdaptor( - request: ProductPipelineRequest[TRequest], - previousResult: ProductPipelineResult[Response] - ): PipelineExecutorRequest[Query] = { - val query = previousResult.transformedQuery - .getOrElse { - throw InvalidStepStateException(identifier, "TransformedQuery") - }.asInstanceOf[Query] - - val pipelineIdentifier = previousResult.pipelineSelectorResult - .map(_.pipelineIdentifier).getOrElse { - throw InvalidStepStateException(identifier, "PipelineSelectorResult") - } - - PipelineExecutorRequest(query, pipelineIdentifier) - } - - override def resultUpdater( - previousPipelineResult: ProductPipelineResult[Response], - executorResult: PipelineExecutorResult[Response] - ): ProductPipelineResult[Response] = { - - val mixerPipelineResult = executorResult.pipelineResult match { - case mixerPipelineResult: MixerPipelineResult[Response] @unchecked => - Some(mixerPipelineResult) - case _ => - None - } - - val recommendationPipelineResult = executorResult.pipelineResult match { - case recommendationPipelineResult: RecommendationPipelineResult[ - _, - Response - ] @unchecked => - Some(recommendationPipelineResult) - case _ => - None - } - - previousPipelineResult.copy( - mixerPipelineResult = mixerPipelineResult, - recommendationPipelineResult = recommendationPipelineResult, - traceId = Trace.idOption.map(_.traceId.toString()), - result = executorResult.pipelineResult.result - ) - } - } - - def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - config: ProductPipelineConfig[TRequest, Query, Response] - ): ProductPipeline[TRequest, Response] = { - - val pipelineIdentifier = config.identifier - - val context = Executor.Context( - PipelineFailureClassifier( - config.failureClassifier.orElse(StoppedGateException.classifier(ProductDisabled))), - parentComponentIdentifierStack.push(pipelineIdentifier) - ) - - val denyLoggedOutUsersGate = if (config.denyLoggedOutUsers) { - Some(DenyLoggedOutUsersGate(pipelineIdentifier)) - } else { - None - } - val enabledGate: ParamGate = - ParamGate(pipelineIdentifier + EnabledGateSuffix, config.paramConfig.EnabledDeciderParam) - val supportedClientGate = - ParamGate( - pipelineIdentifier + SupportedClientGateSuffix, - config.paramConfig.SupportedClientParam) - - /** - * Evaluate enabled decider gate first since if it's off, there is no reason to proceed - * Next evaluate supported client feature switch gate, followed by customer configured gates - */ - val allGates = - denyLoggedOutUsersGate.toSeq ++: enabledGate +: supportedClientGate +: config.gates - - val childPipelines: Seq[Pipeline[Query, Response]] = - config.pipelines.map { - case mixerConfig: MixerPipelineConfig[Query, _, Response] => - mixerConfig.build(context.componentStack, mixerPipelineBuilderFactory) - case recommendationConfig: RecommendationPipelineConfig[Query, _, _, Response] => - recommendationConfig.build(context.componentStack, recommendationPipelineBuilderFactory) - case other => - throw new IllegalArgumentException( - s"Product Pipelines only support Mixer and Recommendation pipelines, not $other") - } - - val pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Response]] = - childPipelines.map { pipeline => - (pipeline.identifier, pipeline) - }.toMap - - val qualityFactorStatus: QualityFactorStatus = - QualityFactorStatus.build(config.qualityFactorConfigs) - - val qualityFactorObserverByPipeline = qualityFactorStatus.qualityFactorByPipeline.mapValues { - qualityFactor => - qualityFactor.buildObserver() - } - - buildGaugesForQualityFactor(pipelineIdentifier, qualityFactorStatus, statsReceiver) - - /** - * Initialize MDC with access logging with everything we have at request time. We can put - * more stuff into MDC later down the pipeline, but at risk of exceptions/errors preventing - * them from being added - */ - val mdcInitArrow = - Arrow.map[ProductPipelineRequest[TRequest], ProductPipelineRequest[TRequest]] { request => - val serviceIdentifier = ServiceIdentifier.fromCertificate(Transport.peerCertificate) - MDC.put("product", config.product.identifier.name) - MDC.put("serviceIdentifier", ServiceIdentifier.asString(serviceIdentifier)) - request - } - - val builtSteps = Seq( - pipelineQueryTransformerStep(config.pipelineQueryTransformer, context), - qualityFactorStep(qualityFactorStatus), - gatesStep(allGates, context), - pipelineSelectorStep(pipelineByIdentifier, config.pipelineSelector, context), - pipelineExecutionStep(pipelineByIdentifier, qualityFactorObserverByPipeline, context) - ) - - val underlying: Arrow[ProductPipelineRequest[TRequest], ProductPipelineResult[Response]] = - buildCombinedArrowFromSteps( - steps = builtSteps, - context = context, - initialEmptyResult = ProductPipelineResult.empty, - stepsInOrderFromConfig = ProductPipelineConfig.stepsInOrder - ) - - /** - * Unlike other components and pipelines, [[ProductPipeline]] must be observed in the - * [[ProductPipelineBuilder]] directly because the resulting [[ProductPipeline.arrow]] - * is run directly without an executor so must contain all stats. - */ - val observed = - wrapProductPipelineWithExecutorBookkeeping[ - ProductPipelineRequest[TRequest], - ProductPipelineResult[Response] - ](context, pipelineIdentifier)(underlying) - - val finalArrow: Arrow[ProductPipelineRequest[TRequest], ProductPipelineResult[Response]] = - Arrow - .letWithArg[ - ProductPipelineRequest[TRequest], - ProductPipelineResult[Response], - StringCenterRequestContext](StringCenterRequestContextLetter)(request => - StringCenterRequestContext( - request.request.clientContext.languageCode, - request.request.clientContext.countryCode - ))( - mdcInitArrow - .andThen(observed) - .onSuccess(result => result.transformedQuery.map(pipelineExecutionLogger(_, result)))) - - val configFromBuilder = config - new ProductPipeline[TRequest, Response] { - override private[core] val config: ProductPipelineConfig[TRequest, _, Response] = - configFromBuilder - override val arrow: Arrow[ProductPipelineRequest[TRequest], ProductPipelineResult[Response]] = - finalArrow - override val identifier: ProductPipelineIdentifier = pipelineIdentifier - override val alerts: Seq[Alert] = config.alerts - override val debugAccessPolicies: Set[AccessPolicy] = config.debugAccessPolicies - override val children: Seq[Component] = allGates ++ childPipelines - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala deleted file mode 100644 index 9e609ed92..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineBuilderFactory.scala +++ /dev/null @@ -1,39 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.product - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineBuilderFactory -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.pipeline_execution_logger.PipelineExecutionLogger -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutor -import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutor -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ProductPipelineBuilderFactory @Inject() ( - gateExecutor: GateExecutor, - pipelineSelectorExecutor: PipelineSelectorExecutor, - pipelineExecutor: PipelineExecutor, - mixerPipelineBuilderFactory: MixerPipelineBuilderFactory, - recommendationPipelineBuilderFactory: RecommendationPipelineBuilderFactory, - statsReceiver: StatsReceiver, - pipelineExecutionLogger: PipelineExecutionLogger) { - def get[ - TRequest <: Request, - Query <: PipelineQuery, - Response - ]: ProductPipelineBuilder[TRequest, Query, Response] = { - new ProductPipelineBuilder[TRequest, Query, Response]( - gateExecutor, - pipelineSelectorExecutor, - pipelineExecutor, - mixerPipelineBuilderFactory, - recommendationPipelineBuilderFactory, - statsReceiver, - pipelineExecutionLogger - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala deleted file mode 100644 index ade9b76a8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineConfig.scala +++ /dev/null @@ -1,107 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.product - -import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.PipelineConfig -import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.product.ProductParamConfig -import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig -import com.twitter.timelines.configapi.Params - -trait ProductPipelineConfig[TRequest <: Request, Query <: PipelineQuery, Response] - extends PipelineConfig { - - override val identifier: ProductPipelineIdentifier - - val product: Product - val paramConfig: ProductParamConfig - - /** - * Product Pipeline Gates will be executed before any other step (including retrieval from mixer - * pipelines). They're executed sequentially, and any "Stop" result will prevent pipeline execution. - */ - def gates: Seq[Gate[Query]] = Seq.empty - - def pipelineQueryTransformer(request: TRequest, params: Params): Query - - /** - * A list of all pipelines that power this product directly (there is no need to include pipelines - * called by those pipelines). - * - * Only pipeline from this list should referenced from the pipelineSelector - */ - def pipelines: Seq[PipelineConfig] - - /** - * A pipeline selector selects a pipeline (from the list in `def pipelines`) to handle the - * current request. - */ - def pipelineSelector(query: Query): ComponentIdentifier - - /** - ** [[qualityFactorConfigs]] associates [[QualityFactorConfig]]s to specific pipelines - * using [[ComponentIdentifier]]. - */ - def qualityFactorConfigs: Map[ComponentIdentifier, QualityFactorConfig] = - Map.empty - - /** - * By default (for safety), product mixer pipelines do not allow logged out requests. - * A "DenyLoggedOutUsersGate" will be generated and added to the pipeline. - * - * You can disable this behavior by overriding `denyLoggedOutUsers` with False. - */ - val denyLoggedOutUsers: Boolean = true - - /** - * A pipeline can define a partial function to rescue failures here. They will be treated as failures - * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here). - */ - def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty - - /** - * Alerts can be used to indicate the pipeline's service level objectives. Alerts and - * dashboards will be automatically created based on this information. - */ - val alerts: Seq[Alert] = Seq.empty - - /** - * Access Policies can be used to gate who can query a product from Product Mixer's query tool - * (go/turntable). - * - * This will typically be gated by an LDAP group associated with your team. For example: - * - * {{{ - * override val debugAccessPolicies: Set[AccessPolicy] = Set(AllowedLdapGroups("NAME")) - * }}} - * - * You can disable all queries by using the [[com.twitter.product_mixer.core.functional_component.common.access_policy.BlockEverything]] policy. - */ - val debugAccessPolicies: Set[AccessPolicy] -} - -object ProductPipelineConfig extends PipelineConfigCompanion { - val pipelineQueryTransformerStep: PipelineStepIdentifier = PipelineStepIdentifier( - "PipelineQueryTransformer") - val qualityFactorStep: PipelineStepIdentifier = PipelineStepIdentifier("QualityFactor") - val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates") - val pipelineSelectorStep: PipelineStepIdentifier = PipelineStepIdentifier("PipelineSelector") - val pipelineExecutionStep: PipelineStepIdentifier = PipelineStepIdentifier("PipelineExecution") - - /** All the Steps which are executed by a [[ProductPipeline]] in the order in which they are run */ - override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq( - pipelineQueryTransformerStep, - qualityFactorStep, - gatesStep, - pipelineSelectorStep, - pipelineExecutionStep - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala deleted file mode 100644 index 7cefde3d7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineRequest.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.product - -import com.twitter.timelines.configapi.Params - -case class ProductPipelineRequest[RequestType](request: RequestType, params: Params) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala deleted file mode 100644 index c0065992a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product/ProductPipelineResult.scala +++ /dev/null @@ -1,62 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.product - -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.mixer.MixerPipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.recommendation.RecommendationPipelineResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.pipeline_selector_executor.PipelineSelectorExecutorResult -import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult - -case class ProductPipelineResult[Result]( - transformedQuery: Option[PipelineQuery], - qualityFactorResult: Option[QualityFactorExecutorResult], - gateResult: Option[GateExecutorResult], - pipelineSelectorResult: Option[PipelineSelectorExecutorResult], - mixerPipelineResult: Option[MixerPipelineResult[Result]], - recommendationPipelineResult: Option[RecommendationPipelineResult[_, Result]], - traceId: Option[String], - failure: Option[PipelineFailure], - result: Option[Result]) - extends PipelineResult[Result] { - - override val resultSize: Int = { - if (mixerPipelineResult.isDefined) { - mixerPipelineResult.map(_.resultSize).getOrElse(0) - } else { - recommendationPipelineResult.map(_.resultSize).getOrElse(0) - } - } - - override def withFailure(failure: PipelineFailure): PipelineResult[Result] = - copy(failure = Some(failure)) - - override def withResult(result: Result): PipelineResult[Result] = copy(result = Some(result)) -} - -object ProductPipelineResult { - def empty[A]: ProductPipelineResult[A] = ProductPipelineResult( - None, - None, - None, - None, - None, - None, - None, - None, - None - ) - - def fromResult[A](result: A): ProductPipelineResult[A] = ProductPipelineResult( - None, - None, - None, - None, - None, - None, - None, - None, - Some(result) - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD deleted file mode 100644 index 506e537c1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/BUILD +++ /dev/null @@ -1,62 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector:insert_append_results", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/common/alert", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala deleted file mode 100644 index fe379c9b9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipeline.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.recommendation - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.RecommendationPipelineIdentifier -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Arrow - -/** - * A Recommendation Pipeline - * - * This is an abstract class, as we only construct these via the [[RecommendationPipelineBuilder]]. - * - * A [[RecommendationPipeline]] is capable of processing requests (queries) and returning responses (results) - * in the correct format to directly send to users. - * - * @tparam Query the domain model for the query or request - * @tparam Candidate the type of the candidates - * @tparam Result the final marshalled result type - */ -abstract class RecommendationPipeline[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - Result] - extends Pipeline[Query, Result] { - override private[core] val config: RecommendationPipelineConfig[Query, Candidate, _, Result] - override val arrow: Arrow[Query, RecommendationPipelineResult[Candidate, Result]] - override val identifier: RecommendationPipelineIdentifier -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala deleted file mode 100644 index 684ec3c6d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilder.scala +++ /dev/null @@ -1,1076 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.recommendation - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.util.logging.Logging -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.RecommendationPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.InvalidStepStateException -import com.twitter.product_mixer.core.pipeline.PipelineBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipeline -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredDecorator -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipeline -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineConfig -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutor -import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutorResult -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor -import com.twitter.stitch.Arrow - -/** - * RecommendationPipelineBuilder builds [[RecommendationPipeline]]s from [[RecommendationPipelineConfig]]s. - * - * You should inject a [[RecommendationPipelineBuilderFactory]] and call `.get` to build these. - * - * @see [[RecommendationPipelineConfig]] for the description of the type parameters. - * - * @note Almost a mirror of MixerPipelineBuilder - */ - -class RecommendationPipelineBuilder[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - DomainResultType <: HasMarshalling, - Result -]( - candidatePipelineExecutor: CandidatePipelineExecutor, - gateExecutor: GateExecutor, - selectorExecutor: SelectorExecutor, - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor, - asyncFeatureMapExecutor: AsyncFeatureMapExecutor, - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor, - filterExecutor: FilterExecutor, - scoringPipelineExecutor: ScoringPipelineExecutor, - candidateDecoratorExecutor: CandidateDecoratorExecutor, - domainMarshallerExecutor: DomainMarshallerExecutor, - transportMarshallerExecutor: TransportMarshallerExecutor, - pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor, - candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory, - scoringPipelineBuilderFactory: ScoringPipelineBuilderFactory, - override val statsReceiver: StatsReceiver) - extends PipelineBuilder[Query] - with Logging { - - override type UnderlyingResultType = Result - override type PipelineResultType = RecommendationPipelineResult[Candidate, Result] - - def qualityFactorStep( - qualityFactorStatus: QualityFactorStatus - ): Step[Query, QualityFactorExecutorResult] = - new Step[Query, QualityFactorExecutorResult] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.qualityFactorStep - - override def executorArrow: Arrow[Query, QualityFactorExecutorResult] = - Arrow - .map[Query, QualityFactorExecutorResult] { _ => - QualityFactorExecutorResult( - pipelineQualityFactors = - qualityFactorStatus.qualityFactorByPipeline.mapValues(_.currentValue) - ) - } - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): Query = query - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: QualityFactorExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(qualityFactorResult = Some(executorResult)) - - override def queryUpdater( - query: Query, - executorResult: QualityFactorExecutorResult - ): Query = { - query match { - case queryWithQualityFactor: HasQualityFactorStatus => - queryWithQualityFactor - .withQualityFactorStatus( - queryWithQualityFactor.qualityFactorStatus.getOrElse(QualityFactorStatus.empty) ++ - qualityFactorStatus - ).asInstanceOf[Query] - case _ => - query - } - } - } - - def gatesStep( - gates: Seq[Gate[Query]], - context: Executor.Context - ): Step[Query, GateExecutorResult] = new Step[Query, GateExecutorResult] { - override def identifier: PipelineStepIdentifier = RecommendationPipelineConfig.gatesStep - - override def executorArrow: Arrow[Query, GateExecutorResult] = - gateExecutor.arrow(gates, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): Query = - query - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: GateExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(gateResult = Some(executorResult)) - } - - def fetchQueryFeaturesStep( - queryFeatureHydrators: Seq[BaseQueryFeatureHydrator[Query, _]], - stepIdentifier: PipelineStepIdentifier, - updater: ResultUpdater[ - RecommendationPipelineResult[Candidate, Result], - QueryFeatureHydratorExecutor.Result - ], - context: Executor.Context - ): Step[Query, QueryFeatureHydratorExecutor.Result] = - new Step[Query, QueryFeatureHydratorExecutor.Result] { - override def identifier: PipelineStepIdentifier = stepIdentifier - - override def executorArrow: Arrow[Query, QueryFeatureHydratorExecutor.Result] = - queryFeatureHydratorExecutor.arrow( - queryFeatureHydrators, - RecommendationPipelineConfig.stepsAsyncFeatureHydrationCanBeCompletedBy, - context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): Query = query - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: QueryFeatureHydratorExecutor.Result - ): RecommendationPipelineResult[Candidate, Result] = - updater(previousPipelineResult, executorResult) - - override def queryUpdater( - query: Query, - executorResult: QueryFeatureHydratorExecutor.Result - ): Query = - query - .withFeatureMap( - query.features - .getOrElse(FeatureMap.empty) ++ executorResult.featureMap).asInstanceOf[Query] - } - - def asyncFeaturesStep( - stepToHydrateFor: PipelineStepIdentifier, - context: Executor.Context - ): Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - new Step[AsyncFeatureMap, AsyncFeatureMapExecutorResults] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.asyncFeaturesStep(stepToHydrateFor) - - override def executorArrow: Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - asyncFeatureMapExecutor.arrow( - stepToHydrateFor, - identifier, - context - ) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): AsyncFeatureMap = - previousResult.mergedAsyncQueryFeatures - .getOrElse( - throw InvalidStepStateException(identifier, "MergedAsyncQueryFeatures") - ) - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: AsyncFeatureMapExecutorResults - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy( - asyncFeatureHydrationResults = previousPipelineResult.asyncFeatureHydrationResults match { - case Some(existingResults) => Some(existingResults ++ executorResult) - case None => Some(executorResult) - }) - - override def queryUpdater( - query: Query, - executorResult: AsyncFeatureMapExecutorResults - ): Query = - if (executorResult.featureMapsByStep - .getOrElse(stepToHydrateFor, FeatureMap.empty).isEmpty) { - query - } else { - query - .withFeatureMap( - query.features - .getOrElse(FeatureMap.empty) ++ executorResult.featureMapsByStep( - stepToHydrateFor)).asInstanceOf[Query] - } - } - - def candidatePipelinesStep( - candidatePipelines: Seq[CandidatePipeline[Query]], - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] = - new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.candidatePipelinesStep - - override def executorArrow: Arrow[CandidatePipeline.Inputs[ - Query - ], CandidatePipelineExecutorResult] = - candidatePipelineExecutor - .arrow( - candidatePipelines, - defaultFailOpenPolicy, - failOpenPolicies, - qualityFactorObserverByPipeline, - context - ) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): CandidatePipeline.Inputs[ - Query - ] = CandidatePipeline.Inputs(query, Seq.empty) - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: CandidatePipelineExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(candidatePipelineResults = Some(executorResult)) - - override def queryUpdater( - query: Query, - executorResult: CandidatePipelineExecutorResult - ): Query = { - val updatedFeatureMap = query.features - .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap - query - .withFeatureMap(updatedFeatureMap).asInstanceOf[Query] - } - } - - def dependentCandidatePipelinesStep( - candidatePipelines: Seq[CandidatePipeline[Query]], - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] = - new Step[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.dependentCandidatePipelinesStep - - override def executorArrow: Arrow[CandidatePipeline.Inputs[ - Query - ], CandidatePipelineExecutorResult] = - candidatePipelineExecutor - .arrow( - candidatePipelines, - defaultFailOpenPolicy, - failOpenPolicies, - qualityFactorObserverByPipeline, - context - ) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): CandidatePipeline.Inputs[ - Query - ] = { - val previousCandidates = previousResult.candidatePipelineResults - .getOrElse { - throw InvalidStepStateException(identifier, "Candidates") - }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty)) - - CandidatePipeline.Inputs(query, previousCandidates) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: CandidatePipelineExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(dependentCandidatePipelineResults = Some(executorResult)) - - override def queryUpdater( - query: Query, - executorResult: CandidatePipelineExecutorResult - ): Query = { - val updatedFeatureMap = query.features - .getOrElse(FeatureMap.empty) ++ executorResult.queryFeatureMap - query - .withFeatureMap(updatedFeatureMap).asInstanceOf[Query] - } - } - - abstract class FilterStep( - filters: Seq[Filter[Query, Candidate]], - context: Executor.Context, - override val identifier: PipelineStepIdentifier) - extends Step[ - (Query, Seq[CandidateWithFeatures[Candidate]]), - FilterExecutorResult[Candidate] - ] { - - def itemCandidates( - previousResult: RecommendationPipelineResult[Candidate, Result] - ): Seq[CandidateWithDetails] - - override def executorArrow: Arrow[ - (Query, Seq[CandidateWithFeatures[Candidate]]), - FilterExecutorResult[Candidate] - ] = - filterExecutor.arrow(filters, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): (Query, Seq[CandidateWithFeatures[Candidate]]) = { - - val extractedItemCandidates = itemCandidates(previousResult).collect { - case itemCandidate: ItemCandidateWithDetails => itemCandidate - } - - (query, extractedItemCandidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]) - } - } - - def postCandidatePipelinesSelectorStep( - selectors: Seq[Selector[Query]], - context: Executor.Context - ): Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = - new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.postCandidatePipelinesSelectorsStep - - override def executorArrow: Arrow[SelectorExecutor.Inputs[ - Query - ], SelectorExecutorResult] = - selectorExecutor.arrow(selectors, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): SelectorExecutor.Inputs[Query] = { - val candidatePipelineResults = previousResult.candidatePipelineResults - .getOrElse { - throw InvalidStepStateException(identifier, "CandidatePipelineResults") - }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty)) - val dependentCandidatePipelineResults = previousResult.dependentCandidatePipelineResults - .getOrElse { - throw InvalidStepStateException(identifier, "DependentCandidatePipelineResults") - }.candidatePipelineResults.flatMap(_.result.getOrElse(Seq.empty)) - - SelectorExecutor.Inputs( - query = query, - candidatesWithDetails = candidatePipelineResults ++ dependentCandidatePipelineResults - ) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: SelectorExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(postCandidatePipelinesSelectorResults = Some(executorResult)) - } - - def postCandidatePipelinesFeatureHydrationStep( - hydrators: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]], - context: Executor.Context - ): Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] = new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.postCandidatePipelinesFeatureHydrationStep - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] = - candidateFeatureHydratorExecutor.arrow(hydrators, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = { - val selectedCandidatesResult = - previousResult.postCandidatePipelinesSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "PostCandidatePipelinesSelectorResults") - }.selectedCandidates - - CandidateFeatureHydratorExecutor.Inputs( - query, - selectedCandidatesResult.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: CandidateFeatureHydratorExecutorResult[Candidate] - ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy( - postCandidatePipelinesFeatureHydrationResults = Some(executorResult) - ) - } - - def globalFiltersStep( - filters: Seq[Filter[Query, Candidate]], - context: Executor.Context - ): Step[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] = - new FilterStep(filters, context, RecommendationPipelineConfig.globalFiltersStep) { - override def itemCandidates( - previousResult: RecommendationPipelineResult[Candidate, Result] - ): Seq[CandidateWithDetails] = { - val candidates = previousResult.postCandidatePipelinesSelectorResults - .getOrElse { - throw InvalidStepStateException(identifier, "PostCandidatePipelineSelectorResults") - }.selectedCandidates.collect { - case itemCandidate: ItemCandidateWithDetails => itemCandidate - } - - val featureMaps = previousResult.postCandidatePipelinesFeatureHydrationResults - .getOrElse { - throw InvalidStepStateException( - identifier, - "PostCandidatePipelineFeatureHydrationResults") - }.results.map(_.features) - // If no hydrators were run, this list would be empty. Otherwise, order and cardinality is - // always ensured to match. - if (featureMaps.isEmpty) { - candidates - } else { - candidates.zip(featureMaps).map { - case (candidate, featureMap) => - candidate.copy(features = candidate.features ++ featureMap) - } - } - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: FilterExecutorResult[Candidate] - ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy( - globalFilterResults = Some(executorResult) - ) - } - - def scoringPipelinesStep( - scoringPipelines: Seq[ScoringPipeline[Query, Candidate]], - context: Executor.Context, - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[ScoringPipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver] - ): Step[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineExecutorResult[ - Candidate - ]] = - new Step[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineExecutorResult[ - Candidate - ]] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.scoringPipelinesStep - - override def executorArrow: Arrow[ - ScoringPipelineExecutor.Inputs[Query], - ScoringPipelineExecutorResult[Candidate] - ] = scoringPipelineExecutor.arrow( - scoringPipelines, - context, - defaultFailOpenPolicy, - failOpenPolicies, - qualityFactorObserverByPipeline - ) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): ScoringPipelineExecutor.Inputs[Query] = { - val selectedCandidates = - previousResult.postCandidatePipelinesSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "PostCandidatePipelinesSelectorResults") - }.selectedCandidates - - val itemCandidates = selectedCandidates.collect { - case itemCandidate: ItemCandidateWithDetails => itemCandidate - } - - val featureMaps = previousResult.postCandidatePipelinesFeatureHydrationResults - .getOrElse { - throw InvalidStepStateException( - identifier, - "PostCandidatePipelineFeatureHydrationResults") - }.results.map(_.features) - // If no hydrators were run, this list would be empty. Otherwise, order and cardinality is - // always ensured to match. - val updatedCandidates = if (featureMaps.isEmpty) { - itemCandidates - } else { - itemCandidates.zip(featureMaps).map { - case (candidate, featureMap) => - candidate.copy(features = candidate.features ++ featureMap) - } - } - - // Filter the original list of candidates to keep only the ones that were kept from - // filtering - val filterResults: Set[Candidate] = previousResult.globalFilterResults - .getOrElse { - throw InvalidStepStateException(identifier, "FilterResults") - }.result.toSet - - val filteredItemCandidates = updatedCandidates.filter { itemCandidate => - filterResults.contains(itemCandidate.candidate.asInstanceOf[Candidate]) - } - - ScoringPipelineExecutor.Inputs( - query, - filteredItemCandidates - ) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: ScoringPipelineExecutorResult[Candidate] - ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult - .copy(scoringPipelineResults = Some(executorResult)) - } - - def resultSelectorsStep( - selectors: Seq[Selector[Query]], - context: Executor.Context - ): Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = - new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.resultSelectorsStep - - override def executorArrow: Arrow[SelectorExecutor.Inputs[ - Query - ], SelectorExecutorResult] = - selectorExecutor.arrow(selectors, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): SelectorExecutor.Inputs[Query] = { - - /** - * See [[ScoringPipelineExecutor]], scoringPipelineResults contains the fully re-merged - * and updated FeatureMap so there's no need to do any recomposition. Scoring Pipeline Results - * has only candidates that were kept in previous filtering, with their final merged feature - * map. - */ - val scorerResults = previousResult.scoringPipelineResults.getOrElse { - throw InvalidStepStateException(identifier, "Scores") - } - - SelectorExecutor.Inputs( - query = query, - candidatesWithDetails = scorerResults.result - ) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: SelectorExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(resultSelectorResults = Some(executorResult)) - } - - def postSelectionFiltersStep( - filters: Seq[Filter[Query, Candidate]], - context: Executor.Context - ): Step[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] = - new FilterStep(filters, context, RecommendationPipelineConfig.postSelectionFiltersStep) { - - override def itemCandidates( - previousResult: RecommendationPipelineResult[Candidate, Result] - ): Seq[CandidateWithDetails] = { - previousResult.resultSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "Candidates") - }.selectedCandidates - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: FilterExecutorResult[Candidate] - ): RecommendationPipelineResult[Candidate, Result] = { - previousPipelineResult.copy(postSelectionFilterResults = Some(executorResult)) - } - } - - def decoratorStep( - decorator: Option[CandidateDecorator[Query, Candidate]], - context: Executor.Context - ): Step[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] = - new Step[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] { - override def identifier: PipelineStepIdentifier = RecommendationPipelineConfig.decoratorStep - - override lazy val executorArrow: Arrow[ - (Query, Seq[CandidateWithFeatures[Candidate]]), - CandidateDecoratorExecutorResult - ] = - candidateDecoratorExecutor.arrow(decorator, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): (Query, Seq[CandidateWithFeatures[Candidate]]) = { - - val selectorResults = previousResult.resultSelectorResults - .getOrElse { - throw InvalidStepStateException(identifier, "SelectorResults") - }.selectedCandidates - .collect { case candidate: ItemCandidateWithDetails => candidate } - - val filterResults = previousResult.postSelectionFilterResults - .getOrElse { - throw InvalidStepStateException(identifier, "PostSelectionFilterResults") - }.result.toSet - - val itemCandidateWithDetailsPostFiltering = - selectorResults - .filter(candidateWithDetails => - filterResults.contains( - candidateWithDetails.candidate - .asInstanceOf[Candidate])) - .asInstanceOf[Seq[CandidateWithFeatures[Candidate]]] - - (query, itemCandidateWithDetailsPostFiltering) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: CandidateDecoratorExecutorResult - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy( - candidateDecoratorResult = Some(executorResult) - ) - } - - def domainMarshallingStep( - domainMarshaller: DomainMarshaller[Query, DomainResultType], - context: Executor.Context - ): Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[ - DomainResultType - ]] = - new Step[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[ - DomainResultType - ]] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.domainMarshallerStep - - override def executorArrow: Arrow[ - DomainMarshallerExecutor.Inputs[Query], - DomainMarshallerExecutor.Result[DomainResultType] - ] = - domainMarshallerExecutor.arrow(domainMarshaller, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): DomainMarshallerExecutor.Inputs[Query] = { - val selectorResults = previousResult.resultSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "SelectorResults") - } - - val filterResults = previousResult.postSelectionFilterResults - .getOrElse { - throw InvalidStepStateException(identifier, "PostSelectionFilterResults") - }.result.toSet - - val filteredResults = selectorResults.selectedCandidates.collect { - case candidate: ItemCandidateWithDetails - if filterResults.contains(candidate.candidate.asInstanceOf[Candidate]) => - candidate - } - - val decoratorResults = previousResult.candidateDecoratorResult - .getOrElse(throw InvalidStepStateException(identifier, "DecoratorStep")).result.map { - decoration => - decoration.candidate -> decoration.presentation - }.toMap - - val finalResults = filteredResults.map { itemWithDetails => - decoratorResults.get(itemWithDetails.candidate) match { - case Some(presentation: ItemPresentation) => - if (itemWithDetails.presentation.isDefined) { - throw PipelineFailure( - category = MisconfiguredDecorator, - reason = "Item Candidate already decorated", - componentStack = Some(context.componentStack)) - } else { - itemWithDetails.copy(presentation = Some(presentation)) - } - case Some(_) => - throw PipelineFailure( - category = MisconfiguredDecorator, - reason = "Item Candidate got back a non ItemPresentation from decorator", - componentStack = Some(context.componentStack)) - case None => itemWithDetails - } - } - DomainMarshallerExecutor.Inputs( - query = query, - candidatesWithDetails = finalResults - ) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: DomainMarshallerExecutor.Result[DomainResultType] - ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy( - domainMarshallerResults = Some(executorResult) - ) - } - - def resultSideEffectsStep( - sideEffects: Seq[PipelineResultSideEffect[Query, DomainResultType]], - context: Executor.Context - ): Step[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] = new Step[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.resultSideEffectsStep - - override def executorArrow: Arrow[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] = pipelineResultSideEffectExecutor.arrow(sideEffects, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): PipelineResultSideEffect.Inputs[Query, DomainResultType] = { - - // Re-apply decorations to the selected results - val resultSelectorResults = { - val decoratorResults = previousResult.candidateDecoratorResult - .getOrElse(throw InvalidStepStateException(identifier, "DecoratorStep")).result.map { - decoration => - decoration.candidate -> decoration.presentation - }.toMap - - val previousSelectorResults = previousResult.resultSelectorResults.getOrElse { - throw InvalidStepStateException(identifier, "SelectorResults") - } - - val filterResults = previousResult.postSelectionFilterResults - .getOrElse { - throw InvalidStepStateException(identifier, "PostSelectionFilterResults") - }.result.toSet - - val filteredSelectorResults = previousSelectorResults.selectedCandidates.collect { - case candidate: ItemCandidateWithDetails - if filterResults.contains(candidate.candidate.asInstanceOf[Candidate]) => - candidate - } - - val decoratedSelectedResults = filteredSelectorResults.map { - case itemWithDetails: ItemCandidateWithDetails => - decoratorResults.get(itemWithDetails.candidate) match { - case Some(presentation: ItemPresentation) => - if (itemWithDetails.presentation.isDefined) { - throw PipelineFailure( - category = MisconfiguredDecorator, - reason = "Item Candidate already decorated", - componentStack = Some(context.componentStack)) - } else { - itemWithDetails.copy(presentation = Some(presentation)) - } - case Some(_) => - throw PipelineFailure( - category = MisconfiguredDecorator, - reason = "Item Candidate got back a non ItemPresentation from decorator", - componentStack = Some(context.componentStack)) - case None => itemWithDetails - } - case item => - // This branch should be impossible to hit since we do a .collect on ItemCandidateWithDetails - // as part of executing the candidate pipelines. - throw PipelineFailure( - category = IllegalStateFailure, - reason = - s"Only ItemCandidateWithDetails expected in pipeline, found: ${item.toString}", - componentStack = Some(context.componentStack) - ) - } - - previousSelectorResults.copy(selectedCandidates = decoratedSelectedResults) - } - - val domainMarshallerResults = previousResult.domainMarshallerResults.getOrElse { - throw InvalidStepStateException(identifier, "DomainMarshallerResults") - } - - PipelineResultSideEffect.Inputs[Query, DomainResultType]( - query = query, - selectedCandidates = resultSelectorResults.selectedCandidates, - remainingCandidates = resultSelectorResults.remainingCandidates, - droppedCandidates = resultSelectorResults.droppedCandidates, - response = domainMarshallerResults.result.asInstanceOf[DomainResultType] - ) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: PipelineResultSideEffectExecutor.Result - ): RecommendationPipelineResult[Candidate, Result] = - previousPipelineResult.copy(resultSideEffectResults = Some(executorResult)) - } - - def transportMarshallingStep( - transportMarshaller: TransportMarshaller[DomainResultType, Result], - context: Executor.Context - ): Step[ - TransportMarshallerExecutor.Inputs[DomainResultType], - TransportMarshallerExecutor.Result[Result] - ] = new Step[TransportMarshallerExecutor.Inputs[ - DomainResultType - ], TransportMarshallerExecutor.Result[Result]] { - override def identifier: PipelineStepIdentifier = - RecommendationPipelineConfig.transportMarshallerStep - - override def executorArrow: Arrow[TransportMarshallerExecutor.Inputs[ - DomainResultType - ], TransportMarshallerExecutor.Result[Result]] = - transportMarshallerExecutor.arrow(transportMarshaller, context) - - override def inputAdaptor( - query: Query, - previousResult: RecommendationPipelineResult[Candidate, Result] - ): TransportMarshallerExecutor.Inputs[DomainResultType] = { - val domainMarshallingResults = previousResult.domainMarshallerResults.getOrElse { - throw InvalidStepStateException(identifier, "DomainMarshallerResults") - } - - // Since the PipelineResult just uses HasMarshalling - val domainResult = domainMarshallingResults.result.asInstanceOf[DomainResultType] - - TransportMarshallerExecutor.Inputs(domainResult) - } - - override def resultUpdater( - previousPipelineResult: RecommendationPipelineResult[Candidate, Result], - executorResult: TransportMarshallerExecutor.Result[Result] - ): RecommendationPipelineResult[Candidate, Result] = previousPipelineResult.copy( - transportMarshallerResults = Some(executorResult), - result = Some(executorResult.result) - ) - } - - def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - config: RecommendationPipelineConfig[ - Query, - Candidate, - DomainResultType, - Result - ] - ): RecommendationPipeline[Query, Candidate, Result] = { - val pipelineIdentifier = config.identifier - - val context = Executor.Context( - PipelineFailureClassifier( - config.failureClassifier.orElse(StoppedGateException.classifier(ProductDisabled))), - parentComponentIdentifierStack.push(pipelineIdentifier) - ) - - val decorator = config.decorator.map(decorator => - CandidateDecorator.copyWithUpdatedIdentifier(decorator, pipelineIdentifier)) - - val qualityFactorStatus: QualityFactorStatus = - QualityFactorStatus.build(config.qualityFactorConfigs) - - val qualityFactorObserverByPipeline = - qualityFactorStatus.qualityFactorByPipeline.mapValues { qualityFactor => - qualityFactor.buildObserver() - } - - buildGaugesForQualityFactor(pipelineIdentifier, qualityFactorStatus, statsReceiver) - - val candidatePipelines: Seq[CandidatePipeline[Query]] = config.candidatePipelines.map { - pipelineConfig: CandidatePipelineConfig[Query, _, _, _] => - pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory) - } - - val dependentCandidatePipelines: Seq[CandidatePipeline[Query]] = - config.dependentCandidatePipelines.map { - pipelineConfig: DependentCandidatePipelineConfig[Query, _, _, _] => - pipelineConfig.build(context.componentStack, candidatePipelineBuilderFactory) - } - - val scoringPipelines: Seq[ScoringPipeline[Query, Candidate]] = config.scoringPipelines.map { - pipelineConfig: ScoringPipelineConfig[Query, Candidate] => - pipelineConfig.build(context.componentStack, scoringPipelineBuilderFactory) - } - - val builtSteps = Seq( - qualityFactorStep(qualityFactorStatus), - gatesStep(config.gates, context), - fetchQueryFeaturesStep( - config.fetchQueryFeatures, - RecommendationPipelineConfig.fetchQueryFeaturesStep, - (previousPipelineResult, executorResult) => - previousPipelineResult.copy(queryFeatures = Some(executorResult)), - context - ), - fetchQueryFeaturesStep( - config.fetchQueryFeaturesPhase2, - RecommendationPipelineConfig.fetchQueryFeaturesPhase2Step, - (previousPipelineResult, executorResult) => - previousPipelineResult.copy( - queryFeaturesPhase2 = Some(executorResult), - mergedAsyncQueryFeatures = Some( - previousPipelineResult.queryFeatures - .getOrElse(throw InvalidStepStateException( - RecommendationPipelineConfig.fetchQueryFeaturesPhase2Step, - "QueryFeatures")) - .asyncFeatureMap ++ executorResult.asyncFeatureMap) - ), - context - ), - asyncFeaturesStep(RecommendationPipelineConfig.candidatePipelinesStep, context), - candidatePipelinesStep( - candidatePipelines, - config.defaultFailOpenPolicy, - config.candidatePipelineFailOpenPolicies, - qualityFactorObserverByPipeline, - context), - asyncFeaturesStep(RecommendationPipelineConfig.dependentCandidatePipelinesStep, context), - dependentCandidatePipelinesStep( - dependentCandidatePipelines, - config.defaultFailOpenPolicy, - config.candidatePipelineFailOpenPolicies, - qualityFactorObserverByPipeline, - context), - asyncFeaturesStep(RecommendationPipelineConfig.postCandidatePipelinesSelectorsStep, context), - postCandidatePipelinesSelectorStep(config.postCandidatePipelinesSelectors, context), - asyncFeaturesStep( - RecommendationPipelineConfig.postCandidatePipelinesFeatureHydrationStep, - context), - postCandidatePipelinesFeatureHydrationStep( - config.postCandidatePipelinesFeatureHydration, - context), - asyncFeaturesStep(RecommendationPipelineConfig.globalFiltersStep, context), - globalFiltersStep(config.globalFilters, context), - asyncFeaturesStep(RecommendationPipelineConfig.scoringPipelinesStep, context), - scoringPipelinesStep( - scoringPipelines, - context, - config.defaultFailOpenPolicy, - config.scoringPipelineFailOpenPolicies, - qualityFactorObserverByPipeline - ), - asyncFeaturesStep(RecommendationPipelineConfig.resultSelectorsStep, context), - resultSelectorsStep(config.resultSelectors, context), - asyncFeaturesStep(RecommendationPipelineConfig.postSelectionFiltersStep, context), - postSelectionFiltersStep(config.postSelectionFilters, context), - asyncFeaturesStep(RecommendationPipelineConfig.decoratorStep, context), - decoratorStep(decorator, context), - domainMarshallingStep(config.domainMarshaller, context), - asyncFeaturesStep(RecommendationPipelineConfig.resultSideEffectsStep, context), - resultSideEffectsStep(config.resultSideEffects, context), - transportMarshallingStep(config.transportMarshaller, context) - ) - - val finalArrow = buildCombinedArrowFromSteps( - steps = builtSteps, - context = context, - initialEmptyResult = RecommendationPipelineResult.empty, - stepsInOrderFromConfig = RecommendationPipelineConfig.stepsInOrder - ) - - val configFromBuilder = config - new RecommendationPipeline[Query, Candidate, Result] { - override private[core] val config: RecommendationPipelineConfig[ - Query, - Candidate, - _, - Result - ] = - configFromBuilder - override val arrow: Arrow[Query, RecommendationPipelineResult[Candidate, Result]] = - finalArrow - override val identifier: RecommendationPipelineIdentifier = pipelineIdentifier - override val alerts: Seq[Alert] = config.alerts - override val children: Seq[Component] = - config.gates ++ - config.fetchQueryFeatures ++ - candidatePipelines ++ - dependentCandidatePipelines ++ - config.postCandidatePipelinesFeatureHydration ++ - config.globalFilters ++ - scoringPipelines ++ - config.postSelectionFilters ++ - config.resultSideEffects ++ - decorator.toSeq ++ - Seq(config.domainMarshaller, config.transportMarshaller) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala deleted file mode 100644 index 6df35985a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineBuilderFactory.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.recommendation - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineBuilderFactory -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineBuilderFactory -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutor -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class RecommendationPipelineBuilderFactory @Inject() ( - candidatePipelineExecutor: CandidatePipelineExecutor, - gateExecutor: GateExecutor, - selectorExecutor: SelectorExecutor, - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor, - asyncFeatureMapExecutor: AsyncFeatureMapExecutor, - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor, - filterExecutor: FilterExecutor, - scoringPipelineExecutor: ScoringPipelineExecutor, - candidateDecoratorExecutor: CandidateDecoratorExecutor, - domainMarshallerExecutor: DomainMarshallerExecutor, - transportMarshallerExecutor: TransportMarshallerExecutor, - pipelineResultSideEffectExecutor: PipelineResultSideEffectExecutor, - candidatePipelineBuilderFactory: CandidatePipelineBuilderFactory, - scoringPipelineBuilderFactory: ScoringPipelineBuilderFactory, - statsReceiver: StatsReceiver) { - - def get[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - DomainResultType <: HasMarshalling, - Result - ]: RecommendationPipelineBuilder[Query, Candidate, DomainResultType, Result] = { - new RecommendationPipelineBuilder[Query, Candidate, DomainResultType, Result]( - candidatePipelineExecutor, - gateExecutor, - selectorExecutor, - queryFeatureHydratorExecutor, - asyncFeatureMapExecutor, - candidateFeatureHydratorExecutor, - filterExecutor, - scoringPipelineExecutor, - candidateDecoratorExecutor, - domainMarshallerExecutor, - transportMarshallerExecutor, - pipelineResultSideEffectExecutor, - candidatePipelineBuilderFactory, - scoringPipelineBuilderFactory, - statsReceiver - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala deleted file mode 100644 index 1e2fa59c2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineConfig.scala +++ /dev/null @@ -1,262 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.recommendation - -import com.twitter.product_mixer.component_library.selector.InsertAppendResults -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.functional_component.gate.Gate -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.RecommendationPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.PipelineConfig -import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.candidate.DependentCandidatePipelineConfig -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineConfig -import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig - -/** - * This is the configuration necessary to generate a Recommendation Pipeline. Product code should create a - * RecommendationPipelineConfig, and then use a RecommendationPipelineBuilder to get the final RecommendationPipeline which can - * process requests. - * - * @tparam Query - The domain model for the query or request - * @tparam Candidate - The type of the candidates that the Candidate Pipelines are generating - * @tparam UnmarshalledResultType - The result type of the pipeline, but before marshalling to a wire protocol like URT - * @tparam Result - The final result that will be served to users - */ -trait RecommendationPipelineConfig[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - UnmarshalledResultType <: HasMarshalling, - Result] - extends PipelineConfig { - - override val identifier: RecommendationPipelineIdentifier - - /** - * Recommendation Pipeline Gates will be executed before any other step (including retrieval from candidate - * pipelines). They're executed sequentially, and any "Stop" result will prevent pipeline execution. - */ - def gates: Seq[Gate[Query]] = Seq.empty - - /** - * A recommendation pipeline can fetch query-level features before candidate pipelines are executed. - */ - def fetchQueryFeatures: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty - - /** - * Candidate pipelines retrieve candidates for possible inclusion in the result - */ - def fetchQueryFeaturesPhase2: Seq[BaseQueryFeatureHydrator[Query, _]] = Seq.empty - - /** - * What candidate pipelines should this Recommendations Pipeline get candidate from? - */ - def candidatePipelines: Seq[CandidatePipelineConfig[Query, _, _, _]] - - /** - * Dependent candidate pipelines to retrieve candidates that depend on the result of [[candidatePipelines]] - * [[DependentCandidatePipelineConfig]] have access to the list of previously retrieved & decorated - * candidates for use in constructing the query object. - */ - def dependentCandidatePipelines: Seq[DependentCandidatePipelineConfig[Query, _, _, _]] = Seq.empty - - /** - * Takes final ranked list of candidates & apply any business logic (e.g, deduplicating and merging - * candidates before scoring). - */ - def postCandidatePipelinesSelectors: Seq[Selector[Query]] = Seq(InsertAppendResults(AllPipelines)) - - /** - * After selectors are run, you can fetch features for each candidate. - * The existing features from previous hydrations are passed in as inputs. You are not expected to - * put them into the resulting feature map yourself - they will be merged for you by the platform. - */ - def postCandidatePipelinesFeatureHydration: Seq[ - BaseCandidateFeatureHydrator[Query, Candidate, _] - ] = - Seq.empty - - /** - * Global filters to run on all candidates. - */ - def globalFilters: Seq[Filter[Query, Candidate]] = Seq.empty - - /** - * By default, a Recommendation Pipeline will fail closed - if any candidate or scoring - * pipeline fails to return a result, then the Recommendation Pipeline will not return a result. - * You can adjust this default policy, or provide specific policies to specific pipelines. - * Those specific policies will take priority. - * - * FailOpenPolicy.All will always fail open (the RecommendationPipeline will continue without that pipeline) - * FailOpenPolicy.Never will always fail closed (the RecommendationPipeline will fail if that pipeline fails) - * - * There's a default policy, and a specific Map of policies that takes precedence. - */ - def defaultFailOpenPolicy: FailOpenPolicy = FailOpenPolicy(Set(ClosedGate)) - def candidatePipelineFailOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy] = - Map.empty - def scoringPipelineFailOpenPolicies: Map[ScoringPipelineIdentifier, FailOpenPolicy] = Map.empty - - /** - ** [[qualityFactorConfigs]] associates [[QualityFactorConfig]]s to specific candidate pipelines - * using [[ComponentIdentifier]]. - */ - def qualityFactorConfigs: Map[ComponentIdentifier, QualityFactorConfig] = - Map.empty - - /** - * Scoring pipelines for scoring candidates. - * @note These do not drop or re-order candidates, you should do those in the sub-sequent selectors - * step based off of the scores on candidates set in those [[ScoringPipeline]]s. - */ - def scoringPipelines: Seq[ScoringPipelineConfig[Query, Candidate]] - - /** - * Takes final ranked list of candidates & apply any business logic (e.g, capping number - * of ad accounts or pacing ad accounts). - */ - def resultSelectors: Seq[Selector[Query]] - - /** - * Takes the final selected list of candidates and applies a final list of filters. - * Useful for doing very expensive filtering at the end of your pipeline. - */ - def postSelectionFilters: Seq[Filter[Query, Candidate]] = Seq.empty - - /** - * Decorators allow for adding Presentations to candidates. While the Presentation can contain any - * arbitrary data, Decorators are often used to add a UrtItemPresentation for URT item support. Most - * customers will prefer to set a decorator in their respective candidate pipeline, however, a final - * global one is available for those that do global decoration as late possible to avoid unnecessary hydrations. - * @note This decorator can only return an ItemPresentation. - * @note This decorator cannot decorate an already decorated candidate from the prior decorator - * step in candidate pipelines. - */ - def decorator: Option[CandidateDecorator[Query, Candidate]] = None - - /** - * Domain marshaller transforms the selections into the model expected by the marshaller - */ - def domainMarshaller: DomainMarshaller[Query, UnmarshalledResultType] - - /** - * Mixer result side effects that are executed after selection and domain marshalling - */ - def resultSideEffects: Seq[PipelineResultSideEffect[Query, UnmarshalledResultType]] = Seq() - - /** - * Transport marshaller transforms the model into our line-level API like URT or JSON - */ - def transportMarshaller: TransportMarshaller[UnmarshalledResultType, Result] - - /** - * A pipeline can define a partial function to rescue failures here. They will be treated as failures - * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here). - */ - def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty - - /** - * Alerts can be used to indicate the pipeline's service level objectives. Alerts and - * dashboards will be automatically created based on this information. - */ - val alerts: Seq[Alert] = Seq.empty - - /** - * This method is used by the product mixer framework to build the pipeline. - */ - private[core] final def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - builder: RecommendationPipelineBuilderFactory - ): RecommendationPipeline[Query, Candidate, Result] = - builder.get.build(parentComponentIdentifierStack, this) -} - -object RecommendationPipelineConfig extends PipelineConfigCompanion { - val qualityFactorStep: PipelineStepIdentifier = PipelineStepIdentifier("QualityFactor") - val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates") - val fetchQueryFeaturesStep: PipelineStepIdentifier = PipelineStepIdentifier("FetchQueryFeatures") - val fetchQueryFeaturesPhase2Step: PipelineStepIdentifier = PipelineStepIdentifier( - "FetchQueryFeaturesPhase2") - val candidatePipelinesStep: PipelineStepIdentifier = PipelineStepIdentifier("CandidatePipelines") - val dependentCandidatePipelinesStep: PipelineStepIdentifier = - PipelineStepIdentifier("DependentCandidatePipelines") - val postCandidatePipelinesSelectorsStep: PipelineStepIdentifier = - PipelineStepIdentifier("PostCandidatePipelinesSelectors") - val postCandidatePipelinesFeatureHydrationStep: PipelineStepIdentifier = - PipelineStepIdentifier("PostCandidatePipelinesFeatureHydration") - val globalFiltersStep: PipelineStepIdentifier = PipelineStepIdentifier("GlobalFilters") - val scoringPipelinesStep: PipelineStepIdentifier = PipelineStepIdentifier("ScoringPipelines") - val resultSelectorsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSelectors") - val postSelectionFiltersStep: PipelineStepIdentifier = PipelineStepIdentifier( - "PostSelectionFilters") - val decoratorStep: PipelineStepIdentifier = PipelineStepIdentifier("Decorator") - val domainMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier("DomainMarshaller") - val resultSideEffectsStep: PipelineStepIdentifier = PipelineStepIdentifier("ResultSideEffects") - val transportMarshallerStep: PipelineStepIdentifier = PipelineStepIdentifier( - "TransportMarshaller") - - /** All the Steps which are executed by a [[RecommendationPipeline]] in the order in which they are run */ - override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq( - qualityFactorStep, - gatesStep, - fetchQueryFeaturesStep, - fetchQueryFeaturesPhase2Step, - asyncFeaturesStep(candidatePipelinesStep), - candidatePipelinesStep, - asyncFeaturesStep(dependentCandidatePipelinesStep), - dependentCandidatePipelinesStep, - asyncFeaturesStep(postCandidatePipelinesSelectorsStep), - postCandidatePipelinesSelectorsStep, - asyncFeaturesStep(postCandidatePipelinesFeatureHydrationStep), - postCandidatePipelinesFeatureHydrationStep, - asyncFeaturesStep(globalFiltersStep), - globalFiltersStep, - asyncFeaturesStep(scoringPipelinesStep), - scoringPipelinesStep, - asyncFeaturesStep(resultSelectorsStep), - resultSelectorsStep, - asyncFeaturesStep(postSelectionFiltersStep), - postSelectionFiltersStep, - asyncFeaturesStep(decoratorStep), - decoratorStep, - domainMarshallerStep, - asyncFeaturesStep(resultSideEffectsStep), - resultSideEffectsStep, - transportMarshallerStep - ) - - /** - * All the Steps which an [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator AsyncHydrator]] - * can be configured to [[com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator.hydrateBefore hydrateBefore]] - */ - override val stepsAsyncFeatureHydrationCanBeCompletedBy: Set[PipelineStepIdentifier] = Set( - candidatePipelinesStep, - dependentCandidatePipelinesStep, - postCandidatePipelinesSelectorsStep, - postCandidatePipelinesFeatureHydrationStep, - globalFiltersStep, - scoringPipelinesStep, - resultSelectorsStep, - postSelectionFiltersStep, - decoratorStep, - resultSideEffectsStep, - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala deleted file mode 100644 index 9e75c8db3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation/RecommendationPipelineResult.scala +++ /dev/null @@ -1,84 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.recommendation - -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.candidate_pipeline_executor.CandidatePipelineExecutorResult -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.quality_factor_executor.QualityFactorExecutorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutorResult -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor - -case class RecommendationPipelineResult[Candidate <: UniversalNoun[Any], ResultType]( - qualityFactorResult: Option[QualityFactorExecutorResult], - gateResult: Option[GateExecutorResult], - queryFeatures: Option[QueryFeatureHydratorExecutor.Result], - queryFeaturesPhase2: Option[QueryFeatureHydratorExecutor.Result], - mergedAsyncQueryFeatures: Option[AsyncFeatureMap], - candidatePipelineResults: Option[CandidatePipelineExecutorResult], - dependentCandidatePipelineResults: Option[CandidatePipelineExecutorResult], - postCandidatePipelinesSelectorResults: Option[SelectorExecutorResult], - postCandidatePipelinesFeatureHydrationResults: Option[ - CandidateFeatureHydratorExecutorResult[Candidate] - ], - globalFilterResults: Option[FilterExecutorResult[Candidate]], - scoringPipelineResults: Option[ScoringPipelineExecutorResult[Candidate]], - resultSelectorResults: Option[SelectorExecutorResult], - postSelectionFilterResults: Option[FilterExecutorResult[Candidate]], - candidateDecoratorResult: Option[CandidateDecoratorExecutorResult], - domainMarshallerResults: Option[DomainMarshallerExecutor.Result[HasMarshalling]], - resultSideEffectResults: Option[PipelineResultSideEffectExecutor.Result], - asyncFeatureHydrationResults: Option[AsyncFeatureMapExecutorResults], - transportMarshallerResults: Option[TransportMarshallerExecutor.Result[ResultType]], - failure: Option[PipelineFailure], - result: Option[ResultType]) - extends PipelineResult[ResultType] { - override val resultSize: Int = result match { - case Some(seqResult @ Seq(_)) => seqResult.length - case Some(_) => 1 - case None => 0 - } - - override def withFailure( - failure: PipelineFailure - ): RecommendationPipelineResult[Candidate, ResultType] = - copy(failure = Some(failure)) - override def withResult(result: ResultType): RecommendationPipelineResult[Candidate, ResultType] = - copy(result = Some(result)) -} - -object RecommendationPipelineResult { - def empty[A <: UniversalNoun[Any], B]: RecommendationPipelineResult[A, B] = - RecommendationPipelineResult( - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD deleted file mode 100644 index 43c431a64..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/selector:insert_append_results", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala deleted file mode 100644 index 9b3bf2a26..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/NewScoringPipelineBuilder.scala +++ /dev/null @@ -1,202 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.scoring - -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult -import com.twitter.product_mixer.core.gate.ParamGate -import com.twitter.product_mixer.core.gate.ParamGate._ -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.NewPipelineBuilder -import com.twitter.product_mixer.core.pipeline.NewPipelineArrowBuilder -import com.twitter.product_mixer.core.pipeline.NewPipelineResult -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.state.HasResult -import com.twitter.product_mixer.core.pipeline.step.candidate_feature_hydrator.CandidateFeatureHydratorStep -import com.twitter.product_mixer.core.pipeline.step.gate.GateStep -import com.twitter.product_mixer.core.pipeline.step.scorer.ScorerStep -import com.twitter.product_mixer.core.pipeline.step.selector.SelectorStep -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject -import scala.collection.immutable.ListMap - -/** - * NewScoringPipelineBuilder builds [[ScoringPipeline]]s from [[ScoringPipelineConfig]]s. - * New because it's meant to eventually replace [[ScoringPipelineBuilder]] - * You should inject a [[ScoringPipelineBuilderFactory]] and call `.get` to build these. - * - * @see [[ScoringPipelineConfig]] for the description of the type parameters - * @tparam Query the type of query these accept. - * @tparam Candidate the domain model for the candidate being scored - */ -class NewScoringPipelineBuilder[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] @Inject() ( - selectionStep: SelectorStep[Query, ScoringPipelineState[Query, Candidate]], - gateStep: GateStep[Query, ScoringPipelineState[Query, Candidate]], - candidateFeatureHydrationStep: CandidateFeatureHydratorStep[ - Query, - Candidate, - ScoringPipelineState[Query, Candidate] - ], - scorerStep: ScorerStep[Query, Candidate, ScoringPipelineState[Query, Candidate]]) - extends NewPipelineBuilder[ScoringPipelineConfig[Query, Candidate], Seq[ - CandidateWithFeatures[Candidate] - ], ScoringPipelineState[Query, Candidate], ScoringPipeline[Query, Candidate]] { - - override def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - arrowBuilder: NewPipelineArrowBuilder[ArrowResult, ArrowState], - scoringPipelineConfig: ScoringPipelineConfig[Query, Candidate] - ): ScoringPipeline[Query, Candidate] = { - val pipelineIdentifier = scoringPipelineConfig.identifier - - val context = Executor.Context( - PipelineFailureClassifier( - scoringPipelineConfig.failureClassifier.orElse( - StoppedGateException.classifier(ClosedGate))), - parentComponentIdentifierStack.push(pipelineIdentifier) - ) - - val enabledGateOpt = scoringPipelineConfig.enabledDeciderParam.map { deciderParam => - ParamGate(pipelineIdentifier + EnabledGateSuffix, deciderParam) - } - val supportedClientGateOpt = scoringPipelineConfig.supportedClientParam.map { param => - ParamGate(pipelineIdentifier + SupportedClientGateSuffix, param) - } - - /** - * Evaluate enabled decider gate first since if it's off, there is no reason to proceed - * Next evaluate supported client feature switch gate, followed by customer configured gates - */ - val allGates = - enabledGateOpt.toSeq ++ supportedClientGateOpt.toSeq ++ scoringPipelineConfig.gates - - val underlyingArrow = arrowBuilder - .add(ScoringPipelineConfig.gatesStep, gateStep, allGates) - .add(ScoringPipelineConfig.selectorsStep, selectionStep, scoringPipelineConfig.selectors) - .add( - ScoringPipelineConfig.preScoringFeatureHydrationPhase1Step, - candidateFeatureHydrationStep, - scoringPipelineConfig.preScoringFeatureHydrationPhase1) - .add( - ScoringPipelineConfig.preScoringFeatureHydrationPhase2Step, - candidateFeatureHydrationStep, - scoringPipelineConfig.preScoringFeatureHydrationPhase2) - .add(ScoringPipelineConfig.scorersStep, scorerStep, scoringPipelineConfig.scorers).buildArrow( - context) - - val finalArrow = Arrow - .map { inputs: ScoringPipeline.Inputs[Query] => - ScoringPipelineState[Query, Candidate](inputs.query, inputs.candidates, ListMap.empty) - }.andThen(underlyingArrow).map { pipelineResult => - ScoringPipelineResult( - gateResults = pipelineResult.executorResultsByPipelineStep - .get(ScoringPipelineConfig.gatesStep) - .map(_.asInstanceOf[GateExecutorResult]), - selectorResults = pipelineResult.executorResultsByPipelineStep - .get(ScoringPipelineConfig.selectorsStep) - .map(_.asInstanceOf[SelectorExecutorResult]), - preScoringHydrationPhase1Result = pipelineResult.executorResultsByPipelineStep - .get(ScoringPipelineConfig.preScoringFeatureHydrationPhase1Step) - .map(_.asInstanceOf[CandidateFeatureHydratorExecutorResult[Candidate]]), - preScoringHydrationPhase2Result = pipelineResult.executorResultsByPipelineStep - .get(ScoringPipelineConfig.preScoringFeatureHydrationPhase2Step) - .map(_.asInstanceOf[CandidateFeatureHydratorExecutorResult[Candidate]]), - scorerResults = pipelineResult.executorResultsByPipelineStep - .get(ScoringPipelineConfig.scorersStep) - .map(_.asInstanceOf[CandidateFeatureHydratorExecutorResult[Candidate]]), - failure = pipelineResult match { - case failure: NewPipelineResult.Failure => - Some(failure.failure) - case _ => None - }, - result = pipelineResult match { - case result: NewPipelineResult.Success[Seq[CandidateWithFeatures[Candidate]]] => - Some(result.result.map { candidateWithFeatures => - ScoredCandidateResult( - candidateWithFeatures.candidate, - candidateWithFeatures.features) - }) - case _ => None - } - ) - } - - new ScoringPipeline[Query, Candidate] { - override val arrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] = - finalArrow - - override val identifier: ScoringPipelineIdentifier = scoringPipelineConfig.identifier - - override val alerts: Seq[Alert] = scoringPipelineConfig.alerts - - override val children: Seq[Component] = - allGates ++ scoringPipelineConfig.preScoringFeatureHydrationPhase1 ++ scoringPipelineConfig.preScoringFeatureHydrationPhase2 ++ scoringPipelineConfig.scorers - - override private[core] val config = scoringPipelineConfig - } - } -} - -case class ScoringPipelineState[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - override val query: Query, - candidates: Seq[ItemCandidateWithDetails], - override val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult]) - extends HasQuery[Query, ScoringPipelineState[Query, Candidate]] - with HasCandidatesWithDetails[ScoringPipelineState[Query, Candidate]] - with HasCandidatesWithFeatures[Candidate, ScoringPipelineState[Query, Candidate]] - with HasExecutorResults[ScoringPipelineState[Query, Candidate]] - with HasResult[Seq[CandidateWithFeatures[Candidate]]] { - - override val candidatesWithDetails: Seq[CandidateWithDetails] = candidates - - override val candidatesWithFeatures: Seq[CandidateWithFeatures[Candidate]] = - candidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]] - - override val buildResult: Seq[CandidateWithFeatures[Candidate]] = candidatesWithFeatures - - override def updateCandidatesWithDetails( - newCandidates: Seq[CandidateWithDetails] - ): ScoringPipelineState[Query, Candidate] = { - this.copy(candidates = newCandidates.asInstanceOf[Seq[ItemCandidateWithDetails]]) - } - - override def updateQuery(newQuery: Query): ScoringPipelineState[Query, Candidate] = - this.copy(query = newQuery) - - override def updateDecorations( - decoration: Seq[Decoration] - ): ScoringPipelineState[Query, Candidate] = ??? - - override def updateCandidatesWithFeatures( - newCandidates: Seq[CandidateWithFeatures[Candidate]] - ): ScoringPipelineState[Query, Candidate] = { - val updatedCandidates = candidates.zip(newCandidates).map { - case (itemCandidateWithDetails, newCandidate) => - itemCandidateWithDetails.copy(features = - itemCandidateWithDetails.features ++ newCandidate.features) - } - this.copy(query, updatedCandidates) - } - - override private[pipeline] def setExecutorResults( - newMap: ListMap[PipelineStepIdentifier, ExecutorResult] - ) = this.copy(executorResultsByPipelineStep = newMap) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala deleted file mode 100644 index a02bbb8b4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipeline.scala +++ /dev/null @@ -1,32 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.scoring - -import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.stitch.Arrow - -/** - * A Scoring Pipeline - * - * This is an abstract class, as we only construct these via the [[ScoringPipelineBuilder]]. - * - * A [[ScoringPipeline]] is capable of pre-filtering candidates for scoring, performing the scoring - * then running selection heuristics (ranking, dropping, etc) based off of the score. - * @tparam Query the domain model for the query or request - * @tparam Candidate the domain model for the candidate being scored - */ -abstract class ScoringPipeline[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends Pipeline[ScoringPipeline.Inputs[Query], Seq[ScoredCandidateResult[Candidate]]] { - override private[core] val config: ScoringPipelineConfig[Query, Candidate] - override val arrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] - override val identifier: ScoringPipelineIdentifier -} - -object ScoringPipeline { - case class Inputs[+Query <: PipelineQuery]( - query: Query, - candidates: Seq[ItemCandidateWithDetails]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala deleted file mode 100644 index d597fa9a5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilder.scala +++ /dev/null @@ -1,367 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.scoring - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult -import com.twitter.product_mixer.core.gate.ParamGate -import com.twitter.product_mixer.core.gate.ParamGate.EnabledGateSuffix -import com.twitter.product_mixer.core.gate.ParamGate.SupportedClientGateSuffix -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.InvalidStepStateException -import com.twitter.product_mixer.core.pipeline.PipelineBuilder -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClosedGate -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipeline.Inputs -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.StoppedGateException -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * ScoringPipelineBuilder builds [[ScoringPipeline]]s from [[ScoringPipelineConfig]]s. - * - * You should inject a [[ScoringPipelineBuilderFactory]] and call `.get` to build these. - * - * @see [[ScoringPipelineConfig]] for the description of the type parameters - * @tparam Query the type of query these accept. - * @tparam Candidate the domain model for the candidate being scored - */ -class ScoringPipelineBuilder[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] @Inject() ( - gateExecutor: GateExecutor, - selectorExecutor: SelectorExecutor, - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor, - override val statsReceiver: StatsReceiver) - extends PipelineBuilder[Inputs[Query]] { - - override type UnderlyingResultType = Seq[ScoredCandidateResult[Candidate]] - override type PipelineResultType = ScoringPipelineResult[Candidate] - - def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - config: ScoringPipelineConfig[Query, Candidate] - ): ScoringPipeline[Query, Candidate] = { - - val pipelineIdentifier = config.identifier - - val context = Executor.Context( - PipelineFailureClassifier( - config.failureClassifier.orElse(StoppedGateException.classifier(ClosedGate))), - parentComponentIdentifierStack.push(pipelineIdentifier) - ) - - val enabledGateOpt = config.enabledDeciderParam.map { deciderParam => - ParamGate(pipelineIdentifier + EnabledGateSuffix, deciderParam) - } - val supportedClientGateOpt = config.supportedClientParam.map { param => - ParamGate(pipelineIdentifier + SupportedClientGateSuffix, param) - } - - /** - * Evaluate enabled decider gate first since if it's off, there is no reason to proceed - * Next evaluate supported client feature switch gate, followed by customer configured gates - */ - val allGates = enabledGateOpt.toSeq ++ supportedClientGateOpt.toSeq ++ config.gates - - val GatesStep = new Step[Query, GateExecutorResult] { - override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.gatesStep - - override lazy val executorArrow: Arrow[Query, GateExecutorResult] = - gateExecutor.arrow(allGates, context) - - override def inputAdaptor( - query: ScoringPipeline.Inputs[Query], - previousResult: ScoringPipelineResult[Candidate] - ): Query = { - query.query - } - - override def resultUpdater( - previousPipelineResult: ScoringPipelineResult[Candidate], - executorResult: GateExecutorResult - ): ScoringPipelineResult[Candidate] = - previousPipelineResult.copy(gateResults = Some(executorResult)) - } - - val SelectorsStep = new Step[SelectorExecutor.Inputs[Query], SelectorExecutorResult] { - override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.selectorsStep - - override def executorArrow: Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = - selectorExecutor.arrow(config.selectors, context) - - override def inputAdaptor( - query: ScoringPipeline.Inputs[Query], - previousResult: ScoringPipelineResult[Candidate] - ): SelectorExecutor.Inputs[Query] = SelectorExecutor.Inputs(query.query, query.candidates) - - override def resultUpdater( - previousPipelineResult: ScoringPipelineResult[Candidate], - executorResult: SelectorExecutorResult - ): ScoringPipelineResult[Candidate] = - previousPipelineResult.copy(selectorResults = Some(executorResult)) - } - - val PreScoringFeatureHydrationPhase1Step = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] { - override def identifier: PipelineStepIdentifier = - ScoringPipelineConfig.preScoringFeatureHydrationPhase1Step - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] = - candidateFeatureHydratorExecutor.arrow(config.preScoringFeatureHydrationPhase1, context) - - override def inputAdaptor( - query: ScoringPipeline.Inputs[Query], - previousResult: ScoringPipelineResult[Candidate] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = { - val selectedCandidatesResult = previousResult.selectorResults.getOrElse { - throw InvalidStepStateException(identifier, "SelectorResults") - }.selectedCandidates - - CandidateFeatureHydratorExecutor.Inputs( - query.query, - selectedCandidatesResult.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]) - } - - override def resultUpdater( - previousPipelineResult: ScoringPipelineResult[Candidate], - executorResult: CandidateFeatureHydratorExecutorResult[Candidate] - ): ScoringPipelineResult[Candidate] = previousPipelineResult.copy( - preScoringHydrationPhase1Result = Some(executorResult) - ) - } - - val PreScoringFeatureHydrationPhase2Step = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] { - override def identifier: PipelineStepIdentifier = - ScoringPipelineConfig.preScoringFeatureHydrationPhase2Step - - override def executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] = - candidateFeatureHydratorExecutor.arrow(config.preScoringFeatureHydrationPhase2, context) - - override def inputAdaptor( - query: ScoringPipeline.Inputs[Query], - previousResult: ScoringPipelineResult[Candidate] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = { - val preScoringHydrationPhase1FeatureMaps: Seq[FeatureMap] = - previousResult.preScoringHydrationPhase1Result - .getOrElse( - throw InvalidStepStateException(identifier, "PreScoringHydrationPhase1Result")) - .results.map(_.features) - - val itemCandidates = previousResult.selectorResults - .getOrElse(throw InvalidStepStateException(identifier, "SelectionResults")) - .selectedCandidates.collect { - case itemCandidate: ItemCandidateWithDetails => itemCandidate - } - // If there is no feature hydration (empty results), no need to attempt merging. - val candidates = if (preScoringHydrationPhase1FeatureMaps.isEmpty) { - itemCandidates - } else { - itemCandidates.zip(preScoringHydrationPhase1FeatureMaps).map { - case (itemCandidate, featureMap) => - itemCandidate.copy(features = itemCandidate.features ++ featureMap) - } - } - - CandidateFeatureHydratorExecutor.Inputs( - query.query, - candidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]) - } - - override def resultUpdater( - previousPipelineResult: ScoringPipelineResult[Candidate], - executorResult: CandidateFeatureHydratorExecutorResult[Candidate] - ): ScoringPipelineResult[Candidate] = previousPipelineResult.copy( - preScoringHydrationPhase2Result = Some(executorResult) - ) - } - - def getMergedPreScoringFeatureMap( - stepIdentifier: PipelineStepIdentifier, - previousResult: ScoringPipelineResult[Candidate] - ): Seq[FeatureMap] = { - val preScoringHydrationPhase1FeatureMaps: Seq[FeatureMap] = - previousResult.preScoringHydrationPhase1Result - .getOrElse( - throw InvalidStepStateException( - stepIdentifier, - "PreScoringHydrationPhase1Result")).results.map(_.features) - - val preScoringHydrationPhase2FeatureMaps: Seq[FeatureMap] = - previousResult.preScoringHydrationPhase2Result - .getOrElse( - throw InvalidStepStateException( - stepIdentifier, - "PreScoringHydrationPhase2Result")).results.map(_.features) - /* - * If either pre-scoring hydration phase feature map is empty, no need to merge them, - * we can just take all non-empty ones. - */ - if (preScoringHydrationPhase1FeatureMaps.isEmpty) { - preScoringHydrationPhase2FeatureMaps - } else if (preScoringHydrationPhase2FeatureMaps.isEmpty) { - preScoringHydrationPhase1FeatureMaps - } else { - // No need to check the size in both, since the inputs to both hydration phases are the - // same and each phase ensures the number of candidates and ordering matches the input. - preScoringHydrationPhase1FeatureMaps.zip(preScoringHydrationPhase2FeatureMaps).map { - case (preScoringHydrationPhase1FeatureMap, preScoringHydrationPhasesFeatureMap) => - preScoringHydrationPhase1FeatureMap ++ preScoringHydrationPhasesFeatureMap - } - } - } - - val ScorersStep = - new Step[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] { - override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.scorersStep - - override def inputAdaptor( - query: ScoringPipeline.Inputs[Query], - previousResult: ScoringPipelineResult[Candidate] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = { - - val mergedPreScoringFeatureHydrationFeatures: Seq[FeatureMap] = - getMergedPreScoringFeatureMap(ScoringPipelineConfig.scorersStep, previousResult) - - val itemCandidates = previousResult.selectorResults - .getOrElse(throw InvalidStepStateException(identifier, "SelectionResults")) - .selectedCandidates.collect { - case itemCandidate: ItemCandidateWithDetails => itemCandidate - } - - // If there was no pre-scoring features hydration, no need to re-merge feature maps - // and construct a new item candidate - val updatedCandidates = if (mergedPreScoringFeatureHydrationFeatures.isEmpty) { - itemCandidates - } else { - itemCandidates.zip(mergedPreScoringFeatureHydrationFeatures).map { - case (itemCandidate, preScoringFeatureMap) => - itemCandidate.copy(features = itemCandidate.features ++ preScoringFeatureMap) - } - } - CandidateFeatureHydratorExecutor.Inputs( - query.query, - updatedCandidates.asInstanceOf[Seq[CandidateWithFeatures[Candidate]]]) - } - - override lazy val executorArrow: Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[ - Candidate - ] - ] = candidateFeatureHydratorExecutor.arrow(config.scorers.toSeq, context) - - override def resultUpdater( - previousPipelineResult: ScoringPipelineResult[Candidate], - executorResult: CandidateFeatureHydratorExecutorResult[Candidate] - ): ScoringPipelineResult[Candidate] = - previousPipelineResult.copy(scorerResults = Some(executorResult)) - } - - val ResultStep = - new Step[Seq[CandidateWithFeatures[UniversalNoun[Any]]], Seq[ - CandidateWithFeatures[UniversalNoun[Any]] - ]] { - override def identifier: PipelineStepIdentifier = ScoringPipelineConfig.resultStep - - override def executorArrow: Arrow[Seq[CandidateWithFeatures[UniversalNoun[Any]]], Seq[ - CandidateWithFeatures[UniversalNoun[Any]] - ]] = Arrow.identity - - override def inputAdaptor( - query: Inputs[Query], - previousResult: ScoringPipelineResult[Candidate] - ): Seq[CandidateWithFeatures[UniversalNoun[Any]]] = previousResult.selectorResults - .getOrElse(throw InvalidStepStateException(identifier, "SelectionResults")) - .selectedCandidates.collect { - case itemCandidate: ItemCandidateWithDetails => itemCandidate - } - - override def resultUpdater( - previousPipelineResult: ScoringPipelineResult[Candidate], - executorResult: Seq[CandidateWithFeatures[UniversalNoun[Any]]] - ): ScoringPipelineResult[Candidate] = { - val scorerResults: Seq[FeatureMap] = previousPipelineResult.scorerResults - .getOrElse(throw InvalidStepStateException(identifier, "ScorerResult")).results.map( - _.features) - - val mergedPreScoringFeatureHydrationFeatureMaps: Seq[FeatureMap] = - getMergedPreScoringFeatureMap(ScoringPipelineConfig.resultStep, previousPipelineResult) - - val itemCandidates = executorResult.asInstanceOf[Seq[ItemCandidateWithDetails]] - val finalFeatureMap = if (mergedPreScoringFeatureHydrationFeatureMaps.isEmpty) { - scorerResults - } else { - scorerResults - .zip(mergedPreScoringFeatureHydrationFeatureMaps).map { - case (preScoringFeatureMap, scoringFeatureMap) => - preScoringFeatureMap ++ scoringFeatureMap - } - } - - val finalResults = itemCandidates.zip(finalFeatureMap).map { - case (itemCandidate, featureMap) => - ScoredCandidateResult(itemCandidate.candidate.asInstanceOf[Candidate], featureMap) - } - previousPipelineResult.withResult(finalResults) - } - } - - val builtSteps = Seq( - GatesStep, - SelectorsStep, - PreScoringFeatureHydrationPhase1Step, - PreScoringFeatureHydrationPhase2Step, - ScorersStep, - ResultStep - ) - - /** The main execution logic for this Candidate Pipeline. */ - val finalArrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] = - buildCombinedArrowFromSteps( - steps = builtSteps, - context = context, - initialEmptyResult = ScoringPipelineResult.empty, - stepsInOrderFromConfig = ScoringPipelineConfig.stepsInOrder - ) - - val configFromBuilder = config - new ScoringPipeline[Query, Candidate] { - override private[core] val config: ScoringPipelineConfig[Query, Candidate] = configFromBuilder - override val arrow: Arrow[ScoringPipeline.Inputs[Query], ScoringPipelineResult[Candidate]] = - finalArrow - override val identifier: ScoringPipelineIdentifier = pipelineIdentifier - override val alerts: Seq[Alert] = config.alerts - override val children: Seq[Component] = - allGates ++ config.preScoringFeatureHydrationPhase1 ++ config.preScoringFeatureHydrationPhase2 ++ config.scorers - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala deleted file mode 100644 index 5b65d0738..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineBuilderFactory.scala +++ /dev/null @@ -1,30 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.scoring - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ScoringPipelineBuilderFactory @Inject() ( - gateExecutor: GateExecutor, - selectorExecutor: SelectorExecutor, - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor, - statsReceiver: StatsReceiver) { - - def get[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] - ]: ScoringPipelineBuilder[Query, Candidate] = { - new ScoringPipelineBuilder[Query, Candidate]( - gateExecutor, - selectorExecutor, - candidateFeatureHydratorExecutor, - statsReceiver - ) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala deleted file mode 100644 index d2b87e01b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineConfig.scala +++ /dev/null @@ -1,131 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.scoring - -import com.twitter.product_mixer.component_library.selector.InsertAppendResults -import com.twitter.product_mixer.core.functional_component.common.AllPipelines -import com.twitter.product_mixer.core.functional_component.common.alert.Alert -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineConfig -import com.twitter.product_mixer.core.pipeline.PipelineConfigCompanion -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.DeciderParam - -/** - * This is the configuration necessary to generate a Scoring Pipeline. Product code should create a - * ScoringPipelineConfig, and then use a ScoringPipelineBuilder to get the final ScoringPipeline which can - * process requests. - * - * @tparam Query - The domain model for the query or request - * @tparam Candidate the domain model for the candidate being scored - */ -trait ScoringPipelineConfig[-Query <: PipelineQuery, Candidate <: UniversalNoun[Any]] - extends PipelineConfig { - - override val identifier: ScoringPipelineIdentifier - - /** - * When these Params are defined, they will automatically be added as Gates in the pipeline - * by the CandidatePipelineBuilder - * - * The enabled decider param can to be used to quickly disable a Candidate Pipeline via Decider - */ - val enabledDeciderParam: Option[DeciderParam[Boolean]] = None - - /** - * This supported client feature switch param can be used with a Feature Switch to control the - * rollout of a new Candidate Pipeline from dogfood to experiment to production - */ - val supportedClientParam: Option[FSParam[Boolean]] = None - - /** [[BaseGate]]s that are applied sequentially, the pipeline will only run if all the Gates are open */ - def gates: Seq[BaseGate[Query]] = Seq.empty - - /** - * Logic for selecting which candidates to score. Note, this doesn't drop the candidates from - * the final result, just whether to score it in this pipeline or not. - */ - def selectors: Seq[Selector[Query]] - - /** - * After selectors are run, you can fetch features for each candidate. - * The existing features from previous hydrations are passed in as inputs. You are not expected to - * put them into the resulting feature map yourself - they will be merged for you by the platform. - */ - def preScoringFeatureHydrationPhase1: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] = - Seq.empty - - /** - * A second phase of feature hydration that can be run after selection and after the first phase - * of pre-scoring feature hydration. You are not expected to put them into the resulting - * feature map yourself - they will be merged for you by the platform. - */ - def preScoringFeatureHydrationPhase2: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] = - Seq.empty - - /** - * Ranker Function for candidates. Scorers are executed in parallel. - * Note: Order does not matter, this could be a Set if Set was covariant over it's type. - */ - def scorers: Seq[Scorer[Query, Candidate]] - - /** - * A pipeline can define a partial function to rescue failures here. They will be treated as failures - * from a monitoring standpoint, and cancellation exceptions will always be propagated (they cannot be caught here). - */ - def failureClassifier: PartialFunction[Throwable, PipelineFailure] = PartialFunction.empty - - /** - * Alerts can be used to indicate the pipeline's service level objectives. Alerts and - * dashboards will be automatically created based on this information. - */ - val alerts: Seq[Alert] = Seq.empty - - /** - * This method is used by the product mixer framework to build the pipeline. - */ - private[core] final def build( - parentComponentIdentifierStack: ComponentIdentifierStack, - builder: ScoringPipelineBuilderFactory - ): ScoringPipeline[Query, Candidate] = - builder.get.build(parentComponentIdentifierStack, this) -} - -object ScoringPipelineConfig extends PipelineConfigCompanion { - def apply[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - scorer: Scorer[Query, Candidate] - ): ScoringPipelineConfig[Query, Candidate] = new ScoringPipelineConfig[Query, Candidate] { - override val identifier: ScoringPipelineIdentifier = ScoringPipelineIdentifier( - s"ScoreAll${scorer.identifier.name}") - - override val selectors: Seq[Selector[Query]] = Seq(InsertAppendResults(AllPipelines)) - - override val scorers: Seq[Scorer[Query, Candidate]] = Seq(scorer) - } - - val gatesStep: PipelineStepIdentifier = PipelineStepIdentifier("Gates") - val selectorsStep: PipelineStepIdentifier = PipelineStepIdentifier("Selectors") - val preScoringFeatureHydrationPhase1Step: PipelineStepIdentifier = - PipelineStepIdentifier("PreScoringFeatureHydrationPhase1") - val preScoringFeatureHydrationPhase2Step: PipelineStepIdentifier = - PipelineStepIdentifier("PreScoringFeatureHydrationPhase2") - val scorersStep: PipelineStepIdentifier = PipelineStepIdentifier("Scorers") - val resultStep: PipelineStepIdentifier = PipelineStepIdentifier("Result") - - /** All the Steps which are executed by a [[ScoringPipeline]] in the order in which they are run */ - override val stepsInOrder: Seq[PipelineStepIdentifier] = Seq( - gatesStep, - selectorsStep, - preScoringFeatureHydrationPhase1Step, - preScoringFeatureHydrationPhase2Step, - scorersStep, - resultStep - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala deleted file mode 100644 index ca1585b4c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring/ScoringPipelineResult.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.scoring - -import com.twitter.product_mixer.core.functional_component.scorer.ScoredCandidateResult -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult - -/** - * The Results of every step during the ScoringPipeline process. The end result contains - * only the candidates that were actually scored (e.g, not dropped by a filter) with an updated, - * combined feature map of all features that were passed in with the candidate plus all features - * returned as part of scoring. - */ -case class ScoringPipelineResult[Candidate <: UniversalNoun[Any]]( - gateResults: Option[GateExecutorResult], - selectorResults: Option[SelectorExecutorResult], - preScoringHydrationPhase1Result: Option[CandidateFeatureHydratorExecutorResult[Candidate]], - preScoringHydrationPhase2Result: Option[CandidateFeatureHydratorExecutorResult[Candidate]], - scorerResults: Option[CandidateFeatureHydratorExecutorResult[ - Candidate - ]], - failure: Option[PipelineFailure], - result: Option[Seq[ScoredCandidateResult[Candidate]]]) - extends PipelineResult[Seq[ScoredCandidateResult[Candidate]]] { - override val resultSize: Int = result.map(_.size).getOrElse(0) - - override def withFailure( - failure: PipelineFailure - ): ScoringPipelineResult[Candidate] = - copy(failure = Some(failure)) - override def withResult( - result: Seq[ScoredCandidateResult[Candidate]] - ): ScoringPipelineResult[Candidate] = - copy(result = Some(result)) -} - -object ScoringPipelineResult { - def empty[Candidate <: UniversalNoun[Any]]: ScoringPipelineResult[Candidate] = - ScoringPipelineResult( - None, - None, - None, - None, - None, - None, - None - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD deleted file mode 100644 index fe26c9f66..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator:decoration", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator:decoration", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala deleted file mode 100644 index 9ff0ed803..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasAsyncFeatureMap.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap - -trait HasAsyncFeatureMap[State] { - def asyncFeatureMap: AsyncFeatureMap - - private[core] def addAsyncFeatureMap(newFeatureMap: AsyncFeatureMap): State -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala deleted file mode 100644 index 85f2937c7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidates.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.model.common.UniversalNoun - -trait HasCandidates[Candidate <: UniversalNoun[Any], T] { - def candidates: Seq[Candidate] - def updateCandidates(newCandidates: Seq[Candidate]): T -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala deleted file mode 100644 index f91d17bb3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithDetails.scala +++ /dev/null @@ -1,11 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails - -trait HasCandidatesWithDetails[T] { - def candidatesWithDetails: Seq[CandidateWithDetails] - def updateCandidatesWithDetails(newCandidates: Seq[CandidateWithDetails]): T - - def updateDecorations(decoration: Seq[Decoration]): T -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala deleted file mode 100644 index 1fa327e6b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasCandidatesWithFeatures.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun - -trait HasCandidatesWithFeatures[Candidate <: UniversalNoun[Any], T] { - def candidatesWithFeatures: Seq[CandidateWithFeatures[Candidate]] - def updateCandidatesWithFeatures(newCandidates: Seq[CandidateWithFeatures[Candidate]]): T -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala deleted file mode 100644 index c22dbe11c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasExecutorResults.scala +++ /dev/null @@ -1,13 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.service.ExecutorResult -import scala.collection.immutable.ListMap - -trait HasExecutorResults[State] { - // We use a list map to maintain the insertion order - val executorResultsByPipelineStep: ListMap[PipelineStepIdentifier, ExecutorResult] - private[pipeline] def setExecutorResults( - newMap: ListMap[PipelineStepIdentifier, ExecutorResult] - ): State -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala deleted file mode 100644 index 42f7f0062..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasParams.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.timelines.configapi.Params - -trait HasParams { - def params: Params -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala deleted file mode 100644 index 89e9bd94e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasQuery.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait HasQuery[Query <: PipelineQuery, T] { - def query: Query - def updateQuery(query: Query): T -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala deleted file mode 100644 index 9058f0561..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasRequest.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -import com.twitter.product_mixer.core.model.marshalling.request.Request - -trait HasRequest[TRequest <: Request] { - def request: TRequest -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala deleted file mode 100644 index 0c5f0dfef..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state/HasResult.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.state - -/** - * Defines how to build a result from a pipeline state. Pipeline States should extend this and - * implement [[buildResult]] which computes the final result from their current state. - * @tparam Result Type of result - */ -trait HasResult[+Result] { - def buildResult(): Result -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD deleted file mode 100644 index cbd8c036d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala deleted file mode 100644 index 99aa9ae87..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/Step.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step - -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow - -/** - * A Step within a Pipeline, a Step is a unitary phase within an entire chain that makes up a pipeline. - * @tparam State The request domain model. - * @tparam ExecutorConfig The configs that should be passed into the executor at build time. - * @tparam ExecutorInput The input type that an executor takes at request time. - * @tparam ExResult The result that a step's executor will return. - * @tparam OutputState The final/updated state a step would output, this is typically taking the ExResult - * and mutating/transforming the State. - */ -trait Step[State, -Config, ExecutorInput, ExResult <: ExecutorResult] { - - /** - * Adapt the state into the expected input for the Step's Arrow. - * - * @param state State object passed into the Step. - * @param config The config object used to build the executor arrow or input. - * @return ExecutorInput that is used in the arrow of the underlying executor. - */ - def adaptInput(state: State, config: Config): ExecutorInput - - /** - * The actual arrow to be executed for the step, taking in the adapted input from [[adaptInput]] - * and returning the expected result. - * @param config Runtime configurations to configure the arrow with. - * @param context Context of Executor. - */ - def arrow( - config: Config, - context: Executor.Context - ): Arrow[ExecutorInput, ExResult] - - /** - * Whether the step is considered a noop/empty based off of input being passed in. Empty - * steps are skipped when being executed. - */ - def isEmpty(config: Config): Boolean - - /** - * Update the passed in state based off of the result from [[arrow]] - * @param state State object passed into the Step. - * @param executorResult Executor result returned from [[arrow]] - * @param config The config object used to build the executor arrow or input. - * @return Updated state object passed. - */ - def updateState(state: State, executorResult: ExResult, config: Config): State -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala deleted file mode 100644 index 9f0c787bb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/AsyncFeatureMapStep.scala +++ /dev/null @@ -1,70 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.async_feature_map - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasAsyncFeatureMap -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutor -import com.twitter.product_mixer.core.service.async_feature_map_executor.AsyncFeatureMapExecutorResults -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * Async Feature Hydrator Step, it takes an existing asyn feature map and executes any hydration - * needed before the next step. The state object is responsible for keeping the updated query - * with the updated feature map. - * - * @param asyncFeatureMapExecutor Async feature map executor - * - * @tparam Query Type of PipelineQuery domain model - * @tparam State The pipeline state domain model. - */ -case class AsyncFeatureMapStep[ - Query <: PipelineQuery, - State <: HasQuery[Query, State] with HasAsyncFeatureMap[State]] @Inject() ( - asyncFeatureMapExecutor: AsyncFeatureMapExecutor) - extends Step[ - State, - AsyncFeatureMapStepConfig, - AsyncFeatureMap, - AsyncFeatureMapExecutorResults - ] { - override def isEmpty(config: AsyncFeatureMapStepConfig): Boolean = false - - override def adaptInput( - state: State, - config: AsyncFeatureMapStepConfig - ): AsyncFeatureMap = state.asyncFeatureMap - - override def arrow( - config: AsyncFeatureMapStepConfig, - context: Executor.Context - ): Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = - asyncFeatureMapExecutor.arrow(config.stepToHydrateFor, config.currentStep, context) - - override def updateState( - state: State, - executorResult: AsyncFeatureMapExecutorResults, - config: AsyncFeatureMapStepConfig - ): State = { - val hydratedFeatureMap = - executorResult.featureMapsByStep.getOrElse(config.stepToHydrateFor, FeatureMap.empty) - if (hydratedFeatureMap.isEmpty) { - state - } else { - val updatedFeatureMap = state.query.features - .getOrElse(FeatureMap.empty) ++ hydratedFeatureMap - state.updateQuery( - state.query - .withFeatureMap(updatedFeatureMap).asInstanceOf[Query]) - } - } -} - -case class AsyncFeatureMapStepConfig( - stepToHydrateFor: PipelineStepIdentifier, - currentStep: PipelineStepIdentifier) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel deleted file mode 100644 index 144fc73d8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/async_feature_map/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD deleted file mode 100644 index a15f0c954..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala deleted file mode 100644 index 94c11256d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_feature_hydrator/CandidateFeatureHydratorStep.scala +++ /dev/null @@ -1,71 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.candidate_feature_hydrator - -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A candidate level feature hydration step, it takes the input list of candidates and the given - * hydrators and executes them. The [[State]] object is responsible for merging the resulting - * feature maps with the hydrated ones in its updateCandidatesWithFeatures. - * - * @param candidateFeatureHydratorExecutor Hydrator Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam Candidate Type of Candidates to hydrate features for. - * @tparam State The pipeline state domain model. - */ -case class CandidateFeatureHydratorStep[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - State <: HasQuery[Query, State] with HasCandidatesWithFeatures[ - Candidate, - State - ]] @Inject() ( - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor) - extends Step[State, Seq[ - BaseCandidateFeatureHydrator[Query, Candidate, _] - ], CandidateFeatureHydratorExecutor.Inputs[ - Query, - Candidate - ], CandidateFeatureHydratorExecutorResult[Candidate]] { - - override def adaptInput( - state: State, - config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = - CandidateFeatureHydratorExecutor.Inputs(state.query, state.candidatesWithFeatures) - - override def arrow( - config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]], - context: Executor.Context - ): Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] = candidateFeatureHydratorExecutor.arrow(config, context) - - override def updateState( - input: State, - executorResult: CandidateFeatureHydratorExecutorResult[Candidate], - config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] - ): State = { - val candidatesWithHydratedFeatures = executorResult.results - if (candidatesWithHydratedFeatures.isEmpty) { - input - } else { - input.updateCandidatesWithFeatures(candidatesWithHydratedFeatures) - } - } - - override def isEmpty( - config: Seq[BaseCandidateFeatureHydrator[Query, Candidate, _]] - ): Boolean = - config.isEmpty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel deleted file mode 100644 index 933fd47a3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala deleted file mode 100644 index 359ff64cd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/candidate_source/CandidateSourceStep.scala +++ /dev/null @@ -1,84 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.candidate_source - -import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource -import com.twitter.product_mixer.core.functional_component.transformer.BaseCandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutor -import com.twitter.product_mixer.core.service.candidate_source_executor.CandidateSourceExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A candidate source step, which takes the query and gets csandidates from the candidate source. - * - * @param candidateSourceExecutor Candidate Source Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam Candidate Type of Candidates to filter - * @tparam State The pipeline state domain model. - */ -case class CandidateSourceStep[ - Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Candidate <: UniversalNoun[Any], - State <: HasQuery[Query, State] with HasCandidatesWithFeatures[Candidate, State]] @Inject() ( - candidateSourceExecutor: CandidateSourceExecutor) - extends Step[ - State, - CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate], - Query, - CandidateSourceExecutorResult[ - Candidate - ] - ] { - override def isEmpty( - config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate] - ): Boolean = false - - override def adaptInput( - state: State, - config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate] - ): Query = state.query - - override def arrow( - config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate], - context: Executor.Context - ): Arrow[Query, CandidateSourceExecutorResult[Candidate]] = candidateSourceExecutor.arrow( - config.candidateSource, - config.queryTransformer, - config.resultTransformer, - config.resultFeaturesTransformers, - context - ) - - override def updateState( - state: State, - executorResult: CandidateSourceExecutorResult[Candidate], - config: CandidateSourceConfig[Query, CandidateSourceQuery, CandidateSourceResult, Candidate] - ): State = state - .updateQuery( - state.query - .withFeatureMap(executorResult.candidateSourceFeatureMap).asInstanceOf[ - Query]).updateCandidatesWithFeatures(executorResult.candidates) -} - -case class CandidateSourceConfig[ - Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Candidate <: UniversalNoun[Any] -]( - candidateSource: BaseCandidateSource[CandidateSourceQuery, CandidateSourceResult], - queryTransformer: BaseCandidatePipelineQueryTransformer[ - Query, - CandidateSourceQuery - ], - resultTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Candidate], - resultFeaturesTransformers: Seq[CandidateFeatureTransformer[CandidateSourceResult]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel deleted file mode 100644 index 88d9b3be9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala deleted file mode 100644 index 9f77bd110..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/decorator/DecoratorStep.scala +++ /dev/null @@ -1,63 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.decorator - -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutor -import com.twitter.product_mixer.core.service.candidate_decorator_executor.CandidateDecoratorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A candidate decoration step, which takes the query and candidates and outputs decorations for them - * - * @param candidateDecoratorExecutor Candidate Source Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam Candidate Type of Candidates to filter - * @tparam State The pipeline state domain model. - */ -case class DecoratorStep[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - State <: HasQuery[Query, State] with HasCandidatesWithDetails[ - State - ] with HasCandidatesWithFeatures[ - Candidate, - State - ]] @Inject() (candidateDecoratorExecutor: CandidateDecoratorExecutor) - extends Step[ - State, - Option[CandidateDecorator[Query, Candidate]], - (Query, Seq[CandidateWithFeatures[Candidate]]), - CandidateDecoratorExecutorResult - ] { - - override def isEmpty(config: Option[CandidateDecorator[Query, Candidate]]): Boolean = - config.isEmpty - - override def adaptInput( - state: State, - config: Option[CandidateDecorator[Query, Candidate]] - ): (Query, Seq[CandidateWithFeatures[Candidate]]) = - (state.query, state.candidatesWithFeatures) - - override def arrow( - config: Option[CandidateDecorator[Query, Candidate]], - context: Executor.Context - ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] = - candidateDecoratorExecutor.arrow(config, context) - - override def updateState( - state: State, - executorResult: CandidateDecoratorExecutorResult, - config: Option[CandidateDecorator[Query, Candidate]] - ): State = { - state.updateDecorations(executorResult.result) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel deleted file mode 100644 index 35b2606fe..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/BUILD.bazel +++ /dev/null @@ -1,30 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala deleted file mode 100644 index 18fee29a8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/domain_marshaller/DomainMarshallerStep.scala +++ /dev/null @@ -1,54 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.domain_marshaller - -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A domain marshaller step, it takes the input list of candidates and the given - * domain marshaller and executes its to return a marshalled result. The [[State]] object is - * responsible for keeping a reference of the built Response. - * - * @param domainMarshallerExecutor Domain Marshaller executor. - * @tparam Query Type of PipelineQuery domain model - * @tparam ResponseType the domain marshalling type expected to be returned. - * @tparam State The pipeline state domain model. - */ -case class DomainMarshallerStep[ - Query <: PipelineQuery, - ResponseType <: HasMarshalling, - State <: HasQuery[Query, State] with HasCandidatesWithDetails[State]] @Inject() ( - domainMarshallerExecutor: DomainMarshallerExecutor) - extends Step[State, DomainMarshaller[Query, ResponseType], DomainMarshallerExecutor.Inputs[ - Query - ], DomainMarshallerExecutor.Result[ResponseType]] { - - override def isEmpty(config: DomainMarshaller[Query, ResponseType]): Boolean = false - - override def adaptInput( - state: State, - config: DomainMarshaller[Query, ResponseType] - ): DomainMarshallerExecutor.Inputs[Query] = - DomainMarshallerExecutor.Inputs(state.query, state.candidatesWithDetails) - - override def arrow( - config: DomainMarshaller[Query, ResponseType], - context: Executor.Context - ): Arrow[DomainMarshallerExecutor.Inputs[Query], DomainMarshallerExecutor.Result[ResponseType]] = - domainMarshallerExecutor.arrow(config, context) - - // Noop since the pipeline updates the executor results for us - override def updateState( - state: State, - executorResult: DomainMarshallerExecutor.Result[ResponseType], - config: DomainMarshaller[Query, ResponseType] - ): State = state - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel deleted file mode 100644 index c5c363f7b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala deleted file mode 100644 index f8d9770e1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/filter/FilterStep.scala +++ /dev/null @@ -1,64 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.filter - -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A candidate filter step, it takes the input list of candidates and the given filter and applies - * the filters on the candidates in sequence, returning the final kept candidates list to State. - * - * @param filterExecutor Filter Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam Candidate Type of Candidates to filter - * @tparam State The pipeline state domain model. - */ -case class FilterStep[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - State <: HasQuery[Query, State] with HasCandidatesWithFeatures[ - Candidate, - State - ]] @Inject() (filterExecutor: FilterExecutor) - extends Step[State, Seq[ - Filter[Query, Candidate] - ], (Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] { - - override def isEmpty(config: Seq[Filter[Query, Candidate]]): Boolean = config.isEmpty - - override def adaptInput( - state: State, - config: Seq[Filter[Query, Candidate]] - ): (Query, Seq[CandidateWithFeatures[Candidate]]) = - (state.query, state.candidatesWithFeatures) - - override def arrow( - config: Seq[Filter[Query, Candidate]], - context: Executor.Context - ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] = - filterExecutor.arrow(config, context) - - override def updateState( - state: State, - executorResult: FilterExecutorResult[Candidate], - config: Seq[Filter[Query, Candidate]] - ): State = { - val keptCandidates = executorResult.result - val candidatesMap = state.candidatesWithFeatures.map { candidatesWithFeatures => - candidatesWithFeatures.candidate -> candidatesWithFeatures - }.toMap - val newCandidates = keptCandidates.flatMap { candidate => - candidatesMap.get(candidate) - } - state.updateCandidatesWithFeatures(newCandidates) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD deleted file mode 100644 index 5ea9ee1bb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala deleted file mode 100644 index c100fb1ed..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/gate/GateStep.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.gate - -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutor -import com.twitter.product_mixer.core.service.gate_executor.GateExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A gate step, it takes the query and the given gates and executes them. Gates do not update state - * if they return continue, and throw an exception if any gate says stopped, thus no state changes - * are expected in this step. The [[NewPipelineArrowBuilder]] and [[PipelineStep]] handle short - * circuiting the pipeline's execution if this throws. - * - * @param gateExecutor Gate Executor for executing the gates - * @tparam Query Type of PipelineQuery domain model - * @tparam State The pipeline state domain model. - */ -case class GateStep[Query <: PipelineQuery, State <: HasQuery[Query, State]] @Inject() ( - gateExecutor: GateExecutor) - extends Step[State, Seq[BaseGate[Query]], Query, GateExecutorResult] { - - override def adaptInput(state: State, config: Seq[BaseGate[Query]]): Query = state.query - - override def arrow( - config: Seq[BaseGate[Query]], - context: Executor.Context - ): Arrow[Query, GateExecutorResult] = gateExecutor.arrow(config, context) - - // Gate Executor is a noop, if it continues, the state isn't changed. If it stops the world, - // an exception gets thrown. - override def updateState( - input: State, - executorResult: GateExecutorResult, - config: Seq[BaseGate[Query]] - ): State = input - - override def isEmpty(config: Seq[BaseGate[Query]]): Boolean = config.isEmpty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel deleted file mode 100644 index 1a727b523..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/BUILD.bazel +++ /dev/null @@ -1,29 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala deleted file mode 100644 index bb152be5d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/group_results/GroupResultsStep.scala +++ /dev/null @@ -1,67 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.group_results - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutor -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorInput -import com.twitter.product_mixer.core.service.group_results_executor.GroupResultsExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A group results step, it takes the input list of candidates and decorations, and assembles - * properly decorated candidates with details. - * - * @param groupResultsExecutor Group results executor - * @tparam Candidate Type of candidates - * @tparam State The pipeline state domain model. - */ -case class GroupResultsStep[ - Candidate <: UniversalNoun[Any], - State <: HasCandidatesWithDetails[State] with HasCandidatesWithFeatures[ - Candidate, - State - ]] @Inject() ( - groupResultsExecutor: GroupResultsExecutor) - extends Step[State, CandidatePipelineContext, GroupResultsExecutorInput[ - Candidate - ], GroupResultsExecutorResult] { - - override def isEmpty(config: CandidatePipelineContext): Boolean = false - override def adaptInput( - state: State, - config: CandidatePipelineContext - ): GroupResultsExecutorInput[Candidate] = { - val presentationMap = state.candidatesWithDetails.flatMap { candidateWithDetails => - candidateWithDetails.presentation - .map { presentation => - candidateWithDetails.getCandidate[UniversalNoun[Any]] -> presentation - } - }.toMap - GroupResultsExecutorInput(state.candidatesWithFeatures, presentationMap) - } - - override def arrow( - config: CandidatePipelineContext, - context: Executor.Context - ): Arrow[GroupResultsExecutorInput[Candidate], GroupResultsExecutorResult] = - groupResultsExecutor.arrow( - config.candidatePipelineIdentifier, - config.candidateSourceIdentifier, - context) - - override def updateState( - state: State, - executorResult: GroupResultsExecutorResult, - config: CandidatePipelineContext - ): State = state.updateCandidatesWithDetails(executorResult.candidatesWithDetails) -} - -case class CandidatePipelineContext( - candidatePipelineIdentifier: CandidatePipelineIdentifier, - candidateSourceIdentifier: CandidateSourceIdentifier) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel deleted file mode 100644 index 94b17381a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/BUILD.bazel +++ /dev/null @@ -1,32 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = [ - "bazel-compatible", - "bazel-only", - ], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala deleted file mode 100644 index c2bdb6ea1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_executor/PipelineExecutorStep.scala +++ /dev/null @@ -1,81 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.pipeline_executor - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.state.HasResult -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.pipeline.step.pipeline_selector.PipelineSelectorResult -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutor -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorRequest -import com.twitter.product_mixer.core.service.pipeline_executor.PipelineExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * Pipeline Execution step that takes a selected pipeline and executes it. - * - * @param pipelineExecutor Pipeline executor that executes the selected pipeline - * - * @tparam Query Pipeline query model with quality factor status - * @tparam Result The expected result type - * @tparam State The pipeline state domain model. - */ -case class PipelineExecutorStep[ - Query <: PipelineQuery, - Result, - State <: HasQuery[Query, State] with HasExecutorResults[State] with HasResult[Result]] @Inject() ( - pipelineExecutor: PipelineExecutor) - extends Step[ - State, - PipelineExecutorStepConfig[Query, Result], - PipelineExecutorRequest[Query], - PipelineExecutorResult[Result] - ] { - - override def isEmpty(config: PipelineExecutorStepConfig[Query, Result]): Boolean = - false - - override def adaptInput( - state: State, - config: PipelineExecutorStepConfig[Query, Result] - ): PipelineExecutorRequest[Query] = { - val pipelineSelectorResult = state.executorResultsByPipelineStep - .getOrElse( - config.selectedPipelineResultIdentifier, - throw PipelineFailure( - IllegalStateFailure, - "Missing Selected Pipeline in Pipeline Executor Step")).asInstanceOf[ - PipelineSelectorResult] - PipelineExecutorRequest(state.query, pipelineSelectorResult.pipelineIdentifier) - } - - override def arrow( - config: PipelineExecutorStepConfig[Query, Result], - context: Executor.Context - ): Arrow[PipelineExecutorRequest[Query], PipelineExecutorResult[Result]] = pipelineExecutor.arrow( - config.pipelinesByIdentifier, - config.qualityFactorObserversByIdentifier, - context - ) - - // Noop since the platform will add the final result to the executor result map then state - // is responsible for reading it in [[WithResult]] - override def updateState( - state: State, - executorResult: PipelineExecutorResult[Result], - config: PipelineExecutorStepConfig[Query, Result] - ): State = state -} - -case class PipelineExecutorStepConfig[Query <: PipelineQuery, Result]( - pipelinesByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Result]], - selectedPipelineResultIdentifier: PipelineStepIdentifier, - qualityFactorObserversByIdentifier: Map[ComponentIdentifier, QualityFactorObserver]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD deleted file mode 100644 index e0babba8b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala deleted file mode 100644 index aa40d4829..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/pipeline_selector/PipelineSelectorStep.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.pipeline_selector - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * Pipeline Selection step to decide which pipeline to execute. This step doesn't update state, as - * the selected pipeline identifier is added to the executor results list map for later retrieval - * - * @tparam Query Pipeline query model - * @tparam State The pipeline state domain model. - */ -case class PipelineSelectorStep[Query <: PipelineQuery, State <: HasQuery[Query, State]] @Inject() ( -) extends Step[State, Query => ComponentIdentifier, Query, PipelineSelectorResult] { - override def isEmpty(config: Query => ComponentIdentifier): Boolean = false - - override def adaptInput( - state: State, - config: Query => ComponentIdentifier - ): Query = state.query - - override def arrow( - config: Query => ComponentIdentifier, - context: Executor.Context - ): Arrow[Query, PipelineSelectorResult] = Arrow.map { query: Query => - PipelineSelectorResult(config(query)) - } - - // Noop since we keep the identifier in the executor results - override def updateState( - state: State, - executorResult: PipelineSelectorResult, - config: Query => ComponentIdentifier - ): State = state -} - -case class PipelineSelectorResult(pipelineIdentifier: ComponentIdentifier) extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel deleted file mode 100644 index a220a9550..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = [ - "bazel-compatible", - "bazel-only", - ], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala deleted file mode 100644 index 0d66a4b57..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/quality_factor/QualityFactorStep.scala +++ /dev/null @@ -1,72 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.quality_factor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.quality_factor.HasQualityFactorStatus -import com.twitter.product_mixer.core.quality_factor.QualityFactorStatus -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * Quality Factor building step that builds up the state snapshot for a map of configs. - * - * @param statsReceiver Stats Receiver used to build finagle gauges for QF State - * - * @tparam Query Pipeline query model with quality factor status - * @tparam State The pipeline state domain model. - */ -case class QualityFactorStep[ - Query <: PipelineQuery with HasQualityFactorStatus, - State <: HasQuery[Query, State]] @Inject() ( - statsReceiver: StatsReceiver) - extends Step[ - State, - QualityFactorStepConfig, - Any, - QualityFactorStepResult - ] { - override def isEmpty(config: QualityFactorStepConfig): Boolean = - config.qualityFactorStatus.qualityFactorByPipeline.isEmpty - - override def adaptInput( - state: State, - config: QualityFactorStepConfig - ): Any = () - - override def arrow( - config: QualityFactorStepConfig, - context: Executor.Context - ): Arrow[Any, QualityFactorStepResult] = { - // We use provideGauge so these gauges live forever even without a reference. - val currentValues = config.qualityFactorStatus.qualityFactorByPipeline.map { - case (identifier, qualityFactor) => - // QF is a relative stat (since the parent pipeline is monitoring a child pipeline) - val scopes = config.pipelineIdentifier.toScopes ++ identifier.toScopes :+ "QualityFactor" - val currentValue = qualityFactor.currentValue.toFloat - statsReceiver.provideGauge(scopes: _*) { - currentValue - } - identifier -> currentValue - } - Arrow.value(QualityFactorStepResult(currentValues)) - } - - override def updateState( - state: State, - executorResult: QualityFactorStepResult, - config: QualityFactorStepConfig - ): State = state.updateQuery( - state.query.withQualityFactorStatus(config.qualityFactorStatus).asInstanceOf[Query]) -} - -case class QualityFactorStepConfig( - pipelineIdentifier: ComponentIdentifier, - qualityFactorStatus: QualityFactorStatus) - -case class QualityFactorStepResult(currentValues: Map[ComponentIdentifier, Float]) - extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel deleted file mode 100644 index 2ed3762c4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala deleted file mode 100644 index 1b119fc2f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_feature_hydrator/QueryFeatureHydratorStep.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.query_feature_hydrator - -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasAsyncFeatureMap -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A query level feature hydration step, it takes the input list of candidates and the given - * hydrators and executes them. The [[State]] object is responsible for merging the resulting - * feature maps with the hydrated ones in its updateCandidatesWithFeatures. - * - * @param queryFeatureHydratorExecutor Hydrator Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam State The pipeline state domain model. - */ -case class QueryFeatureHydratorStep[ - Query <: PipelineQuery, - State <: HasQuery[Query, State] with HasAsyncFeatureMap[State]] @Inject() ( - queryFeatureHydratorExecutor: QueryFeatureHydratorExecutor) - extends Step[State, QueryFeatureHydratorStepConfig[ - Query - ], Query, QueryFeatureHydratorExecutor.Result] { - override def isEmpty(config: QueryFeatureHydratorStepConfig[Query]): Boolean = - config.hydrators.isEmpty - - override def adaptInput(state: State, config: QueryFeatureHydratorStepConfig[Query]): Query = - state.query - - override def arrow( - config: QueryFeatureHydratorStepConfig[Query], - context: Executor.Context - ): Arrow[Query, QueryFeatureHydratorExecutor.Result] = - queryFeatureHydratorExecutor.arrow( - config.hydrators, - config.validPipelineStepIdentifiers, - context) - - override def updateState( - state: State, - executorResult: QueryFeatureHydratorExecutor.Result, - config: QueryFeatureHydratorStepConfig[Query] - ): State = { - val updatedQuery = state.query - .withFeatureMap(executorResult.featureMap).asInstanceOf[Query] - state - .updateQuery(updatedQuery).addAsyncFeatureMap(executorResult.asyncFeatureMap) - } -} - -case class QueryFeatureHydratorStepConfig[Query <: PipelineQuery]( - hydrators: Seq[BaseQueryFeatureHydrator[Query, _]], - validPipelineStepIdentifiers: Set[PipelineStepIdentifier]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel deleted file mode 100644 index dd63b24f6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/BUILD.bazel +++ /dev/null @@ -1,29 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = [ - "bazel-compatible", - "bazel-only", - ], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala deleted file mode 100644 index 37814714b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/query_transformer/QueryTransformerStep.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.query_transformer - -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasParams -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.state.HasRequest -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow -import com.twitter.timelines.configapi.Params - -/** - * Query Transformation Step that takes an incoming thrift request model object and returns a - * pipeline query. The pipeline state is responsible for keeping the updated query. - * - * @tparam TRequest Thrift request domain model - * @tparam Query PipelineQuery type to transform to h - * @tparam State The request domain model - */ -case class QueryTransformerStep[ - TRequest <: Request, - Query <: PipelineQuery, - State <: HasQuery[Query, State] with HasRequest[TRequest] with HasParams -]() extends Step[State, (TRequest, Params) => Query, (TRequest, Params), QueryTransformerResult[ - Query - ]] { - - override def isEmpty(config: (TRequest, Params) => Query): Boolean = false - - override def arrow( - config: (TRequest, Params) => Query, - context: Executor.Context - ): Arrow[(TRequest, Params), QueryTransformerResult[Query]] = Arrow.map { - case (request: TRequest @unchecked, params: Params) => - QueryTransformerResult(config(request, params)) - } - - override def updateState( - state: State, - executorResult: QueryTransformerResult[Query], - config: (TRequest, Params) => Query - ): State = state.updateQuery(executorResult.query) - - override def adaptInput( - state: State, - config: (TRequest, Params) => Query - ): (TRequest, Params) = (state.request, state.params) -} - -case class QueryTransformerResult[Query <: PipelineQuery](query: Query) extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD deleted file mode 100644 index 105cd49a1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/scorer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala deleted file mode 100644 index 938b18d62..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/scorer/ScorerStep.scala +++ /dev/null @@ -1,69 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.scorer - -import com.twitter.product_mixer.core.functional_component.scorer.Scorer -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithFeatures -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A scoring step, it takes the input list of candidates and the given - * scorers and executes them. The [[State]] object is responsible for merging the resulting - * feature maps with the scored ones in its updateCandidatesWithFeatures. - * - * @param candidateFeatureHydratorExecutor Hydrator Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam Candidate Type of Candidates to hydrate features for. - * @tparam State The pipeline state domain model. - */ -case class ScorerStep[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any], - State <: HasQuery[Query, State] with HasCandidatesWithFeatures[ - Candidate, - State - ]] @Inject() ( - candidateFeatureHydratorExecutor: CandidateFeatureHydratorExecutor) - extends Step[State, Seq[ - Scorer[Query, Candidate] - ], CandidateFeatureHydratorExecutor.Inputs[ - Query, - Candidate - ], CandidateFeatureHydratorExecutorResult[Candidate]] { - - override def adaptInput( - state: State, - config: Seq[Scorer[Query, Candidate]] - ): CandidateFeatureHydratorExecutor.Inputs[Query, Candidate] = - CandidateFeatureHydratorExecutor.Inputs(state.query, state.candidatesWithFeatures) - - override def arrow( - config: Seq[Scorer[Query, Candidate]], - context: Executor.Context - ): Arrow[ - CandidateFeatureHydratorExecutor.Inputs[Query, Candidate], - CandidateFeatureHydratorExecutorResult[Candidate] - ] = candidateFeatureHydratorExecutor.arrow(config, context) - - override def updateState( - input: State, - executorResult: CandidateFeatureHydratorExecutorResult[Candidate], - config: Seq[Scorer[Query, Candidate]] - ): State = { - val resultCandidates = executorResult.results - if (resultCandidates.isEmpty) { - input - } else { - input.updateCandidatesWithFeatures(resultCandidates) - } - } - - override def isEmpty(config: Seq[Scorer[Query, Candidate]]): Boolean = - config.isEmpty -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD deleted file mode 100644 index 4479122cd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala deleted file mode 100644 index bc74d2d2b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/selector/SelectorStep.scala +++ /dev/null @@ -1,53 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.selector - -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.state.HasCandidatesWithDetails -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A selection step, it takes the input list of candidates with details and the given - * selectors and executes them to decide which candidates should be selected. - * - * @param selectorExecutor Selector Executor - * @tparam Query Type of PipelineQuery domain model - * @tparam State The pipeline state domain model. - */ -case class SelectorStep[ - Query <: PipelineQuery, - State <: HasQuery[Query, State] with HasCandidatesWithDetails[State]] @Inject() ( - selectorExecutor: SelectorExecutor) - extends Step[State, Seq[ - Selector[Query] - ], SelectorExecutor.Inputs[ - Query - ], SelectorExecutorResult] { - - override def adaptInput( - state: State, - config: Seq[Selector[Query]] - ): SelectorExecutor.Inputs[Query] = - SelectorExecutor.Inputs(state.query, state.candidatesWithDetails) - - override def arrow( - config: Seq[Selector[Query]], - context: Executor.Context - ): Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = - selectorExecutor.arrow(config, context) - - override def updateState( - input: State, - executorResult: SelectorExecutorResult, - config: Seq[Selector[Query]] - ): State = input.updateCandidatesWithDetails(executorResult.selectedCandidates) - - // Selection is a bit different to other steps (i.e, other steps, empty means don't change anything) - // where an empty selection list drops all candidates. - override def isEmpty(config: Seq[Selector[Query]]): Boolean = false -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel deleted file mode 100644 index fb9d33c98..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/BUILD.bazel +++ /dev/null @@ -1,32 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala deleted file mode 100644 index 36e72cff6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/side_effect/SideEffectStep.scala +++ /dev/null @@ -1,102 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.side_effect - -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults -import com.twitter.product_mixer.core.pipeline.state.HasQuery -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor -import com.twitter.product_mixer.core.service.selector_executor.SelectorExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A side effect step, it takes the input list of side effects and and executes them. - * - * @param sideEffectExecutor Side Effect Executor - * - * @tparam Query Type of PipelineQuery domain model - * @tparam DomainResultType Domain Marshaller result type - * @tparam State The pipeline state domain model. - */ -case class SideEffectStep[ - Query <: PipelineQuery, - DomainResultType <: HasMarshalling, - State <: HasQuery[Query, State] with HasExecutorResults[State]] @Inject() ( - sideEffectExecutor: PipelineResultSideEffectExecutor) - extends Step[ - State, - PipelineStepConfig[Query, DomainResultType], - PipelineResultSideEffect.Inputs[ - Query, - DomainResultType - ], - PipelineResultSideEffectExecutor.Result - ] { - override def isEmpty(config: PipelineStepConfig[Query, DomainResultType]): Boolean = - config.sideEffects.isEmpty - - override def adaptInput( - state: State, - config: PipelineStepConfig[Query, DomainResultType] - ): PipelineResultSideEffect.Inputs[Query, DomainResultType] = { - val selectorResults = state.executorResultsByPipelineStep - .getOrElse( - config.selectorStepIdentifier, - throw PipelineFailure( - IllegalStateFailure, - "Missing Selector Result in Side Effect Step")).asInstanceOf[SelectorExecutorResult] - - val domainMarshallerResult = state.executorResultsByPipelineStep - .getOrElse( - config.domainMarshallerStepIdentifier, - throw PipelineFailure( - IllegalStateFailure, - "Missing Domain Marshaller Result in Side Effect Step")).asInstanceOf[ - DomainMarshallerExecutor.Result[DomainResultType]] - - PipelineResultSideEffect.Inputs( - query = state.query, - selectedCandidates = selectorResults.selectedCandidates, - remainingCandidates = selectorResults.remainingCandidates, - droppedCandidates = selectorResults.droppedCandidates, - response = domainMarshallerResult.result - ) - } - - override def arrow( - config: PipelineStepConfig[Query, DomainResultType], - context: Executor.Context - ): Arrow[ - PipelineResultSideEffect.Inputs[Query, DomainResultType], - PipelineResultSideEffectExecutor.Result - ] = sideEffectExecutor.arrow(config.sideEffects, context) - - override def updateState( - state: State, - executorResult: PipelineResultSideEffectExecutor.Result, - config: PipelineStepConfig[Query, DomainResultType] - ): State = state -} - -/** - * Wrapper case class containing side effects to be executed and other information needed to execute - * @param sideEffects The side effects to execute. - * @param selectorStepIdentifier The identifier of the selector step in the parent - * pipeline to get selection results from. - * @param domainMarshallerStepIdentifier The identifier of the domain marshaller step in the parent - * pipeline to get domain marshalled results from. - * - * @tparam Query Type of PipelineQuery domain model - * @tparam DomainResultType Domain Marshaller result type - */ -case class PipelineStepConfig[Query <: PipelineQuery, DomainResultType <: HasMarshalling]( - sideEffects: Seq[PipelineResultSideEffect[Query, DomainResultType]], - selectorStepIdentifier: PipelineStepIdentifier, - domainMarshallerStepIdentifier: PipelineStepIdentifier) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel deleted file mode 100644 index 7b097b33f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -scala_library( - sources = [ - "*.scala", - ], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/state", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala deleted file mode 100644 index 577df3fdd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/step/transport_marshaller/TransportMarshallerStep.scala +++ /dev/null @@ -1,76 +0,0 @@ -package com.twitter.product_mixer.core.pipeline.step.transport_marshaller - -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.state.HasExecutorResults -import com.twitter.product_mixer.core.pipeline.step.Step -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor -import com.twitter.stitch.Arrow -import javax.inject.Inject - -/** - * A transport marshaller step, it takes domain marshalled result as input and returns trasnport - * ready marshalled object. - * The [[State]] object is responsible for keeping a reference of the built marshalled response. - * - * @param transportMarshallerExecutor Domain Marshaller executor. - * @tparam Query Type of PipelineQuery domain model - * @tparam DomainResponseType the domain marshalling type used as input - * @tparam TransportResponseType the expected returned transport type - * @tparam State The pipeline state domain model. - */ -case class TransportMarshallerStep[ - DomainResponseType <: HasMarshalling, - TransportResponseType, - State <: HasExecutorResults[State]] @Inject() ( - transportMarshallerExecutor: TransportMarshallerExecutor) - extends Step[ - State, - TransportMarshallerConfig[DomainResponseType, TransportResponseType], - TransportMarshallerExecutor.Inputs[DomainResponseType], - TransportMarshallerExecutor.Result[TransportResponseType] - ] { - - override def isEmpty( - config: TransportMarshallerConfig[DomainResponseType, TransportResponseType] - ): Boolean = false - - override def adaptInput( - state: State, - config: TransportMarshallerConfig[DomainResponseType, TransportResponseType] - ): TransportMarshallerExecutor.Inputs[DomainResponseType] = { - val domainMarshallerResult = state.executorResultsByPipelineStep - .getOrElse( - config.domainMarshallerStepIdentifier, - throw PipelineFailure( - IllegalStateFailure, - "Missing Domain Marshaller in Transport Marshaller Step")).asInstanceOf[ - DomainMarshallerExecutor.Result[DomainResponseType]] - TransportMarshallerExecutor.Inputs(domainMarshallerResult.result) - } - - // Noop as platform updates executor result - override def updateState( - state: State, - executorResult: TransportMarshallerExecutor.Result[TransportResponseType], - config: TransportMarshallerConfig[DomainResponseType, TransportResponseType] - ): State = state - - override def arrow( - config: TransportMarshallerConfig[DomainResponseType, TransportResponseType], - context: Executor.Context - ): Arrow[TransportMarshallerExecutor.Inputs[ - DomainResponseType - ], TransportMarshallerExecutor.Result[TransportResponseType]] = - transportMarshallerExecutor.arrow(config.transportMarshaller, context) - -} - -case class TransportMarshallerConfig[DomainResponseType <: HasMarshalling, TransportResponseType]( - transportMarshaller: TransportMarshaller[DomainResponseType, TransportResponseType], - domainMarshallerStepIdentifier: PipelineStepIdentifier) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD deleted file mode 100644 index cc258ffe8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer", - "stitch/stitch-core", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/mixer", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala deleted file mode 100644 index c390b599e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfig.scala +++ /dev/null @@ -1,36 +0,0 @@ -package com.twitter.product_mixer.core.product - -import com.twitter.product_mixer.core.functional_component.configapi.registry.ParamConfig -import com.twitter.servo.decider.DeciderKeyName -import com.twitter.timelines.configapi.FSParam -import com.twitter.timelines.configapi.decider.BooleanDeciderParam - -trait ProductParamConfig extends ParamConfig with ProductParamConfigBuilder { - - /** - * This enabled decider param can to be used to quickly disable a Product via Decider - * - * This value must correspond to the deciders configured in the `resources/config/decider.yml` file - */ - val enabledDeciderKey: DeciderKeyName - - /** - * This supported client feature switch param can be used with a Feature Switch to control the - * rollout of a new Product from dogfood to experiment to production - * - * FeatureSwitches are configured by defining both a [[com.twitter.timelines.configapi.Param]] in code - * and in an associated `.yml` file in the __config repo__. - * - * The `.yml` file path is determined by the `feature_switches_path` in your aurora file and tge Product name - * so the resulting path in the __config repo__ is essentially `s"{feature_switches_path}/{snakeCase(Product.identifier)}"` - */ - val supportedClientFSName: String - - object EnabledDeciderParam extends BooleanDeciderParam(enabledDeciderKey) - - object SupportedClientParam - extends FSParam( - name = supportedClientFSName, - default = false - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala deleted file mode 100644 index 0d3490ebe..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/ProductParamConfigBuilder.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.product - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.configapi.registry.ParamConfigBuilder -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.FeatureSwitchOverrideUtil -import com.twitter.timelines.configapi.OptionalOverride -import com.twitter.timelines.configapi.decider.DeciderUtils - -trait ProductParamConfigBuilder extends ParamConfigBuilder { - productParamConfig: ProductParamConfig => - - override def build( - deciderGateBuilder: DeciderGateBuilder, - statsReceiver: StatsReceiver - ): Seq[OptionalOverride[_]] = { - DeciderUtils.getBooleanDeciderOverrides(deciderGateBuilder, EnabledDeciderParam) ++ - FeatureSwitchOverrideUtil.getBooleanFSOverrides(SupportedClientParam) ++ - super.build(deciderGateBuilder, statsReceiver) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD deleted file mode 100644 index 998a18e9d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/inject:guice", - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - ], - exports = [ - "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala deleted file mode 100644 index a4ae726dd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScope.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.product.guice -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.google.inject.Key - -/** - * A specialization of SimpleScope - a simple Guice Scope that takes an initial Product Mixer Product as a key - */ -class ProductScope extends SimpleScope { - def let[T](product: Product)(f: => T): T = super.let(Map(Key.get(classOf[Product]) -> product))(f) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala deleted file mode 100644 index 8345f166e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/ProductScopeModule.scala +++ /dev/null @@ -1,27 +0,0 @@ -package com.twitter.product_mixer.core.product.guice - -import com.google.inject.Provides -import com.twitter.inject.TwitterModule -import com.twitter.product_mixer.core.product.guice.scope.ProductScoped -import com.twitter.product_mixer.core.model.marshalling.request.Product -import javax.inject.Singleton - -/** - * Registers the @ProductScoped scope. - * - * See https://github.com/google/guice/wiki/CustomScopes#registering-the-scope - */ -@Singleton -class ProductScopeModule extends TwitterModule { - - val productScope: ProductScope = new ProductScope - - override def configure(): Unit = { - bindScope(classOf[ProductScoped], productScope) - - bind[Product].toProvider(SimpleScope.SEEDED_KEY_PROVIDER).in(classOf[ProductScoped]) - } - - @Provides - def providesProductScope(): ProductScope = productScope -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala deleted file mode 100644 index ccbf77121..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/guice/SimpleScope.scala +++ /dev/null @@ -1,68 +0,0 @@ -package com.twitter.product_mixer.core.product.guice - -import com.google.inject.Key -import com.google.inject.OutOfScopeException -import com.google.inject.Provider -import com.google.inject.Scope -import com.google.inject.Scopes -import com.twitter.util.Local -import scala.collection.concurrent -import scala.collection.mutable - -/** - * A scala-esque implementation of SimpleScope: https://github.com/google/guice/wiki/CustomScopes#implementing-scope - * - * Scopes the execution of a single block of code via `let` - */ -class SimpleScope extends Scope { - - private val values = new Local[concurrent.Map[Key[_], Any]]() - - /** - * Execute a block with a fresh scope. - * - * You can optionally supply a map of initialObjects to 'seed' the new scope. - */ - def let[T](initialObjects: Map[Key[_], Any] = Map.empty)(f: => T): T = { - val newMap: concurrent.Map[Key[_], Any] = concurrent.TrieMap.empty - - initialObjects.foreach { case (key, value) => newMap.put(key, value) } - - values.let(newMap)(f) - } - - override def scope[T]( - key: Key[T], - unscoped: Provider[T] - ): Provider[T] = () => { - val scopedObjects: mutable.Map[Key[T], Any] = getScopedObjectMap(key) - - scopedObjects - .get(key).map(_.asInstanceOf[T]).getOrElse { - val objectFromUnscoped: T = unscoped.get() - - if (Scopes.isCircularProxy(objectFromUnscoped)) { - objectFromUnscoped // Don't remember proxies - } else { - scopedObjects.put(key, objectFromUnscoped) - objectFromUnscoped - } - } - } - - def getScopedObjectMap[T](key: Key[T]): concurrent.Map[Key[T], Any] = { - values() - .getOrElse( - throw new OutOfScopeException(s"Cannot access $key outside of a scoping block") - ).asInstanceOf[concurrent.Map[Key[T], Any]] - } -} - -object SimpleScope { - - val SEEDED_KEY_PROVIDER: Provider[Nothing] = () => - throw new IllegalStateException( - """If you got here then it means that your code asked for scoped object which should have - | been explicitly seeded in this scope by calling SimpleScope.seed(), - | but was not.""".stripMargin) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD deleted file mode 100644 index 9ecf4adca..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/java/com/twitter/product_mixer/core/product/guice/scope", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi/registry", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/request", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala deleted file mode 100644 index 089aaea5e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductParamRegistry.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.product.registry - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.decider.DeciderGateBuilder -import com.twitter.timelines.configapi.BaseConfigBuilder -import com.twitter.timelines.configapi.Config -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class ProductParamRegistry @Inject() ( - productPipelineRegistryConfig: ProductPipelineRegistryConfig, - deciderGateBuilder: DeciderGateBuilder, - statsReceiver: StatsReceiver) { - - def build(): Seq[Config] = { - val productConfigs = productPipelineRegistryConfig.productPipelineConfigs.map { - productPipelineConfig => - BaseConfigBuilder( - productPipelineConfig.paramConfig.build(deciderGateBuilder, statsReceiver)) - .build(productPipelineConfig.paramConfig.getClass.getSimpleName) - } - - productConfigs - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala deleted file mode 100644 index e04322f6a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistry.scala +++ /dev/null @@ -1,189 +0,0 @@ -package com.twitter.product_mixer.core.product.registry - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.ProductIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.RootIdentifier -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.product.ProductPipeline -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineBuilderFactory -import com.twitter.product_mixer.core.service.component_registry.ComponentRegistry -import com.twitter.product_mixer.core.service.component_registry.ComponentRegistrySnapshot -import com.twitter.product_mixer.shared_library.observer.Observer -import com.twitter.util.Try -import com.twitter.util.Var -import com.twitter.util.logging.Logging -import javax.inject.Inject -import javax.inject.Singleton -import scala.reflect.runtime.universe._ - -@Singleton -class ProductPipelineRegistry @Inject() ( - componentRegistry: ComponentRegistry, - productPipelineRegistryConfig: ProductPipelineRegistryConfig, - productPipelineBuilderFactory: ProductPipelineBuilderFactory, - statsReceiver: StatsReceiver) - extends Logging { - - private val rootIdentifierStack = ComponentIdentifierStack(RootIdentifier()) - - private val rebuildObserver = - Observer.function[Unit](statsReceiver, "ProductPipelineRegistry", "rebuild") - - /** - * Internal state of ProductPipelineRegistry. - * - * Build once on startup, and later whenever `rebuild()` is called. - */ - private[this] val productPipelineByProduct = - Var[Map[Product, ProductPipeline[_ <: Request, _]]](buildProductPipelineByProduct()) - - /** - * Triggers a rebuild of the ProductPipelineRegistry and also the ComponentRegistry - * - * Failed rebuilds will throw an exception - likely one of the listed ones - and the product - * registry and component registry will not be modified. - * - * @throws MultipleProductPipelinesForAProductException - * @throws ComponentIdentifierCollisionException - * @throws ChildComponentCollisionException - */ - private[core] def rebuild(): Unit = { - Try { - rebuildObserver { - productPipelineByProduct.update(buildProductPipelineByProduct()) - } - }.onFailure { ex => - error("Failed to rebuild ProductPipelineRegistry", ex) - }.get() - } - - /** - * register the provided pipeline recursively register all of it's children components - * that are added to the [[Pipeline]]'s [[Pipeline.children]] - */ - private def registerPipelineAndChildren( - componentRegistrySnapshot: ComponentRegistrySnapshot, - pipeline: Pipeline[_, _], - parentIdentifierStack: ComponentIdentifierStack - ): Unit = { - val identifierStackString = - s"${parentIdentifierStack.componentIdentifiers.reverse.mkString("\t->\t")}\t->\t${pipeline.identifier}" - info(identifierStackString) - - componentRegistrySnapshot.register( - component = pipeline, - parentIdentifierStack = parentIdentifierStack) - - val identifierStackWithCurrentPipeline = parentIdentifierStack.push(pipeline.identifier) - pipeline.children.foreach { - case childPipeline: Pipeline[_, _] => - info(s"$identifierStackString\t->\t${childPipeline.identifier}") - registerPipelineAndChildren( - componentRegistrySnapshot, - childPipeline, - identifierStackWithCurrentPipeline) - case component => - info(s"$identifierStackString\t->\t${component.identifier}") - componentRegistrySnapshot.register( - component = component, - parentIdentifierStack = identifierStackWithCurrentPipeline) - } - } - - /* - * Internal method (not for callers outside of this class, see rebuild() for those) - * - * Produces an updated Map[Product, ProductPipeline] and also refreshes the global component registry - */ - private[this] def buildProductPipelineByProduct( - ): Map[Product, ProductPipeline[_ <: Request, _]] = { - - // Build a new component registry snapshot. - val newComponentRegistry = new ComponentRegistrySnapshot() - - info( - "Registering all products, pipelines, and components (this may be helpful if you encounter dependency injection errors)") - info("debug details are in the form of `parent -> child`") - - // handle the case of multiple ProductPipelines having the same product - checkForAndThrowMultipleProductPipelinesForAProduct() - - // Build a Map[Product, ProductPipeline], registering everything in the new component registry recursively - val pipelinesByProduct: Map[Product, ProductPipeline[_ <: Request, _]] = - productPipelineRegistryConfig.productPipelineConfigs.map { productPipelineConfig => - val product = productPipelineConfig.product - info(s"Recursively registering ${product.identifier}") - - // gets the ComponentIdentifierStack without the RootIdentifier since - // we don't want RootIdentifier to show up in stats or errors - val productPipeline = - productPipelineBuilderFactory.get.build( - ComponentIdentifierStack(product.identifier), - productPipelineConfig) - - // gets RootIdentifier so we can register Products under the correct hierarchy - newComponentRegistry.register(product, rootIdentifierStack) - registerPipelineAndChildren( - newComponentRegistry, - productPipeline, - rootIdentifierStack.push(product.identifier)) - - // In addition to registering the component in the main registry, we want to maintain a map of - // product to the product pipeline to allow for O(1) lookup by product on the request hot path - product -> productPipeline - }.toMap - - info( - s"Successfully registered ${newComponentRegistry.getAllRegisteredComponents - .count(_.identifier.isInstanceOf[ProductIdentifier])} products and " + - s"${newComponentRegistry.getAllRegisteredComponents.length} " + - s"components total, query the component registry endpoint for details") - - componentRegistry.set(newComponentRegistry) - - pipelinesByProduct - } - - // handle the case of multiple ProductPipelines having the same product - private def checkForAndThrowMultipleProductPipelinesForAProduct(): Unit = { - productPipelineRegistryConfig.productPipelineConfigs.groupBy(_.product.identifier).foreach { - case (product, productPipelines) if productPipelines.length != 1 => - throw new MultipleProductPipelinesForAProductException( - product, - productPipelines.map(_.identifier)) - case _ => - } - } - - def getProductPipeline[MixerRequest <: Request: TypeTag, ResponseType: TypeTag]( - product: Product - ): ProductPipeline[MixerRequest, ResponseType] = { - // Check and cast the bounded existential types to the concrete types - (typeOf[MixerRequest], typeOf[ResponseType]) match { - case (req, res) if req =:= typeOf[MixerRequest] && res =:= typeOf[ResponseType] => - productPipelineByProduct.sample - .getOrElse(product, throw new ProductNotFoundException(product)) - .asInstanceOf[ProductPipeline[MixerRequest, ResponseType]] - case _ => - throw new UnknownPipelineResponseException(product) - } - } -} - -class ProductNotFoundException(product: Product) - extends RuntimeException(s"No Product found for $product") - -class UnknownPipelineResponseException(product: Product) - extends RuntimeException(s"Unknown pipeline response for $product") - -class MultipleProductPipelinesForAProductException( - product: ProductIdentifier, - pipelineIdentifiers: Seq[ProductPipelineIdentifier]) - extends IllegalStateException(s"Multiple ProductPipelines found for $product, found " + - s"${pipelineIdentifiers - .map(productPipelineIdentifier => s"$productPipelineIdentifier from ${productPipelineIdentifier.file}") - .mkString(", ")} ") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala deleted file mode 100644 index bfa13c1c5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry/ProductPipelineRegistryConfig.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.product.registry - -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineConfig - -trait ProductPipelineRegistryConfig { - def productPipelineConfigs: Seq[ProductPipelineConfig[_ <: Request, _ <: PipelineQuery, _]] -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD deleted file mode 100644 index 758b66385..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finagle/finagle-mux/src/main/scala", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:query", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "servo/util", - "stitch/stitch-core", - "util/util-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala deleted file mode 100644 index d94accb8f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/Bounds.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -/** - * Provides a way to apply inclusive min/max bounds to a given value. - */ -case class Bounds[T](minInclusive: T, maxInclusive: T)(implicit ordering: Ordering[T]) { - - def apply(value: T): T = ordering.min(maxInclusive, ordering.max(minInclusive, value)) - - def isWithin(value: T): Boolean = - ordering.gteq(value, minInclusive) && ordering.lteq(value, maxInclusive) - - def throwIfOutOfBounds(value: T, messagePrefix: String): Unit = - require(isWithin(value), s"$messagePrefix: value must be within $toString") - - override def toString: String = s"[$minInclusive, $maxInclusive]" -} - -object BoundsWithDefault { - def apply[T]( - minInclusive: T, - maxInclusive: T, - default: T - )( - implicit ordering: Ordering[T] - ): BoundsWithDefault[T] = BoundsWithDefault(Bounds(minInclusive, maxInclusive), default) -} - -case class BoundsWithDefault[T](bounds: Bounds[T], default: T)(implicit ordering: Ordering[T]) { - bounds.throwIfOutOfBounds(default, "default") - - def apply(valueOpt: Option[T]): T = valueOpt.map(bounds.apply).getOrElse(default) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala deleted file mode 100644 index 9750f21f6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactor.scala +++ /dev/null @@ -1,34 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.util.Duration -import com.twitter.util.Stopwatch - -case class LinearLatencyQualityFactor( - override val config: LinearLatencyQualityFactorConfig) - extends QualityFactor[Duration] { - - private val delayedUntilInMillis = Stopwatch.timeMillis() + config.initialDelay.inMillis - - private var state: Double = config.qualityFactorBounds.default - - override def currentValue: Double = state - - override def update(latency: Duration): Unit = { - if (Stopwatch.timeMillis() >= delayedUntilInMillis) { - if (latency > config.targetLatency) { - adjustState(getNegativeDelta) - } else { - adjustState(config.delta) - } - } - } - - override def buildObserver(): QualityFactorObserver = LinearLatencyQualityFactorObserver(this) - - private def getNegativeDelta: Double = - -config.delta * config.targetLatencyPercentile / (100.0 - config.targetLatencyPercentile) - - private def adjustState(delta: Double): Unit = { - state = config.qualityFactorBounds.bounds(state + delta) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala deleted file mode 100644 index bd5931d80..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/LinearLatencyQualityFactorObserver.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.util.Duration -import com.twitter.util.Try - -case class LinearLatencyQualityFactorObserver( - override val qualityFactor: LinearLatencyQualityFactor) - extends QualityFactorObserver { - - override def apply(result: Try[_], latency: Duration): Unit = { - result - .onSuccess(_ => qualityFactor.update(latency)) - .onFailure { - case t if qualityFactor.config.ignorableFailures.isDefinedAt(t) => () - case _ => qualityFactor.update(Duration.Top) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala deleted file mode 100644 index 7c65656f7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactor.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -/** - * [[QualityFactor]] is an abstract number that enables a feedback loop to control operation costs and ultimately - * maintain the operation success rate. Abstractly, if operations/calls are too expensive (such as high - * latencies), the quality factor should go down, which helps future calls to ease their demand/load (such as - * reducing request width); if ops/calls are fast, the quality factor should go up, so we can incur more load. - * - * @note to avoid overhead the underlying state may sometimes not be synchronized. - * If a part of an application is unhealthy, it will likely be unhealthy for all threads, - * it will eventually result in a close-enough quality factor value for all thread's view of the state. - * - * In extremely low volume scenarios such as manual testing in a development environment, - * it's possible that different threads will have vastly different views of the underling state, - * but in practice, in production systems, they will be close-enough. - */ -trait QualityFactor[Input] { self => - - /** get the current [[QualityFactor]]'s value */ - def currentValue: Double - - def config: QualityFactorConfig - - /** update of the current `factor` value */ - def update(input: Input): Unit - - /** a [[QualityFactorObserver]] for this [[QualityFactor]] */ - def buildObserver(): QualityFactorObserver - - override def toString: String = { - self.getClass.getSimpleName.stripSuffix("$") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala deleted file mode 100644 index e0ba6f465..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorConfig.scala +++ /dev/null @@ -1,120 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ClientFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.quality_factor.QualityFactorConfig.defaultIgnorableFailures -import com.twitter.servo.util.CancelledExceptionExtractor -import com.twitter.util.Duration -import com.twitter.conversions.DurationOps.RichDuration - -/** - * Quality factor is an abstract number that enables a feedback loop to control operation costs and ultimately - * maintain the operation success rate. Abstractly, if operations/calls are too expensive (such as high - * latencies), the quality factor should go down, which helps future calls to ease their demand/load (such as - * reducing request width); if ops/calls are fast, the quality factor should go up, so we can incur more load. - */ -sealed trait QualityFactorConfig { - - /** - * specifies the quality factor min and max bounds and default value. - */ - def qualityFactorBounds: BoundsWithDefault[Double] - - /** - * initialDelay Specifies how much delay we should have before the quality factor calculation start to kick in. This is - * mostly to ease the load during the initial warmup/startup. - */ - def initialDelay: Duration - - /** - * [[Throwable]]s that should be ignored when calculating - * the [[QualityFactor]] if this is [[PartialFunction.isDefinedAt]] - */ - def ignorableFailures: PartialFunction[Throwable, Unit] = defaultIgnorableFailures -} - -object QualityFactorConfig { - - /** - * Default value for [[QualityFactorConfig.ignorableFailures]] that ignores any - * Cancelled requests and [[ClientFailure]] - */ - val defaultIgnorableFailures: PartialFunction[Throwable, Unit] = { - case PipelineFailure(_: ClientFailure, _, _, _) => () - case CancelledExceptionExtractor(_) => () - } -} - -/** - * This is a linear quality factor implementation, aimed to achieve and maintain a percentile latency target. - * - * If we call quality factor q, target latency t and target percentile p, - * then the q (quality factor) formula should be: - * q += delta for each request with latency <= t - * q -= delta * p / (100 - p) for each request with latency > t ms or a timeout. - * - * When percentile p latency stays at target latency t, then based on the formula above, q will - * stay constant (fluctuates around a constant value). - * - * For example, assume t = 100ms, p = p99, and q = 0.5 - * let's say, p99 latency stays at 100ms when q = 0.5. p99 means that out of every 100 latencies, - * 99 times the latency is below 100ms and 1 time it is above 100ms. So based on the formula above, - * q will increase by "delta" 99 times and it will decrease by delta * p / (100 - p) = delta * 99 once, - * which results in the same q = 0.5. - * - * @param targetLatency This is the latency target, calls with latencies above which will cause quality - * factor to go down, and vice versa. e.g. 500ms. - * @param targetLatencyPercentile This the percentile where the target latency is aimed at. e.g. 95.0. - * @param delta the step for adjusting quality factor. It should be a positive double. If delta is - * too large, then quality factor will fluctuate more, and if it is too small, the - * responsiveness will be reduced. - */ -case class LinearLatencyQualityFactorConfig( - override val qualityFactorBounds: BoundsWithDefault[Double], - override val initialDelay: Duration, - targetLatency: Duration, - targetLatencyPercentile: Double, - delta: Double, - override val ignorableFailures: PartialFunction[Throwable, Unit] = - QualityFactorConfig.defaultIgnorableFailures) - extends QualityFactorConfig { - require( - targetLatencyPercentile >= 50.0 && targetLatencyPercentile < 100.0, - s"Invalid targetLatencyPercentile value: ${targetLatencyPercentile}.\n" + - s"Correct sample values: 95.0, 99.9. Incorrect sample values: 0.95, 0.999." - ) -} - -/** - * A quality factor provides component capacity state based on sampling component - * Queries Per Second (qps) at local host level. - * - * If we call quality factor q, max qps R: - * then the q (quality factor) formula should be: - * q = Math.min([[qualityFactorBounds.bounds.maxInclusive]], q + delta) for each request that observed qps <= R on local host - * q -= delta for each request that observed qps > R on local host - * - * When qps r stays below R, q will stay as constant (value at [[qualityFactorBounds.bounds.maxInclusive]]). - * When qps r starts to increase above R, q will decrease by delta per request, - * with delta being an additive factor that controls how sensitive q is when max qps R is exceeded. - * - * @param initialDelay Specifies an initial delay time to allow query rate counter warm up to start reflecting actual traffic load. - * Qf value would only start to update after this initial delay. - * @param maxQueriesPerSecond The max qps the underlying component can take. Requests go above this qps threshold will cause quality factor to go down. - * @param queriesPerSecondSampleWindow The window of underlying query rate counter counting with and calculate an average qps over the window, - * default to count with 10 seconds time window (i.e. qps = total requests over last 10 secs / 10). - * Note: underlying query rate counter has a sliding window with 10 fixed slices. Therefore a larger - * window would lead to a coarser qps calculation. (e.g. with 60 secs time window, it sliding over 6 seconds slice (60 / 10 = 6 secs)). - * A larger time window also lead to a slower reaction to sudden qps burst, but more robust to flaky qps pattern. - * @param delta The step for adjusting quality factor. It should be a positive double. If the delta is large, the quality factor - * will fluctuate more and be more responsive to exceeding max qps, and if it is small, the quality factor will be less responsive. - */ -case class QueriesPerSecondBasedQualityFactorConfig( - override val qualityFactorBounds: BoundsWithDefault[Double], - override val initialDelay: Duration, - maxQueriesPerSecond: Int, - queriesPerSecondSampleWindow: Duration = 10.seconds, - delta: Double = 0.001, - override val ignorableFailures: PartialFunction[Throwable, Unit] = - QualityFactorConfig.defaultIgnorableFailures) - extends QualityFactorConfig diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala deleted file mode 100644 index e15fb5491..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorObserver.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.util.Duration -import com.twitter.util.Try - -/** Updates the [[QualityFactor]] */ -trait QualityFactorObserver { - - /** The [[QualityFactor]] to update when observing */ - def qualityFactor: QualityFactor[_] - - /** - * updates the [[qualityFactor]] given the result [[Try]] and the latency - * @note implementations must be sure to correctly ignore - * [[QualityFactor.config]]'s [[QualityFactorConfig.ignorableFailures]] - */ - def apply(result: Try[_], latency: Duration): Unit -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala deleted file mode 100644 index 01a327f86..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QualityFactorStatus.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredQualityFactor -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure - -case class QualityFactorStatus( - qualityFactorByPipeline: Map[ComponentIdentifier, QualityFactor[_]]) { - - /** - * returns a new [[QualityFactorStatus]] with all the elements of current QualityFactorStatus and `other`. - * If a [[ComponentIdentifier]] exists in both maps, the Value from `other` takes precedence - */ - def ++(other: QualityFactorStatus): QualityFactorStatus = { - if (other.qualityFactorByPipeline.isEmpty) { - this - } else if (qualityFactorByPipeline.isEmpty) { - other - } else { - QualityFactorStatus(qualityFactorByPipeline ++ other.qualityFactorByPipeline) - } - } -} - -object QualityFactorStatus { - def build[Identifier <: ComponentIdentifier]( - qualityFactorConfigs: Map[Identifier, QualityFactorConfig] - ): QualityFactorStatus = { - QualityFactorStatus( - qualityFactorConfigs.map { - case (key, config: LinearLatencyQualityFactorConfig) => - key -> LinearLatencyQualityFactor(config) - case (key, config: QueriesPerSecondBasedQualityFactorConfig) => - key -> QueriesPerSecondBasedQualityFactor(config) - } - ) - } - - val empty: QualityFactorStatus = QualityFactorStatus(Map.empty) -} - -trait HasQualityFactorStatus { - def qualityFactorStatus: Option[QualityFactorStatus] = None - def withQualityFactorStatus(qualityFactorStatus: QualityFactorStatus): PipelineQuery - - def getQualityFactorCurrentValue( - identifier: ComponentIdentifier - ): Double = getQualityFactor(identifier).currentValue - - def getQualityFactor( - identifier: ComponentIdentifier - ): QualityFactor[_] = qualityFactorStatus - .flatMap(_.qualityFactorByPipeline.get(identifier)) - .getOrElse { - throw PipelineFailure( - MisconfiguredQualityFactor, - s"Quality factor not configured for $identifier") - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala deleted file mode 100644 index a1ba3f373..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactor.scala +++ /dev/null @@ -1,51 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.google.common.annotations.VisibleForTesting -import com.twitter.util.Stopwatch - -case class QueriesPerSecondBasedQualityFactor( - override val config: QueriesPerSecondBasedQualityFactorConfig) - extends QualityFactor[Int] { - - @VisibleForTesting - private[quality_factor] val queryRateCounter: QueryRateCounter = QueryRateCounter( - config.queriesPerSecondSampleWindow) - - private val delayedUntilInMillis = Stopwatch.timeMillis() + config.initialDelay.inMillis - - private var state: Double = config.qualityFactorBounds.default - - override def currentValue: Double = state - - override def update(count: Int = 1): Unit = { - val queryRate = incrementAndGetQueryRateCount(count) - - // Only update quality factor until the initial delay past. - // This allows query rate counter get warm up to reflect - // actual traffic load by the time initial delay expires. - if (Stopwatch.timeMillis() >= delayedUntilInMillis) { - if (queryRate > config.maxQueriesPerSecond) { - state = config.qualityFactorBounds.bounds(state - config.delta) - } else { - state = config.qualityFactorBounds.bounds(state + config.delta) - } - } - } - - private def incrementAndGetQueryRateCount(count: Int): Double = { - // Int.MaxValue is used as a special signal from [[QueriesPerSecondBasedQualityFactorObserver]] - // to indicate a component failure is observed. - // In this case, we do not update queryRateCounter and instead return Int.MaxValue. - // As the largest Int value, this should result in the threshold qps for quality factor being - // exceeded and directly decrementing quality factor. - if (count == Int.MaxValue) { - Int.MaxValue.toDouble - } else { - queryRateCounter.increment(count) - queryRateCounter.getRate() - } - } - - override def buildObserver(): QualityFactorObserver = - QueriesPerSecondBasedQualityFactorObserver(this) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala deleted file mode 100644 index 27f13c8a3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueriesPerSecondBasedQualityFactorObserver.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.util.Duration -import com.twitter.util.Try - -case class QueriesPerSecondBasedQualityFactorObserver( - override val qualityFactor: QueriesPerSecondBasedQualityFactor) - extends QualityFactorObserver { - override def apply( - result: Try[_], - latency: Duration - ): Unit = { - result - .onSuccess(_ => qualityFactor.update()) - .onFailure { - case t if qualityFactor.config.ignorableFailures.isDefinedAt(t) => () - // Degrade qf as a proactive mitigation for any non ignorable failures. - case _ => qualityFactor.update(Int.MaxValue) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala deleted file mode 100644 index 33d4a5375..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor/QueryRateCounter.scala +++ /dev/null @@ -1,21 +0,0 @@ -package com.twitter.product_mixer.core.quality_factor - -import com.twitter.util.Duration -import com.twitter.util.Stopwatch -import com.twitter.util.TokenBucket - -/** - * Query rate counter based on a leaky bucket. For more, see [[com.twitter.util.TokenBucket]]. - */ -case class QueryRateCounter private[quality_factor] ( - queryRateWindow: Duration) { - - private val queryRateWindowInSeconds = queryRateWindow.inSeconds - - private val leakyBucket: TokenBucket = - TokenBucket.newLeakyBucket(ttl = queryRateWindow, reserve = 0, nowMs = Stopwatch.timeMillis) - - def increment(count: Int): Unit = leakyBucket.put(count) - - def getRate(): Double = leakyBucket.count / queryRateWindowInSeconds -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD deleted file mode 100644 index 72565730e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/BUILD +++ /dev/null @@ -1,32 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer", - "servo/util", - "stitch/stitch-core", - "util/util-core", - "util/util-stats", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline:executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer", - "stitch/stitch-core", - "util/util-stats", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala deleted file mode 100644 index d56c1e0fc..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/Executor.scala +++ /dev/null @@ -1,700 +0,0 @@ -package com.twitter.product_mixer.core.service - -import com.twitter.finagle.stats.BroadcastStatsReceiver -import com.twitter.finagle.stats.Counter -import com.twitter.finagle.stats.DefaultStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finagle.tracing.Annotation -import com.twitter.finagle.tracing.Record -import com.twitter.finagle.tracing.Trace -import com.twitter.finagle.tracing.TraceId -import com.twitter.finagle.tracing.TraceServiceName -import com.twitter.finagle.tracing.Tracing.LocalBeginAnnotation -import com.twitter.finagle.tracing.Tracing.LocalEndAnnotation -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.FeatureHydrationFailed -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UncategorizedServerFailure -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.service.Executor.AlwaysFailOpenIncludingProgrammerErrors -import com.twitter.product_mixer.core.service.Executor.Context -import com.twitter.product_mixer.core.service.Executor.TracingConfig -import com.twitter.product_mixer.core.service.Executor.toPipelineFailureWithComponentIdentifierStack -import com.twitter.servo.util.CancelledExceptionExtractor -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch -import com.twitter.stitch.Stitch.Letter -import com.twitter.util.Duration -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Time -import com.twitter.util.Try - -/** - * Base trait that all executors implement - * - * All executors should: - * - implement a `def arrow` or `def apply` with the relevant types for their use case - * and take in an implicit [[PipelineFailureClassifier]] and [[ComponentIdentifierStack]]. - * - add a `@singleton` annotation to the class and `@inject` annotation to the argument list - * - take in a [[StatsReceiver]] - * - * @example {{{ - * @Singleton class MyExecutor @Inject() ( - * override val statsReceiver: StatsReceiver - * ) extends Executor { - * def arrow( - * arg: MyArg, - * ..., - * context: Context - * ): Arrow[In,Out] = ??? - * } - * }}} - */ -private[core] trait Executor { - val statsReceiver: StatsReceiver - - /** - * Applies the `pipelineFailureClassifier` to the output of the `arrow` - * and adds the `componentStack` to the [[PipelineFailure]] - */ - def wrapWithErrorHandling[In, Out]( - context: Context, - currentComponentIdentifier: ComponentIdentifier - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - arrow.mapFailure( - toPipelineFailureWithComponentIdentifierStack(context, currentComponentIdentifier)) - } - - /** - * Chain a `Seq` of [[Arrow.Iso]], only passing successful results to the next [[Arrow.Iso]] - * - * @note the resulting [[Arrow]] runs the passed in [[Arrow]]s one after the other, - * as an ordered execution, this means that each [[Arrow]] is dependent - * on all previous [[Arrow]]s in the `Seq` so no `Stitch` batching can occur - * between them. - */ - def isoArrowsSequentially[T](arrows: Seq[Arrow.Iso[T]]): Arrow.Iso[T] = { - // avoid excess Arrow complexity when there is only a single Arrow - arrows match { - case Seq() => Arrow.identity - case Seq(onlyOneArrow) => onlyOneArrow - case Seq(head, tail @ _*) => - tail.foldLeft(head) { - case (combinedArrow, nextArrow) => combinedArrow.flatMapArrow(nextArrow) - } - } - } - - /** - * Start running the [[Arrow]] in the background returning a [[Stitch.Ref]] which will complete - * when the background task is finished - */ - def startArrowAsync[In, Out](arrow: Arrow[In, Out]): Arrow[In, Stitch[Out]] = { - Arrow - .map { arg: In => - // wrap in a `ref` so we only compute it's value once - Stitch.ref(arrow(arg)) - } - .andThen( - Arrow.zipWithArg( - // satisfy the `ref` async - Arrow.async(Arrow.flatMap[Stitch[Out], Out](identity)))) - .map { case (ref, _) => ref } - } - - /** - * for [[com.twitter.product_mixer.core.model.common.Component]]s which - * are executed per-candidate or which we don't want to record stats for. - * This performs Tracing but does not record Stats - * - * @note This should be used around the computation that includes the execution of the - * underlying Component over all the Candidates, not around each execution - * of the component around each candidate for per-candidate Components. - * - * @note when using this you should only use [[wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing]] - * for handling Stats. - */ - def wrapComponentsWithTracingOnly[In, Out]( - context: Context, - currentComponentIdentifier: ComponentIdentifier - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - Executor.wrapArrowWithLocalTracingSpan( - Arrow - .time(arrow) - .map { - case (result, latency) => - Executor.recordTraceData( - componentStack = context.componentStack, - componentIdentifier = currentComponentIdentifier, - result = result, - latency = latency, - size = None) - result - }.lowerFromTry) - } - - /** - * for [[com.twitter.product_mixer.core.model.common.Component]]s which - * are executed per-candidate. Records Stats but does not do Tracing. - * - * @note when using this you should only use [[wrapPerCandidateComponentsWithTracingOnly]] - * for handling Tracing - */ - def wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing[In, Out]( - context: Context, - currentComponentIdentifier: ComponentIdentifier - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - val observerSideEffect = - ExecutorObserver.executorObserver[Out](context, currentComponentIdentifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Out]( - context = context, - currentComponentIdentifier = currentComponentIdentifier, - executorResultSideEffect = observerSideEffect, - transformer = Return(_), - tracingConfig = TracingConfig.NoTracing - )(arrow) - } - - /** for [[com.twitter.product_mixer.core.model.common.Component]]s */ - def wrapComponentWithExecutorBookkeeping[In, Out]( - context: Context, - currentComponentIdentifier: ComponentIdentifier - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - val observerSideEffect = - ExecutorObserver.executorObserver[Out](context, currentComponentIdentifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Out]( - context = context, - currentComponentIdentifier = currentComponentIdentifier, - executorResultSideEffect = observerSideEffect, - transformer = Return(_) - )(arrow) - } - - /** - * for [[com.twitter.product_mixer.core.model.common.Component]]s which an `onSuccess` - * to add custom stats or logging of results - */ - def wrapComponentWithExecutorBookkeeping[In, Out]( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - onSuccess: Out => Unit - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - val observerSideEffect = - ExecutorObserver.executorObserver[Out](context, currentComponentIdentifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Out]( - context = context, - currentComponentIdentifier = currentComponentIdentifier, - executorResultSideEffect = observerSideEffect, - transformer = Return(_), - onComplete = (transformed: Try[Out]) => transformed.onSuccess(onSuccess) - )(arrow) - } - - /** for [[com.twitter.product_mixer.core.pipeline.Pipeline]]s */ - def wrapPipelineWithExecutorBookkeeping[In, Out <: PipelineResult[_]]( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - qualityFactorObserver: Option[QualityFactorObserver], - failOpenPolicy: FailOpenPolicy = FailOpenPolicy.Never - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - val observerSideEffect = - ExecutorObserver - .pipelineExecutorObserver[Out](context, currentComponentIdentifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Out]( - context = context, - currentComponentIdentifier = currentComponentIdentifier, - executorResultSideEffect = observerSideEffect, - transformer = (result: Out) => result.toTry, - size = Some(_.resultSize()), - failOpenPolicy = failOpenPolicy, - qualityFactorObserver = qualityFactorObserver - )(arrow) - } - - /** for [[com.twitter.product_mixer.core.pipeline.product.ProductPipeline]]s */ - def wrapProductPipelineWithExecutorBookkeeping[In, Out <: PipelineResult[_]]( - context: Context, - currentComponentIdentifier: ProductPipelineIdentifier - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - - val observerSideEffect = - ExecutorObserver - .productPipelineExecutorObserver[Out](currentComponentIdentifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Out]( - context = context, - currentComponentIdentifier = currentComponentIdentifier, - executorResultSideEffect = observerSideEffect, - transformer = _.toTry, - size = Some(_.resultSize()), - failOpenPolicy = - // always save Failures in the Result object instead of failing the request - AlwaysFailOpenIncludingProgrammerErrors - )(arrow) - } - - /** for [[com.twitter.product_mixer.core.model.common.Component]]s which need a result size stat */ - def wrapComponentWithExecutorBookkeepingWithSize[In, Out]( - context: Context, - currentComponentIdentifier: CandidateSourceIdentifier, - size: Out => Int - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - val observerSideEffect = - ExecutorObserver.executorObserverWithSize(context, currentComponentIdentifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Int]( - context = context, - currentComponentIdentifier = currentComponentIdentifier, - executorResultSideEffect = observerSideEffect, - transformer = (out: Out) => Try(size(out)), - size = Some(identity) - )(arrow) - } - - /** for [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step]]s */ - def wrapStepWithExecutorBookkeeping[In, Out]( - context: Context, - identifier: PipelineStepIdentifier, - arrow: Arrow[In, Out], - transformer: Out => Try[Unit] - ): Arrow[In, Out] = { - val observerSideEffect = - ExecutorObserver.stepExecutorObserver(context, identifier, statsReceiver) - - Executor.wrapWithExecutorBookkeeping[In, Out, Unit]( - context = context, - currentComponentIdentifier = identifier, - executorResultSideEffect = observerSideEffect, - transformer = transformer, - failOpenPolicy = AlwaysFailOpenIncludingProgrammerErrors - )(arrow) - } -} - -private[core] object Executor { - - private[service] object TracingConfig { - - /** Used to specify whether a wrapped Arrow should be Traced in [[wrapWithExecutorBookkeeping]] */ - sealed trait TracingConfig - case object NoTracing extends TracingConfig - case object WrapWithSpanAndTracingData extends TracingConfig - } - - /** - * Always fail-open and return the [[com.twitter.product_mixer.core.pipeline.product.ProductPipelineResult]] - * containing the exception, this differs from [[FailOpenPolicy.Always]] in that this will still - * fail-open and return the overall result object even if the underlying failure is the result - * of programmer error. - */ - private val AlwaysFailOpenIncludingProgrammerErrors: FailOpenPolicy = _ => true - - /** - * Wraps an [[Arrow]] so that bookkeeping around the execution occurs uniformly. - * - * @note should __never__ be called directly! - * - * - For successful results, apply the `transformer` - * - convert any exceptions to PipelineFailures - * - record stats and update [[QualityFactorObserver]] - * - wraps the execution in a Trace span and record Trace data (can be turned off by [[TracingConfig]]) - * - applies a trace span and records metadata to the provided `arrow` - * - determine whether to fail-open based on `result.flatMap(transformer)` - * - if failing-open, always return the original result - * - if failing-closed and successful, return the original result - * - otherwise, return the failure (from `result.flatMap(transformer)`) - * - * @param context the [[Executor.Context]] - * @param currentComponentIdentifier the current component's [[ComponentIdentifier]] - * @param executorResultSideEffect the [[ExecutorObserver]] used to record stats - * @param transformer function to convert a successful result into possibly a failed result - * @param failOpenPolicy [[FailOpenPolicy]] to apply to the results of `result.flatMap(transformer)` - * @param qualityFactorObserver [[QualityFactorObserver]] to update based on the results of `result.flatMap(transformer)` - * @param tracingConfig indicates whether the [[Arrow]] should be wrapped with Tracing - * @param onComplete runs the function for its side effects with the result of `result.flatMap(transformer)` - * @param arrow an input [[Arrow]] to wrap so that after it's execution, we perform all these operations - * - * @return the wrapped [[Arrow]] - */ - private[service] def wrapWithExecutorBookkeeping[In, Out, Transformed]( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - executorResultSideEffect: ExecutorObserver[Transformed], - transformer: Out => Try[Transformed], - size: Option[Transformed => Int] = None, - failOpenPolicy: FailOpenPolicy = FailOpenPolicy.Never, - qualityFactorObserver: Option[QualityFactorObserver] = None, - tracingConfig: TracingConfig.TracingConfig = TracingConfig.WrapWithSpanAndTracingData, - onComplete: Try[Transformed] => Unit = { _: Try[Transformed] => () } - )( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = { - - val failureClassifier = - toPipelineFailureWithComponentIdentifierStack(context, currentComponentIdentifier) - - /** transform the results, mapping all exceptions to [[PipelineFailure]]s, and tuple with original result */ - val transformResultAndClassifyFailures: Arrow[Out, (Out, Try[Transformed])] = - Arrow.join( - Arrow.mapFailure(failureClassifier), - Arrow - .transformTry[Out, Transformed](result => - result - .flatMap(transformer) - .rescue { case t => Throw(failureClassifier(t)) }) - .liftToTry - ) - - /** Only record tracing data if [[TracingConfig.WrapWithSpanAndTracingData]] */ - val maybeRecordTracingData: (Try[Transformed], Duration) => Unit = tracingConfig match { - case TracingConfig.NoTracing => (_, _) => () - case TracingConfig.WrapWithSpanAndTracingData => - (transformedAndClassifiedResult, latency) => - recordTraceData( - context.componentStack, - currentComponentIdentifier, - transformedAndClassifiedResult, - latency, - transformedAndClassifiedResult.toOption.flatMap(result => size.map(_.apply(result))) - ) - } - - /** Will never be in a failed state so we can do a simple [[Arrow.map]] */ - val recordStatsAndUpdateQualityFactor = - Arrow - .map[(Try[(Out, Try[Transformed])], Duration), Unit] { - case (tryResultAndTryTransformed, latency) => - val transformedAndClassifiedResult = tryResultAndTryTransformed.flatMap { - case (_, transformed) => transformed - } - executorResultSideEffect(transformedAndClassifiedResult, latency) - qualityFactorObserver.foreach(_.apply(transformedAndClassifiedResult, latency)) - onComplete(transformedAndClassifiedResult) - maybeRecordTracingData(transformedAndClassifiedResult, latency) - }.unit - - /** - * Applies the provided [[FailOpenPolicy]] based on the [[transformer]]'s results, - * returning the original result or an exception - */ - val applyFailOpenPolicyBasedOnTransformedResult: Arrow[ - (Try[(Out, Try[Transformed])], Duration), - Out - ] = - Arrow - .map[(Try[(Out, Try[Transformed])], Duration), Try[(Out, Try[Transformed])]] { - case (tryResultAndTryTransformed, _) => tryResultAndTryTransformed - } - .lowerFromTry - .map { - case (result, Throw(pipelineFailure: PipelineFailure)) - if failOpenPolicy(pipelineFailure.category) => - Return(result) - case (_, t: Throw[_]) => t.asInstanceOf[Throw[Out]] - case (result, _) => Return(result) - }.lowerFromTry - - /** The complete Arrow minus a Local span wrapping */ - val arrowWithTimingExecutorSideEffects = Arrow - .time(arrow.andThen(transformResultAndClassifyFailures)) - .applyEffect(recordStatsAndUpdateQualityFactor) - .andThen(applyFailOpenPolicyBasedOnTransformedResult) - - /** Dont wrap with a span if we are not tracing */ - tracingConfig match { - case TracingConfig.WrapWithSpanAndTracingData => - wrapArrowWithLocalTracingSpan(arrowWithTimingExecutorSideEffects) - case TracingConfig.NoTracing => - arrowWithTimingExecutorSideEffects - } - } - - /** Let-scopes a [[TraceId]] around a computation */ - private[this] object TracingLetter extends Letter[TraceId] { - override def let[S](traceId: TraceId)(s: => S): S = Trace.letId(traceId)(s) - } - - /** - * Wraps the Arrow's execution in a new trace span as a child of the current parent span - * - * @note Should __never__ be called directly! - * - * It's expected that the contained `arrow` will invoke [[recordTraceData]] exactly ONCE - * during it's execution. - * - * @note this does not record any data about the trace, it only sets the [[Trace]] Span - * for the execution of `arrow` - */ - private[service] def wrapArrowWithLocalTracingSpan[In, Out]( - arrow: Arrow[In, Out] - ): Arrow[In, Out] = - Arrow.ifelse( - _ => Trace.isActivelyTracing, - Arrow.let(TracingLetter)(Trace.nextId)(arrow), - arrow - ) - - private[this] object Tracing { - - /** - * Duplicate of [[com.twitter.finagle.tracing.Tracing]]'s `localSpans` which - * uses an un-scoped [[StatsReceiver]] - * - * Since we needed to roll-our-own latency measurement we are unable to increment the - * `local_spans` metric automatically, this is important in the event a service is - * unexpectedly not recording spans or unexpectedly recording too many, so we manually - * increment it - */ - val localSpans: Counter = DefaultStatsReceiver.counter("tracing", "local_spans") - - /** Local Component field of a span in the UI */ - val localComponentTag = "lc" - val sizeTag = "product_mixer.result.size" - val successTag = "product_mixer.result.success" - val successValue = "success" - val cancelledTag = "product_mixer.result.cancelled" - val failureTag = "product_mixer.result.failure" - } - - /** - * Records metadata onto the current [[Trace]] Span - * - * @note Should __never__ be called directly! - * - * This should be called exactly ONCE in the Arrow passed into [[wrapArrowWithLocalTracingSpan]] - * to record data for the Span. - */ - private[service] def recordTraceData[T]( - componentStack: ComponentIdentifierStack, - componentIdentifier: ComponentIdentifier, - result: Try[T], - latency: Duration, - size: Option[Int] = None - ): Unit = { - if (Trace.isActivelyTracing) { - Tracing.localSpans.incr() - val traceId = Trace.id - val endTime = Time.nowNanoPrecision - - // These annotations are needed for the Zipkin UI to display the span properly - TraceServiceName().foreach(Trace.recordServiceName) - Trace.recordRpc(componentIdentifier.snakeCase) // name of the span in the UI - Trace.recordBinary( - Tracing.localComponentTag, - componentStack.peek.toString + "/" + componentIdentifier.toString) - Trace.record(Record(traceId, endTime - latency, Annotation.Message(LocalBeginAnnotation))) - Trace.record(Record(traceId, endTime, Annotation.Message(LocalEndAnnotation))) - - // product mixer specific zipkin data - size.foreach(size => Trace.recordBinary(Tracing.sizeTag, size)) - result match { - case Return(_) => - Trace.recordBinary(Tracing.successTag, Tracing.successValue) - case Throw(CancelledExceptionExtractor(e)) => - Trace.recordBinary(Tracing.cancelledTag, e) - case Throw(e) => - Trace.recordBinary(Tracing.failureTag, e) - } - } - } - - /** - * Returns a tuple of the stats scopes for the current component and the relative scope for - * the parent component and the current component together - * - * This is useful when recording stats for a component by itself as well as stats for calls to that component from it's parent. - * - * @example if the current component has a scope of "currentComponent" and the parent component has a scope of "parentComponent" - * then this will return `(Seq("currentComponent"), Seq("parentComponent", "currentComponent"))` - */ - def buildScopes( - context: Context, - currentComponentIdentifier: ComponentIdentifier - ): Executor.Scopes = { - val parentScopes = context.componentStack.peek.toScopes - val componentScopes = currentComponentIdentifier.toScopes - val relativeScopes = parentScopes ++ componentScopes - Executor.Scopes(componentScopes, relativeScopes) - } - - /** - * Makes a [[BroadcastStatsReceiver]] that will broadcast stats to the correct - * current component's scope and to the scope relative to the parent. - */ - def broadcastStatsReceiver( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - statsReceiver: StatsReceiver - ): StatsReceiver = { - val Executor.Scopes(componentScopes, relativeScopes) = - Executor.buildScopes(context, currentComponentIdentifier) - - BroadcastStatsReceiver( - Seq(statsReceiver.scope(relativeScopes: _*), statsReceiver.scope(componentScopes: _*))) - } - - /** - * Returns a feature map containing all the [[com.twitter.product_mixer.core.feature.Feature]]s - * stored as failures using the exception provided with as the reason wrapped in a PipelineFailure. - * e.g, for features A & B that threw an ExampleException b, this will return: - * { A -> Throw(PipelineFailure(...)), B -> Throw(PipelineFailure(...)) } - */ - def featureMapWithFailuresForFeatures( - features: Set[Feature[_, _]], - error: Throwable, - context: Executor.Context - ): FeatureMap = { - val builder = FeatureMapBuilder() - features.foreach { feature => - val pipelineFailure = PipelineFailure( - FeatureHydrationFailed, - s"Feature hydration failed for ${feature.toString}", - Some(error), - Some(context.componentStack)) - builder.addFailure(feature, pipelineFailure) - } - builder.build() - } - - /** - * Validates and returns back the passed feature map if it passes validation. A feature map - * is considered valid if it contains only the passed `registeredFeatures` features in it, - * nothing else and nothing missing. - */ - @throws(classOf[PipelineFailure]) - def validateFeatureMap( - registeredFeatures: Set[Feature[_, _]], - featureMap: FeatureMap, - context: Executor.Context - ): FeatureMap = { - val hydratedFeatures = featureMap.getFeatures - if (hydratedFeatures == registeredFeatures) { - featureMap - } else { - val missingFeatures = registeredFeatures -- hydratedFeatures - val unregisteredFeatures = hydratedFeatures -- registeredFeatures - throw PipelineFailure( - MisconfiguredFeatureMapFailure, - s"Unregistered features $unregisteredFeatures and missing features $missingFeatures", - None, - Some(context.componentStack) - ) - } - } - - object NotAMisconfiguredFeatureMapFailure { - - /** - * Will return any exception that isn't a [[MisconfiguredFeatureMapFailure]] [[PipelineFailure]] - * Allows for easy [[Arrow.handle]]ing all exceptions that aren't [[MisconfiguredFeatureMapFailure]]s - */ - def unapply(e: Throwable): Option[Throwable] = e match { - case pipelineFailure: PipelineFailure - if pipelineFailure.category == MisconfiguredFeatureMapFailure => - None - case e => Some(e) - } - } - - /** - * contains the scopes for recording metrics for the component by itself and - * the relative scope of that component within it's parent component scope - * - * @see [[Executor.buildScopes]] - */ - case class Scopes(componentScopes: Seq[String], relativeScope: Seq[String]) - - /** - * Wrap the [[Throwable]] in a [[UncategorizedServerFailure]] [[PipelineFailure]] with the original - * [[Throwable]] as the cause, even if it's already a [[PipelineFailure]]. - * - * This ensures that any access to the stored feature will result in a meaningful [[UncategorizedServerFailure]] - * [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory]] in stats which is more useful - * for customers components which access a failed [[Feature]] than the original [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory]]. - */ - def uncategorizedServerFailure( - componentStack: ComponentIdentifierStack, - throwable: Throwable - ): PipelineFailure = { - PipelineFailure( - UncategorizedServerFailure, - reason = "Unclassified Failure in Pipeline", - Some(throwable), - Some(componentStack) - ) - } - - /** - * [[PartialFunction]] that converts any [[Throwable]] into a - * [[PipelineFailure]] based on the provided `failureClassifier` - */ - def toPipelineFailureWithComponentIdentifierStack( - context: Context, - currentComponentIdentifier: ComponentIdentifier - ): PipelineFailureClassifier = { - // if given a `currentComponentIdentifier` then ensure we correctly handle `BasedOnParentComponent` identifier types - val contextWithCurrentComponentIdentifier = - context.pushToComponentStack(currentComponentIdentifier) - PipelineFailureClassifier( - contextWithCurrentComponentIdentifier.pipelineFailureClassifier - .orElse[Throwable, PipelineFailure] { - case CancelledExceptionExtractor(throwable) => throw throwable - case pipelineFailure: PipelineFailure => pipelineFailure - case throwable => - uncategorizedServerFailure( - contextWithCurrentComponentIdentifier.componentStack, - throwable) - }.andThen { pipelineFailure => - pipelineFailure.componentStack match { - case _: Some[_] => pipelineFailure - case None => - pipelineFailure.copy(componentStack = - Some(contextWithCurrentComponentIdentifier.componentStack)) - } - } - ) - } - - /** - * information used by an [[Executor]] that provides context around execution - */ - case class Context( - pipelineFailureClassifier: PipelineFailureClassifier, - componentStack: ComponentIdentifierStack) { - - def pushToComponentStack(newComponentIdentifier: ComponentIdentifier): Context = - copy(componentStack = componentStack.push(newComponentIdentifier)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala deleted file mode 100644 index 16df331fb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorObserver.scala +++ /dev/null @@ -1,146 +0,0 @@ -package com.twitter.product_mixer.core.service - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ProductPipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.Executor.Context -import com.twitter.product_mixer.shared_library.observer.Observer -import com.twitter.product_mixer.shared_library.observer.Observer.Observer -import com.twitter.product_mixer.shared_library.observer.ResultsStatsObserver.ResultsStatsObserver -import com.twitter.util.Duration -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try - -private[core] object ExecutorObserver { - - /** Make a [[ExecutorObserver]] with stats for the [[ComponentIdentifier]] and relative to the parent in the [[Context.componentStack]] */ - def executorObserver[T]( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - statsReceiver: StatsReceiver - ): ExecutorObserver[T] = new ExecutorObserver[T]( - Executor.broadcastStatsReceiver(context, currentComponentIdentifier, statsReceiver)) - - /** Make a [[ExecutorObserverWithSize]] with stats for the [[ComponentIdentifier]] and relative to the parent in the [[Context.componentStack]] */ - def executorObserverWithSize( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - statsReceiver: StatsReceiver - ): ExecutorObserverWithSize = new ExecutorObserverWithSize( - Executor.broadcastStatsReceiver(context, currentComponentIdentifier, statsReceiver)) - - /** Make a [[PipelineExecutorObserver]] with stats for the [[ComponentIdentifier]] and relative to the parent in the [[Context.componentStack]] */ - def pipelineExecutorObserver[T <: PipelineResult[_]]( - context: Context, - currentComponentIdentifier: ComponentIdentifier, - statsReceiver: StatsReceiver - ): PipelineExecutorObserver[T] = new PipelineExecutorObserver[T]( - Executor.broadcastStatsReceiver(context, currentComponentIdentifier, statsReceiver)) - - /** - * Make a [[PipelineExecutorObserver]] specifically for a [[com.twitter.product_mixer.core.pipeline.product.ProductPipeline]] - * with no relative stats - */ - def productPipelineExecutorObserver[T <: PipelineResult[_]]( - currentComponentIdentifier: ProductPipelineIdentifier, - statsReceiver: StatsReceiver - ): PipelineExecutorObserver[T] = - new PipelineExecutorObserver[T](statsReceiver.scope(currentComponentIdentifier.toScopes: _*)) - - /** - * Make a [[PipelineExecutorObserver]] with only stats relative to the parent pipeline - * for [[com.twitter.product_mixer.core.pipeline.PipelineBuilder.Step]]s - */ - def stepExecutorObserver( - context: Context, - currentComponentIdentifier: PipelineStepIdentifier, - statsReceiver: StatsReceiver - ): ExecutorObserver[Unit] = { - new ExecutorObserver[Unit]( - statsReceiver.scope( - Executor.buildScopes(context, currentComponentIdentifier).relativeScope: _*)) - } -} - -/** - * An [[Observer]] which is called as a side effect. Unlike the other observers which wrap a computation, - * this [[Observer]] expects the caller to provide the latency value and wire it in - */ -private[core] sealed class ExecutorObserver[T]( - override val statsReceiver: StatsReceiver) - extends { - - /** - * always empty because we expect an already scoped [[com.twitter.finagle.stats.BroadcastStatsReceiver]] to be passed in - * @note uses early definitions [[https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html]] to avoid null values for `scopes` in [[Observer]] - */ - override val scopes: Seq[String] = Seq.empty -} with Observer[T] { - - /** - * Serialize the provided [[Throwable]], prefixing [[PipelineFailure]]s with their - * [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory.categoryName]] and - * [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory.failureName]] - */ - override def serializeThrowable(throwable: Throwable): Seq[String] = { - throwable match { - case PipelineFailure(category, _, None, _) => - Seq(category.categoryName, category.failureName) - case PipelineFailure(category, _, Some(underlying), _) => - Seq(category.categoryName, category.failureName) ++ serializeThrowable(underlying) - case throwable: Throwable => super.serializeThrowable(throwable) - } - } - - /** record success, failure, and latency stats based on `t` and `latency` */ - def apply(t: Try[T], latency: Duration): Unit = observe(t, latency) -} - -/** - * Same as [[ExecutorObserver]] but records a size stat for [[PipelineResult]]s and - * records a failure counter for the cause of the failure under `failures/$pipelineFailureCategory/$componentType/$componentName`. - * - * @example if `GateIdentifier("MyGate")` is at the top of the [[PipelineFailure.componentStack]] then - * the resulting metric `failures/ClientFailure/Gate/MyGate` will be incremented. - */ -private[core] final class PipelineExecutorObserver[T <: PipelineResult[_]]( - override val statsReceiver: StatsReceiver) - extends ExecutorObserver[T](statsReceiver) - with ResultsStatsObserver[T] { - override val size: T => Int = _.resultSize() - - override def apply(t: Try[T], latency: Duration): Unit = { - super.apply(t, latency) - t match { - case Return(result) => observeResults(result) - case Throw(PipelineFailure(category, _, _, Some(componentIdentifierStack))) => - statsReceiver - .counter( - Seq( - Observer.Failures, - category.categoryName, - category.failureName) ++ componentIdentifierStack.peek.toScopes: _*).incr() - case _ => - } - } -} - -/** Same as [[ExecutorObserver]] but records a size stat */ -private[core] final class ExecutorObserverWithSize( - override val statsReceiver: StatsReceiver) - extends ExecutorObserver[Int](statsReceiver) - with ResultsStatsObserver[Int] { - override val size: Int => Int = identity - - override def apply(t: Try[Int], latency: Duration): Unit = { - super.apply(t, latency) - t match { - case Return(result) => observeResults(result) - case _ => - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala deleted file mode 100644 index 3a37870bd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/ExecutorResult.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.twitter.product_mixer.core.service - -trait ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala deleted file mode 100644 index 799112be2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/AsyncFeatureMapExecutor.scala +++ /dev/null @@ -1,58 +0,0 @@ -package com.twitter.product_mixer.core.service.async_feature_map_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.Executor._ -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class AsyncFeatureMapExecutor @Inject() ( - override val statsReceiver: StatsReceiver) - extends Executor { - - /** - * Forces an [[AsyncFeatureMap]] to hydrate and resolve into a [[FeatureMap]] - * containing all [[com.twitter.product_mixer.core.feature.Feature]]s that are - * supposed to be hydrated before `stepToHydrateBefore`. - */ - def arrow( - stepToHydrateFor: PipelineStepIdentifier, - currentStep: PipelineStepIdentifier, - context: Context - ): Arrow[AsyncFeatureMap, AsyncFeatureMapExecutorResults] = { - Arrow - .map[AsyncFeatureMap, Option[Stitch[FeatureMap]]](_.hydrate(stepToHydrateFor)) - .andThen( - Arrow.choose( - Arrow.Choice.ifDefinedAt( - { case Some(stitchOfFeatureMap) => stitchOfFeatureMap }, - // only stat if there's something to hydrate - wrapComponentWithExecutorBookkeeping(context, currentStep)( - Arrow - .flatMap[Stitch[FeatureMap], FeatureMap](identity) - .map(featureMap => - AsyncFeatureMapExecutorResults(Map(stepToHydrateFor -> featureMap))) - ) - ), - Arrow.Choice.otherwise(Arrow.value(AsyncFeatureMapExecutorResults(Map.empty))) - ) - ) - } -} - -case class AsyncFeatureMapExecutorResults( - featureMapsByStep: Map[PipelineStepIdentifier, FeatureMap]) - extends ExecutorResult { - def ++( - asyncFeatureMapExecutorResults: AsyncFeatureMapExecutorResults - ): AsyncFeatureMapExecutorResults = - AsyncFeatureMapExecutorResults( - featureMapsByStep ++ asyncFeatureMapExecutorResults.featureMapsByStep) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD deleted file mode 100644 index 7b70b50e6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/async_feature_map_executor/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD deleted file mode 100644 index f1b84bbc7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/decorator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/presentation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala deleted file mode 100644 index 141d9bce1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutor.scala +++ /dev/null @@ -1,38 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_decorator_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.decorator.CandidateDecorator -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CandidateDecoratorExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - def arrow[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - decoratorOpt: Option[CandidateDecorator[Query, Candidate]], - context: Executor.Context - ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), CandidateDecoratorExecutorResult] = { - val decoratorArrow = - decoratorOpt match { - case Some(decorator) => - val candidateDecoratorArrow = - Arrow.flatMap[(Query, Seq[CandidateWithFeatures[Candidate]]), Seq[Decoration]] { - case (query, candidatesWithFeatures) => decorator.apply(query, candidatesWithFeatures) - } - - wrapComponentWithExecutorBookkeeping(context, decorator.identifier)( - candidateDecoratorArrow) - - case _ => Arrow.value(Seq.empty[Decoration]) - } - - decoratorArrow.map(CandidateDecoratorExecutorResult) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala deleted file mode 100644 index 3f882c963..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_decorator_executor/CandidateDecoratorExecutorResult.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_decorator_executor - -import com.twitter.product_mixer.core.functional_component.decorator.Decoration -import com.twitter.product_mixer.core.service.ExecutorResult - -case class CandidateDecoratorExecutorResult(result: Seq[Decoration]) extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD deleted file mode 100644 index 8395e2754..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala deleted file mode 100644 index f25e7bedf..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutor.scala +++ /dev/null @@ -1,277 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseBulkCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseCandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.CandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.HydratorCandidateResult -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1CandidateFeatureHydrator -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.MisconfiguredFeatureMapFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.Executor._ -import com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor.CandidateFeatureHydratorExecutor.Inputs -import com.twitter.product_mixer.core.service.feature_hydrator_observer.FeatureHydratorObserver -import com.twitter.stitch.Arrow -import com.twitter.util.Try -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CandidateFeatureHydratorExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - def arrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - hydrators: Seq[BaseCandidateFeatureHydrator[Query, Result, _]], - context: Executor.Context - ): Arrow[ - Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[ - Result - ] - ] = { - - val observer = new FeatureHydratorObserver(statsReceiver, hydrators, context) - - val candidateFeatureHydratorExecutorResults: Seq[Arrow[ - Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ]] = hydrators.map(getCandidateHydratorArrow(_, context, observer)) - - val runHydrators = Arrow.collect(candidateFeatureHydratorExecutorResults).map { - candidateFeatureHydratorExecutorResult: Seq[CandidateFeatureHydratorExecutorResult[Result]] => - candidateFeatureHydratorExecutorResult.foldLeft( - CandidateFeatureHydratorExecutorResult[Result]( - Seq.empty, - Map.empty - ) - ) { (accumulator, additionalResult) => - // accumulator.results and additionalResults.results are either the same length or one may be empty - // checks in each Hydrator's Arrow implementation ensure the ordering and length are correct - val mergedFeatureMaps = - if (accumulator.results.length == additionalResult.results.length) { - // merge if there are results for both and they are the same size - // also handles both being empty - accumulator.results.zip(additionalResult.results).map { - case (accumulatedScoredCandidate, resultScoredCandidate) => - val updatedFeatureMap = - accumulatedScoredCandidate.features ++ resultScoredCandidate.features - HydratorCandidateResult(resultScoredCandidate.candidate, updatedFeatureMap) - } - } else if (accumulator.results.isEmpty) { - // accumulator is empty (the initial case) so use additional results - additionalResult.results - } else { - // empty results but non-empty accumulator due to Hydrator being turned off so use accumulator results - accumulator.results - } - - CandidateFeatureHydratorExecutorResult( - mergedFeatureMaps, - accumulator.individualFeatureHydratorResults ++ additionalResult.individualFeatureHydratorResults - ) - } - } - - Arrow.ifelse[Inputs[Query, Result], CandidateFeatureHydratorExecutorResult[Result]]( - _.candidates.nonEmpty, - runHydrators, - Arrow.value(CandidateFeatureHydratorExecutorResult(Seq.empty, Map.empty))) - } - - /** @note the returned [[Arrow]] must have a result for every candidate passed into it in the same order OR a completely empty result */ - private def getCandidateHydratorArrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - hydrator: BaseCandidateFeatureHydrator[Query, Result, _], - context: Executor.Context, - candidateFeatureHydratorObserver: FeatureHydratorObserver - ): Arrow[ - Inputs[Query, Result], - CandidateFeatureHydratorExecutorResult[Result] - ] = { - val componentExecutorContext = context.pushToComponentStack(hydrator.identifier) - - val validateFeatureMapFn: FeatureMap => FeatureMap = - hydrator match { - // Feature store candidate hydrators store the resulting PredictionRecords and - // not the features, so we cannot validate the same way - case _: FeatureStoreV1CandidateFeatureHydrator[Query, Result] => - identity - case _ => - validateFeatureMap( - hydrator.features.asInstanceOf[Set[Feature[_, _]]], - _, - componentExecutorContext) - } - - val hydratorBaseArrow = hydrator match { - case hydrator: CandidateFeatureHydrator[Query, Result] => - singleCandidateHydratorArrow( - hydrator, - validateFeatureMapFn, - componentExecutorContext, - parentContext = context) - - case hydrator: BaseBulkCandidateFeatureHydrator[Query, Result, _] => - bulkCandidateHydratorArrow( - hydrator, - validateFeatureMapFn, - componentExecutorContext, - parentContext = context) - } - - val candidateFeatureHydratorArrow = - Arrow - .zipWithArg(hydratorBaseArrow) - .map { - case ( - arg: CandidateFeatureHydratorExecutor.Inputs[Query, Result], - featureMapSeq: Seq[FeatureMap]) => - val candidates = arg.candidates.map(_.candidate) - - candidateFeatureHydratorObserver.observeFeatureSuccessAndFailures( - hydrator, - featureMapSeq) - - // Build a map from candidate to FeatureMap - val candidateAndFeatureMaps = if (candidates.size == featureMapSeq.size) { - candidates.zip(featureMapSeq).map { - case (candidate, featureMap) => HydratorCandidateResult(candidate, featureMap) - } - } else { - throw PipelineFailure( - MisconfiguredFeatureMapFailure, - s"Unexpected response length from ${hydrator.identifier}, ensure hydrator returns feature map for all candidates") - } - val individualFeatureHydratorFeatureMaps = - Map(hydrator.identifier -> IndividualFeatureHydratorResult(candidateAndFeatureMaps)) - CandidateFeatureHydratorExecutorResult( - candidateAndFeatureMaps, - individualFeatureHydratorFeatureMaps) - } - - val conditionallyRunArrow = hydrator match { - case hydrator: BaseCandidateFeatureHydrator[Query, Result, _] with Conditionally[ - Query @unchecked - ] => - Arrow.ifelse[Inputs[Query, Result], CandidateFeatureHydratorExecutorResult[Result]]( - { case Inputs(query: Query @unchecked, _) => hydrator.onlyIf(query) }, - candidateFeatureHydratorArrow, - Arrow.value( - CandidateFeatureHydratorExecutorResult( - Seq.empty, - Map(hydrator.identifier -> FeatureHydratorDisabled[Result]()) - )) - ) - case _ => candidateFeatureHydratorArrow - } - - wrapWithErrorHandling(context, hydrator.identifier)(conditionallyRunArrow) - } - - private def singleCandidateHydratorArrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - hydrator: CandidateFeatureHydrator[Query, Result], - validateFeatureMap: FeatureMap => FeatureMap, - componentContext: Context, - parentContext: Context - ): Arrow[Inputs[Query, Result], Seq[FeatureMap]] = { - val inputTransformer = Arrow - .map { inputs: Inputs[Query, Result] => - inputs.candidates.map { candidate => - (inputs.query, candidate.candidate, candidate.features) - } - } - - val hydratorArrow = Arrow - .flatMap[(Query, Result, FeatureMap), FeatureMap] { - case (query, candidate, featureMap) => - hydrator.apply(query, candidate, featureMap) - } - - // validate before observing so validation failures are caught in the metrics - val hydratorArrowWithValidation = hydratorArrow.map(validateFeatureMap) - - // no tracing here since per-Component spans is overkill - val observedArrow = - wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing( - parentContext, - hydrator.identifier - )(hydratorArrowWithValidation) - - // only handle non-validation failures - val liftNonValidationFailuresToFailedFeatures = Arrow.handle[FeatureMap, FeatureMap] { - case NotAMisconfiguredFeatureMapFailure(e) => - featureMapWithFailuresForFeatures(hydrator.features, e, componentContext) - } - - wrapComponentsWithTracingOnly(parentContext, hydrator.identifier)( - inputTransformer.andThen( - Arrow.sequence(observedArrow.andThen(liftNonValidationFailuresToFailedFeatures)) - ) - ) - } - - private def bulkCandidateHydratorArrow[Query <: PipelineQuery, Result <: UniversalNoun[Any]]( - hydrator: BaseBulkCandidateFeatureHydrator[Query, Result, _], - validateFeatureMap: FeatureMap => FeatureMap, - componentContext: Context, - parentContext: Context - ): Arrow[Inputs[Query, Result], Seq[FeatureMap]] = { - val hydratorArrow: Arrow[Inputs[Query, Result], Seq[FeatureMap]] = - Arrow.flatMap { inputs => - hydrator.apply(inputs.query, inputs.candidates) - } - - val validationArrow: Arrow[(Inputs[Query, Result], Seq[FeatureMap]), Seq[FeatureMap]] = Arrow - .map[(Inputs[Query, Result], Seq[FeatureMap]), Seq[FeatureMap]] { - case (inputs, results) => - // For bulk APIs, this ensures no candidates are omitted and also ensures the order is preserved. - if (inputs.candidates.length != results.length) { - throw PipelineFailure( - MisconfiguredFeatureMapFailure, - s"Unexpected response from ${hydrator.identifier}, ensure hydrator returns features for all candidates. Missing results for ${inputs.candidates.length - results.length} candidates" - ) - } - - results.map(validateFeatureMap) - } - - // validate before observing so validation failures are caught in the metrics - val hydratorArrowWithValidation: Arrow[Inputs[Query, Result], Seq[FeatureMap]] = - Arrow.zipWithArg(hydratorArrow).andThen(validationArrow) - - val observedArrow = - wrapComponentWithExecutorBookkeeping(parentContext, hydrator.identifier)( - hydratorArrowWithValidation) - - // only handle non-validation failures - val liftNonValidationFailuresToFailedFeatures = - Arrow.map[(Inputs[Query, Result], Try[Seq[FeatureMap]]), Try[Seq[FeatureMap]]] { - case (inputs, resultTry) => - resultTry.handle { - case NotAMisconfiguredFeatureMapFailure(e) => - val errorFeatureMap = - featureMapWithFailuresForFeatures( - hydrator.features.asInstanceOf[Set[Feature[_, _]]], - e, - componentContext) - inputs.candidates.map(_ => errorFeatureMap) - } - } - - Arrow - .zipWithArg(observedArrow.liftToTry) - .andThen(liftNonValidationFailuresToFailedFeatures) - .lowerFromTry - } -} - -object CandidateFeatureHydratorExecutor { - case class Inputs[+Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - query: Query, - candidates: Seq[CandidateWithFeatures[Candidate]]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala deleted file mode 100644 index 9a865a7b0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_hydrator_executor/CandidateFeatureHydratorExecutorResult.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_feature_hydrator_executor - -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.service.ExecutorResult - -case class CandidateFeatureHydratorExecutorResult[+Result <: UniversalNoun[Any]]( - results: Seq[CandidateWithFeatures[Result]], - individualFeatureHydratorResults: Map[ - _ <: ComponentIdentifier, - BaseIndividualFeatureHydratorResult[Result] - ]) extends ExecutorResult - -sealed trait BaseIndividualFeatureHydratorResult[+Result <: UniversalNoun[Any]] -case class FeatureHydratorDisabled[+Result <: UniversalNoun[Any]]() - extends BaseIndividualFeatureHydratorResult[Result] -case class IndividualFeatureHydratorResult[+Result <: UniversalNoun[Any]]( - result: Seq[CandidateWithFeatures[Result]]) - extends BaseIndividualFeatureHydratorResult[Result] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD deleted file mode 100644 index 40702d280..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala deleted file mode 100644 index 4c4ee849b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutor.scala +++ /dev/null @@ -1,93 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_feature_transformer_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.Executor._ -import com.twitter.stitch.Arrow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CandidateFeatureTransformerExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - def arrow[Result]( - transformers: Seq[CandidateFeatureTransformer[Result]], - context: Executor.Context - ): Arrow[Seq[Result], CandidateFeatureTransformerExecutorResult] = { - if (transformers.isEmpty) { - // must always return a Seq of FeatureMaps, even if there are no Transformers - Arrow.map[Seq[Result], CandidateFeatureTransformerExecutorResult] { candidates => - CandidateFeatureTransformerExecutorResult(candidates.map(_ => FeatureMap.empty), Seq.empty) - } - } else { - val transformerArrows: Seq[Arrow[Seq[Result], Seq[(TransformerIdentifier, FeatureMap)]]] = - transformers.map { transformer => - val transformerContext = context.pushToComponentStack(transformer.identifier) - - val liftNonValidationFailuresToFailedFeatures = - Arrow.handle[FeatureMap, FeatureMap] { - case NotAMisconfiguredFeatureMapFailure(e) => - featureMapWithFailuresForFeatures(transformer.features, e, transformerContext) - } - - val underlyingArrow = Arrow - .map(transformer.transform) - .map(validateFeatureMap(transformer.features, _, transformerContext)) - - val observedArrowWithoutTracing = - wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing( - context, - transformer.identifier)(underlyingArrow) - - val seqArrow = - Arrow.sequence( - observedArrowWithoutTracing - .andThen(liftNonValidationFailuresToFailedFeatures) - .map(transformer.identifier -> _) - ) - - wrapComponentsWithTracingOnly(context, transformer.identifier)(seqArrow) - } - - Arrow.collect(transformerArrows).map { results => - /** - * Inner Seqs are a given Transformer applied to all the candidates - * - * We want to merge the FeatureMaps for each candidate - * from all the Transformers. We do this by merging all the FeatureMaps at - * each index `i` of each Seq in `results` by `transpose`-ing the `results` - * so the inner Seq becomes all the FeatureMaps for Candidate - * at index `i` in the input Seq. - * - * {{{ - * Seq( - * Seq(transformer1FeatureMapCandidate1, ..., transformer1FeatureMapCandidateN), - * ..., - * Seq(transformerMFeatureMapCandidate1, ..., transformerMFeatureMapCandidateN) - * ).transpose == Seq( - * Seq(transformer1FeatureMapCandidate1, ..., transformerMFeatureMapCandidate1), - * ..., - * Seq(transformer1FeatureMapCandidateN, ..., transformerMFeatureMapCandidateN) - * ) - * }}} - * - * we could avoid the transpose if we ran each candidate through all the transformers - * one-after-the-other, but then we couldn't have a single tracing span for all applications - * of a Transformer, so instead we apply each transformer to all candidates together, then - * move onto the next transformer. - * - * It's worth noting that the outer Seq is bounded by the number of Transformers that are - * applied which will typically be small. - */ - val transposed = results.transpose - val combinedMaps = transposed.map(featureMapsForSingleCandidate => - FeatureMap.merge(featureMapsForSingleCandidate.map { case (_, maps) => maps })) - - CandidateFeatureTransformerExecutorResult(combinedMaps, transposed.map(_.toMap)) - } - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala deleted file mode 100644 index 8947897a6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor/CandidateFeatureTransformerExecutorResult.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_feature_transformer_executor - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.identifier.TransformerIdentifier - -case class CandidateFeatureTransformerExecutorResult( - featureMaps: Seq[FeatureMap], - individualFeatureMaps: Seq[Map[TransformerIdentifier, FeatureMap]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD deleted file mode 100644 index f89ba2858..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala deleted file mode 100644 index 6031d6e34..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutor.scala +++ /dev/null @@ -1,82 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_pipeline_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.pipeline.CandidatePipelineResults -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipeline -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineResult -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow -import com.twitter.util.logging.Logging - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class CandidatePipelineExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor - with Logging { - - def arrow[Query <: PipelineQuery]( - candidatePipelines: Seq[CandidatePipeline[Query]], - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[CandidatePipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineExecutorResult] = { - - // Get the `.arrow` of each Candidate Pipeline, and wrap it in a ResultObserver - val observedArrows: Seq[Arrow[CandidatePipeline.Inputs[Query], CandidatePipelineResult]] = - candidatePipelines.map { pipeline => - wrapPipelineWithExecutorBookkeeping( - context = context, - currentComponentIdentifier = pipeline.identifier, - qualityFactorObserver = qualityFactorObserverByPipeline.get(pipeline.identifier), - failOpenPolicy = failOpenPolicies.getOrElse(pipeline.identifier, defaultFailOpenPolicy) - )(pipeline.arrow) - } - - // Collect the results from all the candidate pipelines together - Arrow.zipWithArg(Arrow.collect(observedArrows)).map { - case (input: CandidatePipeline.Inputs[Query], results: Seq[CandidatePipelineResult]) => - val candidateWithDetails = results.flatMap(_.result.getOrElse(Seq.empty)) - val previousCandidateWithDetails = input.query.features - .map(_.getOrElse(CandidatePipelineResults, Seq.empty)) - .getOrElse(Seq.empty) - - val featureMapWithCandidates = FeatureMapBuilder() - .add(CandidatePipelineResults, previousCandidateWithDetails ++ candidateWithDetails) - .build() - - // Merge the query feature hydrator and candidate source query features back in. While this - // is done internally in the pipeline, we have to pass it back since we don't expose the - // updated pipeline query today. - val queryFeatureHydratorFeatureMaps = - results - .flatMap(result => Seq(result.queryFeatures, result.queryFeaturesPhase2)) - .collect { case Some(result) => result.featureMap } - val asyncFeatureHydratorFeatureMaps = - results - .flatMap(_.asyncFeatureHydrationResults) - .flatMap(_.featureMapsByStep.values) - - val candidateSourceFeatureMaps = - results - .flatMap(_.candidateSourceResult) - .map(_.candidateSourceFeatureMap) - - val featureMaps = - (featureMapWithCandidates +: queryFeatureHydratorFeatureMaps) ++ asyncFeatureHydratorFeatureMaps ++ candidateSourceFeatureMaps - val mergedFeatureMap = FeatureMap.merge(featureMaps) - CandidatePipelineExecutorResult( - candidatePipelineResults = results, - queryFeatureMap = mergedFeatureMap) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala deleted file mode 100644 index 8f3805f2f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_pipeline_executor/CandidatePipelineExecutorResult.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_pipeline_executor - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.pipeline.candidate.CandidatePipelineResult - -case class CandidatePipelineExecutorResult( - candidatePipelineResults: Seq[CandidatePipelineResult], - queryFeatureMap: FeatureMap) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD deleted file mode 100644 index c34688181..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala deleted file mode 100644 index 5d6df2678..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutor.scala +++ /dev/null @@ -1,173 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_source_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.functional_component.candidate_source.BaseCandidateSource -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSource -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidateSourceWithExtractedFeatures -import com.twitter.product_mixer.core.functional_component.candidate_source.CandidatesWithSourceFeatures -import com.twitter.product_mixer.core.functional_component.transformer.BaseCandidatePipelineQueryTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidateFeatureTransformer -import com.twitter.product_mixer.core.functional_component.transformer.CandidatePipelineResultsTransformer -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.CandidateSourcePosition -import com.twitter.product_mixer.core.model.common.presentation.CandidateSources -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ExecutionFailed -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.UnexpectedCandidateResult -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.candidate_feature_transformer_executor.CandidateFeatureTransformerExecutor -import com.twitter.product_mixer.core.service.transformer_executor.PerCandidateTransformerExecutor -import com.twitter.product_mixer.core.service.transformer_executor.TransformerExecutor -import com.twitter.stitch.Arrow -import com.twitter.util.Return -import com.twitter.util.Throw -import com.twitter.util.Try -import com.twitter.util.logging.Logging -import javax.inject.Inject -import javax.inject.Singleton -import scala.collection.immutable.ListSet - -/** - * [[CandidateSourceExecutor]]: - * - Executes a [[BaseCandidateSource]], using a [[BaseCandidatePipelineQueryTransformer]] and a [[CandidatePipelineResultsTransformer]] - * - in parallel, uses a [[CandidateFeatureTransformer]] to optionally extract [[com.twitter.product_mixer.core.feature.Feature]]s from the result - * - Handles [[UnexpectedCandidateResult]] [[PipelineFailure]]s returned from [[CandidatePipelineResultsTransformer]] failures by removing those candidates from the result - */ -@Singleton -class CandidateSourceExecutor @Inject() ( - override val statsReceiver: StatsReceiver, - candidateFeatureTransformerExecutor: CandidateFeatureTransformerExecutor, - transformerExecutor: TransformerExecutor, - perCandidateTransformerExecutor: PerCandidateTransformerExecutor) - extends Executor - with Logging { - - def arrow[ - Query <: PipelineQuery, - CandidateSourceQuery, - CandidateSourceResult, - Candidate <: UniversalNoun[Any] - ]( - candidateSource: BaseCandidateSource[CandidateSourceQuery, CandidateSourceResult], - queryTransformer: BaseCandidatePipelineQueryTransformer[ - Query, - CandidateSourceQuery - ], - resultTransformer: CandidatePipelineResultsTransformer[CandidateSourceResult, Candidate], - resultFeaturesTransformers: Seq[CandidateFeatureTransformer[CandidateSourceResult]], - context: Executor.Context - ): Arrow[Query, CandidateSourceExecutorResult[Candidate]] = { - - val candidateSourceArrow: Arrow[CandidateSourceQuery, CandidatesWithSourceFeatures[ - CandidateSourceResult - ]] = - candidateSource match { - case regularCandidateSource: CandidateSource[CandidateSourceQuery, CandidateSourceResult] => - Arrow.flatMap(regularCandidateSource.apply).map { candidates => - CandidatesWithSourceFeatures(candidates, FeatureMap.empty) - } - case candidateSourceWithExtractedFeatures: CandidateSourceWithExtractedFeatures[ - CandidateSourceQuery, - CandidateSourceResult - ] => - Arrow.flatMap(candidateSourceWithExtractedFeatures.apply) - } - - val resultsTransformerArrow: Arrow[Seq[CandidateSourceResult], Seq[Try[Candidate]]] = - perCandidateTransformerExecutor.arrow(resultTransformer, context) - - val featureMapTransformersArrow: Arrow[ - Seq[CandidateSourceResult], - Seq[FeatureMap] - ] = - candidateFeatureTransformerExecutor - .arrow(resultFeaturesTransformers, context).map(_.featureMaps) - - val candidatesResultArrow: Arrow[CandidatesWithSourceFeatures[CandidateSourceResult], Seq[ - (Candidate, FeatureMap) - ]] = Arrow - .map[CandidatesWithSourceFeatures[CandidateSourceResult], Seq[CandidateSourceResult]]( - _.candidates) - .andThen(Arrow - .joinMap(resultsTransformerArrow, featureMapTransformersArrow) { - case (transformed, features) => - if (transformed.length != features.length) - throw PipelineFailure( - ExecutionFailed, - s"Found ${transformed.length} candidates and ${features.length} FeatureMaps, expected their lengths to be equal") - transformed.iterator - .zip(features.iterator) - .collect { case ErrorHandling(result) => result } - .toSeq - }) - - // Build the final CandidateSourceExecutorResult - val executorResultArrow: Arrow[ - (FeatureMap, Seq[(Candidate, FeatureMap)]), - CandidateSourceExecutorResult[ - Candidate - ] - ] = Arrow.map { - case (queryFeatures: FeatureMap, results: Seq[(Candidate, FeatureMap)]) => - val candidatesWithFeatures: Seq[FetchedCandidateWithFeatures[Candidate]] = - results.zipWithIndex.map { - case ((candidate, featureMap), index) => - FetchedCandidateWithFeatures( - candidate, - featureMap + (CandidateSourcePosition, index) + (CandidateSources, ListSet( - candidateSource.identifier)) - ) - } - CandidateSourceExecutorResult( - candidates = candidatesWithFeatures, - candidateSourceFeatureMap = queryFeatures - ) - } - - val queryTransformerArrow = - transformerExecutor.arrow[Query, CandidateSourceQuery](queryTransformer, context) - - val combinedArrow = - queryTransformerArrow - .andThen(candidateSourceArrow) - .andThen( - Arrow - .join( - Arrow.map[CandidatesWithSourceFeatures[CandidateSourceResult], FeatureMap]( - _.features), - candidatesResultArrow - )) - .andThen(executorResultArrow) - - wrapComponentWithExecutorBookkeepingWithSize[Query, CandidateSourceExecutorResult[Candidate]]( - context, - candidateSource.identifier, - result => result.candidates.size - )(combinedArrow) - } - - object ErrorHandling { - - /** Silently drop [[UnexpectedCandidateResult]] */ - def unapply[Candidate]( - candidateTryAndFeatureMap: (Try[Candidate], FeatureMap) - ): Option[(Candidate, FeatureMap)] = { - val (candidateTry, featureMap) = candidateTryAndFeatureMap - val candidateOpt = candidateTry match { - case Throw(PipelineFailure(UnexpectedCandidateResult, _, _, _)) => None - case Throw(ex) => throw ex - case Return(r) => Some(r) - } - - candidateOpt.map { candidate => (candidate, featureMap) } - } - } -} - -case class FetchedCandidateWithFeatures[Candidate <: UniversalNoun[Any]]( - candidate: Candidate, - features: FeatureMap) - extends CandidateWithFeatures[Candidate] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala deleted file mode 100644 index 451bae1ae..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_source_executor/CandidateSourceExecutorResult.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.service.candidate_source_executor - -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.service.ExecutorResult - -case class CandidateSourceExecutorResult[Candidate <: UniversalNoun[Any]]( - candidates: Seq[FetchedCandidateWithFeatures[Candidate]], - candidateSourceFeatureMap: FeatureMap) - extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD deleted file mode 100644 index 34d6b7fda..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "util/util-slf4j-api", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala deleted file mode 100644 index 14b70aa84..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/ComponentRegistry.scala +++ /dev/null @@ -1,182 +0,0 @@ -package com.twitter.product_mixer.core.service.component_registry - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.util.Activity -import com.twitter.util.Future -import com.twitter.util.Try -import com.twitter.util.logging.Logging -import java.util.concurrent.ConcurrentHashMap -import javax.inject.Inject -import javax.inject.Singleton -import scala.collection.JavaConverters._ - -/** - * The [[ComponentRegistry]] works closely with [[ComponentIdentifier]]s and the [[com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry]] - * to provide the Product Mixer framework information about the [[com.twitter.product_mixer.core.pipeline.Pipeline]]s and [[Component]]s - * that make up an application. - * - * This registration allows us to configure alerts and dashboards, - * to query your application structure letting us display the graph of the execution and the results of queries, - * and to garner insight into usages. - * - * The registry is a snapshot of the state of the world when pipelines were last built successfully. - * For most services, this only happens once on startup. However, some services may rebuild their - * pipelines dynamically later on. - */ - -@Singleton -class ComponentRegistry @Inject() (statsReceiver: StatsReceiver) { - // Initially pending until the first snapshot is built by [[ProductPipelineRegistry]] - private val (snapshotActivity, snapshotWitness) = Activity[ComponentRegistrySnapshot]() - private val snapshotCount = statsReceiver.counter("ComponentRegistry", "SnapshotCount") - - def get: Future[ComponentRegistrySnapshot] = snapshotActivity.values.toFuture.lowerFromTry - private[core] def set(snapshot: ComponentRegistrySnapshot): Unit = { - snapshotCount.incr() - snapshotWitness.notify(Try(snapshot)) - } -} - -class ComponentRegistrySnapshot() extends Logging { - - /** for storing the [[RegisteredComponent]]s */ - private[this] val componentRegistry = - new ConcurrentHashMap[ComponentIdentifier, RegisteredComponent] - - /** for determining the children of a [[ComponentIdentifier]] */ - private[this] val componentChildren = - new ConcurrentHashMap[ComponentIdentifier, Set[ComponentIdentifier]] - - /** for determining [[ComponentIdentifier]] uniqueness within a given [[ComponentIdentifierStack]] */ - private[this] val componentHierarchy = - new ConcurrentHashMap[ComponentIdentifierStack, Set[ComponentIdentifier]] - - /** - * Register the given [[Component]] at the end of path provided by `parentIdentifierStack` - * or throws an exception if adding the component results in an invalid configuration. - * - * @throws ChildComponentCollisionException if a [[Component]] with the same [[ComponentIdentifier]] is registered - * more than once under the same parent. - * e.g. if you register `ComponentA` under `ProductA -> PipelineA` twice, - * this exception will be thrown when registering `ComponentA` the second - * time. This is pretty much always a configuration error due to copy-pasting - * and forgetting to update the identifier, or accidentally using the same - * component twice under the same parent. If this didn't throw, stats from - * these 2 components would be indistinguishable. - * - * @throws ComponentIdentifierCollisionException if a [[Component]] with the same [[ComponentIdentifier]] is registered - * but it's type is not the same as a previously registered [[Component]] - * with the same [[ComponentIdentifier]] - * e.g. if you register 2 [[Component]]s with the same [[ComponentIdentifier]] - * such as `new Component` and an instance of - * `class MyComponent extends Component` the `new Component` will have a - * type of `Component` and the other one will have a type of `MyComponent` - * which will throw. This is usually due to copy-pasting a component as - * a starting point and forgetting to update the identifier. If this - * didn't throw, absolute stats from these 2 components would be - * indistinguishable. - * - * - * @note this will log details of component identifier reuse if the underling components are not equal, but otherwise are of the same class. - * Their stats will be merged and indistinguishable but since they are the same name and same class, we assume the differences are - * minor enough that this is okay, but make a note in the log at startup in case someone sees unexpected metrics, we can look - * back at the logs and see the details. - * - * @param component the component to register - * @param parentIdentifierStack the complete [[ComponentIdentifierStack]] excluding the current [[Component]]'s [[ComponentIdentifier]] - */ - def register( - component: Component, - parentIdentifierStack: ComponentIdentifierStack - ): Unit = synchronized { - val identifier = component.identifier - val parentIdentifier = parentIdentifierStack.peek - - val registeredComponent = - RegisteredComponent(identifier, component, component.identifier.file.value) - - componentRegistry.asScala - .get(identifier) - .filter(_.component != component) // only do the foreach if the components aren't equal - .foreach { - case existingComponent if existingComponent.component.getClass != component.getClass => - /** - * The same component may be registered under different parent components. - * However, different component types cannot use the same component identifier. - * - * This catches some copy-pasting of a config or component and forgetting to update the identifier. - */ - throw new ComponentIdentifierCollisionException( - componentIdentifier = identifier, - component = registeredComponent, - existingComponent = componentRegistry.get(identifier), - parentIdentifierStack = parentIdentifierStack, - existingIdentifierStack = componentHierarchy.search[ComponentIdentifierStack]( - 1, - (stack, identifiers) => if (identifiers.contains(identifier)) stack else null) - ) - case existingComponent => - /** - * The same component may be registered under different parent components. - * However, if the components are not equal it __may be__ a configuration error - * so we log a detailed description of the issue in case they need to debug. - * - * This warns customers of some copy-pasting of a config or component and forgetting to update the - * identifier and of reusing components with hard-coded values which are configured differently. - */ - val existingIdentifierStack = componentHierarchy.search[ComponentIdentifierStack]( - 1, - (stack, identifiers) => if (identifiers.contains(identifier)) stack else null) - logger.info( - s"Found duplicate identifiers for non-equal components, $identifier from ${registeredComponent.sourceFile} " + - s"under ${parentIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")} " + - s"was already defined and is unequal to ${existingComponent.sourceFile} " + - s"under ${existingIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")}. " + - s"Merging these components in the registry, this will result in their metrics being merged. " + - s"If these components should have separate metrics, consider providing unique identifiers for them instead." - ) - } - - /** The same component may not be registered multiple times under the same parent */ - if (componentHierarchy.getOrDefault(parentIdentifierStack, Set.empty).contains(identifier)) - throw new ChildComponentCollisionException(identifier, parentIdentifierStack) - - // add component to registry - componentRegistry.putIfAbsent(identifier, registeredComponent) - // add component to parent's `children` set for easy lookup - componentChildren.merge(parentIdentifier, Set(identifier), _ ++ _) - // add the component to the hierarchy under it's parent's identifier stack - componentHierarchy.merge(parentIdentifierStack, Set(identifier), _ ++ _) - } - - def getAllRegisteredComponents: Seq[RegisteredComponent] = - componentRegistry.values.asScala.toSeq.sorted - - def getChildComponents(component: ComponentIdentifier): Seq[ComponentIdentifier] = - Option(componentChildren.get(component)) match { - case Some(components) => components.toSeq.sorted(ComponentIdentifier.ordering) - case None => Seq.empty - } -} - -class ComponentIdentifierCollisionException( - componentIdentifier: ComponentIdentifier, - component: RegisteredComponent, - existingComponent: RegisteredComponent, - parentIdentifierStack: ComponentIdentifierStack, - existingIdentifierStack: ComponentIdentifierStack) - extends IllegalArgumentException( - s"Tried to register component $componentIdentifier: of type ${component.component.getClass} from ${component.sourceFile} " + - s"under ${parentIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")} " + - s"but it was already defined with a different type ${existingComponent.component.getClass} from ${existingComponent.sourceFile} " + - s"under ${existingIdentifierStack.componentIdentifiers.reverse.mkString(" -> ")}. " + - s"Ensure you aren't reusing a component identifier which can happen when copy-pasting existing component code by accident") - -class ChildComponentCollisionException( - componentIdentifier: ComponentIdentifier, - parentIdentifierStack: ComponentIdentifierStack) - extends IllegalArgumentException( - s"Component $componentIdentifier already defined under parent component $parentIdentifierStack") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala deleted file mode 100644 index 6ddadc033..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/component_registry/RegisteredComponent.scala +++ /dev/null @@ -1,15 +0,0 @@ -package com.twitter.product_mixer.core.service.component_registry - -import com.twitter.product_mixer.core.model.common.Component -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier - -object RegisteredComponent { - // Sort by ComponentIdentifier which has its own implicit ordering defined - implicit val ordering: Ordering[RegisteredComponent] = - Ordering.by[RegisteredComponent, ComponentIdentifier](_.component.identifier) -} - -case class RegisteredComponent( - identifier: ComponentIdentifier, - component: Component, - sourceFile: String) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala deleted file mode 100644 index 4c0aa8b88..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/AuthorizationService.scala +++ /dev/null @@ -1,82 +0,0 @@ -package com.twitter.product_mixer.core.service.debug_query - -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicy -import com.twitter.product_mixer.core.functional_component.common.access_policy.AccessPolicyEvaluator -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.core.pipeline.pipeline_failure.Authentication -import com.twitter.product_mixer.core.pipeline.pipeline_failure.BadRequest -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.turntable.{thriftscala => t} -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Basic class that provides a verification method for checking if a call to our debugging - * features is allowed/authorized to make said call. - * @param isServiceLocal Whether the service is being run locally. - */ -@Singleton -class AuthorizationService @Inject() (@Flag(ServiceLocal) isServiceLocal: Boolean) { - import AuthorizationService._ - - /** - * Check whether a call to a given product is authorized. Throws an [[UnauthorizedServiceCallException]] - * if not. - * @param requestingServiceIdentifier The Service Identifier of the calling service - * @param productAccessPolicies The access policies of the product being called. - * @param requestContext The request context of the caller. - */ - def verifyRequestAuthorization( - componentIdentifierStack: ComponentIdentifierStack, - requestingServiceIdentifier: ServiceIdentifier, - productAccessPolicies: Set[AccessPolicy], - requestContext: t.TurntableRequestContext - ): Unit = { - val isServiceCallAuthorized = - requestingServiceIdentifier.role == AllowedServiceIdentifierRole && requestingServiceIdentifier.service == AllowedServiceIdentifierName - val userLdapGroups = requestContext.ldapGroups.map(_.toSet) - - val accessPolicyAllowed = AccessPolicyEvaluator.evaluate( - productAccessPolicies = productAccessPolicies, - userLdapGroups = userLdapGroups.getOrElse(Set.empty) - ) - - if (!isServiceLocal && !isServiceCallAuthorized) { - throw new UnauthorizedServiceCallException( - requestingServiceIdentifier, - componentIdentifierStack) - } - - if (!isServiceLocal && !accessPolicyAllowed) { - throw new InsufficientAccessException( - userLdapGroups, - productAccessPolicies, - componentIdentifierStack) - } - } -} - -object AuthorizationService { - final val AllowedServiceIdentifierRole = "turntable" - final val AllowedServiceIdentifierName = "turntable" -} - -class UnauthorizedServiceCallException( - serviceIdentifier: ServiceIdentifier, - componentIdentifierStack: ComponentIdentifierStack) - extends PipelineFailure( - BadRequest, - s"Unexpected Service tried to call Turntable Debug endpoint: ${ServiceIdentifier.asString(serviceIdentifier)}", - componentStack = Some(componentIdentifierStack)) - -class InsufficientAccessException( - ldapGroups: Option[Set[String]], - desiredAccessPolicies: Set[AccessPolicy], - componentIdentifierStack: ComponentIdentifierStack) - extends PipelineFailure( - Authentication, - s"Request did not satisfy access policies: $desiredAccessPolicies with ldapGroups = $ldapGroups", - componentStack = Some(componentIdentifierStack)) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD deleted file mode 100644 index 251996247..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/BUILD +++ /dev/null @@ -1,20 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/configapi", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/recommendation", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala", - "product-mixer/turntable/service/src/main/scala/com/twitter/turntable/context:key", - "stitch/stitch-core", - "util/util-core:scala", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala deleted file mode 100644 index 22870d3d5..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryNotSupportedService.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.twitter.product_mixer.core.service.debug_query - -import com.twitter.finagle.Service -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineResult -import com.twitter.scrooge.{Request => ScroogeRequest} -import com.twitter.scrooge.{Response => ScroogeResponse} -import com.twitter.util.Future -import com.twitter.product_mixer.core.{thriftscala => t} -import com.twitter.util.jackson.ScalaObjectMapper - -/** - * All Mixers must implement a debug query interface. This can be a problem for in-place migrations - * where a service may only partially implement Product Mixer patterns. This service can be used as - * a noop implementation of [[DebugQueryService]] until the Mixer service is fully migrated. - */ -object DebugQueryNotSupportedService - extends Service[ScroogeRequest[_], ScroogeResponse[t.PipelineExecutionResult]] { - - val failureJson: String = { - val message = "This service does not support debug queries, this is usually due to an active " + - "in-place migration to Product Mixer. Please reach out in #product-mixer if you have any questions." - - ScalaObjectMapper().writeValueAsString( - ProductPipelineResult( - transformedQuery = None, - qualityFactorResult = None, - gateResult = None, - pipelineSelectorResult = None, - mixerPipelineResult = None, - recommendationPipelineResult = None, - traceId = None, - failure = Some(PipelineFailure(ProductDisabled, message)), - result = None, - )) - } - - override def apply( - thriftRequest: ScroogeRequest[_] - ): Future[ScroogeResponse[t.PipelineExecutionResult]] = - Future.value(ScroogeResponse(t.PipelineExecutionResult(failureJson))) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala deleted file mode 100644 index 9a8f5f413..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/DebugQueryService.scala +++ /dev/null @@ -1,109 +0,0 @@ -package com.twitter.product_mixer.core.service.debug_query - -import com.fasterxml.jackson.databind.SerializationFeature -import com.twitter.finagle.Service -import com.twitter.finagle.context.Contexts -import com.twitter.finagle.tracing.Trace.traceLocal -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.transport.Transport -import com.twitter.product_mixer.core.functional_component.configapi.ParamsBuilder -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifierStack -import com.twitter.product_mixer.core.model.marshalling.request.Product -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.product.ProductPipeline -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest -import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry -import com.twitter.product_mixer.core.{thriftscala => t} -import com.twitter.scrooge.ThriftStruct -import com.twitter.scrooge.{Request => ScroogeRequest} -import com.twitter.scrooge.{Response => ScroogeResponse} -import com.twitter.stitch.Stitch -import com.twitter.turntable.context.TurntableRequestContextKey -import com.twitter.util.jackson.ScalaObjectMapper -import javax.inject.Inject -import javax.inject.Singleton -import scala.reflect.runtime.universe.TypeTag - -/** - * Returns the complete execution log for a pipeline query. These endpoints are intended for - * debugging (primarily through Turntable). - */ -@Singleton -class DebugQueryService @Inject() ( - productPipelineRegistry: ProductPipelineRegistry, - paramsBuilder: ParamsBuilder, - authorizationService: AuthorizationService) { - - private val mapper = - ScalaObjectMapper.builder - .withAdditionalJacksonModules(Seq(ParamsSerializerModule)) - .withSerializationConfig( - Map( - // These are copied from the default serialization config. - SerializationFeature.WRITE_DATES_AS_TIMESTAMPS -> false, - SerializationFeature.WRITE_ENUMS_USING_TO_STRING -> true, - // Generally we want to be defensive when serializing since we don't control everything that's - // serialized. This issue also came up when trying to serialize Unit as part of sync side effects. - SerializationFeature.FAIL_ON_EMPTY_BEANS -> false, - )) - // The default implementation represents numbers as JSON Numbers (i.e. Double with 53 bit precision - // which leads to Snowflake IDs being cropped in the case of tweets. - .withNumbersAsStrings(true) - .objectMapper - - def apply[ - ThriftRequest <: ThriftStruct with Product1[MixerServiceRequest], - MixerServiceRequest <: ThriftStruct, - MixerRequest <: Request - ]( - unmarshaller: MixerServiceRequest => MixerRequest - )( - implicit requestTypeTag: TypeTag[MixerRequest] - ): Service[ScroogeRequest[ThriftRequest], ScroogeResponse[t.PipelineExecutionResult]] = { - (thriftRequest: ScroogeRequest[ThriftRequest]) => - { - - val request = unmarshaller(thriftRequest.args._1) - val params = paramsBuilder.build( - clientContext = request.clientContext, - product = request.product, - featureOverrides = request.debugParams.flatMap(_.featureOverrides).getOrElse(Map.empty) - ) - - val productPipeline = productPipelineRegistry - .getProductPipeline[MixerRequest, Any](request.product) - verifyRequestAuthorization(request.product, productPipeline) - Contexts.broadcast.letClear(TurntableRequestContextKey) { - Stitch - .run(productPipeline - .arrow(ProductPipelineRequest(request, params)).map { detailedResult => - // Serialization can be slow so a trace is useful both for optimization by the Promix - // team and to give visibility to customers. - val serializedJSON = - traceLocal("serialize_debug_response")(mapper.writeValueAsString(detailedResult)) - t.PipelineExecutionResult(serializedJSON) - }) - .map(ScroogeResponse(_)) - } - } - } - - private def verifyRequestAuthorization( - product: Product, - productPipeline: ProductPipeline[_, _] - ): Unit = { - val serviceIdentifier = ServiceIdentifier.fromCertificate(Transport.peerCertificate) - val requestContext = Contexts.broadcast - .get(TurntableRequestContextKey).getOrElse(throw MissingTurntableRequestContextException) - - val componentStack = ComponentIdentifierStack(productPipeline.identifier, product.identifier) - authorizationService.verifyRequestAuthorization( - componentStack, - serviceIdentifier, - productPipeline.debugAccessPolicies, - requestContext) - } -} - -object MissingTurntableRequestContextException - extends Exception("Request is missing turntable request context") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala deleted file mode 100644 index e7265378f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/debug_query/ParamsSerializerModule.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.service.debug_query - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.SerializerProvider -import com.fasterxml.jackson.databind.ser.std.StdSerializer -import com.twitter.timelines.configapi.Params -import com.fasterxml.jackson.databind.module.SimpleModule -import com.twitter.timelines.configapi.Config - -object ParamsSerializerModule extends SimpleModule { - addSerializer(ParamsConfigSerializer) - addSerializer(ParamsStdSerializer) -} - -object ParamsStdSerializer extends StdSerializer[Params](classOf[Params]) { - override def serialize( - value: Params, - gen: JsonGenerator, - provider: SerializerProvider - ): Unit = { - gen.writeStartObject() - gen.writeObjectField("applied_params", value.allAppliedValues) - gen.writeEndObject() - } -} - -object ParamsConfigSerializer extends StdSerializer[Config](classOf[Config]) { - override def serialize( - value: Config, - gen: JsonGenerator, - provider: SerializerProvider - ): Unit = { - gen.writeString(value.simpleName) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD deleted file mode 100644 index a56fdf2f4..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/premarshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala deleted file mode 100644 index f0dc0e263..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/domain_marshaller_executor/DomainMarshallerExecutor.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.twitter.product_mixer.core.service.domain_marshaller_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.premarshaller.DomainMarshaller -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor.Inputs -import com.twitter.product_mixer.core.service.domain_marshaller_executor.DomainMarshallerExecutor.Result -import com.twitter.stitch.Arrow -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Executes a [[DomainMarshaller]]. - * - * @note This is a synchronous transform, so we don't observe it directly. Failures and such - * can be observed at the parent pipeline. - */ -@Singleton -class DomainMarshallerExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - def arrow[Query <: PipelineQuery, DomainResponseType <: HasMarshalling]( - marshaller: DomainMarshaller[Query, DomainResponseType], - context: Executor.Context - ): Arrow[Inputs[Query], Result[DomainResponseType]] = { - val arrow = Arrow - .map[Inputs[Query], DomainMarshallerExecutor.Result[DomainResponseType]] { - case Inputs(query, candidates) => - DomainMarshallerExecutor.Result(marshaller(query, candidates)) - } - - wrapComponentWithExecutorBookkeeping(context, marshaller.identifier)(arrow) - } -} - -object DomainMarshallerExecutor { - case class Inputs[Query <: PipelineQuery]( - query: Query, - candidatesWithDetails: Seq[CandidateWithDetails]) - case class Result[+DomainResponseType](result: DomainResponseType) extends ExecutorResult -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD deleted file mode 100644 index f3991968f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala deleted file mode 100644 index b37134907..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer/FeatureHydratorObserver.scala +++ /dev/null @@ -1,136 +0,0 @@ -package com.twitter.product_mixer.core.service.feature_hydrator_observer - -import com.twitter.finagle.stats.BroadcastStatsReceiver -import com.twitter.finagle.stats.Counter -import com.twitter.finagle.stats.RollupStatsReceiver -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.ml.featurestore.lib.data.HydrationError -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featurestorev1.featurevalue.FeatureStoreV1ResponseFeature -import com.twitter.product_mixer.core.functional_component.feature_hydrator.FeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1CandidateFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.shared_library.observer.Observer -import com.twitter.servo.util.CancelledExceptionExtractor -import com.twitter.util.Throw -import com.twitter.util.Throwables - -class FeatureHydratorObserver( - statsReceiver: StatsReceiver, - hydrators: Seq[FeatureHydrator[_]], - context: Executor.Context) { - - private val hydratorAndFeatureToStats: Map[ - ComponentIdentifier, - Map[Feature[_, _], FeatureCounters] - ] = - hydrators.map { hydrator => - val hydratorScope = Executor.buildScopes(context, hydrator.identifier) - val featureToCounterMap: Map[Feature[_, _], FeatureCounters] = hydrator.features - .asInstanceOf[Set[Feature[_, _]]].map { feature => - val scopedStats = scopedBroadcastStats(hydratorScope, feature) - // Initialize so we have them registered - val requestsCounter = scopedStats.counter(Observer.Requests) - val successCounter = scopedStats.counter(Observer.Success) - // These are dynamic so we can't really cache them - scopedStats.counter(Observer.Failures) - scopedStats.counter(Observer.Cancelled) - feature -> FeatureCounters(requestsCounter, successCounter, scopedStats) - }.toMap - hydrator.identifier -> featureToCounterMap - }.toMap - - def observeFeatureSuccessAndFailures( - hydrator: FeatureHydrator[_], - featureMaps: Seq[FeatureMap] - ): Unit = { - - val features = hydrator.features.asInstanceOf[Set[Feature[_, _]]] - - val failedFeaturesWithErrorNames: Map[Feature[_, _], Seq[Seq[String]]] = hydrator match { - case _: FeatureStoreV1QueryFeatureHydrator[_] | - _: FeatureStoreV1CandidateFeatureHydrator[_, _] => - featureMaps.toIterator - .flatMap(_.getTry(FeatureStoreV1ResponseFeature).toOption.map(_.failedFeatures)).flatMap { - failureMap: Map[_ <: Feature[_, _], Set[HydrationError]] => - failureMap.flatMap { - case (feature, errors: Set[HydrationError]) => - errors.headOption.map { error => - feature -> Seq(Observer.Failures, error.errorType) - } - }.toIterator - }.toSeq.groupBy { case (feature, _) => feature }.mapValues { seqOfTuples => - seqOfTuples.map { case (_, error) => error } - } - - case _: FeatureHydrator[_] => - features.toIterator - .flatMap { feature => - featureMaps - .flatMap(_.underlyingMap - .get(feature).collect { - case Throw(CancelledExceptionExtractor(throwable)) => - (feature, Observer.Cancelled +: Throwables.mkString(throwable)) - case Throw(throwable) => - (feature, Observer.Failures +: Throwables.mkString(throwable)) - }) - }.toSeq.groupBy { case (feature, _) => feature }.mapValues { seqOfTuples => - seqOfTuples.map { case (_, error) => error } - } - } - - val failedFeaturesWithErrorCountsMap: Map[Feature[_, _], Map[Seq[String], Int]] = - failedFeaturesWithErrorNames.mapValues(_.groupBy { statKey => statKey }.mapValues(_.size)) - - val featuresToCounterMap = hydratorAndFeatureToStats.getOrElse( - hydrator.identifier, - throw new MissingHydratorException(hydrator.identifier)) - features.foreach { feature => - val hydratorFeatureCounters: FeatureCounters = featuresToCounterMap.getOrElse( - feature, - throw new MissingFeatureException(hydrator.identifier, feature)) - val failedMapsCount = failedFeaturesWithErrorNames.getOrElse(feature, Seq.empty).size - val failedFeatureErrorCounts = failedFeaturesWithErrorCountsMap.getOrElse(feature, Map.empty) - - hydratorFeatureCounters.requestsCounter.incr(featureMaps.size) - hydratorFeatureCounters.successCounter.incr(featureMaps.size - failedMapsCount) - failedFeatureErrorCounts.foreach { - case (failure, count) => - hydratorFeatureCounters.scopedStats.counter(failure: _*).incr(count) - } - } - } - - private def scopedBroadcastStats( - hydratorScope: Executor.Scopes, - feature: Feature[_, _], - ): StatsReceiver = { - val suffix = Seq("Feature", feature.toString) - val localScope = hydratorScope.componentScopes ++ suffix - val relativeScope = hydratorScope.relativeScope ++ suffix - new RollupStatsReceiver( - BroadcastStatsReceiver( - Seq( - statsReceiver.scope(localScope: _*), - statsReceiver.scope(relativeScope: _*), - ) - )) - } -} - -case class FeatureCounters( - requestsCounter: Counter, - successCounter: Counter, - scopedStats: StatsReceiver) - -class MissingHydratorException(featureHydratorIdentifier: ComponentIdentifier) - extends Exception(s"Missing Feature Hydrator in Stats Map: ${featureHydratorIdentifier.name}") - -class MissingFeatureException( - featureHydratorIdentifier: ComponentIdentifier, - feature: Feature[_, _]) - extends Exception( - s"Missing Feature in Stats Map: ${feature.toString} for ${featureHydratorIdentifier.name}") diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD deleted file mode 100644 index 313fde03c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/filter", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala deleted file mode 100644 index 2d463e90b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutor.scala +++ /dev/null @@ -1,172 +0,0 @@ -package com.twitter.product_mixer.core.service.filter_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.filter.Filter -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.filter_executor.FilterExecutor.FilterState -import com.twitter.stitch.Arrow -import com.twitter.stitch.Arrow.Iso -import javax.inject.Inject -import javax.inject.Singleton -import scala.collection.immutable.Queue - -/** - * Applies a `Seq[Filter]` in sequential order. - * Returns the results and a detailed Seq of each filter's results (for debugging / coherence). - * - * Note that each successive filter is only passed the 'kept' Seq from the previous filter, not the full - * set of candidates. - */ -@Singleton -class FilterExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor { - - private val Kept = "kept" - private val Removed = "removed" - - def arrow[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - filters: Seq[Filter[Query, Candidate]], - context: Executor.Context - ): Arrow[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterExecutorResult[Candidate]] = { - - val filterArrows = filters.map(getIsoArrowForFilter(_, context)) - val combinedArrow = isoArrowsSequentially(filterArrows) - - Arrow - .map[(Query, Seq[CandidateWithFeatures[Candidate]]), FilterState[Query, Candidate]] { - case (query, filterCandidates) => - // transform the input to the initial state of a `FilterExecutorResult` - val initialFilterExecutorResult = - FilterExecutorResult(filterCandidates.map(_.candidate), Queue.empty) - val allCandidates: Map[Candidate, CandidateWithFeatures[Candidate]] = - filterCandidates.map { fc => - (fc.candidate, fc) - }.toMap - - FilterState(query, allCandidates, initialFilterExecutorResult) - } - .flatMapArrow(combinedArrow) - .map { - case FilterState(_, _, filterExecutorResult) => - filterExecutorResult.copy(individualFilterResults = - // materialize the Queue into a List for faster future iterations - filterExecutorResult.individualFilterResults.toList) - } - - } - - /** - * Adds filter specific stats, generic [[wrapComponentWithExecutorBookkeeping]] stats, and wraps with failure handling - * - * If the filter is a [[Conditionally]] ensures that we dont record stats if its turned off - * - * @note For performance, the [[FilterExecutorResult.individualFilterResults]] is build backwards - the head being the most recent result. - * @param filter the filter to make an [[Arrow]] out of - * @param context the [[Executor.Context]] for the pipeline this is a part of - */ - private def getIsoArrowForFilter[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - filter: Filter[Query, Candidate], - context: Executor.Context - ): Iso[FilterState[Query, Candidate]] = { - val broadcastStatsReceiver = - Executor.broadcastStatsReceiver(context, filter.identifier, statsReceiver) - - val keptCounter = broadcastStatsReceiver.counter(Kept) - val removedCounter = broadcastStatsReceiver.counter(Removed) - - val filterArrow = Arrow.flatMap[ - (Query, Seq[CandidateWithFeatures[Candidate]]), - FilterExecutorIndividualResult[Candidate] - ] { - case (query, candidates) => - filter.apply(query, candidates).map { result => - FilterExecutorIndividualResult( - identifier = filter.identifier, - kept = result.kept, - removed = result.removed) - } - } - - val observedArrow: Arrow[ - (Query, Seq[CandidateWithFeatures[Candidate]]), - FilterExecutorIndividualResult[ - Candidate - ] - ] = wrapComponentWithExecutorBookkeeping( - context = context, - currentComponentIdentifier = filter.identifier, - onSuccess = { result: FilterExecutorIndividualResult[Candidate] => - keptCounter.incr(result.kept.size) - removedCounter.incr(result.removed.size) - } - )( - filterArrow - ) - - val conditionallyRunArrow: Arrow[ - (Query, Seq[CandidateWithFeatures[Candidate]]), - IndividualFilterResults[ - Candidate - ] - ] = - filter match { - case filter: Filter[Query, Candidate] with Conditionally[ - Filter.Input[Query, Candidate] @unchecked - ] => - Arrow.ifelse( - { - case (query, candidates) => - filter.onlyIf(Filter.Input(query, candidates)) - }, - observedArrow, - Arrow.value(ConditionalFilterDisabled(filter.identifier)) - ) - case _ => observedArrow - } - - // return an `Iso` arrow for easier composition later - Arrow - .zipWithArg( - Arrow - .map[FilterState[Query, Candidate], (Query, Seq[CandidateWithFeatures[Candidate]])] { - case FilterState(query, candidateToFeaturesMap, FilterExecutorResult(result, _)) => - (query, result.flatMap(candidateToFeaturesMap.get)) - }.andThen(conditionallyRunArrow)) - .map { - case ( - FilterState(query, allCandidates, filterExecutorResult), - filterResult: FilterExecutorIndividualResult[Candidate]) => - val resultWithCurrentPrepended = - filterExecutorResult.individualFilterResults :+ filterResult - val newFilterExecutorResult = FilterExecutorResult( - result = filterResult.kept, - individualFilterResults = resultWithCurrentPrepended) - FilterState(query, allCandidates, newFilterExecutorResult) - - case (filterState, filterDisabledResult: ConditionalFilterDisabled) => - filterState.copy( - executorResult = filterState.executorResult.copy( - individualFilterResults = - filterState.executorResult.individualFilterResults :+ filterDisabledResult - )) - } - } -} - -object FilterExecutor { - - /** - * FilterState is an internal representation of the state that is passed between each individual filter arrow. - * - * @param query: The query - * @param candidateToFeaturesMap: A lookup mapping from Candidate -> FilterCandidate, to rebuild the inputs quickly for the next filter - * @param executorResult: The in-progress executor result - */ - private case class FilterState[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - query: Query, - candidateToFeaturesMap: Map[Candidate, CandidateWithFeatures[Candidate]], - executorResult: FilterExecutorResult[Candidate]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala deleted file mode 100644 index bc0336620..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/filter_executor/FilterExecutorResult.scala +++ /dev/null @@ -1,18 +0,0 @@ -package com.twitter.product_mixer.core.service.filter_executor - -import com.twitter.product_mixer.core.model.common.identifier.FilterIdentifier -import com.twitter.product_mixer.core.service.ExecutorResult - -case class FilterExecutorResult[Candidate]( - result: Seq[Candidate], - individualFilterResults: Seq[IndividualFilterResults[Candidate]]) - extends ExecutorResult - -sealed trait IndividualFilterResults[+Candidate] -case class ConditionalFilterDisabled(identifier: FilterIdentifier) - extends IndividualFilterResults[Nothing] -case class FilterExecutorIndividualResult[+Candidate]( - identifier: FilterIdentifier, - kept: Seq[Candidate], - removed: Seq[Candidate]) - extends IndividualFilterResults[Candidate] diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD deleted file mode 100644 index 8b4ea4292..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/gate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala deleted file mode 100644 index 32d4e4410..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/ExecutedGateResult.scala +++ /dev/null @@ -1,6 +0,0 @@ -package com.twitter.product_mixer.core.service.gate_executor - -import com.twitter.product_mixer.core.functional_component.gate.GateResult -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier - -case class ExecutedGateResult(identifier: GateIdentifier, result: GateResult) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala deleted file mode 100644 index c1de292e8..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutor.scala +++ /dev/null @@ -1,107 +0,0 @@ -package com.twitter.product_mixer.core.service.gate_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.gate.BaseGate -import com.twitter.product_mixer.core.functional_component.gate.GateResult -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow -import com.twitter.stitch.Arrow.Iso -import com.twitter.util.Return -import com.twitter.util.Throw - -import javax.inject.Inject -import javax.inject.Singleton -import scala.collection.immutable.Queue - -/** - * A GateExecutor takes a Seq[Gate], executes them all sequentially, and - * determines a final Continue or Stop decision. - */ -@Singleton -class GateExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor { - - private val Continue = "continue" - private val Skipped = "skipped" - private val Stop = "stop" - - def arrow[Query <: PipelineQuery]( - gates: Seq[BaseGate[Query]], - context: Executor.Context - ): Arrow[Query, GateExecutorResult] = { - - val gateArrows = gates.map(getIsoArrowForGate(_, context)) - val combinedArrow = isoArrowsSequentially(gateArrows) - - Arrow - .map { query: Query => (query, GateExecutorResult(Queue.empty)) } - .andThen(combinedArrow) - .map { - case (_, gateExecutorResult) => - // materialize the Queue into a List for faster future iterations - GateExecutorResult(gateExecutorResult.individualGateResults.toList) - } - } - - /** - * Each gate is transformed into a Iso Arrow over (Quest, List[GatewayResult]). - * - * This arrow: - * - Adapts the input and output types of the underlying Gate arrow (an [[Iso[(Query, QueryResult)]]) - * - throws a [[StoppedGateException]] if [[GateResult.continue]] is false - * - if its not false, prepends the current results to the [[GateExecutorResult.individualGateResults]] list - */ - private def getIsoArrowForGate[Query <: PipelineQuery]( - gate: BaseGate[Query], - context: Executor.Context - ): Iso[(Query, GateExecutorResult)] = { - val broadcastStatsReceiver = - Executor.broadcastStatsReceiver(context, gate.identifier, statsReceiver) - - val continueCounter = broadcastStatsReceiver.counter(Continue) - val skippedCounter = broadcastStatsReceiver.counter(Skipped) - val stopCounter = broadcastStatsReceiver.counter(Stop) - - val observedArrow = wrapComponentWithExecutorBookkeeping( - context, - gate.identifier, - onSuccess = { gateResult: GateResult => - gateResult match { - case GateResult.Continue => continueCounter.incr() - case GateResult.Skipped => skippedCounter.incr() - case GateResult.Stop => stopCounter.incr() - } - } - )(gate.arrow) - - val inputAdapted: Arrow[(Query, GateExecutorResult), GateResult] = - Arrow - .map[(Query, GateExecutorResult), Query] { case (query, _) => query } - .andThen(observedArrow) - - val zipped = Arrow.zipWithArg(inputAdapted) - - // at each step, the current `GateExecutorResult.continue` value is correct for all already run gates - val withStoppedGatesAsExceptions = zipped.map { - case ((query, previousResults), currentResult) if currentResult.continue => - Return( - ( - query, - GateExecutorResult( - previousResults.individualGateResults :+ ExecutedGateResult( - gate.identifier, - currentResult)) - )) - case _ => Throw(StoppedGateException(gate.identifier)) - }.lowerFromTry - - /** - * we gather stats before converting closed gates to exceptions because a closed gate - * isn't a failure for the gate, its a normal behavior - * but we do want to remap the the [[StoppedGateException]] created because the [[BaseGate]] is closed - * to the correct [[com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure]], - * so we remap with [[wrapWithErrorHandling]] - */ - wrapWithErrorHandling(context, gate.identifier)(withStoppedGatesAsExceptions) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala deleted file mode 100644 index 2a38cd59b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/GateExecutorResult.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.service.gate_executor - -import com.twitter.product_mixer.core.service.ExecutorResult - -case class GateExecutorResult( - individualGateResults: Seq[ExecutedGateResult]) - extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala deleted file mode 100644 index 7bd7bae29..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/gate_executor/StoppedGateException.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.service.gate_executor - -import com.twitter.product_mixer.core.model.common.identifier.GateIdentifier -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureCategory -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailureClassifier - -import scala.util.control.NoStackTrace - -case class StoppedGateException(identifier: GateIdentifier) - extends Exception("Closed gate stopped execution of the pipeline") - with NoStackTrace { - override def toString: String = s"StoppedGateException($identifier)" -} - -object StoppedGateException { - - /** - * Creates a [[PipelineFailureClassifier]] that is used as the default for classifying failures - * in a pipeline by mapping [[StoppedGateException]] to a [[PipelineFailure]] with the provided - * [[PipelineFailureCategory]] - */ - def classifier( - category: PipelineFailureCategory - ): PipelineFailureClassifier = PipelineFailureClassifier { - case stoppedGateException: StoppedGateException => - PipelineFailure(category, stoppedGateException.getMessage, Some(stoppedGateException)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD deleted file mode 100644 index c34688181..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-core/src/main/scala", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/candidate_source", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/candidate_feature_transformer_executor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala deleted file mode 100644 index beb665c64..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/group_results_executor/GroupResultsExecutor.scala +++ /dev/null @@ -1,122 +0,0 @@ -package com.twitter.product_mixer.core.service.group_results_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMapBuilder -import com.twitter.product_mixer.core.model.common.CandidateWithFeatures -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.CandidatePipelineIdentifier -import com.twitter.product_mixer.core.model.common.identifier.CandidateSourceIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PlatformIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidatePipelines -import com.twitter.product_mixer.core.model.common.presentation.CandidateSourcePosition -import com.twitter.product_mixer.core.model.common.presentation.CandidateSources -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ItemPresentation -import com.twitter.product_mixer.core.model.common.presentation.ModuleCandidateWithDetails -import com.twitter.product_mixer.core.model.common.presentation.ModulePresentation -import com.twitter.product_mixer.core.model.common.presentation.UniversalPresentation -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.stitch.Arrow -import javax.inject.Inject -import javax.inject.Singleton -import scala.collection.immutable.ListSet - -// Most executors are in the core.service package, but this one is pipeline specific -@Singleton -class GroupResultsExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor { - - val identifier: ComponentIdentifier = PlatformIdentifier("GroupResults") - - def arrow[Candidate <: UniversalNoun[Any]]( - pipelineIdentifier: CandidatePipelineIdentifier, - sourceIdentifier: CandidateSourceIdentifier, - context: Executor.Context - ): Arrow[GroupResultsExecutorInput[Candidate], GroupResultsExecutorResult] = { - - val groupArrow = Arrow.map { input: GroupResultsExecutorInput[Candidate] => - val modules: Map[Option[ModulePresentation], Seq[CandidateWithFeatures[Candidate]]] = - input.candidates - .map { candidate: CandidateWithFeatures[Candidate] => - val modulePresentationOpt: Option[ModulePresentation] = - input.decorations.get(candidate.candidate).collect { - case itemPresentation: ItemPresentation - if itemPresentation.modulePresentation.isDefined => - itemPresentation.modulePresentation.get - } - - (candidate, modulePresentationOpt) - }.groupBy { - case (_, modulePresentationOpt) => modulePresentationOpt - }.mapValues { - resultModuleOptTuples: Seq[ - (CandidateWithFeatures[Candidate], Option[ModulePresentation]) - ] => - resultModuleOptTuples.map { - case (result, _) => result - } - } - - // Modules should be in their original order, but the groupBy above isn't stable. - // Sort them by the sourcePosition, using the sourcePosition of their first contained - // candidate. - val sortedModules: Seq[(Option[ModulePresentation], Seq[CandidateWithFeatures[Candidate]])] = - modules.toSeq - .sortBy { - case (_, results) => - results.headOption.map(_.features.get(CandidateSourcePosition)) - } - - val candidatesWithDetails: Seq[CandidateWithDetails] = sortedModules.flatMap { - case (modulePresentationOpt, resultsSeq) => - val itemsWithDetails = resultsSeq.map { result => - val presentationOpt = input.decorations.get(result.candidate) match { - case itemPresentation @ Some(_: ItemPresentation) => itemPresentation - case _ => None - } - - val baseFeatureMap = FeatureMapBuilder() - .add(CandidatePipelines, ListSet.empty + pipelineIdentifier) - .build() - - ItemCandidateWithDetails( - candidate = result.candidate, - presentation = presentationOpt, - features = baseFeatureMap ++ result.features - ) - } - - modulePresentationOpt - .map { modulePresentation => - val moduleSourcePosition = - resultsSeq.head.features.get(CandidateSourcePosition) - val baseFeatureMap = FeatureMapBuilder() - .add(CandidatePipelines, ListSet.empty + pipelineIdentifier) - .add(CandidateSourcePosition, moduleSourcePosition) - .add(CandidateSources, ListSet.empty + sourceIdentifier) - .build() - - Seq( - ModuleCandidateWithDetails( - candidates = itemsWithDetails, - presentation = Some(modulePresentation), - features = baseFeatureMap - )) - }.getOrElse(itemsWithDetails) - } - - GroupResultsExecutorResult(candidatesWithDetails) - } - - wrapWithErrorHandling(context, identifier)(groupArrow) - } -} - -case class GroupResultsExecutorInput[Candidate <: UniversalNoun[Any]]( - candidates: Seq[CandidateWithFeatures[Candidate]], - decorations: Map[UniversalNoun[Any], UniversalPresentation]) - -case class GroupResultsExecutorResult(candidatesWithDetails: Seq[CandidateWithDetails]) - extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala deleted file mode 100644 index af5ed42b9..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/AllowListedPipelineExecutionLogger.scala +++ /dev/null @@ -1,183 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_execution_logger - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.inject.annotations.Flag -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.PipelineExecutionLoggerAllowList -import com.twitter.product_mixer.core.module.product_mixer_flags.ProductMixerFlagModule.ServiceLocal -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.util.FuturePools -import com.twitter.product_mixer.shared_library.observer.Observer.FutureObserver -import com.twitter.util.Try -import com.twitter.util.logging.Logging -import pprint.PPrinter -import pprint.Tree -import pprint.Util -import pprint.tuplePrefix -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Initial implementation from: - * https://stackoverflow.com/questions/15718506/scala-how-to-print-case-classes-like-pretty-printed-tree/57080463#57080463 - */ -object AllowListedPipelineExecutionLogger { - - /** - * Given a case class who's arguments are all declared fields on the class, - * returns an iterator of the field name and values - */ - private[pipeline_execution_logger] def caseClassFields( - caseClass: Product - ): Iterator[(String, Any)] = { - val fieldValues = caseClass.productIterator.toSet - val fields = caseClass.getClass.getDeclaredFields.toSeq - .filterNot(f => f.isSynthetic || java.lang.reflect.Modifier.isStatic(f.getModifiers)) - fields.iterator - .map { f => - f.setAccessible(true) - f.getName -> f.get(caseClass) - }.filter { case (_, v) => fieldValues.contains(v) } - } - - /** - * Returns whether a given [[Product]] is a case class which we can render nicely which: - * - has a [[Product.productArity]] <= the number of declared fields - * - isn't a built in binary operator - * - isn't a tuple - * - who's arguments are fields (not methods) - * - every [[Product.productElement]] has a corresponding field - * - * This will return false for some case classes where we can not reliably determine which field names correspond to - * each value in the case class (this can happen if a case class implements an abstract class resulting in val fields - * becoming methods. - */ - private[pipeline_execution_logger] def isRenderableCaseClass(caseClass: Product): Boolean = { - val possibleToBeRenderableCaseClass = - caseClass.getClass.getDeclaredFields.length >= caseClass.productArity - val isntBuiltInOperator = - !(caseClass.productArity == 2 && Util.isOperator(caseClass.productPrefix)) - val isntTuple = !caseClass.getClass.getName.startsWith(tuplePrefix) - val declaredFieldsMatchesCaseClassFields = { - val caseClassFields = caseClass.productIterator.toSet - caseClass.getClass.getDeclaredFields.iterator - .filterNot(f => f.isSynthetic || java.lang.reflect.Modifier.isStatic(f.getModifiers)) - .count { f => - f.setAccessible(true) - caseClassFields.contains(f.get(caseClass)) - } >= caseClass.productArity - } - - possibleToBeRenderableCaseClass && isntBuiltInOperator && isntTuple && declaredFieldsMatchesCaseClassFields - } - - /** Makes a [[Tree]] which will render as `key = value` */ - private def keyValuePair(key: String, value: Tree): Tree = { - Tree.Infix(Tree.Literal(key), "=", value) - } - - /** - * Special handling for case classes who's field names can be easily paired with their values. - * This will make the [[PPrinter]] render them as - * {{{ - * CaseClassName( - * field1 = value1, - * field2 = value2 - * ) - * }}} - * instead of - * {{{ - * CaseClassName( - * value1, - * value2 - * ) - * }}} - * - * For case classes who's fields end up being compiled as methods, this will fall back - * to the built in handling of case classes without their field names. - */ - private[pipeline_execution_logger] def additionalHandlers: PartialFunction[Any, Tree] = { - case caseClass: Product if isRenderableCaseClass(caseClass) => - Tree.Apply( - caseClass.productPrefix, - caseClassFields(caseClass).flatMap { - case (key, value) => - val valueTree = printer.treeify(value, false, true) - Seq(keyValuePair(key, valueTree)) - } - ) - } - - /** - * [[PPrinter]] instance to use when rendering scala objects - * uses BlackAndWhite because colors mangle the output when looking at the logs in plain text - */ - private val printer: PPrinter = PPrinter.BlackWhite.copy( - // arbitrary high value to turn off truncation - defaultHeight = Int.MaxValue, - // the relatively high width will cause some wrapping but many of the pretty printed objects - // will be sparse (e.g. None,\n None,\n, None,\n) - defaultWidth = 300, - // use reflection to print field names (can be deleted in Scala 2.13) - additionalHandlers = additionalHandlers - ) - - /** Given any scala object, return a String representation of it */ - private[pipeline_execution_logger] def objectAsString(o: Any): String = - printer.tokenize(o).mkString -} - -@Singleton -class AllowListedPipelineExecutionLogger @Inject() ( - @Flag(ServiceLocal) isServiceLocal: Boolean, - @Flag(PipelineExecutionLoggerAllowList) allowList: Seq[String], - statsReceiver: StatsReceiver) - extends PipelineExecutionLogger - with Logging { - - private val scopedStats = statsReceiver.scope("AllowListedPipelineExecutionLogger") - - val allowListRoles: Set[String] = allowList.toSet - - private val futurePool = - FuturePools.boundedFixedThreadPool( - "AllowListedPipelineExecutionLogger", - // single thread, may need to be adjusted higher if it cant keep up with the work queue - fixedThreadCount = 1, - // arbitrarily large enough to handle spikes without causing large allocations or retaining past multiple GC cycles - workQueueSize = 100, - scopedStats - ) - - private val futureObserver = new FutureObserver[Unit](scopedStats, Seq.empty) - - private val loggerOutputPath = Try(System.getProperty("log.allow_listed_execution_logger.output")) - - override def apply(pipelineQuery: PipelineQuery, message: Any): Unit = { - - val userRoles: Set[String] = pipelineQuery.clientContext.userRoles.getOrElse(Set.empty) - - // Check if this request is in the allowlist via a cleverly optimized set intersection - val allowListed = - if (allowListRoles.size > userRoles.size) - userRoles.exists(allowListRoles.contains) - else - allowListRoles.exists(userRoles.contains) - - if (isServiceLocal || allowListed) { - futureObserver( - /** - * failure to enqueue the work will result with a failed [[com.twitter.util.Future]] - * containing a [[java.util.concurrent.RejectedExecutionException]] which the wrapping [[futureObserver]] - * will record metrics for. - */ - futurePool { - logger.info(AllowListedPipelineExecutionLogger.objectAsString(message)) - - if (isServiceLocal && loggerOutputPath.isReturn) { - println(s"Logged request to: ${loggerOutputPath.get()}") - } - } - ) - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD deleted file mode 100644 index dffbcc694..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/google/inject:guice", - "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject", - "3rdparty/jvm/com/lihaoyi:pprint", - "3rdparty/jvm/net/codingwell:scala-guice", - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-core/src/main/scala/com/twitter/inject", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - ], - exports = [ - "3rdparty/jvm/com/google/inject:guice", - "3rdparty/jvm/com/google/inject/extensions:guice-assistedinject", - "3rdparty/jvm/com/lihaoyi:pprint", - "3rdparty/jvm/net/codingwell:scala-guice", - "finatra/inject/inject-app/src/main/java/com/twitter/inject/annotations", - "finatra/inject/inject-core/src/main/scala", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/module/product_mixer_flags", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala deleted file mode 100644 index e6c7535c7..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_execution_logger/PipelineExecutionLogger.scala +++ /dev/null @@ -1,7 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_execution_logger - -import com.twitter.product_mixer.core.pipeline.PipelineQuery - -trait PipelineExecutionLogger { - def apply(pipelineQuery: PipelineQuery, message: Any): Unit -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD deleted file mode 100644 index fbc1b6b8c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala deleted file mode 100644 index 511973cb1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutor.scala +++ /dev/null @@ -1,66 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.pipeline_failure.InvalidPipelineSelected -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow -import com.twitter.util.logging.Logging - -import javax.inject.Inject -import javax.inject.Singleton - -/** - * PipelineExecutor executes a single pipeline (of any type) - * It does not currently support fail open/closed policies like CandidatePipelineExecutor does - * In the future, maybe they can be merged. - */ - -case class PipelineExecutorRequest[Query](query: Query, pipelineIdentifier: ComponentIdentifier) - -@Singleton -class PipelineExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor - with Logging { - - def arrow[Query, ResultType]( - pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, ResultType]], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - context: Executor.Context - ): Arrow[PipelineExecutorRequest[Query], PipelineExecutorResult[ResultType]] = { - - val wrappedPipelineArrowsByIdentifier = pipelineByIdentifier.mapValues { pipeline => - wrapPipelineWithExecutorBookkeeping( - context, - pipeline.identifier, - qualityFactorObserverByPipeline.get(pipeline.identifier))(pipeline.arrow) - } - - val appliedPipelineArrow = Arrow - .identity[PipelineExecutorRequest[Query]] - .map { - case PipelineExecutorRequest(query, pipelineIdentifier) => - val pipeline = wrappedPipelineArrowsByIdentifier.getOrElse( - pipelineIdentifier, - // throwing instead of returning a `Throw(_)` and then `.lowerFromTry` because this is an exceptional case and we want to emphasize that by explicitly throwing - // this case should never happen since this is checked in the `PipelineSelectorExecutor` but we check it anyway - throw PipelineFailure( - InvalidPipelineSelected, - s"${context.componentStack.peek} attempted to execute $pipelineIdentifier", - // the `componentStack` includes the missing pipeline so it can show up in metrics easier - componentStack = Some(context.componentStack.push(pipelineIdentifier)) - ) - ) - (pipeline, query) - } - // less efficient than an `andThen` but since we dispatch this dynamically we need to use either `applyArrow` or `flatMap` and this is the better of those options - .applyArrow - .map(PipelineExecutorResult(_)) - - // no additional error handling needed since we populate the component stack above already - appliedPipelineArrow - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala deleted file mode 100644 index 9953b4666..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_executor/PipelineExecutorResult.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_executor - -import com.twitter.product_mixer.core.pipeline.PipelineResult -import com.twitter.product_mixer.core.service.ExecutorResult - -case class PipelineExecutorResult[ResultType]( - pipelineResult: PipelineResult[ResultType]) - extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD deleted file mode 100644 index 1aecf5960..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/side_effect", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala deleted file mode 100644 index 2506db301..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_result_side_effect_executor/PipelineResultSideEffectExecutor.scala +++ /dev/null @@ -1,91 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.side_effect.ExecuteSynchronously -import com.twitter.product_mixer.core.functional_component.side_effect.FailOpen -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect -import com.twitter.product_mixer.core.functional_component.side_effect.PipelineResultSideEffect.Inputs -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.identifier.SideEffectIdentifier -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.product_mixer.core.service.pipeline_result_side_effect_executor.PipelineResultSideEffectExecutor._ -import com.twitter.stitch.Arrow -import com.twitter.util.Return -import com.twitter.util.Try -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PipelineResultSideEffectExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - def arrow[Query <: PipelineQuery, MixerDomainResultType <: HasMarshalling]( - sideEffects: Seq[PipelineResultSideEffect[Query, MixerDomainResultType]], - context: Executor.Context - ): Arrow[Inputs[Query, MixerDomainResultType], PipelineResultSideEffectExecutor.Result] = { - - val individualArrows: Seq[ - Arrow[Inputs[Query, MixerDomainResultType], (SideEffectIdentifier, SideEffectResultType)] - ] = sideEffects.map { - case synchronousSideEffect: ExecuteSynchronously => - val failsRequestIfThrows = { - wrapComponentWithExecutorBookkeeping(context, synchronousSideEffect.identifier)( - Arrow.flatMap(synchronousSideEffect.apply)) - } - synchronousSideEffect match { - case failOpen: FailOpen => - // lift the failure - failsRequestIfThrows.liftToTry.map(t => - (failOpen.identifier, SynchronousSideEffectResult(t))) - case _ => - // don't encapsulate the failure - failsRequestIfThrows.map(_ => - (synchronousSideEffect.identifier, SynchronousSideEffectResult(Return.Unit))) - } - - case sideEffect => - Arrow - .async( - wrapComponentWithExecutorBookkeeping(context, sideEffect.identifier)( - Arrow.flatMap(sideEffect.apply))) - .andThen(Arrow.value((sideEffect.identifier, SideEffectResult))) - } - - val conditionallyRunArrows = sideEffects.zip(individualArrows).map { - case ( - sideEffect: Conditionally[ - PipelineResultSideEffect.Inputs[Query, MixerDomainResultType] @unchecked - ], - arrow) => - Arrow.ifelse[ - Inputs[Query, MixerDomainResultType], - (SideEffectIdentifier, SideEffectResultType)]( - input => sideEffect.onlyIf(input), - arrow, - Arrow.value((sideEffect.identifier, TurnedOffByConditionally))) - case (_, arrow) => arrow - } - - Arrow - .collect(conditionallyRunArrows) - .map(results => Result(results)) - } -} - -object PipelineResultSideEffectExecutor { - case class Result(sideEffects: Seq[(SideEffectIdentifier, SideEffectResultType)]) - extends ExecutorResult - - sealed trait SideEffectResultType - - /** The [[PipelineResultSideEffect]] was executed asynchronously in a fire-and-forget way so no result will be available */ - case object SideEffectResult extends SideEffectResultType - - /** The result of the [[PipelineResultSideEffect]] that was executed with [[ExecuteSynchronously]] */ - case class SynchronousSideEffectResult(result: Try[Unit]) extends SideEffectResultType - - /** The result for when a [[PipelineResultSideEffect]] is turned off by [[Conditionally]]'s [[Conditionally.onlyIf]] */ - case object TurnedOffByConditionally extends SideEffectResultType -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD deleted file mode 100644 index 7c5725005..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "finatra/inject/inject-slf4j/src/main/scala/com/twitter/inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala deleted file mode 100644 index bf211b63d..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutor.scala +++ /dev/null @@ -1,48 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_selector_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.util.logging.Logging -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PlatformIdentifier -import com.twitter.product_mixer.core.pipeline.Pipeline -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.InvalidPipelineSelected -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class PipelineSelectorExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor - with Logging { - - val identifier: ComponentIdentifier = PlatformIdentifier("PipelineSelector") - - def arrow[Query <: PipelineQuery, Response]( - pipelineByIdentifier: Map[ComponentIdentifier, Pipeline[Query, Response]], - pipelineSelector: Query => ComponentIdentifier, - context: Executor.Context - ): Arrow[Query, PipelineSelectorExecutorResult] = { - - val validateSelectedPipelineExists = Arrow - .map(pipelineSelector) - .map { chosenIdentifier => - if (pipelineByIdentifier.contains(chosenIdentifier)) { - PipelineSelectorExecutorResult(chosenIdentifier) - } else { - // throwing instead of returning a `Throw(_)` and then `.lowerFromTry` because this is an exceptional case and we want to emphasize that by explicitly throwing - throw PipelineFailure( - InvalidPipelineSelected, - s"${context.componentStack.peek} attempted to select $chosenIdentifier", - // the `componentStack` includes the missing pipeline so it can show up in metrics easier - componentStack = Some(context.componentStack.push(chosenIdentifier)) - ) - } - } - - wrapWithErrorHandling(context, identifier)(validateSelectedPipelineExists) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala deleted file mode 100644 index 3ffc8297f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/pipeline_selector_executor/PipelineSelectorExecutorResult.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.core.service.pipeline_selector_executor - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier - -case class PipelineSelectorExecutorResult(pipelineIdentifier: ComponentIdentifier) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD deleted file mode 100644 index ae1c9b4fd..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/quality_factor", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala deleted file mode 100644 index 43acb992f..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/quality_factor_executor/QualityFactorExecutorResult.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.twitter.product_mixer.core.service.quality_factor_executor - -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier - -case class QualityFactorExecutorResult( - pipelineQualityFactors: Map[ComponentIdentifier, Double]) - -object QualityFactorExecutorResult { - val empty: QualityFactorExecutorResult = QualityFactorExecutorResult(Map.empty) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala deleted file mode 100644 index b7a3e5819..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/AsyncIndividualFeatureHydratorResultSerializer.scala +++ /dev/null @@ -1,24 +0,0 @@ -package com.twitter.product_mixer.core.service.query_feature_hydrator_executor - -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.databind.JsonSerializer -import com.fasterxml.jackson.databind.SerializerProvider -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.AsyncIndividualFeatureHydratorResult - -/** A [[JsonSerializer]] that skips the `Stitch` values */ -private[query_feature_hydrator_executor] class AsyncIndividualFeatureHydratorResultSerializer() - extends JsonSerializer[AsyncIndividualFeatureHydratorResult] { - - override def serialize( - asyncIndividualFeatureHydratorResult: AsyncIndividualFeatureHydratorResult, - gen: JsonGenerator, - serializers: SerializerProvider - ): Unit = - serializers.defaultSerializeValue( - // implicitly calls `toString` on the identifier because they are keys in the Map - Map( - asyncIndividualFeatureHydratorResult.hydrateBefore -> - asyncIndividualFeatureHydratorResult.features.map(_.toString)), - gen - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD deleted file mode 100644 index ffceb6261..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/BUILD +++ /dev/null @@ -1,28 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/feature_hydrator_observer", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/feature/featuremap/asyncfeaturemap", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/feature_hydrator/featurestorev1", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala deleted file mode 100644 index 8d6e3c4c6..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/query_feature_hydrator_executor/QueryFeatureHydratorExecutor.scala +++ /dev/null @@ -1,217 +0,0 @@ -package com.twitter.product_mixer.core.service.query_feature_hydrator_executor - -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.Feature -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.feature.featuremap.asyncfeaturemap.AsyncFeatureMap -import com.twitter.product_mixer.core.functional_component.feature_hydrator.AsyncHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.BaseQueryFeatureHydrator -import com.twitter.product_mixer.core.functional_component.feature_hydrator.featurestorev1.FeatureStoreV1QueryFeatureHydrator -import com.twitter.product_mixer.core.model.common.Conditionally -import com.twitter.product_mixer.core.model.common.identifier.FeatureHydratorIdentifier -import com.twitter.product_mixer.core.model.common.identifier.PipelineStepIdentifier -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.Executor._ -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.product_mixer.core.service.feature_hydrator_observer.FeatureHydratorObserver -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.AsyncIndividualFeatureHydratorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.BaseIndividualFeatureHydratorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.FeatureHydratorDisabled -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.IndividualFeatureHydratorResult -import com.twitter.product_mixer.core.service.query_feature_hydrator_executor.QueryFeatureHydratorExecutor.validateAsyncQueryFeatureHydrator -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class QueryFeatureHydratorExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - - def arrow[Query <: PipelineQuery]( - hydrators: Seq[BaseQueryFeatureHydrator[Query, _]], - validPipelineSteps: Set[PipelineStepIdentifier], - context: Executor.Context - ): Arrow[Query, QueryFeatureHydratorExecutor.Result] = { - - val observer = new FeatureHydratorObserver(statsReceiver, hydrators, context) - val hydratorsWithErrorHandling = - hydrators.map { hydrator => - val queryFeatureHydratorArrow = - getQueryHydratorArrow(hydrator, context, observer) - val wrappedWithAsyncHandling = - handleAsyncHydrator(hydrator, validPipelineSteps, queryFeatureHydratorArrow) - handleConditionally(hydrator, wrappedWithAsyncHandling) - } - - Arrow - .collect(hydratorsWithErrorHandling) - .map { - results: Seq[ - (FeatureHydratorIdentifier, BaseIndividualFeatureHydratorResult) - ] => - val combinedFeatureMap = FeatureMap.merge(results.collect { - case (_, IndividualFeatureHydratorResult(featureMap)) => featureMap - }) - - val asyncFeatureMaps = results.collect { - case ( - hydratorIdentifier, - AsyncIndividualFeatureHydratorResult(hydrateBefore, featuresToHydrate, ref)) => - (hydratorIdentifier, hydrateBefore, featuresToHydrate, ref) - } - - QueryFeatureHydratorExecutor.Result( - individualFeatureMaps = results.toMap, - featureMap = combinedFeatureMap, - asyncFeatureMap = AsyncFeatureMap.fromFeatureMaps(asyncFeatureMaps) - ) - } - } - - def handleConditionally[Query <: PipelineQuery]( - hydrator: BaseQueryFeatureHydrator[Query, _], - arrow: Arrow[ - Query, - BaseIndividualFeatureHydratorResult - ] - ): Arrow[ - Query, - (FeatureHydratorIdentifier, BaseIndividualFeatureHydratorResult) - ] = { - val conditionallyRunArrow = hydrator match { - case hydrator: BaseQueryFeatureHydrator[Query, _] with Conditionally[Query @unchecked] => - Arrow.ifelse[Query, BaseIndividualFeatureHydratorResult]( - hydrator.onlyIf, - arrow, - Arrow.value(FeatureHydratorDisabled) - ) - case _ => arrow - } - - Arrow.join( - Arrow.value(hydrator.identifier), - conditionallyRunArrow - ) - } - - def handleAsyncHydrator[Query <: PipelineQuery]( - hydrator: BaseQueryFeatureHydrator[Query, _], - validPipelineSteps: Set[PipelineStepIdentifier], - arrow: Arrow[ - Query, - IndividualFeatureHydratorResult - ] - ): Arrow[Query, BaseIndividualFeatureHydratorResult] = { - hydrator match { - case hydrator: BaseQueryFeatureHydrator[ - Query, - _ - ] with AsyncHydrator => - validateAsyncQueryFeatureHydrator(hydrator, validPipelineSteps) - - startArrowAsync(arrow.map(_.featureMap)) - .map { ref => - AsyncIndividualFeatureHydratorResult( - hydrator.hydrateBefore, - hydrator.features.asInstanceOf[Set[Feature[_, _]]], - ref - ) - } - - case _ => arrow - } - } - - def getQueryHydratorArrow[Query <: PipelineQuery]( - hydrator: BaseQueryFeatureHydrator[Query, _], - context: Executor.Context, - queryFeatureHydratorObserver: FeatureHydratorObserver - ): Arrow[Query, IndividualFeatureHydratorResult] = { - - val componentExecutorContext = context.pushToComponentStack(hydrator.identifier) - val hydratorArrow: Arrow[Query, FeatureMap] = - Arrow.flatMap { query: Query => hydrator.hydrate(query) } - - val validationFn: FeatureMap => FeatureMap = hydrator match { - // Feature store query hydrators store the resulting PredictionRecord and not - // the features, so we cannot validate the same way - case _: FeatureStoreV1QueryFeatureHydrator[Query] => - identity - case _ => - validateFeatureMap( - hydrator.features.asInstanceOf[Set[Feature[_, _]]], - _, - componentExecutorContext) - } - - // record the component-level stats - val observedArrow = - wrapComponentWithExecutorBookkeeping[Query, FeatureMap]( - context, - hydrator.identifier - )(hydratorArrow.map(validationFn)) - - // store non-configuration errors in the FeatureMap - val liftNonValidationFailuresToFailedFeatures = Arrow.handle[FeatureMap, FeatureMap] { - case NotAMisconfiguredFeatureMapFailure(e) => - featureMapWithFailuresForFeatures( - hydrator.features.asInstanceOf[Set[Feature[_, _]]], - e, - componentExecutorContext) - } - - val observedLiftedAndWrapped = observedArrow - .andThen(liftNonValidationFailuresToFailedFeatures) - .applyEffect(Arrow.map[FeatureMap, Unit](featureMap => - // record per-feature stats, this is separate from the component stats handled by `wrapWithExecutorBookkeeping` - queryFeatureHydratorObserver.observeFeatureSuccessAndFailures(hydrator, Seq(featureMap)))) - .map(IndividualFeatureHydratorResult) - - observedLiftedAndWrapped - } -} - -object QueryFeatureHydratorExecutor { - case class Result( - individualFeatureMaps: Map[ - FeatureHydratorIdentifier, - BaseIndividualFeatureHydratorResult - ], - featureMap: FeatureMap, - asyncFeatureMap: AsyncFeatureMap) - extends ExecutorResult - - sealed trait BaseIndividualFeatureHydratorResult - - case object FeatureHydratorDisabled extends BaseIndividualFeatureHydratorResult - case class IndividualFeatureHydratorResult(featureMap: FeatureMap) - extends BaseIndividualFeatureHydratorResult - - /** Async result, serializes without the [[Stitch]] field since it's not serializable */ - @JsonSerialize(using = classOf[AsyncIndividualFeatureHydratorResultSerializer]) - case class AsyncIndividualFeatureHydratorResult( - hydrateBefore: PipelineStepIdentifier, - features: Set[Feature[_, _]], - ref: Stitch[FeatureMap]) - extends BaseIndividualFeatureHydratorResult - - /** - * Validates whether the [[AsyncHydrator.hydrateBefore]] [[PipelineStepIdentifier]] is valid - * - * @param asyncQueryFeatureHydrator the hydrator to validate - * @param validPipelineSteps a Set of [[PipelineStepIdentifier]]s which are valid places to populate async - * [[Feature]]s in a [[com.twitter.product_mixer.core.pipeline.Pipeline]] - */ - def validateAsyncQueryFeatureHydrator( - asyncQueryFeatureHydrator: AsyncHydrator, - validPipelineSteps: Set[PipelineStepIdentifier] - ): Unit = - require( - validPipelineSteps.contains(asyncQueryFeatureHydrator.hydrateBefore), - s"`AsyncHydrator.hydrateBefore` contained ${asyncQueryFeatureHydrator.hydrateBefore} which was not in the parent pipeline's " + - s"`PipelineConfig` Companion object field `stepsAsyncFeatureHydrationCanBeCompletedBy = $validPipelineSteps`." - ) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD deleted file mode 100644 index 2b03f2775..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/scoring", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala deleted file mode 100644 index 47b3a762a..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutor.scala +++ /dev/null @@ -1,172 +0,0 @@ -package com.twitter.product_mixer.core.service.scoring_pipeline_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.feature.featuremap.FeatureMap -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.identifier.ComponentIdentifier -import com.twitter.product_mixer.core.model.common.identifier.ScoringPipelineIdentifier -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.FailOpenPolicy -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipeline -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineResult -import com.twitter.product_mixer.core.quality_factor.QualityFactorObserver -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.scoring_pipeline_executor.ScoringPipelineExecutor.ScoringPipelineState -import com.twitter.stitch.Arrow -import com.twitter.stitch.Arrow.Iso -import com.twitter.util.logging.Logging - -import javax.inject.Inject -import javax.inject.Singleton -import scala.collection.immutable.Queue - -@Singleton -class ScoringPipelineExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor - with Logging { - def arrow[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - pipelines: Seq[ScoringPipeline[Query, Candidate]], - context: Executor.Context, - defaultFailOpenPolicy: FailOpenPolicy, - failOpenPolicies: Map[ScoringPipelineIdentifier, FailOpenPolicy], - qualityFactorObserverByPipeline: Map[ComponentIdentifier, QualityFactorObserver], - ): Arrow[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineExecutorResult[Candidate]] = { - val scoringPipelineArrows = pipelines.map { pipeline => - val failOpenPolicy = failOpenPolicies.getOrElse(pipeline.identifier, defaultFailOpenPolicy) - val qualityFactorObserver = qualityFactorObserverByPipeline.get(pipeline.identifier) - - getIsoArrowForScoringPipeline( - pipeline, - context, - failOpenPolicy, - qualityFactorObserver - ) - } - val combinedArrow = isoArrowsSequentially(scoringPipelineArrows) - Arrow - .map[ScoringPipelineExecutor.Inputs[Query], ScoringPipelineState[Query, Candidate]] { - case input => - ScoringPipelineState( - input.query, - input.itemCandidatesWithDetails, - ScoringPipelineExecutorResult(input.itemCandidatesWithDetails, Queue.empty)) - }.flatMapArrow(combinedArrow).map { state => - state.executorResult.copy(individualPipelineResults = - // materialize the Queue into a List for faster future iterations - state.executorResult.individualPipelineResults.toList) - } - } - - private def getIsoArrowForScoringPipeline[ - Query <: PipelineQuery, - Candidate <: UniversalNoun[Any] - ]( - pipeline: ScoringPipeline[Query, Candidate], - context: Executor.Context, - failOpenPolicy: FailOpenPolicy, - qualityFactorObserver: Option[QualityFactorObserver] - ): Iso[ScoringPipelineState[Query, Candidate]] = { - val pipelineArrow = Arrow - .map[ScoringPipelineState[Query, Candidate], ScoringPipeline.Inputs[Query]] { state => - ScoringPipeline.Inputs(state.query, state.allCandidates) - }.flatMapArrow(pipeline.arrow) - - val observedArrow = wrapPipelineWithExecutorBookkeeping( - context, - pipeline.identifier, - qualityFactorObserver, - failOpenPolicy)(pipelineArrow) - - Arrow - .zipWithArg( - observedArrow - ).map { - case ( - scoringPipelinesState: ScoringPipelineState[Query, Candidate], - scoringPipelineResult: ScoringPipelineResult[Candidate]) => - val updatedCandidates: Seq[ItemCandidateWithDetails] = - mkUpdatedCandidates(pipeline.identifier, scoringPipelinesState, scoringPipelineResult) - ScoringPipelineState( - scoringPipelinesState.query, - updatedCandidates, - scoringPipelinesState.executorResult - .copy( - updatedCandidates, - scoringPipelinesState.executorResult.individualPipelineResults :+ scoringPipelineResult) - ) - } - } - - private def mkUpdatedCandidates[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - scoringPipelineIdentifier: ScoringPipelineIdentifier, - scoringPipelinesState: ScoringPipelineState[Query, Candidate], - scoringPipelineResult: ScoringPipelineResult[Candidate] - ): Seq[ItemCandidateWithDetails] = { - if (scoringPipelineResult.failure.isEmpty) { - - /** - * It's important that we map back from which actual item candidate was scored by looking - * at the selector results. This is to defend against the same candidate being selected - * from two different candidate pipelines. If one is selected and the other isn't, we - * should only score the selected one. If both are selected and each is scored differently - * we should get the right score for each. - */ - val selectedItemCandidates: Seq[ItemCandidateWithDetails] = - scoringPipelineResult.selectorResults - .getOrElse(throw PipelineFailure( - IllegalStateFailure, - s"Missing Selector Results in Scoring Pipeline $scoringPipelineIdentifier")).selectedCandidates.collect { - case itemCandidateWithDetails: ItemCandidateWithDetails => - itemCandidateWithDetails - } - val scoredFeatureMaps: Seq[FeatureMap] = scoringPipelineResult.result - .getOrElse(Seq.empty).map(_.features) - - if (scoredFeatureMaps.isEmpty) { - // It's possible that all Scorers are [[Conditionally]] off. In this case, we return empty - // and don't validate the list size since this is done in the hydrator/scorer executor. - scoringPipelinesState.allCandidates - } else if (selectedItemCandidates.length != scoredFeatureMaps.length) { - // The length of the inputted candidates should always match the returned feature map, unless - throw PipelineFailure( - IllegalStateFailure, - s"Missing configured scorer result, length of scorer results does not match the length of selected candidates") - } else { - /* Zip the selected item candidate seq back to the scored feature maps, this works - * because the scored results will always have the same number of elements returned - * and it should match the same order. We then loop through all candidates because the - * expectation is to always keep the result since a subsequent scoring pipeline can score a - * candidate that the current one did not. We only update the feature map of the candidate - * if it was selected and scored. - */ - val selectedItemCandidateToScorerMap: Map[ItemCandidateWithDetails, FeatureMap] = - selectedItemCandidates.zip(scoredFeatureMaps).toMap - scoringPipelinesState.allCandidates.map { itemCandidateWithDetails => - selectedItemCandidateToScorerMap.get(itemCandidateWithDetails) match { - case Some(scorerResult) => - itemCandidateWithDetails.copy(features = - itemCandidateWithDetails.features ++ scorerResult) - case None => itemCandidateWithDetails - } - } - } - } else { - // If the underlying scoring pipeline has failed open, just keep the existing candidates - scoringPipelinesState.allCandidates - } - } -} - -object ScoringPipelineExecutor { - private case class ScoringPipelineState[Query <: PipelineQuery, Candidate <: UniversalNoun[Any]]( - query: Query, - allCandidates: Seq[ItemCandidateWithDetails], - executorResult: ScoringPipelineExecutorResult[Candidate]) - - case class Inputs[Query <: PipelineQuery]( - query: Query, - itemCandidatesWithDetails: Seq[ItemCandidateWithDetails]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala deleted file mode 100644 index a018be70c..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/scoring_pipeline_executor/ScoringPipelineExecutorResult.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.twitter.product_mixer.core.service.scoring_pipeline_executor - -import com.twitter.product_mixer.core.model.common.UniversalNoun -import com.twitter.product_mixer.core.model.common.presentation.ItemCandidateWithDetails -import com.twitter.product_mixer.core.pipeline.scoring.ScoringPipelineResult - -case class ScoringPipelineExecutorResult[Candidate <: UniversalNoun[Any]]( - result: Seq[ItemCandidateWithDetails], - individualPipelineResults: Seq[ScoringPipelineResult[Candidate]]) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD deleted file mode 100644 index 34a1ddc21..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - "util/util-core:scala", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/selector", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/candidate", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala deleted file mode 100644 index ba9b946a0..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutor.scala +++ /dev/null @@ -1,105 +0,0 @@ -package com.twitter.product_mixer.core.service.selector_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.selector.Selector -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.identifier.SelectorIdentifier -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.pipeline.PipelineQuery -import com.twitter.product_mixer.core.pipeline.pipeline_failure.IllegalStateFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow - -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Applies a `Seq[Selector]` in sequential order. - * Returns the results, and also a detailed list each selector's results (for debugging / understandability). - */ -@Singleton -class SelectorExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor { - def arrow[Query <: PipelineQuery]( - selectors: Seq[Selector[Query]], - context: Executor.Context - ): Arrow[SelectorExecutor.Inputs[Query], SelectorExecutorResult] = { - - if (selectors.isEmpty) { - throw PipelineFailure( - IllegalStateFailure, - "Must provide a non-empty Seq of Selectors. Check the config indicated by the componentStack and ensure that a non-empty Selector Seq is provided.", - componentStack = Some(context.componentStack) - ) - } - - val selectorArrows = - selectors.zipWithIndex.foldLeft(Arrow.identity[(Query, IndexedSeq[SelectorResult])]) { - case (previousSelectorArrows, (selector, index)) => - val selectorResult = getIndividualSelectorIsoArrow(selector, index, context) - previousSelectorArrows.andThen(selectorResult) - } - - Arrow - .zipWithArg( - Arrow - .map[SelectorExecutor.Inputs[Query], (Query, IndexedSeq[SelectorResult])] { - case SelectorExecutor.Inputs(query, candidates) => - (query, IndexedSeq(SelectorResult(candidates, Seq.empty))) - }.andThen(selectorArrows)).map { - case (inputs, (_, selectorResults)) => - // the last results, safe because it's always non-empty since it starts with 1 element in it - val SelectorResult(remainingCandidates, result) = selectorResults.last - - val resultsAndRemainingCandidates = - (result.iterator ++ remainingCandidates.iterator).toSet - - // the droppedCandidates are all the candidates which are in neither the result or remainingCandidates - val droppedCandidates = inputs.candidatesWithDetails.iterator - .filterNot(resultsAndRemainingCandidates.contains) - .toIndexedSeq - - SelectorExecutorResult( - selectedCandidates = result, - remainingCandidates = remainingCandidates, - droppedCandidates = droppedCandidates, - individualSelectorResults = - selectorResults.tail // `.tail` to remove the initial state we had - ) - } - } - - private def getIndividualSelectorIsoArrow[Query <: PipelineQuery]( - selector: Selector[Query], - index: Int, - context: Executor.Context - ): Arrow.Iso[(Query, IndexedSeq[SelectorResult])] = { - val identifier = SelectorIdentifier(selector.getClass.getSimpleName, index) - - val arrow = Arrow - .identity[(Query, IndexedSeq[SelectorResult])] - .map { - case (query, previousResults) => - // last is safe here because we pass in a non-empty IndexedSeq - val previousResult = previousResults.last - val currentResult = selector.apply( - query, - previousResult.remainingCandidates, - previousResult.result - ) - (query, previousResults :+ currentResult) - } - - wrapComponentsWithTracingOnly(context, identifier)( - wrapWithErrorHandling(context, identifier)( - arrow - ) - ) - } -} - -object SelectorExecutor { - case class Inputs[Query <: PipelineQuery]( - query: Query, - candidatesWithDetails: Seq[CandidateWithDetails]) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala deleted file mode 100644 index 8b6038feb..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/selector_executor/SelectorExecutorResult.scala +++ /dev/null @@ -1,12 +0,0 @@ -package com.twitter.product_mixer.core.service.selector_executor - -import com.twitter.product_mixer.core.functional_component.selector.SelectorResult -import com.twitter.product_mixer.core.model.common.presentation.CandidateWithDetails -import com.twitter.product_mixer.core.service.ExecutorResult - -case class SelectorExecutorResult( - selectedCandidates: Seq[CandidateWithDetails], - remainingCandidates: Seq[CandidateWithDetails], - droppedCandidates: Seq[CandidateWithDetails], - individualSelectorResults: Seq[SelectorResult]) - extends ExecutorResult diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD deleted file mode 100644 index 4cb8369e2..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - "stitch/stitch-core", - "strato/config/src/thrift/com/twitter/strato/graphql:api-media-graphql-scala", - "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala", - "strato/config/src/thrift/com/twitter/strato/graphql:topics-graphql-scala", - "util/util-core:scala", - ], - exports = [ - "strato/config/src/thrift/com/twitter/strato/graphql:graphql-scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala deleted file mode 100644 index 0dbda7321..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/slice/SliceService.scala +++ /dev/null @@ -1,29 +0,0 @@ -package com.twitter.product_mixer.core.service.slice - -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest -import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry -import com.twitter.stitch.Stitch -import com.twitter.strato.graphql.thriftscala.SliceResult -import com.twitter.timelines.configapi.Params - -import javax.inject.Inject -import javax.inject.Singleton -import scala.reflect.runtime.universe.TypeTag - -/** - * Look up and execute Slice products in the [[ProductPipelineRegistry]] - */ -@Singleton -class SliceService @Inject() (productPipelineRegistry: ProductPipelineRegistry) { - - def getSliceResponse[RequestType <: Request]( - request: RequestType, - params: Params - )( - implicit requestTypeTag: TypeTag[RequestType] - ): Stitch[SliceResult] = - productPipelineRegistry - .getProductPipeline[RequestType, SliceResult](request.product) - .process(ProductPipelineRequest(request, params)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD deleted file mode 100644 index 2e7568b01..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/transformer", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala deleted file mode 100644 index 19a3ed126..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/PerCandidateTransformerExecutor.scala +++ /dev/null @@ -1,35 +0,0 @@ -package com.twitter.product_mixer.core.service.transformer_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.transformer.Transformer -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow -import com.twitter.util.Try -import javax.inject.Inject -import javax.inject.Singleton - -/** - * For wrapping [[Transformer]]s that are applied per-candidate - * - * Records a single span for running all the components, - * but stats per-component. - */ -@Singleton -class PerCandidateTransformerExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - - def arrow[In, Out]( - transformer: Transformer[In, Out], - context: Executor.Context, - ): Arrow[Seq[In], Seq[Try[Out]]] = { - val perCandidateArrow = wrapPerCandidateComponentWithExecutorBookkeepingWithoutTracing( - context, - transformer.identifier - )(Arrow.map(transformer.transform)).liftToTry - - wrapComponentsWithTracingOnly( - context, - transformer.identifier - )(Arrow.sequence(perCandidateArrow)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala deleted file mode 100644 index bdefad6f3..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transformer_executor/TransformerExecutor.scala +++ /dev/null @@ -1,22 +0,0 @@ -package com.twitter.product_mixer.core.service.transformer_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.transformer.Transformer -import com.twitter.product_mixer.core.service.Executor -import com.twitter.stitch.Arrow - -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class TransformerExecutor @Inject() (override val statsReceiver: StatsReceiver) extends Executor { - def arrow[In, Out]( - transformer: Transformer[In, Out], - context: Executor.Context - ): Arrow[In, Out] = { - wrapComponentWithExecutorBookkeeping( - context, - transformer.identifier - )(Arrow.map(transformer.transform)) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD deleted file mode 100644 index 7cedc62ae..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], - exports = [ - "3rdparty/jvm/javax/inject:javax.inject", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/common/identifier", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service", - "stitch/stitch-core", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala deleted file mode 100644 index c93c9000e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/transport_marshaller_executor/TransportMarshallerExecutor.scala +++ /dev/null @@ -1,40 +0,0 @@ -package com.twitter.product_mixer.core.service.transport_marshaller_executor - -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.core.functional_component.marshaller.TransportMarshaller -import com.twitter.product_mixer.core.model.marshalling.HasMarshalling -import com.twitter.product_mixer.core.service.Executor -import com.twitter.product_mixer.core.service.ExecutorResult -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor.Inputs -import com.twitter.product_mixer.core.service.transport_marshaller_executor.TransportMarshallerExecutor.Result -import com.twitter.stitch.Arrow -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Executes a [[TransportMarshaller]]. - * - * @note This is a synchronous transform, so we don't observe it directly. Failures and such - * can be observed at the parent pipeline. - */ -@Singleton -class TransportMarshallerExecutor @Inject() (override val statsReceiver: StatsReceiver) - extends Executor { - - def arrow[DomainResponseType <: HasMarshalling, TransportResponseType]( - marshaller: TransportMarshaller[DomainResponseType, TransportResponseType], - context: Executor.Context - ): Arrow[Inputs[DomainResponseType], Result[TransportResponseType]] = { - val arrow = - Arrow.map[Inputs[DomainResponseType], Result[TransportResponseType]] { - case Inputs(domainResponse) => Result(marshaller(domainResponse)) - } - - wrapComponentWithExecutorBookkeeping(context, marshaller.identifier)(arrow) - } -} - -object TransportMarshallerExecutor { - case class Inputs[DomainResponseType <: HasMarshalling](domainResponse: DomainResponseType) - case class Result[TransportResponseType](result: TransportResponseType) extends ExecutorResult -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD deleted file mode 100644 index 1f4780222..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/com/lihaoyi:pprint", - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urp", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urp", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - "stitch/stitch-core", - "util/util-core:scala", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala deleted file mode 100644 index 0e08f670e..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urp/UrpService.scala +++ /dev/null @@ -1,26 +0,0 @@ -package com.twitter.product_mixer.core.service.urp - -import com.twitter.pages.render.{thriftscala => urp} -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest -import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Params - -import javax.inject.Inject -import javax.inject.Singleton -import scala.reflect.runtime.universe.TypeTag - -@Singleton -class UrpService @Inject() (productPipelineRegistry: ProductPipelineRegistry) { - - def getUrpResponse[RequestType <: Request]( - request: RequestType, - params: Params - )( - implicit requestTypeTag: TypeTag[RequestType] - ): Stitch[urp.Page] = - productPipelineRegistry - .getProductPipeline[RequestType, urp.Page](request.product) - .process(ProductPipelineRequest(request, params)) -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD deleted file mode 100644 index b4c6c49a1..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/BUILD +++ /dev/null @@ -1,20 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "3rdparty/jvm/javax/inject:javax.inject", - "configapi/configapi-core", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/functional_component/marshaller/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/model/marshalling/response/urt", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/product/registry", - "product-mixer/core/src/main/thrift/com/twitter/product_mixer/core:thrift-scala", - "stitch/stitch-core", - "util/util-core:scala", - "util/util-jackson/src/main/scala/com/twitter/util/jackson", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala deleted file mode 100644 index 2f8c79d60..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/service/urt/UrtService.scala +++ /dev/null @@ -1,60 +0,0 @@ -package com.twitter.product_mixer.core.service.urt - -import com.fasterxml.jackson.databind.SerializationFeature -import com.twitter.product_mixer.core.functional_component.marshaller.response.urt.UrtTransportMarshaller -import com.twitter.product_mixer.core.model.marshalling.request.Request -import com.twitter.product_mixer.core.pipeline.pipeline_failure.PipelineFailure -import com.twitter.product_mixer.core.pipeline.pipeline_failure.ProductDisabled -import com.twitter.product_mixer.core.pipeline.product.ProductPipelineRequest -import com.twitter.product_mixer.core.product.registry.ProductPipelineRegistry -import com.twitter.product_mixer.core.{thriftscala => t} -import com.twitter.stitch.Stitch -import com.twitter.timelines.configapi.Params -import com.twitter.timelines.render.{thriftscala => urt} -import com.twitter.util.jackson.ScalaObjectMapper - -import javax.inject.Inject -import javax.inject.Singleton -import scala.reflect.runtime.universe.TypeTag - -/** - * Look up and execute products in the [[ProductPipelineRegistry]] - */ -@Singleton -class UrtService @Inject() (productPipelineRegistry: ProductPipelineRegistry) { - - def getUrtResponse[RequestType <: Request]( - request: RequestType, - params: Params - )( - implicit requestTypeTag: TypeTag[RequestType] - ): Stitch[urt.TimelineResponse] = - productPipelineRegistry - .getProductPipeline[RequestType, urt.TimelineResponse](request.product) - .process(ProductPipelineRequest(request, params)) - .handle { - // Detect ProductDisabled and convert it to TimelineUnavailable - case pipelineFailure: PipelineFailure if pipelineFailure.category == ProductDisabled => - UrtTransportMarshaller.unavailable("") - } - - /** - * Get detailed pipeline execution as a serialized JSON String - */ - def getPipelineExecutionResult[RequestType <: Request]( - request: RequestType, - params: Params - )( - implicit requestTypeTag: TypeTag[RequestType] - ): Stitch[t.PipelineExecutionResult] = - productPipelineRegistry - .getProductPipeline[RequestType, urt.TimelineResponse](request.product) - .arrow(ProductPipelineRequest(request, params)).map { detailedResult => - val mapper = ScalaObjectMapper() - // configure so that exception is not thrown whenever case class is not serializable - mapper.underlying.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) - val serializedJSON = mapper.writePrettyString(detailedResult) - t.PipelineExecutionResult(serializedJSON) - } - -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD deleted file mode 100644 index 14035e637..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-core/src/main", - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "servo/util", - "snowflake:id", - "stitch/stitch-core", - "util/util-core:util-core-util", - "util/util-stats", - ], - exports = [ - "product-mixer/core/src/main/scala/com/twitter/product_mixer/core/pipeline/pipeline_failure", - "servo/util", - "snowflake:id", - "stitch/stitch-core", - "util/util-core:util-core-util", - "util/util-stats", - ], -) diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala deleted file mode 100644 index 52885db34..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/FuturePools.scala +++ /dev/null @@ -1,101 +0,0 @@ -package com.twitter.product_mixer.core.util - -import com.twitter.concurrent.NamedPoolThreadFactory -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.util.Duration -import com.twitter.util.FuturePool - -import java.util.concurrent.ArrayBlockingQueue -import java.util.concurrent.BlockingQueue -import java.util.concurrent.LinkedBlockingQueue -import java.util.concurrent.ThreadPoolExecutor -import java.util.concurrent.TimeUnit - -/** - * Utility for making [[FuturePool]] with finite thread counts and different work queue options - * while also monitoring the size of the work queue that's used. - * - * This only handles the cases where the number of threads are bounded. - * For unbounded numbers of threads in a [[FuturePool]] use [[FuturePool.interruptibleUnboundedPool]] instead. - */ -object FuturePools { - - /** - * Makes a [[FuturePool]] with a fixed number of threads and a work queue - * with a maximum size of `maxWorkQueueSize`. - * - * @note the [[FuturePool]] returns a failed [[com.twitter.util.Future]]s containing - * [[java.util.concurrent.RejectedExecutionException]] when trying to enqueue - * work when the work queue is full. - */ - def boundedFixedThreadPool( - name: String, - fixedThreadCount: Int, - workQueueSize: Int, - statsReceiver: StatsReceiver - ): FuturePool = - futurePool( - name = name, - minThreads = fixedThreadCount, - maxThreads = fixedThreadCount, - keepIdleThreadsAlive = Duration.Zero, - workQueue = new ArrayBlockingQueue[Runnable](workQueueSize), - statsReceiver = statsReceiver - ) - - /** - * Makes a [[FuturePool]] with a fix number of threads and an unbounded work queue - * - * @note Since the work queue is unbounded, this will fill up memory if the available worker threads can't keep up - */ - def unboundedFixedThreadPool( - name: String, - fixedThreadCount: Int, - statsReceiver: StatsReceiver - ): FuturePool = - futurePool( - name = name, - minThreads = fixedThreadCount, - maxThreads = fixedThreadCount, - keepIdleThreadsAlive = Duration.Zero, - workQueue = new LinkedBlockingQueue[Runnable], - statsReceiver = statsReceiver - ) - - /** - * Makes a [[FuturePool]] with the provided thread configuration and - * who's `workQueue` is monitored by a [[com.twitter.finagle.stats.Gauge]] - * - * @note if `minThreads` == `maxThreads` then the threadpool has a fixed size - * - * @param name name of the threadpool - * @param minThreads minimum number of threads in the pool - * @param maxThreads maximum number of threads in the pool - * @param keepIdleThreadsAlive threads that are idle for this long will be removed from - * the pool if there are more than `minThreads` in the pool. - * If the pool size is fixed this is ignored. - */ - private def futurePool( - name: String, - minThreads: Int, - maxThreads: Int, - keepIdleThreadsAlive: Duration, - workQueue: BlockingQueue[Runnable], - statsReceiver: StatsReceiver - ): FuturePool = { - val gaugeReference = statsReceiver.addGauge("workQueueSize")(workQueue.size()) - - val threadFactory = new NamedPoolThreadFactory(name, makeDaemons = true) - - val executorService = - new ThreadPoolExecutor( - minThreads, - maxThreads, // ignored by ThreadPoolExecutor when an unbounded queue is provided - keepIdleThreadsAlive.inMillis, - TimeUnit.MILLISECONDS, - workQueue, - threadFactory) - - FuturePool.interruptible(executorService) - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala deleted file mode 100644 index cb0a92657..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/OffloadFuturePools.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.twitter.product_mixer.core.util - -import com.twitter.finagle.offload.OffloadFuturePool -import com.twitter.util.Future - -object OffloadFuturePools { - - def parallelize[In, Out]( - inputSeq: Seq[In], - transformer: In => Out, - parallelism: Int - ): Future[Seq[Out]] = { - parallelize(inputSeq, transformer.andThen(Some(_)), parallelism, None).map(_.flatten) - } - - def parallelize[In, Out]( - inputSeq: Seq[In], - transformer: In => Out, - parallelism: Int, - default: Out - ): Future[Seq[Out]] = { - val threadProcessFutures = (0 until parallelism).map { i => - OffloadFuturePool.getPool(partitionAndProcessInput(inputSeq, transformer, i, parallelism)) - } - - val resultMap = Future.collect(threadProcessFutures).map(_.flatten.toMap) - - Future.collect { - inputSeq.indices.map { idx => - resultMap.map(_.getOrElse(idx, default)) - } - } - } - - private def partitionAndProcessInput[In, Out]( - inputSeq: Seq[In], - transformer: In => Out, - threadId: Int, - parallelism: Int - ): Seq[(Int, Out)] = { - partitionInputForThread(inputSeq, threadId, parallelism) - .map { - case (inputRecord, idx) => - (idx, transformer(inputRecord)) - } - } - - private def partitionInputForThread[In]( - inputSeq: Seq[In], - threadId: Int, - parallelism: Int - ): Seq[(In, Int)] = { - inputSeq.zipWithIndex - .filter { - case (_, idx) => idx % parallelism == threadId - case _ => false - } - } -} diff --git a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala b/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala deleted file mode 100644 index eb55b231b..000000000 --- a/product-mixer/core/src/main/scala/com/twitter/product_mixer/core/util/SortIndexBuilder.scala +++ /dev/null @@ -1,17 +0,0 @@ -package com.twitter.product_mixer.core.util - -import com.twitter.snowflake.id.SnowflakeId -import com.twitter.util.Time - -object SortIndexBuilder { - - /** the [[Time]] from a [[SnowflakeId]] */ - def idToTime(id: Long): Time = - Time.fromMilliseconds(SnowflakeId.unixTimeMillisOrFloorFromId(id)) - - /** the first [[SnowflakeId]] possible for a given [[Time]] */ - def timeToId(time: Time): Long = SnowflakeId.firstIdFor(time) - - /** the first [[SnowflakeId]] possible for a given unix epoch millis */ - def timeToId(timeMillis: Long): Long = SnowflakeId.firstIdFor(timeMillis) -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD deleted file mode 100644 index 2be84e6a8..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-core/src/main", - "finagle/finagle-http/src/main/scala", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "util/util-core", - ], - exports = [ - "finagle/finagle-core/src/main", - "finagle/finagle-http/src/main/scala", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "util/util-core", - ], -) diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala deleted file mode 100644 index fd203cacf..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientBuilder.scala +++ /dev/null @@ -1,57 +0,0 @@ -package com.twitter.product_mixer.shared_library.http_client - -import com.twitter.finagle.Http -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.mtls.client.MtlsStackClient._ -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.util.Duration - -object FinagleHttpClientBuilder { - - /** - * Build a Finagle HTTP client with S2S Auth / Mutual TLS - * - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param serviceIdentifier Service ID used to S2S Auth - * @param statsReceiver Stats - * - * @return Finagle HTTP Client with S2S Auth / Mutual TLS - */ - def buildFinagleHttpClientMutualTls( - requestTimeout: Duration, - connectTimeout: Duration, - acquisitionTimeout: Duration, - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver - ): Http.Client = - buildFinagleHttpClient( - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - statsReceiver = statsReceiver - ).withMutualTls(serviceIdentifier) - - /** - * Build a Finagle HTTP client - * - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param statsReceiver stats - * - * @return Finagle HTTP Client - */ - def buildFinagleHttpClient( - requestTimeout: Duration, - connectTimeout: Duration, - acquisitionTimeout: Duration, - statsReceiver: StatsReceiver, - ): Http.Client = - Http.client - .withStatsReceiver(statsReceiver) - .withRequestTimeout(requestTimeout) - .withTransport.connectTimeout(connectTimeout) - .withSession.acquisitionTimeout(acquisitionTimeout) -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala deleted file mode 100644 index a2f4a5764..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/FinagleHttpClientWithProxyBuilder.scala +++ /dev/null @@ -1,97 +0,0 @@ -package com.twitter.product_mixer.shared_library.http_client - -import com.twitter.finagle.Http -import com.twitter.finagle.Service -import com.twitter.finagle.client.Transporter -import com.twitter.finagle.http.ProxyCredentials -import com.twitter.finagle.http.Request -import com.twitter.finagle.http.Response -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.shared_library.http_client.FinagleHttpClientBuilder.buildFinagleHttpClient -import com.twitter.util.Duration - -object FinagleHttpClientWithProxyBuilder { - - /** - * Build a Finagle HTTP client with Egress Proxy support using Credentials - * - * @param twitterProxyHostPort Twitter egress proxy host port - * @param remoteProxyHostPort Remote proxy host port - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param proxyCredentials Proxy credentials - * @param statsReceiver Stats - * - * @return Finagle HTTP client with Egress Proxy support using Credentials - */ - def buildFinagleHttpClientWithCredentialProxy( - twitterProxyHostPort: HttpHostPort, - remoteProxyHostPort: HttpHostPort, - requestTimeout: Duration, - connectTimeout: Duration, - acquisitionTimeout: Duration, - proxyCredentials: ProxyCredentials, - statsReceiver: StatsReceiver, - ): Http.Client = { - val httpClient = buildFinagleHttpClient( - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - statsReceiver = statsReceiver - ) - - httpClient.withTransport - .httpProxyTo( - host = remoteProxyHostPort.toString, - credentials = Transporter.Credentials(proxyCredentials.username, proxyCredentials.password)) - .withTls(remoteProxyHostPort.host) - } - - /** - * Build a Finagle HTTP client with Egress Proxy support - * - * @param twitterProxyHostPort Twitter egress proxy host port - * @param remoteProxyHostPort Remote proxy host port - * @param requestTimeout HTTP client request timeout - * @param connectTimeout HTTP client transport connect timeout - * @param acquisitionTimeout HTTP client session acquisition timeout - * @param statsReceiver Stats - * - * @return Finagle HTTP client with Egress Proxy support - */ - def buildFinagleHttpClientWithProxy( - twitterProxyHostPort: HttpHostPort, - remoteProxyHostPort: HttpHostPort, - requestTimeout: Duration, - connectTimeout: Duration, - acquisitionTimeout: Duration, - statsReceiver: StatsReceiver, - ): Http.Client = { - val httpClient = buildFinagleHttpClient( - requestTimeout = requestTimeout, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - statsReceiver = statsReceiver - ) - - httpClient.withTransport - .httpProxyTo(remoteProxyHostPort.toString) - .withTls(remoteProxyHostPort.host) - } - - /** - * Build a Finagle HTTP service with Egress Proxy support - * - * @param finagleHttpClientWithProxy Finagle HTTP client from which to build the service - * @param twitterProxyHostPort Twitter egress proxy host port - * - * @return Finagle HTTP service with Egress Proxy support - */ - def buildFinagleHttpServiceWithProxy( - finagleHttpClientWithProxy: Http.Client, - twitterProxyHostPort: HttpHostPort - ): Service[Request, Response] = { - finagleHttpClientWithProxy.newService(twitterProxyHostPort.toString) - } -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala deleted file mode 100644 index ceab3d24e..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/http_client/HttpHostPort.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.twitter.product_mixer.shared_library.http_client - -case class HttpHostPort(host: String, port: Int) { - override val toString: String = s"$host:$port" -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD deleted file mode 100644 index 3de790d1f..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authentication", - "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authorization", - "finagle/finagle-core/src/main", - "finagle/finagle-thriftmux/src/main/scala", - "src/scala/com/twitter/storehaus_internal/manhattan/config", - "src/thrift/com/twitter/manhattan:v1-scala", - "storage/clients/manhattan", - "util/util-core", - ], - exports = [ - "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authentication", - "finagle-internal/mtls/src/main/scala/com/twitter/finagle/mtls/authorization", - "finagle/finagle-core/src/main", - "src/scala/com/twitter/storehaus_internal/manhattan/config", - "storage/clients/manhattan", - "util/util-core", - ], -) diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala deleted file mode 100644 index a9903a4e0..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/manhattan_client/ManhattanClientBuilder.scala +++ /dev/null @@ -1,116 +0,0 @@ -package com.twitter.product_mixer.shared_library.manhattan_client - -import com.twitter.finagle.mtls.authentication.EmptyServiceIdentifier -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.ssl.OpportunisticTls -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.manhattan.v1.{thriftscala => mh} -import com.twitter.storage.client.manhattan.kv.Experiments -import com.twitter.storage.client.manhattan.kv.Experiments.Experiment -import com.twitter.storage.client.manhattan.kv.Guarantee -import com.twitter.storage.client.manhattan.kv.ManhattanKVClient -import com.twitter.storage.client.manhattan.kv.ManhattanKVClientMtlsParams -import com.twitter.storage.client.manhattan.kv.ManhattanKVEndpoint -import com.twitter.storage.client.manhattan.kv.ManhattanKVEndpointBuilder -import com.twitter.storage.client.manhattan.kv.NoMtlsParams -import com.twitter.storehaus_internal.manhattan.ManhattanCluster -import com.twitter.util.Duration - -object ManhattanClientBuilder { - - /** - * Build a ManhattanKVClient/Endpoint [[ManhattanKVEndpoint]] / [[ManhattanKVClient]] - * - * @param cluster Manhattan cluster - * @param appId Manhattan appid - * @param numTries Max number of times to try - * @param maxTimeout Max request timeout - * @param maxItemsPerRequest Max items per request - * @param guarantee Consistency guarantee - * @param serviceIdentifier Service ID used to S2S Auth - * @param statsReceiver Stats - * @param experiments MH client experiments to include - * @return ManhattanKVEndpoint - */ - def buildManhattanEndpoint( - cluster: ManhattanCluster, - appId: String, - numTries: Int, - maxTimeout: Duration, - guarantee: Guarantee, - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver, - maxItemsPerRequest: Int = 100, - experiments: Seq[Experiment] = Seq(Experiments.ApertureLoadBalancer) - ): ManhattanKVEndpoint = { - val client = buildManhattanClient( - cluster, - appId, - serviceIdentifier, - experiments - ) - - ManhattanKVEndpointBuilder(client) - .defaultGuarantee(guarantee) - .defaultMaxTimeout(maxTimeout) - .maxRetryCount(numTries) - .maxItemsPerRequest(maxItemsPerRequest) - .statsReceiver(statsReceiver) - .build() - } - - /** - * Build a ManhattanKVClient - * - * @param cluster Manhattan cluster - * @param appId Manhattan appid - * @param serviceIdentifier Service ID used to S2S Auth - * @param experiments MH client experiments to include - * - * @return ManhattanKVClient - */ - def buildManhattanClient( - cluster: ManhattanCluster, - appId: String, - serviceIdentifier: ServiceIdentifier, - experiments: Seq[Experiment] = Seq(Experiments.ApertureLoadBalancer) - ): ManhattanKVClient = { - val mtlsParams = serviceIdentifier match { - case EmptyServiceIdentifier => NoMtlsParams - case serviceIdentifier => - ManhattanKVClientMtlsParams( - serviceIdentifier = serviceIdentifier, - opportunisticTls = OpportunisticTls.Required) - } - - val label = s"manhattan/${cluster.prefix}" - - new ManhattanKVClient( - appId = appId, - dest = cluster.wilyName, - mtlsParams = mtlsParams, - label = label, - experiments = experiments - ) - } - - def buildManhattanV1FinagleClient( - cluster: ManhattanCluster, - serviceIdentifier: ServiceIdentifier, - experiments: Seq[Experiment] = Seq(Experiments.ApertureLoadBalancer) - ): mh.ManhattanCoordinator.MethodPerEndpoint = { - val mtlsParams = serviceIdentifier match { - case EmptyServiceIdentifier => NoMtlsParams - case serviceIdentifier => - ManhattanKVClientMtlsParams( - serviceIdentifier = serviceIdentifier, - opportunisticTls = OpportunisticTls.Required) - } - - val label = s"manhattan/${cluster.prefix}" - - Experiments - .clientWithExperiments(experiments, mtlsParams) - .build[mh.ManhattanCoordinator.MethodPerEndpoint](cluster.wilyName, label) - } -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD deleted file mode 100644 index dfd7ba2b1..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-memcached/src/main/scala", - "finatra-internal/mtls-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "servo/repo/src/main/scala", - ], - exports = [ - "finagle/finagle-memcached/src/main/scala", - "finatra-internal/mtls-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "servo/repo/src/main/scala", - ], -) diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala deleted file mode 100644 index 62453afbd..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/memcached_client/MemcachedClientBuilder.scala +++ /dev/null @@ -1,117 +0,0 @@ -package com.twitter.product_mixer.shared_library.memcached_client - -import com.twitter.finagle.memcached.Client -import com.twitter.finagle.memcached.protocol.Command -import com.twitter.finagle.memcached.protocol.Response -import com.twitter.finagle.mtls.client.MtlsStackClient._ -import com.twitter.finagle.service.RetryExceptionsFilter -import com.twitter.finagle.service.RetryPolicy -import com.twitter.finagle.service.TimeoutFilter -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finagle.util.DefaultTimer -import com.twitter.finagle.GlobalRequestTimeoutException -import com.twitter.finagle.Memcached -import com.twitter.finagle.liveness.FailureAccrualFactory -import com.twitter.finagle.liveness.FailureAccrualPolicy -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.hashing.KeyHasher -import com.twitter.util.Duration - -object MemcachedClientBuilder { - - /** - * Build a Finagle Memcached [[Client]]. - * - * @param destName Destination as a Wily path e.g. "/s/sample/sample". - * @param numTries Maximum number of times to try. - * @param requestTimeout Thrift client timeout per request. The Finagle default - * is unbounded which is almost never optimal. - * @param globalTimeout Thrift client total timeout. The Finagle default is - * unbounded which is almost never optimal. - * @param connectTimeout Thrift client transport connect timeout. The Finagle - * default of one second is reasonable but we lower this - * to match acquisitionTimeout for consistency. - * @param acquisitionTimeout Thrift client session acquisition timeout. The Finagle - * default is unbounded which is almost never optimal. - * @param serviceIdentifier Service ID used to S2S Auth. - * @param statsReceiver Stats. - * @param failureAccrualPolicy Policy to determine when to mark a cache server as dead. - * Memcached client will use default failure accrual policy - * if it is not set. - * @param keyHasher Hash algorithm that hashes a key into a 32-bit or 64-bit - * number. Memcached client will use default hash algorithm - * if it is not set. - * - * @see [[https://confluence.twitter.biz/display/CACHE/Finagle-memcached+User+Guide user guide]] - * @return Finagle Memcached [[Client]] - */ - def buildMemcachedClient( - destName: String, - numTries: Int, - requestTimeout: Duration, - globalTimeout: Duration, - connectTimeout: Duration, - acquisitionTimeout: Duration, - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver, - failureAccrualPolicy: Option[FailureAccrualPolicy] = None, - keyHasher: Option[KeyHasher] = None - ): Client = { - buildRawMemcachedClient( - numTries, - requestTimeout, - globalTimeout, - connectTimeout, - acquisitionTimeout, - serviceIdentifier, - statsReceiver, - failureAccrualPolicy, - keyHasher - ).newRichClient(destName) - } - - def buildRawMemcachedClient( - numTries: Int, - requestTimeout: Duration, - globalTimeout: Duration, - connectTimeout: Duration, - acquisitionTimeout: Duration, - serviceIdentifier: ServiceIdentifier, - statsReceiver: StatsReceiver, - failureAccrualPolicy: Option[FailureAccrualPolicy] = None, - keyHasher: Option[KeyHasher] = None - ): Memcached.Client = { - val globalTimeoutFilter = new TimeoutFilter[Command, Response]( - timeout = globalTimeout, - exception = new GlobalRequestTimeoutException(globalTimeout), - timer = DefaultTimer) - val retryFilter = new RetryExceptionsFilter[Command, Response]( - RetryPolicy.tries(numTries), - DefaultTimer, - statsReceiver) - - val client = Memcached.client.withTransport - .connectTimeout(connectTimeout) - .withMutualTls(serviceIdentifier) - .withSession - .acquisitionTimeout(acquisitionTimeout) - .withRequestTimeout(requestTimeout) - .withStatsReceiver(statsReceiver) - .filtered(globalTimeoutFilter.andThen(retryFilter)) - - (keyHasher, failureAccrualPolicy) match { - case (Some(hasher), Some(policy)) => - client - .withKeyHasher(hasher) - .configured(FailureAccrualFactory.Param(() => policy)) - case (Some(hasher), None) => - client - .withKeyHasher(hasher) - case (None, Some(policy)) => - client - .configured(FailureAccrualFactory.Param(() => policy)) - case _ => - client - } - } -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD deleted file mode 100644 index 325ddbae3..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - platform = "java8", - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "servo/util", - "stitch/stitch-core", - "util/util-core:util-core-util", - "util/util-stats", - ], - exports = [ - "servo/util", - "stitch/stitch-core", - "util/util-core:util-core-util", - "util/util-stats", - ], -) diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala deleted file mode 100644 index df9e8389d..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/Observer.scala +++ /dev/null @@ -1,203 +0,0 @@ -package com.twitter.product_mixer.shared_library.observer - -import com.twitter.finagle.stats.Counter -import com.twitter.finagle.stats.RollupStatsReceiver -import com.twitter.finagle.stats.Stat -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.servo.util.CancelledExceptionExtractor -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch -import com.twitter.util.Duration -import com.twitter.util.Future -import com.twitter.util.Throwables -import com.twitter.util.Try - -/** - * Helper functions to observe requests, success, failures, cancellations, exceptions, and latency. - * Supports native functions and asynchronous operations. - */ -object Observer { - val Requests = "requests" - val Success = "success" - val Failures = "failures" - val Cancelled = "cancelled" - val Latency = "latency_ms" - - /** - * Helper function to observe a stitch - * - * @see [[StitchObserver]] - */ - def stitch[T](statsReceiver: StatsReceiver, scopes: String*): StitchObserver[T] = - new StitchObserver[T](statsReceiver, scopes) - - /** - * Helper function to observe an arrow - * - * @see [[ArrowObserver]] - */ - def arrow[In, Out](statsReceiver: StatsReceiver, scopes: String*): ArrowObserver[In, Out] = - new ArrowObserver[In, Out](statsReceiver, scopes) - - /** - * Helper function to observe a future - * - * @see [[FutureObserver]] - */ - def future[T](statsReceiver: StatsReceiver, scopes: String*): FutureObserver[T] = - new FutureObserver[T](statsReceiver, scopes) - - /** - * Helper function to observe a function - * - * @see [[FunctionObserver]] - */ - def function[T](statsReceiver: StatsReceiver, scopes: String*): FunctionObserver[T] = - new FunctionObserver[T](statsReceiver, scopes) - - /** - * [[StitchObserver]] can record latency stats, success counters, and - * detailed failure stats for the results of a Stitch computation. - */ - class StitchObserver[T]( - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends Observer[T] { - - /** - * Record stats for the provided Stitch. - * The result of the computation is passed through. - * - * @note the provided Stitch must contain the parts that need to be timed. - * Using this on just the result of the computation the latency stat - * will be incorrect. - */ - def apply(stitch: => Stitch[T]): Stitch[T] = - Stitch.time(stitch).map(observe.tupled).lowerFromTry - } - - /** - * [[ArrowObserver]] can record the latency stats, success counters, and - * detailed failure stats for the result of an Arrow computation. - * The result of the computation is passed through. - */ - class ArrowObserver[In, Out]( - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends Observer[Out] { - - /** - * Returns a new Arrow that records stats when it's run. - * The result of the Arrow is passed through. - * - * @note the provided Arrow must contain the parts that need to be timed. - * Using this on just the result of the computation the latency stat - * will be incorrect. - */ - def apply(arrow: Arrow[In, Out]): Arrow[In, Out] = - Arrow.time(arrow).map(observe.tupled).lowerFromTry - } - - /** - * [[FutureObserver]] can record latency stats, success counters, and - * detailed failure stats for the results of a Future computation. - */ - class FutureObserver[T]( - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends Observer[T] { - - /** - * Record stats for the provided Future. - * The result of the computation is passed through. - * - * @note the provided Future must contain the parts that need to be timed. - * Using this on just the result of the computation the latency stat - * will be incorrect. - */ - def apply(future: => Future[T]): Future[T] = - Stat - .timeFuture(latencyStat)(future) - .onSuccess(observeSuccess) - .onFailure(observeFailure) - } - - /** - * [[FunctionObserver]] can record latency stats, success counters, and - * detailed failure stats for the results of a computation computation. - */ - class FunctionObserver[T]( - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends Observer[T] { - - /** - * Record stats for the provided computation. - * The result of the computation is passed through. - * - * @note the provided computation must contain the parts that need to be timed. - * Using this on just the result of the computation the latency stat - * will be incorrect. - */ - def apply(f: => T): T = { - Try(Stat.time(latencyStat)(f)) - .onSuccess(observeSuccess) - .onFailure(observeFailure) - .apply() - } - } - - /** [[Observer]] provides methods for recording latency, success, and failure stats */ - trait Observer[T] { - protected val statsReceiver: StatsReceiver - - /** Scopes that prefix all stats */ - protected val scopes: Seq[String] - - private val rollupStatsReceiver = new RollupStatsReceiver(statsReceiver.scope(scopes: _*)) - private val requestsCounter: Counter = statsReceiver.counter(scopes :+ Requests: _*) - private val successCounter: Counter = statsReceiver.counter(scopes :+ Success: _*) - - // create the stats so their metrics paths are always present but - // defer to the [[RollupStatsReceiver]] to increment these stats - rollupStatsReceiver.counter(Failures) - rollupStatsReceiver.counter(Cancelled) - - /** Serialize a throwable and it's causes into a seq of Strings for scoping metrics */ - protected def serializeThrowable(throwable: Throwable): Seq[String] = - Throwables.mkString(throwable) - - /** Used to record latency in milliseconds */ - protected val latencyStat: Stat = statsReceiver.stat(scopes :+ Latency: _*) - - /** Records the latency from a [[Duration]] */ - protected val observeLatency: Duration => Unit = { latency => - latencyStat.add(latency.inMilliseconds) - } - - /** Records successes */ - protected val observeSuccess: T => Unit = { _ => - requestsCounter.incr() - successCounter.incr() - } - - /** Records failures and failure details */ - protected val observeFailure: Throwable => Unit = { - case CancelledExceptionExtractor(throwable) => - requestsCounter.incr() - rollupStatsReceiver.counter(Cancelled +: serializeThrowable(throwable): _*).incr() - case throwable => - requestsCounter.incr() - rollupStatsReceiver.counter(Failures +: serializeThrowable(throwable): _*).incr() - } - - /** Records the latency, successes, and failures */ - protected val observe: (Try[T], Duration) => Try[T] = - (response: Try[T], runDuration: Duration) => { - observeLatency(runDuration) - response - .onSuccess(observeSuccess) - .onFailure(observeFailure) - } - } -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala deleted file mode 100644 index e77676509..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsObserver.scala +++ /dev/null @@ -1,281 +0,0 @@ -package com.twitter.product_mixer.shared_library.observer - -import com.twitter.finagle.stats.Counter -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.shared_library.observer.Observer.ArrowObserver -import com.twitter.product_mixer.shared_library.observer.Observer.FunctionObserver -import com.twitter.product_mixer.shared_library.observer.Observer.FutureObserver -import com.twitter.product_mixer.shared_library.observer.Observer.Observer -import com.twitter.product_mixer.shared_library.observer.Observer.StitchObserver -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch -import com.twitter.util.Future -import com.twitter.util.Try - -/** - * Helper functions to observe requests, successes, failures, cancellations, exceptions, latency, - * and result counts. Supports native functions and asynchronous operations. - */ -object ResultsObserver { - val Total = "total" - val Found = "found" - val NotFound = "not_found" - - /** - * Helper function to observe a stitch and result counts - * - * @see [[StitchResultsObserver]] - */ - def stitchResults[T]( - size: T => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): StitchResultsObserver[T] = { - new StitchResultsObserver[T](size, statsReceiver, scopes) - } - - /** - * Helper function to observe a stitch and traversable (e.g. Seq, Set) result counts - * - * @see [[StitchResultsObserver]] - */ - def stitchResults[T <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): StitchResultsObserver[T] = { - new StitchResultsObserver[T](_.size, statsReceiver, scopes) - } - - /** - * Helper function to observe an arrow and result counts - * - * @see [[ArrowResultsObserver]] - */ - def arrowResults[In, Out]( - size: Out => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): ArrowResultsObserver[In, Out] = { - new ArrowResultsObserver[In, Out](size, statsReceiver, scopes) - } - - /** - * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts - * - * @see [[ArrowResultsObserver]] - */ - def arrowResults[In, Out <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): ArrowResultsObserver[In, Out] = { - new ArrowResultsObserver[In, Out](_.size, statsReceiver, scopes) - } - - /** - * Helper function to observe an arrow and result counts - * - * @see [[TransformingArrowResultsObserver]] - */ - def transformingArrowResults[In, Out, Transformed]( - transformer: Out => Try[Transformed], - size: Transformed => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): TransformingArrowResultsObserver[In, Out, Transformed] = { - new TransformingArrowResultsObserver[In, Out, Transformed]( - transformer, - size, - statsReceiver, - scopes) - } - - /** - * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts - * - * @see [[TransformingArrowResultsObserver]] - */ - def transformingArrowResults[In, Out, Transformed <: TraversableOnce[_]]( - transformer: Out => Try[Transformed], - statsReceiver: StatsReceiver, - scopes: String* - ): TransformingArrowResultsObserver[In, Out, Transformed] = { - new TransformingArrowResultsObserver[In, Out, Transformed]( - transformer, - _.size, - statsReceiver, - scopes) - } - - /** - * Helper function to observe a future and result counts - * - * @see [[FutureResultsObserver]] - */ - def futureResults[T]( - size: T => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): FutureResultsObserver[T] = { - new FutureResultsObserver[T](size, statsReceiver, scopes) - } - - /** - * Helper function to observe a future and traversable (e.g. Seq, Set) result counts - * - * @see [[FutureResultsObserver]] - */ - def futureResults[T <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): FutureResultsObserver[T] = { - new FutureResultsObserver[T](_.size, statsReceiver, scopes) - } - - /** - * Helper function to observe a function and result counts - * - * @see [[FunctionResultsObserver]] - */ - def functionResults[T]( - size: T => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): FunctionResultsObserver[T] = { - new FunctionResultsObserver[T](size, statsReceiver, scopes) - } - - /** - * Helper function to observe a function and traversable (e.g. Seq, Set) result counts - * - * @see [[FunctionResultsObserver]] - */ - def functionResults[T <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): FunctionResultsObserver[T] = { - new FunctionResultsObserver[T](_.size, statsReceiver, scopes) - } - - /** [[StitchObserver]] that also records result size */ - class StitchResultsObserver[T]( - override val size: T => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends StitchObserver[T](statsReceiver, scopes) - with ResultsObserver[T] { - - override def apply(stitch: => Stitch[T]): Stitch[T] = - super - .apply(stitch) - .onSuccess(observeResults) - } - - /** [[ArrowObserver]] that also records result size */ - class ArrowResultsObserver[In, Out]( - override val size: Out => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends ArrowObserver[In, Out](statsReceiver, scopes) - with ResultsObserver[Out] { - - override def apply(arrow: Arrow[In, Out]): Arrow[In, Out] = - super - .apply(arrow) - .onSuccess(observeResults) - } - - /** - * [[TransformingArrowResultsObserver]] functions like an [[ArrowObserver]] except - * that it transforms the result using [[transformer]] before recording stats. - * - * The original non-transformed result is then returned. - */ - class TransformingArrowResultsObserver[In, Out, Transformed]( - val transformer: Out => Try[Transformed], - override val size: Transformed => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends Observer[Transformed] - with ResultsObserver[Transformed] { - - /** - * Returns a new Arrow that records stats on the result after applying [[transformer]] when it's run. - * The original, non-transformed, result of the Arrow is passed through. - * - * @note the provided Arrow must contain the parts that need to be timed. - * Using this on just the result of the computation the latency stat - * will be incorrect. - */ - def apply(arrow: Arrow[In, Out]): Arrow[In, Out] = { - Arrow - .time(arrow) - .map { - case (response, stitchRunDuration) => - observe(response.flatMap(transformer), stitchRunDuration) - .onSuccess(observeResults) - response - }.lowerFromTry - } - } - - /** [[FutureObserver]] that also records result size */ - class FutureResultsObserver[T]( - override val size: T => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends FutureObserver[T](statsReceiver, scopes) - with ResultsObserver[T] { - - override def apply(future: => Future[T]): Future[T] = - super - .apply(future) - .onSuccess(observeResults) - } - - /** [[FunctionObserver]] that also records result size */ - class FunctionResultsObserver[T]( - override val size: T => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends FunctionObserver[T](statsReceiver, scopes) - with ResultsObserver[T] { - - override def apply(f: => T): T = observeResults(super.apply(f)) - } - - /** [[ResultsObserver]] provides methods for recording stats for the result size */ - trait ResultsObserver[T] { - protected val statsReceiver: StatsReceiver - - /** Scopes that prefix all stats */ - protected val scopes: Seq[String] - - protected val totalCounter: Counter = statsReceiver.counter(scopes :+ Total: _*) - protected val foundCounter: Counter = statsReceiver.counter(scopes :+ Found: _*) - protected val notFoundCounter: Counter = statsReceiver.counter(scopes :+ NotFound: _*) - - /** given a [[T]] returns it's size. */ - protected val size: T => Int - - /** Records the size of the `results` using [[size]] and return the original value. */ - protected def observeResults(results: T): T = { - val resultsSize = size(results) - observeResultsWithSize(results, resultsSize) - } - - /** - * Records the `resultsSize` and returns the `results` - * - * This is useful if the size is already available and is expensive to calculate. - */ - protected def observeResultsWithSize(results: T, resultsSize: Int): T = { - if (resultsSize > 0) { - totalCounter.incr(resultsSize) - foundCounter.incr() - } else { - notFoundCounter.incr() - } - results - } - } -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala deleted file mode 100644 index a637e23d8..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/observer/ResultsStatsObserver.scala +++ /dev/null @@ -1,243 +0,0 @@ -package com.twitter.product_mixer.shared_library.observer - -import com.twitter.finagle.stats.Stat -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.product_mixer.shared_library.observer.Observer.ArrowObserver -import com.twitter.product_mixer.shared_library.observer.Observer.FunctionObserver -import com.twitter.product_mixer.shared_library.observer.Observer.FutureObserver -import com.twitter.product_mixer.shared_library.observer.Observer.Observer -import com.twitter.product_mixer.shared_library.observer.Observer.StitchObserver -import com.twitter.product_mixer.shared_library.observer.ResultsObserver.ResultsObserver -import com.twitter.stitch.Arrow -import com.twitter.stitch.Stitch -import com.twitter.util.Future -import com.twitter.util.Try - -/** - * Helper functions to observe requests, successes, failures, cancellations, exceptions, latency, - * and result counts and time-series stats. Supports native functions and asynchronous operations. - * - * Note that since time-series stats are expensive to compute (relative to counters), prefer - * [[ResultsObserver]] unless a time-series stat is needed. - */ -object ResultsStatsObserver { - val Size = "size" - - /** - * Helper function to observe a stitch and result counts and time-series stats - */ - def stitchResultsStats[T]( - size: T => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): StitchResultsStatsObserver[T] = { - new StitchResultsStatsObserver[T](size, statsReceiver, scopes) - } - - /** - * Helper function to observe a stitch and traversable (e.g. Seq, Set) result counts and - * time-series stats - */ - def stitchResultsStats[T <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): StitchResultsStatsObserver[T] = { - new StitchResultsStatsObserver[T](_.size, statsReceiver, scopes) - } - - /** - * Helper function to observe an arrow and result counts and time-series stats - */ - def arrowResultsStats[T, U]( - size: U => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): ArrowResultsStatsObserver[T, U] = { - new ArrowResultsStatsObserver[T, U](size, statsReceiver, scopes) - } - - /** - * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts and - * * time-series stats - */ - def arrowResultsStats[T, U <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): ArrowResultsStatsObserver[T, U] = { - new ArrowResultsStatsObserver[T, U](_.size, statsReceiver, scopes) - } - - /** - * Helper function to observe an arrow and result counts - * - * @see [[TransformingArrowResultsStatsObserver]] - */ - def transformingArrowResultsStats[In, Out, Transformed]( - transformer: Out => Try[Transformed], - size: Transformed => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): TransformingArrowResultsStatsObserver[In, Out, Transformed] = { - new TransformingArrowResultsStatsObserver[In, Out, Transformed]( - transformer, - size, - statsReceiver, - scopes) - } - - /** - * Helper function to observe an arrow and traversable (e.g. Seq, Set) result counts - * - * @see [[TransformingArrowResultsStatsObserver]] - */ - def transformingArrowResultsStats[In, Out, Transformed <: TraversableOnce[_]]( - transformer: Out => Try[Transformed], - statsReceiver: StatsReceiver, - scopes: String* - ): TransformingArrowResultsStatsObserver[In, Out, Transformed] = { - new TransformingArrowResultsStatsObserver[In, Out, Transformed]( - transformer, - _.size, - statsReceiver, - scopes) - } - - /** - * Helper function to observe a future and result counts and time-series stats - */ - def futureResultsStats[T]( - size: T => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): FutureResultsStatsObserver[T] = { - new FutureResultsStatsObserver[T](size, statsReceiver, scopes) - } - - /** - * Helper function to observe a future and traversable (e.g. Seq, Set) result counts and - * time-series stats - */ - def futureResultsStats[T <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): FutureResultsStatsObserver[T] = { - new FutureResultsStatsObserver[T](_.size, statsReceiver, scopes) - } - - /** - * Helper function observe a function and result counts and time-series stats - */ - def functionResultsStats[T]( - size: T => Int, - statsReceiver: StatsReceiver, - scopes: String* - ): FunctionResultsStatsObserver[T] = { - new FunctionResultsStatsObserver[T](size, statsReceiver, scopes) - } - - /** - * Helper function observe a function and traversable (e.g. Seq, Set) result counts and - * time-series stats - */ - def functionResultsStats[T <: TraversableOnce[_]]( - statsReceiver: StatsReceiver, - scopes: String* - ): FunctionResultsStatsObserver[T] = { - new FunctionResultsStatsObserver[T](_.size, statsReceiver, scopes) - } - - class StitchResultsStatsObserver[T]( - override val size: T => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends StitchObserver[T](statsReceiver, scopes) - with ResultsStatsObserver[T] { - - override def apply(stitch: => Stitch[T]): Stitch[T] = - super - .apply(stitch) - .onSuccess(observeResults) - } - - class ArrowResultsStatsObserver[T, U]( - override val size: U => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends ArrowObserver[T, U](statsReceiver, scopes) - with ResultsStatsObserver[U] { - - override def apply(arrow: Arrow[T, U]): Arrow[T, U] = - super - .apply(arrow) - .onSuccess(observeResults) - } - - /** - * [[TransformingArrowResultsStatsObserver]] functions like an [[ArrowObserver]] except - * that it transforms the result using [[transformer]] before recording stats. - * - * The original non-transformed result is then returned. - */ - class TransformingArrowResultsStatsObserver[In, Out, Transformed]( - val transformer: Out => Try[Transformed], - override val size: Transformed => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends Observer[Transformed] - with ResultsStatsObserver[Transformed] { - - /** - * Returns a new Arrow that records stats on the result after applying [[transformer]] when it's run. - * The original, non-transformed, result of the Arrow is passed through. - * - * @note the provided Arrow must contain the parts that need to be timed. - * Using this on just the result of the computation the latency stat - * will be incorrect. - */ - def apply(arrow: Arrow[In, Out]): Arrow[In, Out] = { - Arrow - .time(arrow) - .map { - case (response, stitchRunDuration) => - observe(response.flatMap(transformer), stitchRunDuration) - .onSuccess(observeResults) - response - }.lowerFromTry - } - } - - class FutureResultsStatsObserver[T]( - override val size: T => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends FutureObserver[T](statsReceiver, scopes) - with ResultsStatsObserver[T] { - - override def apply(future: => Future[T]): Future[T] = - super - .apply(future) - .onSuccess(observeResults) - } - - class FunctionResultsStatsObserver[T]( - override val size: T => Int, - override val statsReceiver: StatsReceiver, - override val scopes: Seq[String]) - extends FunctionObserver[T](statsReceiver, scopes) - with ResultsStatsObserver[T] { - - override def apply(f: => T): T = { - observeResults(super.apply(f)) - } - } - - trait ResultsStatsObserver[T] extends ResultsObserver[T] { - private val sizeStat: Stat = statsReceiver.stat(scopes :+ Size: _*) - - protected override def observeResults(results: T): T = { - val resultsSize = size(results) - sizeStat.add(resultsSize) - observeResultsWithSize(results, resultsSize) - } - } -} diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD deleted file mode 100644 index 8569f2d61..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/BUILD +++ /dev/null @@ -1,20 +0,0 @@ -scala_library( - sources = ["*.scala"], - compiler_option_sets = ["fatal_warnings"], - strict_deps = True, - tags = ["bazel-compatible"], - dependencies = [ - "finagle/finagle-core/src/main", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "util/util-core", - ], - exports = [ - "finagle/finagle-core/src/main", - "finagle/finagle-thriftmux/src/main/scala", - "finatra-internal/mtls-http/src/main/scala", - "finatra-internal/mtls-thriftmux/src/main/scala", - "util/util-core", - ], -) diff --git a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala b/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala deleted file mode 100644 index b8c25b5a1..000000000 --- a/product-mixer/shared-library/src/main/scala/com/twitter/product_mixer/shared_library/thrift_client/FinagleThriftClientBuilder.scala +++ /dev/null @@ -1,198 +0,0 @@ -package com.twitter.product_mixer.shared_library.thrift_client - -import com.twitter.conversions.DurationOps._ -import com.twitter.finagle.ThriftMux -import com.twitter.finagle.mtls.authentication.ServiceIdentifier -import com.twitter.finagle.mtls.client.MtlsStackClient._ -import com.twitter.finagle.stats.StatsReceiver -import com.twitter.finagle.thrift.ClientId -import com.twitter.finagle.thrift.service.Filterable -import com.twitter.finagle.thrift.service.MethodPerEndpointBuilder -import com.twitter.finagle.thrift.service.ServicePerEndpointBuilder -import com.twitter.finagle.thriftmux.MethodBuilder -import com.twitter.util.Duration -import org.apache.thrift.protocol.TProtocolFactory - -sealed trait Idempotency -case object NonIdempotent extends Idempotency -case class Idempotent(maxExtraLoadPercent: Double) extends Idempotency - -object FinagleThriftClientBuilder { - - /** - * Library to build a Finagle Thrift method per endpoint client is a less error-prone way when - * compared to the builders in Finagle. This is achieved by requiring values for fields that should - * always be set in practice. For example, request timeouts in Finagle are unbounded when not - * explicitly set, and this method requires that timeout durations are passed into the method and - * set on the Finagle builder. - * - * Usage of - * [[com.twitter.inject.thrift.modules.ThriftMethodBuilderClientModule]] is almost always preferred, - * and the Product Mixer component library [[com.twitter.product_mixer.component_library.module]] - * package contains numerous examples. However, if multiple versions of a client are needed e.g. - * for different timeout settings, this method is useful to easily provide multiple variants. - * - * @example - * {{{ - * final val SampleServiceClientName = "SampleServiceClient" - * @Provides - * @Singleton - * @Named(SampleServiceClientName) - * def provideSampleServiceClient( - * serviceIdentifier: ServiceIdentifier, - * clientId: ClientId, - * statsReceiver: StatsReceiver, - * ): SampleService.MethodPerEndpoint = - * buildFinagleMethodPerEndpoint[SampleService.ServicePerEndpoint, SampleService.MethodPerEndpoint]( - * serviceIdentifier = serviceIdentifier, - * clientId = clientId, - * dest = "/s/sample/sample", - * label = "sample", - * statsReceiver = statsReceiver, - * idempotency = Idempotent(5.percent), - * timeoutPerRequest = 200.milliseconds, - * timeoutTotal = 400.milliseconds - * ) - * }}} - * @param serviceIdentifier Service ID used to S2S Auth - * @param clientId Client ID - * @param dest Destination as a Wily path e.g. "/s/sample/sample" - * @param label Label of the client - * @param statsReceiver Stats - * @param idempotency Idempotency semantics of the client - * @param timeoutPerRequest Thrift client timeout per request. The Finagle default is - * unbounded which is almost never optimal. - * @param timeoutTotal Thrift client total timeout. The Finagle default is - * unbounded which is almost never optimal. - * If the client is set as idempotent, which adds a - * [[com.twitter.finagle.client.BackupRequestFilter]], - * be sure to leave enough room for the backup request. A - * reasonable (albeit usually too large) starting point is to - * make the total timeout 2x relative to the per request timeout. - * If the client is set as non-idempotent, the total timeout and - * the per request timeout should be the same, as there will be - * no backup requests. - * @param connectTimeout Thrift client transport connect timeout. The Finagle default - * of one second is reasonable but we lower this to match - * acquisitionTimeout for consistency. - * @param acquisitionTimeout Thrift client session acquisition timeout. The Finagle default - * is unbounded which is almost never optimal. - * @param protocolFactoryOverride Override the default protocol factory - * e.g. [[org.apache.thrift.protocol.TCompactProtocol.Factory]] - * @param servicePerEndpointBuilder implicit service per endpoint builder - * @param methodPerEndpointBuilder implicit method per endpoint builder - * - * @see [[https://twitter.github.io/finagle/guide/MethodBuilder.html user guide]] - * @see [[https://twitter.github.io/finagle/guide/MethodBuilder.html#idempotency user guide]] - * @return method per endpoint Finagle Thrift Client - */ - def buildFinagleMethodPerEndpoint[ - ServicePerEndpoint <: Filterable[ServicePerEndpoint], - MethodPerEndpoint - ]( - serviceIdentifier: ServiceIdentifier, - clientId: ClientId, - dest: String, - label: String, - statsReceiver: StatsReceiver, - idempotency: Idempotency, - timeoutPerRequest: Duration, - timeoutTotal: Duration, - connectTimeout: Duration = 500.milliseconds, - acquisitionTimeout: Duration = 500.milliseconds, - protocolFactoryOverride: Option[TProtocolFactory] = None, - )( - implicit servicePerEndpointBuilder: ServicePerEndpointBuilder[ServicePerEndpoint], - methodPerEndpointBuilder: MethodPerEndpointBuilder[ServicePerEndpoint, MethodPerEndpoint] - ): MethodPerEndpoint = { - val service: ServicePerEndpoint = buildFinagleServicePerEndpoint( - serviceIdentifier = serviceIdentifier, - clientId = clientId, - dest = dest, - label = label, - statsReceiver = statsReceiver, - idempotency = idempotency, - timeoutPerRequest = timeoutPerRequest, - timeoutTotal = timeoutTotal, - connectTimeout = connectTimeout, - acquisitionTimeout = acquisitionTimeout, - protocolFactoryOverride = protocolFactoryOverride - ) - - ThriftMux.Client.methodPerEndpoint(service) - } - - /** - * Build a Finagle Thrift service per endpoint client. - * - * @note [[buildFinagleMethodPerEndpoint]] should be preferred over the service per endpoint variant - * - * @param serviceIdentifier Service ID used to S2S Auth - * @param clientId Client ID - * @param dest Destination as a Wily path e.g. "/s/sample/sample" - * @param label Label of the client - * @param statsReceiver Stats - * @param idempotency Idempotency semantics of the client - * @param timeoutPerRequest Thrift client timeout per request. The Finagle default is - * unbounded which is almost never optimal. - * @param timeoutTotal Thrift client total timeout. The Finagle default is - * unbounded which is almost never optimal. - * If the client is set as idempotent, which adds a - * [[com.twitter.finagle.client.BackupRequestFilter]], - * be sure to leave enough room for the backup request. A - * reasonable (albeit usually too large) starting point is to - * make the total timeout 2x relative to the per request timeout. - * If the client is set as non-idempotent, the total timeout and - * the per request timeout should be the same, as there will be - * no backup requests. - * @param connectTimeout Thrift client transport connect timeout. The Finagle default - * of one second is reasonable but we lower this to match - * acquisitionTimeout for consistency. - * @param acquisitionTimeout Thrift client session acquisition timeout. The Finagle default - * is unbounded which is almost never optimal. - * @param protocolFactoryOverride Override the default protocol factory - * e.g. [[org.apache.thrift.protocol.TCompactProtocol.Factory]] - * - * @return service per endpoint Finagle Thrift Client - */ - def buildFinagleServicePerEndpoint[ServicePerEndpoint <: Filterable[ServicePerEndpoint]]( - serviceIdentifier: ServiceIdentifier, - clientId: ClientId, - dest: String, - label: String, - statsReceiver: StatsReceiver, - idempotency: Idempotency, - timeoutPerRequest: Duration, - timeoutTotal: Duration, - connectTimeout: Duration = 500.milliseconds, - acquisitionTimeout: Duration = 500.milliseconds, - protocolFactoryOverride: Option[TProtocolFactory] = None, - )( - implicit servicePerEndpointBuilder: ServicePerEndpointBuilder[ServicePerEndpoint] - ): ServicePerEndpoint = { - val thriftMux: ThriftMux.Client = ThriftMux.client - .withMutualTls(serviceIdentifier) - .withClientId(clientId) - .withLabel(label) - .withStatsReceiver(statsReceiver) - .withTransport.connectTimeout(connectTimeout) - .withSession.acquisitionTimeout(acquisitionTimeout) - - val protocolThriftMux: ThriftMux.Client = protocolFactoryOverride - .map { protocolFactory => - thriftMux.withProtocolFactory(protocolFactory) - }.getOrElse(thriftMux) - - val methodBuilder: MethodBuilder = protocolThriftMux - .methodBuilder(dest) - .withTimeoutPerRequest(timeoutPerRequest) - .withTimeoutTotal(timeoutTotal) - - val idempotencyMethodBuilder: MethodBuilder = idempotency match { - case NonIdempotent => methodBuilder.nonIdempotent - case Idempotent(maxExtraLoad) => methodBuilder.idempotent(maxExtraLoad = maxExtraLoad) - } - - idempotencyMethodBuilder.servicePerEndpoint[ServicePerEndpoint] - } -}