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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD.docx new file mode 100644 index 000000000..a32207692 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.docx new file mode 100644 index 000000000..c2ad7e90b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_tweetypie/TweetTweetypieCandidateFeatureHydrator.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD.docx new file mode 100644 index 000000000..10ae306a4 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.docx new file mode 100644 index 000000000..fce0c5f70 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/candidate/tweet_visibility_reason/TweetVisibilityReasonBulkCandidateFeatureHydrator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.docx new file mode 100644 index 000000000..d9441fee7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/AsyncQueryFeatureHydrator.docx differ 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/async/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD.docx new file mode 100644 index 000000000..486daded2 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/async/BUILD.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.docx new file mode 100644 index 000000000..614bbaec9 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.docx new file mode 100644 index 000000000..11f9610cd Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydrator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.docx new file mode 100644 index 000000000..032bab8e2 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/CrMlRankerCommonQueryFeatureHydratorBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.docx new file mode 100644 index 000000000..0b632e01a Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/cr_ml_ranker/RankingConfigBuilder.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD.docx new file mode 100644 index 000000000..411bfc991 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.docx new file mode 100644 index 000000000..b0e1c872b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/impressed_tweets/ImpressedTweetsQueryFeatureHydrator.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD.docx new file mode 100644 index 000000000..0b0ab0898 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.docx new file mode 100644 index 000000000..52fd841d7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/logged_in_only/LoggedInOnlyQueryFeatureHydrator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.docx new file mode 100644 index 000000000..2ef6a0592 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/AsyncParamGatedQueryFeatureHydrator.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD.docx new file mode 100644 index 000000000..0b0ab0898 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.docx new file mode 100644 index 000000000..d80e29222 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/ParamGatedQueryFeatureHydrator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.docx new file mode 100644 index 000000000..24cb4e711 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/AsyncParamGatedFeatureStoreV1QueryFeatureHydrator.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD.docx new file mode 100644 index 000000000..7b6deeae5 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.docx new file mode 100644 index 000000000..a420b5d35 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/param_gated/featurestorev1/ParamGatedFeatureStoreV1QueryFeatureHydrator.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.docx new file mode 100644 index 000000000..7552e925f Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.docx new file mode 100644 index 000000000..e9ad328eb Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/feature_hydrator/query/qualityfactor_gated/QualityFactorGatedQueryFeatureHydrator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.docx new file mode 100644 index 000000000..b36aa2fdc Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/AdaptiveLongIntBloomFilterDedupFilter.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD.docx new file mode 100644 index 000000000..7b3a946c1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.docx new file mode 100644 index 000000000..02cd9564e Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ExcludedIdsFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.docx new file mode 100644 index 000000000..cba9c063e Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.docx new file mode 100644 index 000000000..fa35c5da7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/FeatureValueConditionalFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.docx new file mode 100644 index 000000000..6d14d718b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/HasAuthorIdFeatureFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.docx new file mode 100644 index 000000000..1941fd2c7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/ParamGatedFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.docx new file mode 100644 index 000000000..1318fd7fd Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/PredicateFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.docx new file mode 100644 index 000000000..e25d968ed Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/SnowflakeIdAgeFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.docx new file mode 100644 index 000000000..5d28bf230 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorCountryFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.docx new file mode 100644 index 000000000..36bf1b206 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetAuthorIsSelfFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.docx new file mode 100644 index 000000000..e1981c275 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetIsNotReplyFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.docx new file mode 100644 index 000000000..52642a7e7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetLanguageFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.docx new file mode 100644 index 000000000..70e73adf7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/TweetVisibilityFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.docx new file mode 100644 index 000000000..7f1e205e5 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/UrtUnorderedExcludeIdsCursorFilter.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.docx new file mode 100644 index 000000000..cb60a0abd Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.docx new file mode 100644 index 000000000..43c5716a0 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/list_visibility/ListVisibilityFilter.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.docx new file mode 100644 index 000000000..4afc3ee13 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.docx new file mode 100644 index 000000000..0c6d22426 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/filter/tweet_impression/TweetImpressionFilter.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD.docx new file mode 100644 index 000000000..07cd1745e Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.docx new file mode 100644 index 000000000..691376f62 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/DefinedCountryCodeGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.docx new file mode 100644 index 000000000..40cc6d73c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FeatureGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.docx new file mode 100644 index 000000000..3a0f9c173 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/FirstPageGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.docx new file mode 100644 index 000000000..afe4ba931 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NoCandidatesGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.docx new file mode 100644 index 000000000..ff173f49b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyAdsQueryStringGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.docx new file mode 100644 index 000000000..ebefeca50 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/NonEmptyCandidatesGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.docx new file mode 100644 index 000000000..f68fe633f Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/QualityFactorGate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.docx new file mode 100644 index 000000000..304880194 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/AnyCandidatesWithoutFeatureGate.docx differ 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/gate/any_candidates_without_feature/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.docx new file mode 100644 index 000000000..34b86d9b7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/gate/any_candidates_without_feature/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.docx new file mode 100644 index 000000000..437d36aae Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ArticleCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.docx new file mode 100644 index 000000000..7a9f680d9 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/AudioSpaceCandidate.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD.docx new file mode 100644 index 000000000..ce2633100 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.docx new file mode 100644 index 000000000..29e1ccd0f Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CardCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.docx new file mode 100644 index 000000000..8f0b7dba1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CommerceItemCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.docx new file mode 100644 index 000000000..f8fb68112 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/CursorCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.docx new file mode 100644 index 000000000..15d35aeae Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMConvoCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.docx new file mode 100644 index 000000000..6d2c4aae7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/DMEventCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.docx new file mode 100644 index 000000000..31b679d36 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/GenericSummaryCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.docx new file mode 100644 index 000000000..5a4472928 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/LabelCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.docx new file mode 100644 index 000000000..4b8ae3992 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/MomentAnnotationCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.docx new file mode 100644 index 000000000..683c6dfc3 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/PromptCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.docx new file mode 100644 index 000000000..1ae66eaa1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ShowAlertCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.docx new file mode 100644 index 000000000..07e058553 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TopicCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.docx new file mode 100644 index 000000000..abed147ed Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TweetCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.docx new file mode 100644 index 000000000..8b46e03e3 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/TwitterListCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.docx new file mode 100644 index 000000000..1d8c6d5fd Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/UserCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.docx new file mode 100644 index 000000000..24ab22869 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/AdsCandidate.docx differ 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/ads/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD.docx new file mode 100644 index 000000000..6d4a2c57b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/ads/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.docx new file mode 100644 index 000000000..3fdcfd79d Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdCreativeCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.docx new file mode 100644 index 000000000..4e69e45fe Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdGroupCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.docx new file mode 100644 index 000000000..cbb77dcd9 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/AdUnitCandidate.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD.docx new file mode 100644 index 000000000..fbe87cab1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.docx new file mode 100644 index 000000000..d0e6bde14 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/CampaignCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.docx new file mode 100644 index 000000000..65f253288 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/hubble/FundingSourceCandidate.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD.docx new file mode 100644 index 000000000..3c0af49b6 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.docx new file mode 100644 index 000000000..90a6ba470 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/QuerySuggestionCandidate.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.docx new file mode 100644 index 000000000..4006ba0de Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/suggestion/SpellingSuggestionCandidate.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD.docx new file mode 100644 index 000000000..2e15e2c32 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.docx new file mode 100644 index 000000000..9d5e60627 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/candidate/trends_events/UnifiedTrendEventCandidate.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD.docx new file mode 100644 index 000000000..228950b05 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.docx new file mode 100644 index 000000000..f1ac11e0c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/OrderedCursor.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.docx new file mode 100644 index 000000000..3d1c26cc3 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/PassThroughCursor.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.docx new file mode 100644 index 000000000..19eba7657 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedBloomFilterCursor.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.docx new file mode 100644 index 000000000..d3e148bf4 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UnorderedExcludeIdsCursor.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.docx new file mode 100644 index 000000000..2082c0725 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/cursor/UrtPlaceholderCursor.docx differ 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/feature/flexible_injection_pipeline/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.docx new file mode 100644 index 000000000..c0b5929bc Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/feature/flexible_injection_pipeline/BUILD.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD.docx new file mode 100644 index 000000000..9a19232fc Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.docx new file mode 100644 index 000000000..21da9ffc8 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/slice/SliceItemPresentation.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD.docx new file mode 100644 index 000000000..92ab4b9eb Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.docx new file mode 100644 index 000000000..cdebf9550 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/ConversationModuleItem.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.docx new file mode 100644 index 000000000..dce0b6d76 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtItemPresentation.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.docx new file mode 100644 index 000000000..6390c0888 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtModulePresentation.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.docx new file mode 100644 index 000000000..6e9f0b5b5 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/presentation/urt/UrtOperationPresentation.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.docx new file mode 100644 index 000000000..feab686d6 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/AdsQuery.docx differ 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/model/query/ads/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD.docx new file mode 100644 index 000000000..deee5b225 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/model/query/ads/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.docx new file mode 100644 index 000000000..789da8d6c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/AccountRecommendationsMixerModule.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD.docx new file mode 100644 index 000000000..31b5cc484 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.docx new file mode 100644 index 000000000..539eecfc8 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ConversationServiceModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.docx new file mode 100644 index 000000000..de9bccd74 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/CrMixerClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.docx new file mode 100644 index 000000000..36a4c2afd Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/DarkTrafficFilterModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.docx new file mode 100644 index 000000000..35ccf4f02 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/EarlybirdModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.docx new file mode 100644 index 000000000..55e740fe2 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/ExploreRankerClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.docx new file mode 100644 index 000000000..41918ec96 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/FollowRecommenderServiceModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.docx new file mode 100644 index 000000000..8100626b4 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/GizmoduckClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.docx new file mode 100644 index 000000000..811d3e6a0 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/HomeScorerClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.docx new file mode 100644 index 000000000..d1d96fd24 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/InterestsDiscoveryServiceModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.docx new file mode 100644 index 000000000..aef3c98bf Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/OnboardingTaskServiceModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.docx new file mode 100644 index 000000000..3f1658c5c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/PeopleDiscoveryServiceModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.docx new file mode 100644 index 000000000..01e370a42 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/SocialGraphServiceModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.docx new file mode 100644 index 000000000..f5171fd1d Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineMixerClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.docx new file mode 100644 index 000000000..65fc6642a Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineRankerClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.docx new file mode 100644 index 000000000..850df215b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineScorerClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.docx new file mode 100644 index 000000000..fd4e1c139 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TimelineServiceClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.docx new file mode 100644 index 000000000..46342a21c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetImpressionStoreModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.docx new file mode 100644 index 000000000..a3d121c3c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/TweetyPieClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.docx new file mode 100644 index 000000000..7a7c20e0c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/UserSessionStoreModule.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.docx new file mode 100644 index 000000000..2daa65349 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.docx new file mode 100644 index 000000000..5d2408f0b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/cr_ml_ranker/CrMlRankerModule.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD.docx new file mode 100644 index 000000000..f93b321ff Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.docx new file mode 100644 index 000000000..3e4e90ec9 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.docx new file mode 100644 index 000000000..7d95c59f2 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithCredentialProxyModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.docx new file mode 100644 index 000000000..740c74fe8 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinagleHttpClientWithProxyModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.docx new file mode 100644 index 000000000..2ba79c45c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.docx new file mode 100644 index 000000000..2fcaf7512 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithCredentialProxyModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.docx new file mode 100644 index 000000000..ebee741c9 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/FinatraHttpClientWithProxyModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.docx new file mode 100644 index 000000000..3600f34f5 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/module/http/ProxyCredentialsModule.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.docx new file mode 100644 index 000000000..42f6a90c4 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..bc55ed8cc Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.docx new file mode 100644 index 000000000..5b38ea064 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineQueryTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.docx new file mode 100644 index 000000000..7e42ea02e Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsCandidatePipelineResultsTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.docx new file mode 100644 index 000000000..337bf146b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..9d870f624 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.docx new file mode 100644 index 000000000..04272f8c6 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDependentCandidatePipelineQueryTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.docx new file mode 100644 index 000000000..e723421ff Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/AdsDisplayLocationBuilder.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD.docx new file mode 100644 index 000000000..ef03c4ae6 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.docx new file mode 100644 index 000000000..526a44528 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/CountNumOrganicItems.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.docx new file mode 100644 index 000000000..6f67716ce Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/GetOrganicItemIds.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.docx new file mode 100644 index 000000000..70d39149f Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/PromotedTweetsOnlyFilter.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.docx new file mode 100644 index 000000000..b8ed601ec Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/ads/ValidAdImpressionIdFilter.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.docx new file mode 100644 index 000000000..a15633af6 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.docx new file mode 100644 index 000000000..4e0731d86 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..122520193 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptCandidatePipelineConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.docx new file mode 100644 index 000000000..5a4663a9d Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..917365161 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/FlipPromptDependentCandidatePipelineConfigBuilder.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD.docx new file mode 100644 index 000000000..53440dd8c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.docx new file mode 100644 index 000000000..cebd45d7f Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipCandidateFeatureTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.docx new file mode 100644 index 000000000..c8c54394b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipInjectionParams.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.docx new file mode 100644 index 000000000..e13a8a306 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/FlipQueryTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.docx new file mode 100644 index 000000000..d06ad65a1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/flexible_injection_pipeline/transformer/PromptResultsTransformer.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.docx new file mode 100644 index 000000000..cd1e51f69 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.docx new file mode 100644 index 000000000..19e86bb63 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidateDecorator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.docx new file mode 100644 index 000000000..3625ead9c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.docx new file mode 100644 index 000000000..f291d598d Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmCandidatePipelineQueryTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.docx new file mode 100644 index 000000000..901613e63 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..237458755 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmDependentCandidatePipelineConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.docx new file mode 100644 index 000000000..8ee338f75 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowArmResponseFeatureTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.docx new file mode 100644 index 000000000..64a2ac33b Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidateDecorator.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.docx new file mode 100644 index 000000000..0d7d30952 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..313dfecd8 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.docx new file mode 100644 index 000000000..dfbf942c4 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowCandidatePipelineQueryTransformer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.docx new file mode 100644 index 000000000..3d43af736 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowClientEventDetailsBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.docx new file mode 100644 index 000000000..e74d81d00 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfig.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.docx new file mode 100644 index 000000000..e035f67d1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowDependentCandidatePipelineConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.docx new file mode 100644 index 000000000..1c6eb415c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/pipeline/candidate/who_to_follow_module/WhoToFollowResponseFeatureTransformer.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD.docx new file mode 100644 index 000000000..830af6447 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.docx new file mode 100644 index 000000000..f6b3259b4 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/CursorSerializer.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.docx new file mode 100644 index 000000000..58cc85de5 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/cursor/UrtCursorSerializer.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD.docx new file mode 100644 index 000000000..d6b8581ea Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.docx new file mode 100644 index 000000000..74c8bf112 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/SliceDomainMarshaller.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD.docx new file mode 100644 index 000000000..8d00a7277 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.docx new file mode 100644 index 000000000..c1779c25d Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.docx new file mode 100644 index 000000000..1ea455945 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedNextCursorUpdater.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.docx new file mode 100644 index 000000000..930911898 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.docx new file mode 100644 index 000000000..e2dc74246 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/OrderedPreviousCursorUpdater.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.docx new file mode 100644 index 000000000..420a07ee2 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/ShouldInclude.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.docx new file mode 100644 index 000000000..0de446a91 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.docx new file mode 100644 index 000000000..431056162 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.docx new file mode 100644 index 000000000..05fb92996 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/slice/builder/SliceCursorUpdater.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD.docx new file mode 100644 index 000000000..910a0168e Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.docx new file mode 100644 index 000000000..6639523a2 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/UrpDomainMarshaller.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD.docx new file mode 100644 index 000000000..463554f3d Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.docx new file mode 100644 index 000000000..e8ec0d661 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageBodyBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.docx new file mode 100644 index 000000000..fcf465ac0 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageHeaderBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.docx new file mode 100644 index 000000000..f01180698 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/PageNavBarBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.docx new file mode 100644 index 000000000..ff8d2ec78 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/StaticTimelineScribeConfigBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.docx new file mode 100644 index 000000000..9c898e9e7 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urp/builder/TimelineScribeConfigBuilder.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD.docx new file mode 100644 index 000000000..9ca2aef74 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.docx new file mode 100644 index 000000000..33d9441f1 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UndecoratedUrtDomainMarshaller.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.docx new file mode 100644 index 000000000..51e8a0430 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/UrtDomainMarshaller.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.docx new file mode 100644 index 000000000..cfb226ce5 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesInstructionBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.docx new file mode 100644 index 000000000..e26e50f69 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithAddToModuleInstructionBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.docx new file mode 100644 index 000000000..24a7ecbde Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithPinnedAndReplaceInstructionBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.docx new file mode 100644 index 000000000..ce1b62f86 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceAndShowAlertInstructionBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.docx new file mode 100644 index 000000000..327d0d742 Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithReplaceInstructionBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.docx new file mode 100644 index 000000000..7f1d23c7a Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddEntriesWithShowCoverInstructionBuilder.docx differ 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.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.docx new file mode 100644 index 000000000..b52bfc4df Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/AddToModuleInstructionBuilder.docx differ 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/BUILD.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD.docx new file mode 100644 index 000000000..0013d469c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BUILD.docx differ diff --git a/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.docx b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.docx new file mode 100644 index 000000000..83ed01a7c Binary files /dev/null and b/product-mixer/component-library/src/main/scala/com/twitter/product_mixer/component_library/premarshaller/urt/builder/BaseUnorderedExcludeIdsBottomCursorBuilder.docx differ 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) - } -}